db2_query 0.3.2 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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