db2_query 0.3.2 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a863b9451d52ea28e71b1477cfd7275bb76b34c91a1302208f4052674dc7b901
4
- data.tar.gz: 555eafaa282e3cab7a0d4231592a6d2a6d3087d0c194f98040dff1724f5da0f2
3
+ metadata.gz: 3e06666a1eee58811d081a1d8da67e2d3e814d91ef15a0c12bb5b306ee130aed
4
+ data.tar.gz: fa7ebb35a4e9019f9619416ed4c97fa410e663d3eb58b9320314002e759c501e
5
5
  SHA512:
6
- metadata.gz: 917d8a2a7a1eefbb85185d021642f42115e7fd51969b302752f1284e274799fca9d7b24c3f6a7fdc764fa9a79cfd6cac7245e4500b0005d5e498f1e718e63a5b
7
- data.tar.gz: 353f50ef752eaaee361c939c21f6552e4fa5c8b5bc81a0face640aae420d889fcb1fb148bd0d7b74e8fec3b1867ffa31df9996cacb05465302e512ec0a5d2147
6
+ metadata.gz: b538e762bf70e00782cc09eb56151c0db034dd13e7b757e8261c27e0e2caafbcd7da70b21a310d8881fe2072e3fd9d56fa072c3499fcd14ab7db97dbac24a2ce
7
+ data.tar.gz: c507ee06457bd6d84e6232ee5bb900cad7dc26249281fab2bb80e04382ea1f5aafd03a6fe182c056ac997176e33b8236bf587207638c1901ddaef694b53bc7a7
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2021 yohanes oktavianus lumentut
1
+ Copyright Yohanes Lumentut
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -2,11 +2,13 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/db2_query.svg)](https://badge.fury.io/rb/db2_query)
4
4
 
5
- A Rails 5 & Rails 6 plugin for handling Db2 SQL database `SIUD` statement (`SELECT`, `INSERT`, `UPDATE`, `DELETE`) by using ODBC connection.
5
+ A Rails 7 (Ruby v3.1.0) plugin for connecting Db2 with Rails appplication by using ODBC connection.
6
+ Db2Query execute plain SQL instead of using query builder
6
7
 
7
- Note: Tested at Rails 5.2.6 and Rails 6.1.4
8
+ Note: Tested at Rails 7.1.2 on Ruby v3.1.0
8
9
 
9
10
  ## 1. Installation
11
+
10
12
  Add this line to your application's Gemfile:
11
13
 
12
14
  ```ruby
@@ -14,16 +16,23 @@ gem 'db2_query'
14
16
  ```
15
17
 
16
18
  And then execute:
19
+
17
20
  ```bash
18
21
  $ bundle
22
+ ...
19
23
  ```
20
24
 
21
25
  Or install it yourself as:
26
+
22
27
  ```bash
23
28
  $ gem install db2_query
29
+ ...
24
30
  ```
31
+
25
32
  ## 2. Initialization
33
+
26
34
  Execute **db2query:init** task at the app root to create database configurations and initializer file.
35
+
27
36
  ```bash
28
37
  $ rake db2query:init
29
38
  create config/db2query.yml
@@ -33,20 +42,22 @@ $ rake db2query:init
33
42
  Complete the configurations by editing the files according to your application requirement.
34
43
 
35
44
  ### Database Configuration
45
+
36
46
  File **config/db2query.yml** consist of DSN/database name and connection pool config:
47
+
37
48
  ```yml
38
49
  development:
39
- dsn: ARUNIT
50
+ dsn: LIBDEV
40
51
  idle: 5
41
52
  pool: 5
42
53
  timeout: 5
43
54
  test:
44
- dsn: ARUNIT
55
+ dsn: LIBTEST
45
56
  idle: 5
46
57
  pool: 5
47
58
  timeout: 5
48
59
  production:
49
- dsn: ARUNIT
60
+ dsn: LIBPROD
50
61
  idle: 5
51
62
  pool: 5
52
63
  timeout: 5
@@ -57,7 +68,9 @@ Key **idle** is a **client** idle maximum limit value (in minutes) to avoid the
57
68
  [**Ensure**](https://github.com/yohaneslumentut/db2_query/wiki/DB2-ODBC-Connection#verify-odbc-connection) that **unixodbc** has been installed and test your connection first by using **isql** commands.
58
69
 
59
70
  ### Initializer File
71
+
60
72
  This file is used by **Db2Query::Base** to load **field types** configurations and establish a **connection** instance.
73
+
61
74
  ```ruby
62
75
  # app_root/config/initializers/db2query.rb
63
76
 
@@ -70,7 +83,10 @@ end
70
83
  ```
71
84
 
72
85
  ### Custom Field Type
73
- **FieldTypes** are classes that used by **Db2Query** to format the data before sending it to the database by using `serialize` method and converting the **query result** before consumed by your **Rails application** by using `deserialize` method. Both `serialize` and `deserialize` operations are only applied when you provide **QueryDefinitions** on your query. By default, there are ten field types that can be used in your [query definitions](#32-querydefinitions) :
86
+
87
+ **FieldTypes** are classes that are used by **Db2Query** to format the data before sending it to the database by using `serialize` method and `deserialize` the returned query result data by converting the **query result** before consumed by your **Rails application**. Both `serialize` and `deserialize` operations are only applied when you provide **QueryDefinitions** on your query.
88
+
89
+ By default, there are ten field types that can be used in your [query definitions](#32-querydefinitions) :
74
90
 
75
91
  ```ruby
76
92
  DEFAULT_FIELD_TYPES = {
@@ -86,7 +102,9 @@ end
86
102
  timestamp: Db2Query::Type::Timestamp
87
103
  }
88
104
  ```
105
+
89
106
  You can use your own Field type class by extending **Db2Query::Type::Value** class. For example:
107
+
90
108
  ```ruby
91
109
  class CustomTypeClass < Db2Query::Type::Value
92
110
  # Method to convert data from ruby type value into data that is understood by Db2
@@ -100,7 +118,9 @@ You can use your own Field type class by extending **Db2Query::Type::Value** cla
100
118
  end
101
119
  end
102
120
  ```
103
- Then map the classes into a variable and load it into the **Db2Query::Base** by using **set_field_types** method in the initializer file.
121
+
122
+ Then put the classes into a field types hash constant and load it into the **Db2Query::Base** by using **set_field_types** method in the initializer file.
123
+
104
124
  ```ruby
105
125
  # app_root/config/initializers/db2query.rb
106
126
 
@@ -122,28 +142,26 @@ end
122
142
 
123
143
  ## 3. Usage
124
144
 
125
- Once you completely do [**Installation**](#1-installation) & [**Initialization**](#2-initialization), basically you has been ready to use **Db2Query::Base** with three additional conventions: **SQL Convention**, **Field Type Convention**, **Argument Key Convention**.
145
+ Once you completely do the [**Installation**](#1-installation) & [**Initialization**](#2-initialization) steps, basically you has been ready to use **Db2Query::Base**. There are three additional rules that help **Db2Query** run properly: **SQL Convention**, **Field Type Convention**, and **Argument Key Convention**.
126
146
 
127
147
  **SQL Convention**:
128
- > **"** Dollar symbol **$** is used as the prefix of all column names **in the WHERE clause** of provided **Parameterized Query** SQL string. It is used as a pointer in the binding process of key and value of query arguments. We have to provide it manually in the SQL string of each **Parameterized Query**. Here, **Parameterized Query** is used to minimize SQL injection risks.**"**
129
-
130
- **Field Type Convention**:
131
- > **"** **field_name** written in **query_definition** block must be in downcased format.**"**
132
-
133
- **Argument Key Convention**:
134
- > **"** **Argument Key** passed into query have to follow its parameter written in the SQL. It is case-sensitive. If the parameter in your SQL is written in downcase format, then your argument key has to be in downcase format too.**"**
135
-
148
+ > A colon **:** is used as the prefix of all column names of provided **Parameterized Query** SQL string. It is used in determining query arguments key and value binding process. We have to provide it manually in the SQL string of each **Parameterized Query**. Here, **Parameterized Query** is used to minimize SQL injection risks.
136
149
 
137
150
  ```ruby
138
151
  # SQL Convention Examples
139
152
  # Example of Parameterized Query SQL usage
140
153
 
141
- Db2Query::Base.query("SELECT * FROM USERS WHERE $email = ?", "my_account@email.com")
154
+ Db2Query::Base.query("SELECT * FROM USERS WHERE email = :email", "my_account@email.com")
142
155
 
143
156
  # Example of Normal SQL usage
144
157
 
145
158
  Db2Query::Base.query("SELECT * FROM USERS WHERE email = 'my_account@email.com'")
159
+ ```
146
160
 
161
+ **Field Type Convention**:
162
+ > Query definition's **field_name** written in **query_definition** block must be in downcased format.
163
+
164
+ ```ruby
147
165
  # Field Type Convention Example
148
166
 
149
167
  module Definitions
@@ -158,60 +176,85 @@ module Definitions
158
176
  end
159
177
  end
160
178
  end
179
+ ```
180
+
181
+ **Argument Key Convention**:
182
+ > The letter case of a **Named Argument** key that passed into a query, has to follow its parameter letter case format that is written in the SQL. The argument key is case-sensitive. If the parameter in your SQL is written in downcase format, then your argument key has to be in downcase format too, and vice versa.
161
183
 
184
+ ```ruby
162
185
  # Argument Key Convention Example
163
186
 
187
+ class MyQuery < Db2Query::Base
188
+ ...
189
+ query :find_by, <<-SQL
190
+ SELECT * FROM USERS WHERE id = :id
191
+ SQL
192
+ ...
193
+ end
194
+
164
195
  MyQuery.find_user_by_id id: 10000
165
196
 
166
197
  ```
167
198
 
168
-
169
199
  ### 3.1 Basic Usage
170
200
 
171
201
  #### Base Class Query Methods
172
202
 
173
203
  ##### #query(sql, args)
204
+
174
205
  A raw query to perform a `connection.run(sql, args)` operation and returns an array of hashes representing each row record being executed.
206
+
175
207
  ```ruby
176
- Db2Query::Base.query("SELECT * FROM USERS WHERE $id < ?", 10003)
208
+ Db2Query::Base.query("SELECT * FROM USERS WHERE id < :id", 10003)
177
209
  => [{:id=>10000, :first_name=>"Taisha", :last_name=>"Kutch", :email=>"willie.lesch@toy.org"}, {:id=>10001, :first_name=>"Setsuko", :last_name=>"Kutch", :email=>"thelma@purdy.co"}, {:id=>10002, :first_name=>"Trina", :last_name=>"Mayer", :email=>"dorsey_upton@flatley-gulgowski.name"}]
178
210
  ```
179
211
 
180
212
  ##### #query_rows(sql)
213
+
181
214
  Execute the `SELECT Statement SQL` and returns collections of arrays consisting of row values.
215
+
182
216
  ```ruby
183
217
  Db2Query::Base.query_rows("SELECT * FROM USERS WHERE id < 10003")
184
218
  => [[10000, "Taisha", "Kutch", "willie.lesch@toy.org"], [10001, "Setsuko", "Kutch", "thelma@purdy.co"], [10002, "Trina", "Mayer", "dorsey_upton@flatley-gulgowski.name"]]
185
219
  ```
186
220
 
187
221
  ##### #query_value(sql)
222
+
188
223
  Execute the `SELECT Statement SQL` and returns the first value of the query results first row.
224
+
189
225
  ```ruby
190
226
  Db2Query::Base.query_value("SELECT * FROM USERS WHERE id < 10003")
191
227
  => 10000
192
228
  ```
193
229
 
194
230
  ##### #query_values(sql)
231
+
195
232
  Execute the `SELECT Statement SQL` and returns a collection of the first value of each query result rows.
233
+
196
234
  ```ruby
197
235
  Db2Query::Base.query_values("SELECT * FROM USERS WHERE id < 10003")
198
236
  => [10000, 10001, 10002]
199
237
  ```
200
238
 
201
239
  ##### #execute(sql, args)
240
+
202
241
  A method to execute `DUI Statement SQL` by using `connection.do(sql, args)`
242
+
203
243
  ```ruby
204
- Db2Query::Base.execute("DELETE FROM users WHERE $id = ?", 10000)
244
+ Db2Query::Base.execute("DELETE FROM users WHERE id = :id", 10000)
205
245
  => -1
206
246
  ```
207
247
 
208
248
  ### 3.2 QueryDefinitions
209
249
 
250
+ #### 3.2.1 Query Field Definitions
251
+
210
252
  QueryDefinitions is helpful when you need formatter methods that **serialize** the data before it being sent to the database and **deserialize** database output data before being consumed by **Rails application**. The real examples are **Binary** and **Boolean** field types.
211
253
  At **Db2Query::Type::Binary**, the data `unpacked` by `serialize` method before sending to the database and do `deserialize` operation to `pack` the database returned data.
212
254
  QueryDefinition can be used as **Query Schema** where the **field types** of a query are outlined. The field-type written in QueryDefinition has to follow the **Field Type Convention**.
213
255
 
214
- A QueryDefinitions reside in `app_root/app/queries/definitions` directory. It is automatically created when you create your query by using run `rails g query query_name` [**generator**](#33-generator) command. The QueryDefinitions class can be defined as follow:
256
+ A QueryDefinitions reside in `app_root/app/queries/definitions` directory. It is automatically created when you create your query by running `rails g query query_name` [**generator**](#33-generator) command. The QueryDefinitions class can be defined as follow:
257
+
215
258
  ```ruby
216
259
  # app_root/app/queries/definitions/your_query_definitions.rb
217
260
  module Definitions
@@ -230,6 +273,7 @@ module Definitions
230
273
  end
231
274
  end
232
275
  ```
276
+
233
277
  For Example:
234
278
 
235
279
  ```ruby
@@ -257,6 +301,21 @@ end
257
301
 
258
302
  ```
259
303
 
304
+ #### 3.2.2 Query Argument Types
305
+
306
+ Sometimes, the `query arguments` do not exist in query definitions fields. In such a case, a `Db2Query::QueryArgumentError` will be raised. So, we have to provide `query argument types` at the Query class.
307
+
308
+ ```ruby
309
+ module NameSpace
310
+ class QueryName < Db2Query::Base
311
+ query_arguments :user_by_email, { email: :string, trim: true }
312
+
313
+ def user_by_email_sql
314
+ "SELECT id, first_name, last_name FROM USERS WHERE email = :email"
315
+ end
316
+ end
317
+ end
318
+ ```
260
319
 
261
320
  ### 3.3 Generator
262
321
 
@@ -265,9 +324,10 @@ Create query class by using `rails g query NAME` commands. For example:
265
324
  ```bash
266
325
  $ rails g query NameSpace::Name --defines=first_query --queries=next_query --lambdas=last_query
267
326
  create app/queries/name_space/name_query.rb
268
- create app/queries/definitions/movies_query_definitions.rb
327
+ create app/queries/definitions/name_space/name_query_definitions.rb
269
328
  create test/queries/name_space/name_query_test.rb
270
329
  ```
330
+
271
331
  This will create `app/queries/name_space/name_query.rb` file in `app/queries` directory.
272
332
 
273
333
  ```ruby
@@ -339,9 +399,11 @@ end
339
399
  ```
340
400
 
341
401
  #### 3.4.1 Plain Query (--defines)
402
+
342
403
  Query implementation that uses the plain method. The method name must have a `_sql` suffix and return SQL statement string.
343
404
 
344
405
  Example:
406
+
345
407
  ```ruby
346
408
  class MyQuery < Db2Query::Base
347
409
  def all_users_sql
@@ -349,15 +411,17 @@ class MyQuery < Db2Query::Base
349
411
  end
350
412
 
351
413
  def find_user_by_id_sql
352
- "SELECT * FROM USERS WHERE $id = ?"
414
+ "SELECT * FROM USERS WHERE id = :id"
353
415
  end
354
416
  end
355
417
  ```
356
418
 
357
419
  #### 3.4.2 String Query (--queries)
420
+
358
421
  Query implementation that uses the built-in `query` method. The input arguments consist of `query_name` symbol and SQL statement
359
422
 
360
423
  Example:
424
+
361
425
  ```ruby
362
426
  class MyQuery < Db2Query::Base
363
427
  query :all_users, <<-SQL
@@ -365,15 +429,17 @@ class MyQuery < Db2Query::Base
365
429
  SQL
366
430
 
367
431
  query :find_user_by_id, <<-SQL
368
- SELECT * FROM USERS WHERE $id = ?
369
- end
432
+ SELECT * FROM USERS WHERE id = :id
433
+ SQL
370
434
  end
371
435
  ```
372
436
 
373
437
  #### 3.4.3 Lambda Query (--lambdas)
438
+
374
439
  Query implementation that uses the built-in `query` method. The input arguments consist of the `query_name` symbol and a lambda function. We have to pass `args` as the arguments of a lambda function. Do not change the `args` with let's say `-> id, email { ... }`. Just leave it written as `args`. The `args` is used by `Db2Query::Base` to store `query_name` and the other `arg` inputs.
375
440
 
376
441
  Example:
442
+
377
443
  ```ruby
378
444
  class MyQuery < Db2Query::Base
379
445
  query :all_users, -> args {
@@ -381,7 +447,7 @@ class MyQuery < Db2Query::Base
381
447
  }
382
448
 
383
449
  query :find_user_by_id, -> args {
384
- fetch("SELECT * FROM USERS WHERE $id = ?", args)
450
+ fetch("SELECT * FROM USERS WHERE id = :id", args)
385
451
  }
386
452
  end
387
453
  ```
@@ -397,6 +463,7 @@ irb(main):001:0> MyQuery.find_user_by_id 10000
397
463
  SQL (3.0ms) SELECT * FROM USERS WHERE id = ? [["id", 10000]]
398
464
  => #<Db2Query::Result [#<Record id: 10004, first_name: Yohanes, ...]>
399
465
  ```
466
+
400
467
  If you pass a key-value argument into query, the key has to follow **Argument Key Convention**
401
468
 
402
469
  ```bash
@@ -407,6 +474,7 @@ irb(main):001:0> MyQuery.find_user_by_id(id: 10000)
407
474
  ```
408
475
 
409
476
  And use it at your application
477
+
410
478
  ```ruby
411
479
  users = MyQuery.all
412
480
  user_records = users.records
@@ -425,24 +493,28 @@ user.last_name # => "Lumentut"
425
493
  user.email # => "yohanes@github.com"
426
494
  ```
427
495
 
428
- ### 3.5 SQL extention (`@extention`)
429
- For a reusable `sql`, we can extend it by using a combination of `extention` and `sql_with_extention` methods, with an `@extention` pointer at SQL statement.
496
+ ### 3.5 SQL extension (`@extension`)
497
+
498
+ For the sake of reusable SQL string, we can reuse the most commonly used SQL part by implementing `sql_with_extension` methods with an SQL string argument contain `@extension` pointer at SQL statement.
499
+
430
500
  ```ruby
431
501
  class MyQuery < Db2Query::Base
432
502
  # reusable SQL
433
- _SQL = -> extention {
434
- sql_with_extention("SELECT * FROM USERS WHERE @extention", extention)
503
+ _SQL = -> extension {
504
+ sql_with_extension("SELECT * FROM USERS WHERE @extension", extension)
435
505
  }
436
506
 
437
507
  # implementation
438
- query :user_by_email, _SQL.("$email = ?")
508
+ query :user_by_email, _SQL.("email = :email")
439
509
  end
440
510
  ```
511
+
441
512
  ```bash
442
- irb(main):001:0> MyQuery.user_by_email
513
+ irb(main):001:0> MyQuery.user_by_email email: "yohanes@github.com"
443
514
  SQL (2.7ms) SELECT * FROM USERS email = ? [["email", "yohanes@github.com"]]
444
515
  => #<Db2Query::Result [#<Record id: 10000, first_name: Yohanes, ...]>
445
516
  ```
517
+
446
518
  ```ruby
447
519
  user = MyQuery.user_by_email "yohanes@github.com"
448
520
  user.id # => 10000
@@ -450,7 +522,9 @@ user.first_name # => "Yohanes"
450
522
  user.last_name # => "Lumentut"
451
523
  user.email # => "yohanes@github.com"
452
524
  ```
525
+
453
526
  ### 3.6 List input (`@list`)
527
+
454
528
  For an array consist list of inputs, we can use `fetch_list` method and `@list` pointer at the SQL statement.
455
529
 
456
530
  ```ruby
@@ -460,12 +534,14 @@ class MyQuery < Db2Query::Base
460
534
  }
461
535
  end
462
536
  ```
537
+
463
538
  ```bash
464
539
  irb(main):007:0> MyQuery.user_by_ids [10000,10001,10002]
465
540
  SQL (2.8ms) SELECT * FROM USERS WHERE ID IN ('10000', '10001', '10002')
466
541
  => #<Db2Query::Result [#<Record id: 10000, name: "Carol", last_name: "Danvers", email: "captain.marvel@marvel.universe.com">, #<Record id: 10001, first_name: "Natasha", last_name: "Romanova", email: "black.widow@marvel.universe">, #<Record id: 10002, first_name: "Wanda", last_name: "Maximoff", email: "scarlet.witch@marvel.universe.com">]>
467
542
 
468
543
  ```
544
+
469
545
  ```ruby
470
546
  users = MyQuery.user_by_ids [10000,10001,10002]
471
547
  user = users.first
@@ -478,12 +554,15 @@ user.email # => "captain.marvel@marvel.universe.com"
478
554
  ```
479
555
 
480
556
  ### 3.7 Formatter
557
+
481
558
  For the latest version of **Db2Query**, there is no more **Db2Query::Formatter** class. We can implement our formater into **deserialize** method of our [**QueryDefinitions**](#32-querydefinitions).
482
559
 
483
560
  If you upgrade from the previous version, you have to run **`rake db2query:init`** again to override the initializer. Please create a backup of your Formatter classes before you do this operation. Then you can implement your Formatter methods into your **QueryDefinitions**.
484
561
 
485
562
  ## 4. Available Result Object methods
563
+
486
564
  `Db2Query::Result` inherit all `ActiveRecord::Result` methods with additional custom methods:
565
+
487
566
  1. `records` to convert query result into an array of Result query's Record objects.
488
567
  2. `record` to get the first Record Object of Result query.
489
568
  3. `to_h` to convert query result into an array of hashes with symbolized keys.
@@ -503,10 +582,11 @@ end
503
582
  ```
504
583
 
505
584
  Utilize the goodness of rails model `scope`
585
+
506
586
  ```ruby
507
587
  class User < Db2Record
508
588
  scope :by_name, -> *args {
509
- query("SELECT * FROM USERS WHERE $first_name = ? AND $last_name = ?", args)
589
+ query("SELECT * FROM USERS WHERE first_name = :first_name AND last_name = :last_name", args)
510
590
  }
511
591
  end
512
592
  ```
@@ -518,6 +598,7 @@ SQL Load (3.28ms) SELECT * FROM USERS WHERE first_name = ? AND last_name = ? [[
518
598
  ```
519
599
 
520
600
  Another example:
601
+
521
602
  ```ruby
522
603
  class User < Db2Record
523
604
  scope :age_gt, -> *args {
@@ -535,6 +616,18 @@ SQL Load (3.28ms) SELECT * FROM USERS WHERE age > 500
535
616
  ## 6. Examples
536
617
 
537
618
  For complete examples please see the basic examples [here](https://github.com/yohaneslumentut/db2_query/blob/master/test/dummy/app/queries/user_query.rb).
619
+ Please see [**Db2Session**](https://github.com/yohaneslumentut/db2_session) for **REST** and **GraphQL** implementation of multi-user on the remote server.
620
+
621
+ ## 7. Test
622
+
623
+ To run a development test:
624
+
625
+ ```bash
626
+ $ bin/test test
627
+ Db2 Version : DB2 v11.5.8.0
628
+ ...
629
+ ```
630
+
631
+ ## 8. License
538
632
 
539
- ## 7. License
540
633
  The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1,13 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "bundler/setup"
4
- require "bundler/gem_tasks"
5
- require "rake/testtask"
6
2
 
7
- Rake::TestTask.new(:test) do |t|
8
- t.libs << "test"
9
- t.pattern = "test/**/*_test.rb"
10
- t.verbose = false
11
- end
12
-
13
- task default: :test
3
+ require "bundler/gem_tasks"
@@ -4,7 +4,6 @@ module Db2Query
4
4
  class Base
5
5
  include Config
6
6
  include Helper
7
- include Quoting
8
7
  include DbConnection
9
8
  include FieldType
10
9
  include Core
@@ -25,27 +25,44 @@ module Db2Query
25
25
  end
26
26
 
27
27
  def query(*query_args)
28
- if query_args[1].respond_to?(:call)
28
+ if query_args.first.is_a?(Symbol)
29
29
  query_name, body = query_args
30
- singleton_class.define_method(query_name) do |*args|
31
- body.call(args << { query_name: query_name })
30
+
31
+ body_lambda = if body.is_a?(Proc)
32
+ -> args { body.call(args << { query_name: query_name }) }
33
+ elsif body.is_a?(String)
34
+ definition = definitions.lookup_query(query_name, body.strip)
35
+ -> args { exec_query_result(definition, args) }
36
+ else
37
+ raise Db2Query::QueryMethodError.new
32
38
  end
33
- elsif query_args[0].is_a?(String)
34
- sql, query_args = [query_args.first.strip, query_args.drop(1)]
35
- query = raw_query(sql, query_args)
36
- connection.raw_query(query.db2_spec_sql, query.args)
37
- elsif query_args[1].is_a?(String) && query_args[1].strip.length > 0
38
- query_name, sql = query_args
39
- query = definitions.lookup_query(query_name, sql.strip)
39
+
40
40
  singleton_class.define_method(query_name) do |*args|
41
- exec_query_result(query, args)
41
+ body_lambda.call(args)
42
+ end
43
+ elsif query_args.first.is_a?(String)
44
+ sql, args = [query_args.first.strip, query_args.drop(1)]
45
+
46
+ definition = Query.new.tap do |d|
47
+ d.define_sql(sql)
48
+ d.define_args(args)
42
49
  end
50
+
51
+ connection.raw_query(definition.db2_spec_sql, definition.args)
43
52
  else
44
- raise Db2Query::QueryMethodError.new
53
+ raise Db2Query::Error, "Wrong query implementation"
45
54
  end
46
55
  end
47
56
  alias define query
48
57
 
58
+ def query_arguments_map
59
+ @query_arguments_map ||= {}
60
+ end
61
+
62
+ def query_arguments(query_name, argument_types)
63
+ query_arguments_map[query_name] = argument_types
64
+ end
65
+
49
66
  def fetch(sql, args = [])
50
67
  query = definitions.lookup_query(args, sql)
51
68
  query.validate_select_query
@@ -60,7 +77,10 @@ module Db2Query
60
77
  private
61
78
  def new_definitions
62
79
  definition_class = "Definitions::#{name}Definitions"
63
- Object.const_get(definition_class).new(field_types_map)
80
+ Object.const_get(definition_class).new(
81
+ query_arguments_map,
82
+ field_types_map
83
+ )
64
84
  rescue Exception => e
65
85
  raise Db2Query::Error, e.message
66
86
  end
@@ -71,13 +91,6 @@ module Db2Query
71
91
  end
72
92
  end
73
93
 
74
- def raw_query(sql, args)
75
- Query.new.tap do |query|
76
- query.define_sql(sql)
77
- query.define_args(args)
78
- end
79
- end
80
-
81
94
  def define_sql_query(method_name)
82
95
  sql_query_name = sql_query_symbol(method_name)
83
96
  sql_statement = allocate.method(sql_query_name).call
@@ -35,11 +35,10 @@ module Db2Query
35
35
  end
36
36
  end
37
37
 
38
- attr_reader :config, :connection_pool, :instrumenter, :lock
38
+ attr_reader :config, :connection_pool, :instrumenter, :mutex
39
39
 
40
40
  delegate :with, :current_state, :disconnect!, :reload, to: :connection_pool
41
41
  delegate :instrument, to: :instrumenter
42
- delegate :synchronize, to: :lock
43
42
 
44
43
  include Logger
45
44
  include DbStatements
@@ -47,7 +46,8 @@ module Db2Query
47
46
  def initialize(config)
48
47
  @config = config
49
48
  @instrumenter = ActiveSupport::Notifications.instrumenter
50
- @lock = ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
49
+ @mutex = Mutex.new
50
+ @connection_pool = nil
51
51
  create_connection_pool
52
52
  end
53
53
 
@@ -58,7 +58,7 @@ module Db2Query
58
58
  end
59
59
 
60
60
  def create_connection_pool
61
- synchronize do
61
+ mutex.synchronize do
62
62
  return @connection_pool if @connection_pool
63
63
  @connection_pool = Pool.new(pool_config) { DbClient.new(config) }
64
64
  end
@@ -3,9 +3,11 @@
3
3
  module Db2Query
4
4
  class Definitions
5
5
  attr_accessor :types, :types_map
6
+ attr_reader :arguments_map
6
7
 
7
- def initialize(types_map)
8
- @types_map = types_map
8
+ def initialize(query_arguments_map, field_types_map)
9
+ @arguments_map = query_arguments_map
10
+ @types_map = field_types_map
9
11
  describe
10
12
  initialize_types
11
13
  end
@@ -26,14 +28,24 @@ module Db2Query
26
28
 
27
29
  def lookup(query_name)
28
30
  queries.fetch(query_name)
29
- rescue
30
- raise Db2Query::QueryDefinitionError.new(name, query_name)
31
+ rescue Exception => e
32
+ if defined?(name)
33
+ raise Db2Query::QueryDefinitionError.new(name, query_name)
34
+ else
35
+ raise Db2Query::Error, e.message
36
+ end
31
37
  end
32
38
 
33
39
  def lookup_query(*args)
34
40
  query_name, sql = query_definitions(args)
35
41
  lookup(query_name).tap do |query|
36
42
  query.define_sql(sql)
43
+ query.argument_keys.each do |key|
44
+ key, key_def = query_arg_key(query, key)
45
+ query.argument_types.store(key, data_type_instance(key_def))
46
+ rescue
47
+ raise Db2Query::QueryArgumentError.new(query_name, key)
48
+ end
37
49
  end
38
50
  end
39
51
 
@@ -75,5 +87,13 @@ module Db2Query
75
87
  else args
76
88
  end
77
89
  end
90
+
91
+ def query_arg_key(query, key)
92
+ [key, unless arguments_map[query.query_name].nil?
93
+ arguments_map[query.query_name][key]
94
+ else
95
+ query.columns[key]
96
+ end]
97
+ end
78
98
  end
79
99
  end