db2_query 0.3.3 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- 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 +3 -9
- data/lib/db2_query/tasks.rb +2 -2
- data/lib/db2_query/version.rb +1 -3
- data/lib/db2_query.rb +4 -8
- data/lib/{db2_query/tasks → tasks}/database.rake +1 -1
- data/lib/{db2_query/tasks → tasks}/init.rake +1 -1
- data/lib/{db2_query/tasks → tasks}/initializer.rake +1 -1
- data/lib/{db2_query/tasks → tasks}/templates/database.rb.tt +1 -1
- metadata +30 -85
- 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
- /data/lib/{db2_query/tasks → tasks}/templates/initializer.rb.tt +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15218013893ba937f84cb4d9d11b1a6730b93fd5fbe8b9ff8cccf9a233a2a9cc
|
4
|
+
data.tar.gz: 308a3c04b923f18b0ec03d460dd0db50fa690a08d7a5a170a48811b1794529b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d8509a82c8ccde64f8ce4aec2b8415664be920249dcaff20a61795e84f8ee9b19220f10a4e07bf2367c9e70a1e69a1c4e3011f2cc1775861c69ee35d1176d3c
|
7
|
+
data.tar.gz: 425983ab6752bca8d3f8a0462e09b08e0a5367795b03df6a31a27b69bc8221551c2ae4680c004ad0db0f3e7a6b66201596cd959ac6494b010644ddf834670449
|
data/MIT-LICENSE
CHANGED
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
|
+
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,9 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Db2Query
|
4
2
|
class Railtie < ::Rails::Railtie
|
5
|
-
railtie_name :db2_query
|
6
|
-
|
7
3
|
rake_tasks do
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
config.app_generators do
|
12
|
-
require "#{Db2Query.root}/rails/generators/query/query_generator.rb"
|
4
|
+
load "tasks/init.rake"
|
5
|
+
load "tasks/database.rake"
|
6
|
+
load "tasks/initializer.rake"
|
13
7
|
end
|
14
8
|
end
|
15
9
|
end
|
data/lib/db2_query/tasks.rb
CHANGED
@@ -12,7 +12,7 @@ module Db2Query
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class DatabaseTask < Tasks
|
15
|
-
source_root File.expand_path("
|
15
|
+
source_root File.expand_path("../../tasks/templates", __FILE__)
|
16
16
|
|
17
17
|
def create_database_config_file
|
18
18
|
template "database.rb", File.join("config/db2query.yml")
|
@@ -20,7 +20,7 @@ module Db2Query
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class InitializerTask < Tasks
|
23
|
-
source_root File.expand_path("
|
23
|
+
source_root File.expand_path("../../tasks/templates", __FILE__)
|
24
24
|
|
25
25
|
def create_initializer_file
|
26
26
|
template "initializer.rb", File.join("config/initializers/db2query.rb")
|
data/lib/db2_query/version.rb
CHANGED
data/lib/db2_query.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
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"
|
6
|
+
require "db2_query/tasks"
|
10
7
|
|
11
8
|
module Db2Query
|
9
|
+
# Your code goes here...
|
12
10
|
autoload :Version, "db2_query/version"
|
13
11
|
autoload :Error, "db2_query/error"
|
14
12
|
autoload :Config, "db2_query/config"
|
@@ -45,5 +43,3 @@ module Db2Query
|
|
45
43
|
__dir__
|
46
44
|
end
|
47
45
|
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.7
|
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-05 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,11 @@ 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/
|
185
|
-
- lib/
|
186
|
-
- lib/
|
187
|
-
- lib/
|
128
|
+
- lib/tasks/database.rake
|
129
|
+
- lib/tasks/init.rake
|
130
|
+
- lib/tasks/initializer.rake
|
131
|
+
- lib/tasks/templates/database.rb.tt
|
132
|
+
- lib/tasks/templates/initializer.rb.tt
|
188
133
|
homepage: https://github.com/yohaneslumentut/db2_query
|
189
134
|
licenses:
|
190
135
|
- MIT
|
@@ -207,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
152
|
- !ruby/object:Gem::Version
|
208
153
|
version: '0'
|
209
154
|
requirements: []
|
210
|
-
rubygems_version: 3.
|
155
|
+
rubygems_version: 3.3.3
|
211
156
|
signing_key:
|
212
157
|
specification_version: 4
|
213
158
|
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 %>
|
File without changes
|