db2_query 0.3.3 → 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 +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +80 -18
- data/Rakefile +1 -11
- data/lib/db2_query/db_connection.rb +3 -4
- data/lib/db2_query/definitions.rb +8 -2
- data/lib/db2_query/error.rb +12 -0
- data/lib/db2_query/logger.rb +1 -1
- data/lib/db2_query/query.rb +9 -6
- data/lib/db2_query/railtie.rb +0 -11
- data/lib/db2_query/version.rb +1 -3
- data/lib/db2_query.rb +3 -8
- data/lib/tasks/db2_query_tasks.rake +4 -0
- metadata +26 -85
- data/lib/db2_query/tasks/database.rake +0 -10
- data/lib/db2_query/tasks/init.rake +0 -9
- data/lib/db2_query/tasks/initializer.rake +0 -10
- data/lib/db2_query/tasks/templates/database.rb.tt +0 -19
- data/lib/db2_query/tasks/templates/initializer.rb.tt +0 -8
- data/lib/rails/generators/query/USAGE +0 -15
- data/lib/rails/generators/query/query_generator.rb +0 -70
- data/lib/rails/generators/query/templates/query.rb.tt +0 -26
- data/lib/rails/generators/query/templates/query_definitions.rb.tt +0 -18
- data/lib/rails/generators/query/templates/unit_test.rb.tt +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e06666a1eee58811d081a1d8da67e2d3e814d91ef15a0c12bb5b306ee130aed
|
4
|
+
data.tar.gz: fa7ebb35a4e9019f9619416ed4c97fa410e663d3eb58b9320314002e759c501e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b538e762bf70e00782cc09eb56151c0db034dd13e7b757e8261c27e0e2caafbcd7da70b21a310d8881fe2072e3fd9d56fa072c3499fcd14ab7db97dbac24a2ce
|
7
|
+
data.tar.gz: c507ee06457bd6d84e6232ee5bb900cad7dc26249281fab2bb80e04382ea1f5aafd03a6fe182c056ac997176e33b8236bf587207638c1901ddaef694b53bc7a7
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/db2_query)
|
4
4
|
|
5
|
-
A Rails
|
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
|
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,7 +42,9 @@ $ 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
50
|
dsn: LIBDEV
|
@@ -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,8 @@ end
|
|
70
83
|
```
|
71
84
|
|
72
85
|
### Custom Field Type
|
73
|
-
|
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.
|
74
88
|
|
75
89
|
By default, there are ten field types that can be used in your [query definitions](#32-querydefinitions) :
|
76
90
|
|
@@ -88,7 +102,9 @@ By default, there are ten field types that can be used in your [query definition
|
|
88
102
|
timestamp: Db2Query::Type::Timestamp
|
89
103
|
}
|
90
104
|
```
|
105
|
+
|
91
106
|
You can use your own Field type class by extending **Db2Query::Type::Value** class. For example:
|
107
|
+
|
92
108
|
```ruby
|
93
109
|
class CustomTypeClass < Db2Query::Type::Value
|
94
110
|
# Method to convert data from ruby type value into data that is understood by Db2
|
@@ -102,7 +118,9 @@ You can use your own Field type class by extending **Db2Query::Type::Value** cla
|
|
102
118
|
end
|
103
119
|
end
|
104
120
|
```
|
121
|
+
|
105
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
|
+
|
106
124
|
```ruby
|
107
125
|
# app_root/config/initializers/db2query.rb
|
108
126
|
|
@@ -127,13 +145,13 @@ end
|
|
127
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**.
|
128
146
|
|
129
147
|
**SQL Convention**:
|
130
|
-
>
|
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.
|
131
149
|
|
132
150
|
```ruby
|
133
151
|
# SQL Convention Examples
|
134
152
|
# Example of Parameterized Query SQL usage
|
135
153
|
|
136
|
-
Db2Query::Base.query("SELECT * FROM USERS WHERE
|
154
|
+
Db2Query::Base.query("SELECT * FROM USERS WHERE email = :email", "my_account@email.com")
|
137
155
|
|
138
156
|
# Example of Normal SQL usage
|
139
157
|
|
@@ -169,7 +187,7 @@ end
|
|
169
187
|
class MyQuery < Db2Query::Base
|
170
188
|
...
|
171
189
|
query :find_by, <<-SQL
|
172
|
-
SELECT * FROM USERS WHERE
|
190
|
+
SELECT * FROM USERS WHERE id = :id
|
173
191
|
SQL
|
174
192
|
...
|
175
193
|
end
|
@@ -178,43 +196,52 @@ MyQuery.find_user_by_id id: 10000
|
|
178
196
|
|
179
197
|
```
|
180
198
|
|
181
|
-
|
182
199
|
### 3.1 Basic Usage
|
183
200
|
|
184
201
|
#### Base Class Query Methods
|
185
202
|
|
186
203
|
##### #query(sql, args)
|
204
|
+
|
187
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
|
+
|
188
207
|
```ruby
|
189
|
-
Db2Query::Base.query("SELECT * FROM USERS WHERE
|
208
|
+
Db2Query::Base.query("SELECT * FROM USERS WHERE id < :id", 10003)
|
190
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"}]
|
191
210
|
```
|
192
211
|
|
193
212
|
##### #query_rows(sql)
|
213
|
+
|
194
214
|
Execute the `SELECT Statement SQL` and returns collections of arrays consisting of row values.
|
215
|
+
|
195
216
|
```ruby
|
196
217
|
Db2Query::Base.query_rows("SELECT * FROM USERS WHERE id < 10003")
|
197
218
|
=> [[10000, "Taisha", "Kutch", "willie.lesch@toy.org"], [10001, "Setsuko", "Kutch", "thelma@purdy.co"], [10002, "Trina", "Mayer", "dorsey_upton@flatley-gulgowski.name"]]
|
198
219
|
```
|
199
220
|
|
200
221
|
##### #query_value(sql)
|
222
|
+
|
201
223
|
Execute the `SELECT Statement SQL` and returns the first value of the query results first row.
|
224
|
+
|
202
225
|
```ruby
|
203
226
|
Db2Query::Base.query_value("SELECT * FROM USERS WHERE id < 10003")
|
204
227
|
=> 10000
|
205
228
|
```
|
206
229
|
|
207
230
|
##### #query_values(sql)
|
231
|
+
|
208
232
|
Execute the `SELECT Statement SQL` and returns a collection of the first value of each query result rows.
|
233
|
+
|
209
234
|
```ruby
|
210
235
|
Db2Query::Base.query_values("SELECT * FROM USERS WHERE id < 10003")
|
211
236
|
=> [10000, 10001, 10002]
|
212
237
|
```
|
213
238
|
|
214
239
|
##### #execute(sql, args)
|
240
|
+
|
215
241
|
A method to execute `DUI Statement SQL` by using `connection.do(sql, args)`
|
242
|
+
|
216
243
|
```ruby
|
217
|
-
Db2Query::Base.execute("DELETE FROM users WHERE
|
244
|
+
Db2Query::Base.execute("DELETE FROM users WHERE id = :id", 10000)
|
218
245
|
=> -1
|
219
246
|
```
|
220
247
|
|
@@ -227,6 +254,7 @@ At **Db2Query::Type::Binary**, the data `unpacked` by `serialize` method before
|
|
227
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**.
|
228
255
|
|
229
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
|
+
|
230
258
|
```ruby
|
231
259
|
# app_root/app/queries/definitions/your_query_definitions.rb
|
232
260
|
module Definitions
|
@@ -245,6 +273,7 @@ module Definitions
|
|
245
273
|
end
|
246
274
|
end
|
247
275
|
```
|
276
|
+
|
248
277
|
For Example:
|
249
278
|
|
250
279
|
```ruby
|
@@ -271,17 +300,18 @@ module Definitions
|
|
271
300
|
end
|
272
301
|
|
273
302
|
```
|
303
|
+
|
274
304
|
#### 3.2.2 Query Argument Types
|
275
305
|
|
276
|
-
Sometimes, the `query arguments` do not exist in query definitions fields. In such a case, we have to provide `query argument types` at the Query class.
|
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.
|
277
307
|
|
278
308
|
```ruby
|
279
309
|
module NameSpace
|
280
310
|
class QueryName < Db2Query::Base
|
281
|
-
|
311
|
+
query_arguments :user_by_email, { email: :string, trim: true }
|
282
312
|
|
283
313
|
def user_by_email_sql
|
284
|
-
"SELECT id, first_name, last_name FROM USERS WHERE
|
314
|
+
"SELECT id, first_name, last_name FROM USERS WHERE email = :email"
|
285
315
|
end
|
286
316
|
end
|
287
317
|
end
|
@@ -297,6 +327,7 @@ $ rails g query NameSpace::Name --defines=first_query --queries=next_query --la
|
|
297
327
|
create app/queries/definitions/name_space/name_query_definitions.rb
|
298
328
|
create test/queries/name_space/name_query_test.rb
|
299
329
|
```
|
330
|
+
|
300
331
|
This will create `app/queries/name_space/name_query.rb` file in `app/queries` directory.
|
301
332
|
|
302
333
|
```ruby
|
@@ -368,9 +399,11 @@ end
|
|
368
399
|
```
|
369
400
|
|
370
401
|
#### 3.4.1 Plain Query (--defines)
|
402
|
+
|
371
403
|
Query implementation that uses the plain method. The method name must have a `_sql` suffix and return SQL statement string.
|
372
404
|
|
373
405
|
Example:
|
406
|
+
|
374
407
|
```ruby
|
375
408
|
class MyQuery < Db2Query::Base
|
376
409
|
def all_users_sql
|
@@ -378,15 +411,17 @@ class MyQuery < Db2Query::Base
|
|
378
411
|
end
|
379
412
|
|
380
413
|
def find_user_by_id_sql
|
381
|
-
"SELECT * FROM USERS WHERE
|
414
|
+
"SELECT * FROM USERS WHERE id = :id"
|
382
415
|
end
|
383
416
|
end
|
384
417
|
```
|
385
418
|
|
386
419
|
#### 3.4.2 String Query (--queries)
|
420
|
+
|
387
421
|
Query implementation that uses the built-in `query` method. The input arguments consist of `query_name` symbol and SQL statement
|
388
422
|
|
389
423
|
Example:
|
424
|
+
|
390
425
|
```ruby
|
391
426
|
class MyQuery < Db2Query::Base
|
392
427
|
query :all_users, <<-SQL
|
@@ -394,15 +429,17 @@ class MyQuery < Db2Query::Base
|
|
394
429
|
SQL
|
395
430
|
|
396
431
|
query :find_user_by_id, <<-SQL
|
397
|
-
SELECT * FROM USERS WHERE
|
432
|
+
SELECT * FROM USERS WHERE id = :id
|
398
433
|
SQL
|
399
434
|
end
|
400
435
|
```
|
401
436
|
|
402
437
|
#### 3.4.3 Lambda Query (--lambdas)
|
438
|
+
|
403
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.
|
404
440
|
|
405
441
|
Example:
|
442
|
+
|
406
443
|
```ruby
|
407
444
|
class MyQuery < Db2Query::Base
|
408
445
|
query :all_users, -> args {
|
@@ -410,7 +447,7 @@ class MyQuery < Db2Query::Base
|
|
410
447
|
}
|
411
448
|
|
412
449
|
query :find_user_by_id, -> args {
|
413
|
-
fetch("SELECT * FROM USERS WHERE
|
450
|
+
fetch("SELECT * FROM USERS WHERE id = :id", args)
|
414
451
|
}
|
415
452
|
end
|
416
453
|
```
|
@@ -426,6 +463,7 @@ irb(main):001:0> MyQuery.find_user_by_id 10000
|
|
426
463
|
SQL (3.0ms) SELECT * FROM USERS WHERE id = ? [["id", 10000]]
|
427
464
|
=> #<Db2Query::Result [#<Record id: 10004, first_name: Yohanes, ...]>
|
428
465
|
```
|
466
|
+
|
429
467
|
If you pass a key-value argument into query, the key has to follow **Argument Key Convention**
|
430
468
|
|
431
469
|
```bash
|
@@ -436,6 +474,7 @@ irb(main):001:0> MyQuery.find_user_by_id(id: 10000)
|
|
436
474
|
```
|
437
475
|
|
438
476
|
And use it at your application
|
477
|
+
|
439
478
|
```ruby
|
440
479
|
users = MyQuery.all
|
441
480
|
user_records = users.records
|
@@ -455,6 +494,7 @@ user.email # => "yohanes@github.com"
|
|
455
494
|
```
|
456
495
|
|
457
496
|
### 3.5 SQL extension (`@extension`)
|
497
|
+
|
458
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.
|
459
499
|
|
460
500
|
```ruby
|
@@ -465,14 +505,16 @@ class MyQuery < Db2Query::Base
|
|
465
505
|
}
|
466
506
|
|
467
507
|
# implementation
|
468
|
-
query :user_by_email, _SQL.("
|
508
|
+
query :user_by_email, _SQL.("email = :email")
|
469
509
|
end
|
470
510
|
```
|
511
|
+
|
471
512
|
```bash
|
472
513
|
irb(main):001:0> MyQuery.user_by_email email: "yohanes@github.com"
|
473
514
|
SQL (2.7ms) SELECT * FROM USERS email = ? [["email", "yohanes@github.com"]]
|
474
515
|
=> #<Db2Query::Result [#<Record id: 10000, first_name: Yohanes, ...]>
|
475
516
|
```
|
517
|
+
|
476
518
|
```ruby
|
477
519
|
user = MyQuery.user_by_email "yohanes@github.com"
|
478
520
|
user.id # => 10000
|
@@ -480,7 +522,9 @@ user.first_name # => "Yohanes"
|
|
480
522
|
user.last_name # => "Lumentut"
|
481
523
|
user.email # => "yohanes@github.com"
|
482
524
|
```
|
525
|
+
|
483
526
|
### 3.6 List input (`@list`)
|
527
|
+
|
484
528
|
For an array consist list of inputs, we can use `fetch_list` method and `@list` pointer at the SQL statement.
|
485
529
|
|
486
530
|
```ruby
|
@@ -490,12 +534,14 @@ class MyQuery < Db2Query::Base
|
|
490
534
|
}
|
491
535
|
end
|
492
536
|
```
|
537
|
+
|
493
538
|
```bash
|
494
539
|
irb(main):007:0> MyQuery.user_by_ids [10000,10001,10002]
|
495
540
|
SQL (2.8ms) SELECT * FROM USERS WHERE ID IN ('10000', '10001', '10002')
|
496
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">]>
|
497
542
|
|
498
543
|
```
|
544
|
+
|
499
545
|
```ruby
|
500
546
|
users = MyQuery.user_by_ids [10000,10001,10002]
|
501
547
|
user = users.first
|
@@ -508,12 +554,15 @@ user.email # => "captain.marvel@marvel.universe.com"
|
|
508
554
|
```
|
509
555
|
|
510
556
|
### 3.7 Formatter
|
557
|
+
|
511
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).
|
512
559
|
|
513
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**.
|
514
561
|
|
515
562
|
## 4. Available Result Object methods
|
563
|
+
|
516
564
|
`Db2Query::Result` inherit all `ActiveRecord::Result` methods with additional custom methods:
|
565
|
+
|
517
566
|
1. `records` to convert query result into an array of Result query's Record objects.
|
518
567
|
2. `record` to get the first Record Object of Result query.
|
519
568
|
3. `to_h` to convert query result into an array of hashes with symbolized keys.
|
@@ -533,10 +582,11 @@ end
|
|
533
582
|
```
|
534
583
|
|
535
584
|
Utilize the goodness of rails model `scope`
|
585
|
+
|
536
586
|
```ruby
|
537
587
|
class User < Db2Record
|
538
588
|
scope :by_name, -> *args {
|
539
|
-
query("SELECT * FROM USERS WHERE
|
589
|
+
query("SELECT * FROM USERS WHERE first_name = :first_name AND last_name = :last_name", args)
|
540
590
|
}
|
541
591
|
end
|
542
592
|
```
|
@@ -548,6 +598,7 @@ SQL Load (3.28ms) SELECT * FROM USERS WHERE first_name = ? AND last_name = ? [[
|
|
548
598
|
```
|
549
599
|
|
550
600
|
Another example:
|
601
|
+
|
551
602
|
```ruby
|
552
603
|
class User < Db2Record
|
553
604
|
scope :age_gt, -> *args {
|
@@ -567,5 +618,16 @@ SQL Load (3.28ms) SELECT * FROM USERS WHERE age > 500
|
|
567
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).
|
568
619
|
Please see [**Db2Session**](https://github.com/yohaneslumentut/db2_session) for **REST** and **GraphQL** implementation of multi-user on the remote server.
|
569
620
|
|
570
|
-
## 7.
|
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
|
632
|
+
|
571
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
|
-
|
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"
|
@@ -35,11 +35,10 @@ module Db2Query
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
attr_reader :config, :connection_pool, :instrumenter, :
|
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,7 @@ module Db2Query
|
|
47
46
|
def initialize(config)
|
48
47
|
@config = config
|
49
48
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
50
|
-
@
|
49
|
+
@mutex = Mutex.new
|
51
50
|
@connection_pool = nil
|
52
51
|
create_connection_pool
|
53
52
|
end
|
@@ -59,7 +58,7 @@ module Db2Query
|
|
59
58
|
end
|
60
59
|
|
61
60
|
def create_connection_pool
|
62
|
-
synchronize do
|
61
|
+
mutex.synchronize do
|
63
62
|
return @connection_pool if @connection_pool
|
64
63
|
@connection_pool = Pool.new(pool_config) { DbClient.new(config) }
|
65
64
|
end
|
@@ -28,8 +28,12 @@ module Db2Query
|
|
28
28
|
|
29
29
|
def lookup(query_name)
|
30
30
|
queries.fetch(query_name)
|
31
|
-
rescue
|
32
|
-
|
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
|
33
37
|
end
|
34
38
|
|
35
39
|
def lookup_query(*args)
|
@@ -39,6 +43,8 @@ module Db2Query
|
|
39
43
|
query.argument_keys.each do |key|
|
40
44
|
key, key_def = query_arg_key(query, key)
|
41
45
|
query.argument_types.store(key, data_type_instance(key_def))
|
46
|
+
rescue
|
47
|
+
raise Db2Query::QueryArgumentError.new(query_name, key)
|
42
48
|
end
|
43
49
|
end
|
44
50
|
end
|
data/lib/db2_query/error.rb
CHANGED
@@ -78,4 +78,16 @@ module Db2Query
|
|
78
78
|
"The query body needs to be callable or is a SQL statement string"
|
79
79
|
end
|
80
80
|
end
|
81
|
+
|
82
|
+
class QueryArgumentError < StandardError
|
83
|
+
def initialize(query_name, arg_key)
|
84
|
+
@query_name = query_name
|
85
|
+
@arg_key = arg_key
|
86
|
+
super(message)
|
87
|
+
end
|
88
|
+
|
89
|
+
def message
|
90
|
+
"Data type of `#{@arg_key}` not found at `:#{@query_name}` query definitions"
|
91
|
+
end
|
92
|
+
end
|
81
93
|
end
|
data/lib/db2_query/logger.rb
CHANGED
data/lib/db2_query/query.rb
CHANGED
@@ -14,9 +14,12 @@ module Db2Query
|
|
14
14
|
@types = {}
|
15
15
|
end
|
16
16
|
|
17
|
-
def define_sql(
|
18
|
-
@keys
|
19
|
-
@sql
|
17
|
+
def define_sql(raw_sql)
|
18
|
+
@keys = []
|
19
|
+
@sql = raw_sql.gsub(/:\w+/) do |match|
|
20
|
+
@keys << match[1..]
|
21
|
+
'?'
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
def map_column(name, args)
|
@@ -96,9 +99,9 @@ module Db2Query
|
|
96
99
|
end
|
97
100
|
|
98
101
|
private
|
99
|
-
def sql_arguments(raw_sql)
|
100
|
-
|
101
|
-
end
|
102
|
+
# def sql_arguments(raw_sql)
|
103
|
+
# raw_sql.scan(/\$\S+/).map { |arg| arg.gsub!(/[$=,)]/, "").to_sym }
|
104
|
+
# end
|
102
105
|
|
103
106
|
def serialized_arg(arg, key)
|
104
107
|
query_name.nil? ? arg : argument_type(key).serialize(arg)
|
data/lib/db2_query/railtie.rb
CHANGED
@@ -1,15 +1,4 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Db2Query
|
4
2
|
class Railtie < ::Rails::Railtie
|
5
|
-
railtie_name :db2_query
|
6
|
-
|
7
|
-
rake_tasks do
|
8
|
-
Dir.glob("#{Db2Query.root}/db2_query/tasks/*.rake").each { |f| load f }
|
9
|
-
end
|
10
|
-
|
11
|
-
config.app_generators do
|
12
|
-
require "#{Db2Query.root}/rails/generators/query/query_generator.rb"
|
13
|
-
end
|
14
3
|
end
|
15
4
|
end
|
data/lib/db2_query/version.rb
CHANGED
data/lib/db2_query.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require "active_support"
|
4
|
-
require "active_support/concurrency/load_interlock_aware_monitor"
|
5
|
-
require "active_record"
|
6
|
-
require "active_model/type"
|
1
|
+
require "db2_query/version"
|
2
|
+
require "db2_query/railtie"
|
7
3
|
require "connection_pool"
|
8
4
|
require "odbc_utf8"
|
9
5
|
require "db2_query/error"
|
10
6
|
|
11
7
|
module Db2Query
|
8
|
+
# Your code goes here...
|
12
9
|
autoload :Version, "db2_query/version"
|
13
10
|
autoload :Error, "db2_query/error"
|
14
11
|
autoload :Config, "db2_query/config"
|
@@ -45,5 +42,3 @@ module Db2Query
|
|
45
42
|
__dir__
|
46
43
|
end
|
47
44
|
end
|
48
|
-
|
49
|
-
require "db2_query/railtie" if defined?(Rails)
|
metadata
CHANGED
@@ -1,125 +1,75 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: db2_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Yohanes Lumentut
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
19
|
+
version: '7.1'
|
24
20
|
- - ">="
|
25
21
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
|
28
|
-
name: rubocop
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
22
|
+
version: 7.1.2
|
23
|
+
type: :runtime
|
35
24
|
prerelease: false
|
36
25
|
version_requirements: !ruby/object:Gem::Requirement
|
37
26
|
requirements:
|
38
|
-
- - "
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rubocop-performance
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
27
|
+
- - "~>"
|
46
28
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
29
|
+
version: '7.1'
|
52
30
|
- - ">="
|
53
31
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
32
|
+
version: 7.1.2
|
55
33
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
34
|
+
name: tty-progressbar
|
57
35
|
requirement: !ruby/object:Gem::Requirement
|
58
36
|
requirements:
|
59
|
-
- - "
|
37
|
+
- - "~>"
|
60
38
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
39
|
+
version: '0.18'
|
62
40
|
type: :development
|
63
41
|
prerelease: false
|
64
42
|
version_requirements: !ruby/object:Gem::Requirement
|
65
43
|
requirements:
|
66
|
-
- - "
|
44
|
+
- - "~>"
|
67
45
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
46
|
+
version: '0.18'
|
69
47
|
- !ruby/object:Gem::Dependency
|
70
48
|
name: faker
|
71
49
|
requirement: !ruby/object:Gem::Requirement
|
72
50
|
requirements:
|
73
|
-
- - "
|
51
|
+
- - "~>"
|
74
52
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
53
|
+
version: '3.2'
|
76
54
|
type: :development
|
77
55
|
prerelease: false
|
78
56
|
version_requirements: !ruby/object:Gem::Requirement
|
79
57
|
requirements:
|
80
|
-
- - "
|
58
|
+
- - "~>"
|
81
59
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: byebug
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: rails
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
60
|
+
version: '3.2'
|
111
61
|
- !ruby/object:Gem::Dependency
|
112
62
|
name: connection_pool
|
113
63
|
requirement: !ruby/object:Gem::Requirement
|
114
64
|
requirements:
|
115
|
-
- -
|
65
|
+
- - "~>"
|
116
66
|
- !ruby/object:Gem::Version
|
117
67
|
version: 2.2.5
|
118
68
|
type: :runtime
|
119
69
|
prerelease: false
|
120
70
|
version_requirements: !ruby/object:Gem::Requirement
|
121
71
|
requirements:
|
122
|
-
- -
|
72
|
+
- - "~>"
|
123
73
|
- !ruby/object:Gem::Version
|
124
74
|
version: 2.2.5
|
125
75
|
- !ruby/object:Gem::Dependency
|
@@ -136,8 +86,8 @@ dependencies:
|
|
136
86
|
- - ">="
|
137
87
|
- !ruby/object:Gem::Version
|
138
88
|
version: '0'
|
139
|
-
description: A Rails
|
140
|
-
|
89
|
+
description: A Rails 7 (Ruby v3.1.0) plugin for connecting Db2 with Rails appplication
|
90
|
+
by using ODBC connection.
|
141
91
|
email:
|
142
92
|
- yohanes.lumentut@gmail.com
|
143
93
|
executables: []
|
@@ -164,11 +114,6 @@ files:
|
|
164
114
|
- lib/db2_query/result.rb
|
165
115
|
- lib/db2_query/sql_statement.rb
|
166
116
|
- lib/db2_query/tasks.rb
|
167
|
-
- lib/db2_query/tasks/database.rake
|
168
|
-
- lib/db2_query/tasks/init.rake
|
169
|
-
- lib/db2_query/tasks/initializer.rake
|
170
|
-
- lib/db2_query/tasks/templates/database.rb.tt
|
171
|
-
- lib/db2_query/tasks/templates/initializer.rb.tt
|
172
117
|
- lib/db2_query/type/binary.rb
|
173
118
|
- lib/db2_query/type/boolean.rb
|
174
119
|
- lib/db2_query/type/date.rb
|
@@ -180,11 +125,7 @@ files:
|
|
180
125
|
- lib/db2_query/type/timestamp.rb
|
181
126
|
- lib/db2_query/type/value.rb
|
182
127
|
- lib/db2_query/version.rb
|
183
|
-
- lib/
|
184
|
-
- lib/rails/generators/query/query_generator.rb
|
185
|
-
- lib/rails/generators/query/templates/query.rb.tt
|
186
|
-
- lib/rails/generators/query/templates/query_definitions.rb.tt
|
187
|
-
- lib/rails/generators/query/templates/unit_test.rb.tt
|
128
|
+
- lib/tasks/db2_query_tasks.rake
|
188
129
|
homepage: https://github.com/yohaneslumentut/db2_query
|
189
130
|
licenses:
|
190
131
|
- MIT
|
@@ -207,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
148
|
- !ruby/object:Gem::Version
|
208
149
|
version: '0'
|
209
150
|
requirements: []
|
210
|
-
rubygems_version: 3.
|
151
|
+
rubygems_version: 3.3.3
|
211
152
|
signing_key:
|
212
153
|
specification_version: 4
|
213
154
|
summary: Rails Db2 ODBC plugin
|
@@ -1,15 +0,0 @@
|
|
1
|
-
Description:
|
2
|
-
Stubs out a new query. Pass the query name, either
|
3
|
-
CamelCased or under_scored, and an optional list of its methods as arguments.
|
4
|
-
|
5
|
-
To create a query within a module, just use namespace pattern as the other rails generators do.
|
6
|
-
|
7
|
-
To create query class methods, you can use 3 options:
|
8
|
-
1. Plain SQL methods --defines
|
9
|
-
2. Query Methods with SQL string, --queries
|
10
|
-
3. Query Methods with lambda, --lambdas
|
11
|
-
|
12
|
-
Example:
|
13
|
-
$ rails g query NameSpace::Name --queries query_1 --defines query_2 --lambdas query_3
|
14
|
-
create app/queries/name_space/name_query.rb
|
15
|
-
create test/queries/name_space/name_query_test.rb
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rails/generators"
|
4
|
-
require "fileutils"
|
5
|
-
|
6
|
-
module Rails
|
7
|
-
module Generators
|
8
|
-
class QueryGenerator < Rails::Generators::NamedBase
|
9
|
-
source_root File.expand_path("../templates", __FILE__)
|
10
|
-
|
11
|
-
class_option :skip_unit_test, type: :boolean, default: false, desc: "Skip unit test file creation"
|
12
|
-
class_option :defines, type: :array, default: [], desc: "Plain query method options"
|
13
|
-
class_option :queries, type: :array, default: [], desc: "Query method SQL options"
|
14
|
-
class_option :lambdas, type: :array, default: [], desc: "Query method with callable args"
|
15
|
-
|
16
|
-
def create_query_file
|
17
|
-
template "query.rb", File.join("app/queries", class_path, "#{file_name}_query.rb")
|
18
|
-
end
|
19
|
-
|
20
|
-
def create_query_definitions_file
|
21
|
-
template "query_definitions.rb", File.join("app/queries/definitions", class_path, "#{file_name}_query_definitions.rb")
|
22
|
-
end
|
23
|
-
|
24
|
-
def create_query_test_file
|
25
|
-
unless options[:skip_unit_test]
|
26
|
-
template "unit_test.rb", File.join("test/queries", class_path, "#{file_name}_query_test.rb")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
def assign_names!(name)
|
32
|
-
super(name)
|
33
|
-
@method_options = options.slice("defines", "queries", "lambdas")
|
34
|
-
@query_methods = @method_options.map { |key, val| val }.flatten
|
35
|
-
end
|
36
|
-
|
37
|
-
def query_class_name
|
38
|
-
"#{file_name.camelize}Query"
|
39
|
-
end
|
40
|
-
|
41
|
-
def namespaced_query?
|
42
|
-
!class_path.empty?
|
43
|
-
end
|
44
|
-
|
45
|
-
def namespaced_names
|
46
|
-
class_path
|
47
|
-
end
|
48
|
-
|
49
|
-
def namespaced_content(content)
|
50
|
-
namespaced_names.reverse_each do |namespace_name|
|
51
|
-
content = "module #{namespace_name.camelize}\n#{indent(content)}\nend"
|
52
|
-
end
|
53
|
-
content
|
54
|
-
end
|
55
|
-
|
56
|
-
def module_namespacing(&block)
|
57
|
-
content = capture(&block)
|
58
|
-
content = namespaced_content(content) if namespaced_query?
|
59
|
-
concat(content)
|
60
|
-
end
|
61
|
-
|
62
|
-
def module_definitions_namespacing(&block)
|
63
|
-
content = capture(&block)
|
64
|
-
content = namespaced_content(content) if namespaced_query?
|
65
|
-
definitions_namespace_content = "module Definitions\n#{indent(content)}\nend"
|
66
|
-
concat(definitions_namespace_content)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
<% module_namespacing do -%>
|
4
|
-
class <%= query_class_name %> < <%= "Db2Query::Base" -%>
|
5
|
-
<% if @query_methods.empty? %>
|
6
|
-
<%= indent("query :to_do, <<-SQL\n") %>
|
7
|
-
<%= indent("SQL\n") %>
|
8
|
-
<%= indent("def to_do_sql\n") %>
|
9
|
-
<%= indent("end") %>
|
10
|
-
<% end -%>
|
11
|
-
<% @method_options.each do |key, val| -%>
|
12
|
-
<% val.each_with_index do |option, index| -%>
|
13
|
-
<% case key when 'defines' -%>
|
14
|
-
<%= indent("def #{option}_sql\n") %>
|
15
|
-
<%= indent("end") %>
|
16
|
-
<% when 'queries' %>
|
17
|
-
<%= indent("query :#{option}, <<-SQL\n") %>
|
18
|
-
<%= indent("SQL") %>
|
19
|
-
<% when 'lambdas' %>
|
20
|
-
<%= indent("query :#{option}, -> args {\n") %>
|
21
|
-
<%= indent("}") %>
|
22
|
-
<% end -%>
|
23
|
-
<% end -%>
|
24
|
-
<% end -%>
|
25
|
-
<%= 'end' -%>
|
26
|
-
<% end %>
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
<% module_definitions_namespacing do -%>
|
4
|
-
class <%= query_class_name %>Definitions < <%= "Db2Query::Definitions" %>
|
5
|
-
<% if @query_methods.empty? %>
|
6
|
-
<%= indent("def describe\n") -%>
|
7
|
-
<%= indent("") %>
|
8
|
-
<%= indent("end") %>
|
9
|
-
<% else %>
|
10
|
-
<%= indent("def describe") -%>
|
11
|
-
<% @query_methods.each do |method| %>
|
12
|
-
<%= indent("query_definition :#{method} do |c|\n") %>
|
13
|
-
<%= indent("end") %>
|
14
|
-
<% end -%>
|
15
|
-
<%= indent("end") %>
|
16
|
-
<% end %>
|
17
|
-
<%= 'end' -%>
|
18
|
-
<% end %>
|