db2_query 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +399 -147
  3. data/lib/db2_query.rb +36 -9
  4. data/lib/db2_query/base.rb +13 -0
  5. data/lib/db2_query/config.rb +14 -14
  6. data/lib/db2_query/core.rb +59 -118
  7. data/lib/db2_query/db_client.rb +56 -0
  8. data/lib/db2_query/db_connection.rb +67 -0
  9. data/lib/db2_query/db_statements.rb +87 -0
  10. data/lib/db2_query/definitions.rb +79 -0
  11. data/lib/db2_query/error.rb +71 -6
  12. data/lib/db2_query/field_type.rb +31 -0
  13. data/lib/db2_query/helper.rb +49 -0
  14. data/lib/db2_query/logger.rb +14 -4
  15. data/lib/db2_query/query.rb +117 -0
  16. data/lib/db2_query/quoting.rb +102 -0
  17. data/lib/db2_query/railtie.rb +5 -2
  18. data/lib/db2_query/result.rb +45 -33
  19. data/lib/db2_query/sql_statement.rb +34 -0
  20. data/lib/db2_query/tasks.rb +29 -0
  21. data/lib/db2_query/tasks/database.rake +2 -33
  22. data/lib/db2_query/tasks/init.rake +1 -1
  23. data/lib/db2_query/tasks/initializer.rake +2 -33
  24. data/lib/db2_query/tasks/templates/database.rb.tt +19 -0
  25. data/lib/db2_query/tasks/templates/initializer.rb.tt +8 -0
  26. data/lib/db2_query/type/binary.rb +19 -0
  27. data/lib/db2_query/type/boolean.rb +41 -0
  28. data/lib/db2_query/type/date.rb +34 -0
  29. data/lib/db2_query/type/decimal.rb +15 -0
  30. data/lib/db2_query/type/integer.rb +15 -0
  31. data/lib/db2_query/type/string.rb +30 -0
  32. data/lib/db2_query/type/text.rb +11 -0
  33. data/lib/db2_query/type/time.rb +30 -0
  34. data/lib/db2_query/type/timestamp.rb +30 -0
  35. data/lib/db2_query/type/value.rb +29 -0
  36. data/lib/db2_query/version.rb +1 -1
  37. data/lib/rails/generators/query/USAGE +15 -0
  38. data/lib/rails/generators/query/query_generator.rb +70 -0
  39. data/lib/rails/generators/query/templates/query.rb.tt +26 -0
  40. data/lib/rails/generators/query/templates/query_definitions.rb.tt +12 -0
  41. data/lib/rails/generators/query/templates/unit_test.rb.tt +9 -0
  42. metadata +49 -10
  43. data/lib/db2_query/connection.rb +0 -125
  44. data/lib/db2_query/formatter.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a62d60225cd34e421f6d6fd8becf1d45bb6e0ffb35db266bac881734a4b15340
4
- data.tar.gz: 8b02f4869439de1dcdb14cfca0f731ee99ce143f504b6a56c7e04db74684da65
3
+ metadata.gz: a863b9451d52ea28e71b1477cfd7275bb76b34c91a1302208f4052674dc7b901
4
+ data.tar.gz: 555eafaa282e3cab7a0d4231592a6d2a6d3087d0c194f98040dff1724f5da0f2
5
5
  SHA512:
6
- metadata.gz: a684c13ff35469b6f53c13b0bcd2c21c997b9b51abce517bc66ca920a4cc764ae885a1746b1e256d50945cc038d240739c8de72045b899af6e63421b8a520c24
7
- data.tar.gz: a2698708b312200a55f93334c5f27b5345f9b0515a6ca8aee82926562388178588766bb708959178f26488774a3994a5e88f2181691e8604f9d7ac6f62a2dcfb
6
+ metadata.gz: 917d8a2a7a1eefbb85185d021642f42115e7fd51969b302752f1284e274799fca9d7b24c3f6a7fdc764fa9a79cfd6cac7245e4500b0005d5e498f1e718e63a5b
7
+ data.tar.gz: 353f50ef752eaaee361c939c21f6552e4fa5c8b5bc81a0face640aae420d889fcb1fb148bd0d7b74e8fec3b1867ffa31df9996cacb05465302e512ec0a5d2147
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # DB2Query
1
+ # Db2Query
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/db2_query.svg)](https://badge.fury.io/rb/db2_query)
4
4
 
@@ -6,7 +6,7 @@ A Rails 5 & Rails 6 plugin for handling Db2 SQL database `SIUD` statement (`SELE
6
6
 
7
7
  Note: Tested at Rails 5.2.6 and Rails 6.1.4
8
8
 
9
- ## Installation
9
+ ## 1. Installation
10
10
  Add this line to your application's Gemfile:
11
11
 
12
12
  ```ruby
@@ -22,20 +22,18 @@ Or install it yourself as:
22
22
  ```bash
23
23
  $ gem install db2_query
24
24
  ```
25
-
26
- ## Initialization
27
- Execute init task at the app root
25
+ ## 2. Initialization
26
+ Execute **db2query:init** task at the app root to create database configurations and initializer file.
28
27
  ```bash
29
28
  $ rake db2query:init
29
+ create config/db2query.yml
30
+ create config/initializers/db2query.rb
30
31
  ```
31
- Db2Query will generate two required files:
32
- - `config/db2query.yml`
33
- - `config/initializers/db2query.rb`
34
32
 
35
- Edit those files according to the requirement.
33
+ Complete the configurations by editing the files according to your application requirement.
36
34
 
37
35
  ### Database Configuration
38
- At version 0.3.0, `db2query.yml` only use DSN connection config:
36
+ File **config/db2query.yml** consist of DSN/database name and connection pool config:
39
37
  ```yml
40
38
  development:
41
39
  dsn: ARUNIT
@@ -54,201 +52,452 @@ At version 0.3.0, `db2query.yml` only use DSN connection config:
54
52
  timeout: 5
55
53
  ```
56
54
 
57
- Note: `idle` is a `db_client` idle maximum limit value (in minutes) to avoid the client disconnected by the host server. Setting this value to zero will lead to an "ODBC driver Communication Link Failure. Comm rc 10054 . [CWBCO1047](https://www.ibm.com/support/pages/cwbco1047-any-function-uses-database-host-server)" error after a certain period of time.
55
+ Key **idle** is a **client** idle maximum limit value (in minutes) to avoid the client being disconnected by the host server. Setting this value to zero will lead to an "ODBC driver Communication Link Failure. Comm rc 10054 . [CWBCO1047](https://www.ibm.com/support/pages/cwbco1047-any-function-uses-database-host-server)" error after your application idle in a certain period of time.
58
56
 
59
- Ensure that `unixodbc` have been installed and test your connection first by using `isql` commands.
57
+ [**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.
60
58
 
61
- Example:
59
+ ### Initializer File
60
+ This file is used by **Db2Query::Base** to load **field types** configurations and establish a **connection** instance.
61
+ ```ruby
62
+ # app_root/config/initializers/db2query.rb
62
63
 
63
- ARUNIT DSN connection test
64
- ```bash
65
- $ isql -v ARUNIT
66
- +---------------------------------------+
67
- | Connected! |
68
- | |
69
- | sql-statement |
70
- | help [tablename] |
71
- | quit |
72
- | |
73
- +---------------------------------------+
74
- SQL>
64
+ require "db2_query"
65
+
66
+ Db2Query::Base.initiation do |base|
67
+ base.set_field_types # or base.set_field_types(CUSTOM_FIELD_TYPES) if you have CUSTOM TYPES
68
+ base.establish_connection
69
+ end
70
+ ```
71
+
72
+ ### 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) :
74
+
75
+ ```ruby
76
+ DEFAULT_FIELD_TYPES = {
77
+ binary: Db2Query::Type::Binary,
78
+ boolean: Db2Query::Type::Boolean,
79
+ string: Db2Query::Type::String,
80
+ varchar: Db2Query::Type::String,
81
+ longvarchar: Db2Query::Type::String,
82
+ decimal: Db2Query::Type::Decimal,
83
+ integer: Db2Query::Type::Integer,
84
+ date: Db2Query::Type::Date,
85
+ time: Db2Query::Type::Time,
86
+ timestamp: Db2Query::Type::Timestamp
87
+ }
75
88
  ```
89
+ You can use your own Field type class by extending **Db2Query::Type::Value** class. For example:
90
+ ```ruby
91
+ class CustomTypeClass < Db2Query::Type::Value
92
+ # Method to convert data from ruby type value into data that is understood by Db2
93
+ def serialize(value)
94
+ # Your logic
95
+ end
96
+
97
+ # Method to convert Db2 database output data type that is recognized by your rails app
98
+ def deserialize(value)
99
+ # Your logic
100
+ end
101
+ end
102
+ ```
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.
104
+ ```ruby
105
+ # app_root/config/initializers/db2query.rb
106
+
107
+ require "db2_query"
108
+
109
+ CUSTOM_FIELD_TYPES = {
110
+ binary: CustomBinaryTypeClass
111
+ integer: CustomIntegerTypeClass
112
+ string: CustomStringTypeClass
113
+ ...
114
+ }
115
+
116
+ Db2Query::Base.initiation do |base|
117
+ base.set_field_types(CUSTOM_FIELD_TYPES)
118
+ base.establish_connection
119
+ end
76
120
 
77
- ## Usage
78
- Note: Version 0.1.0 use `Db2Query` namespace. Version 0.2 use `DB2Query`. At version 0.3.0 we use `Db2Query` , revert back to the previous namespace.
121
+ ```
79
122
 
80
- ### Basic Usage
81
- Create query class that inherit from `DB2Query::Base` in `app/queries` folder.
123
+ ## 3. Usage
82
124
 
83
- Note: `$`symbol is used as column name prefix.
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**.
84
126
 
85
- ### 1. `query` method
86
- The `query` method must have 2 inputs:
87
- 1. Method name
88
- 2. Body (can be an SQL statement or lamda).
127
+ **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.**"**
89
135
 
90
- The lambda is used to facilitate us in using `built-in methods` as shown at examples below:
91
136
 
92
- Example 1.
93
137
  ```ruby
94
- class User < Db2Query::Base
95
- query :find_by, <<-SQL
96
- SELECT * FROM LIBTEST.USERS WHERE $id = ?
97
- SQL
138
+ # SQL Convention Examples
139
+ # Example of Parameterized Query SQL usage
140
+
141
+ Db2Query::Base.query("SELECT * FROM USERS WHERE $email = ?", "my_account@email.com")
142
+
143
+ # Example of Normal SQL usage
144
+
145
+ Db2Query::Base.query("SELECT * FROM USERS WHERE email = 'my_account@email.com'")
146
+
147
+ # Field Type Convention Example
148
+
149
+ module Definitions
150
+ class UsersQueryDefinitions < Db2Query::Definitions
151
+ def describe
152
+ query_definition :all do |c|
153
+ c.id :integer
154
+ c.first_name :varchar
155
+ c.last_name :varchar
156
+ c.email :varchar
157
+ end
158
+ end
159
+ end
98
160
  end
161
+
162
+ # Argument Key Convention Example
163
+
164
+ MyQuery.find_user_by_id id: 10000
165
+
99
166
  ```
100
- ```bash
101
- irb(main):004:0> User.find_by 10000
102
- SQL (3.2ms) SELECT * FROM LIBTEST.USERS WHERE id = ? [["id", 10000]]
103
- => #<DB2Query::Result @records=[#<Record id: 10000, first_name: "Strange", last_name: "Stephen", email: "strange@marvel.universe.com">]>
167
+
168
+
169
+ ### 3.1 Basic Usage
170
+
171
+ #### Base Class Query Methods
172
+
173
+ ##### #query(sql, args)
174
+ A raw query to perform a `connection.run(sql, args)` operation and returns an array of hashes representing each row record being executed.
175
+ ```ruby
176
+ Db2Query::Base.query("SELECT * FROM USERS WHERE $id < ?", 10003)
177
+ => [{: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"}]
104
178
  ```
105
- Example 2.
179
+
180
+ ##### #query_rows(sql)
181
+ Execute the `SELECT Statement SQL` and returns collections of arrays consisting of row values.
106
182
  ```ruby
107
- class User < Db2query::Base
108
- query :id_greater_than, -> id {
109
- exec_query({}, "SELECT * FROM LIBTEST.USERS WHERE $id > ?", [id])
110
- }
183
+ Db2Query::Base.query_rows("SELECT * FROM USERS WHERE id < 10003")
184
+ => [[10000, "Taisha", "Kutch", "willie.lesch@toy.org"], [10001, "Setsuko", "Kutch", "thelma@purdy.co"], [10002, "Trina", "Mayer", "dorsey_upton@flatley-gulgowski.name"]]
185
+ ```
186
+
187
+ ##### #query_value(sql)
188
+ Execute the `SELECT Statement SQL` and returns the first value of the query results first row.
189
+ ```ruby
190
+ Db2Query::Base.query_value("SELECT * FROM USERS WHERE id < 10003")
191
+ => 10000
192
+ ```
193
+
194
+ ##### #query_values(sql)
195
+ Execute the `SELECT Statement SQL` and returns a collection of the first value of each query result rows.
196
+ ```ruby
197
+ Db2Query::Base.query_values("SELECT * FROM USERS WHERE id < 10003")
198
+ => [10000, 10001, 10002]
199
+ ```
200
+
201
+ ##### #execute(sql, args)
202
+ A method to execute `DUI Statement SQL` by using `connection.do(sql, args)`
203
+ ```ruby
204
+ Db2Query::Base.execute("DELETE FROM users WHERE $id = ?", 10000)
205
+ => -1
206
+ ```
207
+
208
+ ### 3.2 QueryDefinitions
209
+
210
+ 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
+ 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
+ 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
+
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:
215
+ ```ruby
216
+ # app_root/app/queries/definitions/your_query_definitions.rb
217
+ module Definitions
218
+ class YourQueryDefinitions < Db2Query::Definitions
219
+ def describe # method that is used by Db2Query to describe your query definition
220
+ query_definition :your_first_query_name do |c|
221
+ c.field_name :field_type, options
222
+ ...
223
+ end
224
+
225
+ query_definition :your_next_query_name do |c|
226
+ c.field_name :field_type, options
227
+ ...
228
+ end
229
+ end
230
+ end
111
231
  end
112
232
  ```
233
+ For Example:
234
+
235
+ ```ruby
236
+ # app_root/app/queries/definitions/users_query_definitions.rb
237
+
238
+ module Definitions
239
+ class UsersQueryDefinitions < Db2Query::Definitions
240
+ def describe
241
+ query_definition :all do |c|
242
+ c.id :integer
243
+ c.first_name :varchar
244
+ c.last_name :varchar
245
+ c.email :varchar
246
+ end
247
+
248
+ query_definition :insert do |c|
249
+ c.id :integer
250
+ c.first_name :varchar
251
+ c.last_name :varchar
252
+ c.email :varchar
253
+ end
254
+ end
255
+ end
256
+ end
257
+
258
+ ```
259
+
260
+
261
+ ### 3.3 Generator
262
+
263
+ Create query class by using `rails g query NAME` commands. For example:
264
+
113
265
  ```bash
114
- irb(main):003:0> User.id_greater_than 10000
115
- SQL (3.2ms) SELECT * FROM LIBTEST.USERS WHERE id > ? [["id", 1000]]
116
- => #<Db2Query::Result [#<Record id: 10000, first_name: "Strange", last_name: "Stephen", email: "strange@marvel.universe.com">...">]>
266
+ $ rails g query NameSpace::Name --defines=first_query --queries=next_query --lambdas=last_query
267
+ create app/queries/name_space/name_query.rb
268
+ create app/queries/definitions/movies_query_definitions.rb
269
+ create test/queries/name_space/name_query_test.rb
117
270
  ```
118
- Example 3.
271
+ This will create `app/queries/name_space/name_query.rb` file in `app/queries` directory.
272
+
119
273
  ```ruby
120
- class User < Db2query::Base
121
- query :insert_record, -> args {
122
- exec_query({},
123
- "INSERT INTO users ($id, $first_name, $last_name, $email) VALUES (?, ?, ?, ?)", args
124
- )
125
- }
274
+ module NameSpace
275
+ class Name < Db2Query::Base
276
+ def first_query_sql
277
+
278
+ end
279
+
280
+ query :next_query, <<-SQL
281
+
282
+ SQL
283
+
284
+ query :last_query, -> {
285
+
286
+ }
287
+ end
126
288
  end
127
289
  ```
128
- ```bash
129
- irb(main):002:0> User.insert_record [77777, "Ancient", "One", "ancientone@marvel.universe.com"]
130
- SQL (3651.2ms) SELECT * FROM NEW TABLE (INSERT INTO users (id, first_name, last_name, email) VALUES (?, ?, ?, ?)) [["id,", 77777], ["first_name,", "Ancient"], ["last_name,", "One"], ["email)", "ancientone@marvel.universe.com"]]
131
- => #<Db2Query::Result [#<Record id: 77777, first_name: "Ancient", last_name: "One", email: "ancientone@marvel.universe.com">]>
290
+
291
+ ```ruby
292
+ # app_root/app/queries/definitions/name_space/name_query.rb
293
+
294
+ module Definitions
295
+ module NameSpace
296
+ class NameQueryDefinition < Db2Query::Definitions
297
+ def describe # method that is used by Db2Query to describe your query definition
298
+ query_definition :first_query do |c|
299
+
300
+ end
301
+
302
+ query_definition :next_query do |c|
303
+
304
+ end
305
+
306
+ query_definition :last_query do |c|
307
+
308
+ end
309
+ end
310
+ end
311
+ end
312
+ end
132
313
  ```
133
314
 
134
- ### 2. Plain/normal method
135
- At a plain/normal sql method we add `_sql` suffix. For example `find_by_sql`
315
+ Please run `rails g query --help` to get more information on how to use the file generator.
316
+
317
+ ### 3.4 Queries Methods
318
+
319
+ In a **Query** class that extends **Db2Query::Base** class, there are 3 ways of query implementation:
320
+
136
321
  ```ruby
137
- class User < Db2Query::Base
138
- def find_by_sql
139
- "SELECT * FROM LIBTEST.USERS WHERE $id = ?"
322
+ class MyQuery < Db2Query::Base
323
+ # 1. Plain Query (--defines)
324
+ def query_name_sql
325
+ "YOUR AMAZING SQL STATEMENT STRING"
140
326
  end
327
+
328
+ # 2. String Query (--queries)
329
+ query :query_name, <<-SQL
330
+ YOUR AMAZING SQL STATEMENT
331
+ SQL
332
+
333
+ # 3. Lambda Query (--lambdas)
334
+ query :query_name, -> args {
335
+ # implement fetch, fetch_list, and exec_query
336
+ fetch("YOUR AMAZING SQL", args)
337
+ }
141
338
  end
142
339
  ```
143
- Then we can call it by using `find_by` class method.
144
- ```bash
145
- irb(main):001:0> User.find_by 10000
146
- SQL Load (3.28ms) SELECT * FROM LIBTEST.USERS WHERE id = ? [["id", 10000]]
147
- => #<DB2Query::Result @records=[#<Record id: 10000, first_name: "Strange", last_name: "Stephen", email: "strange@marvel.universe.com">]>
340
+
341
+ #### 3.4.1 Plain Query (--defines)
342
+ Query implementation that uses the plain method. The method name must have a `_sql` suffix and return SQL statement string.
343
+
344
+ Example:
345
+ ```ruby
346
+ class MyQuery < Db2Query::Base
347
+ def all_users_sql
348
+ "SELECT * FROM USERS"
349
+ end
350
+
351
+ def find_user_by_id_sql
352
+ "SELECT * FROM USERS WHERE $id = ?"
353
+ end
354
+ end
148
355
  ```
149
- Or with hash arguments input
356
+
357
+ #### 3.4.2 String Query (--queries)
358
+ Query implementation that uses the built-in `query` method. The input arguments consist of `query_name` symbol and SQL statement
359
+
360
+ Example:
150
361
  ```ruby
151
- class User < Db2Query::Base
152
- def by_name_and_email_sql
153
- "SELECT * FROM LIBTEST.USERS WHERE $first_name = ? AND $email = ?"
362
+ class MyQuery < Db2Query::Base
363
+ query :all_users, <<-SQL
364
+ SELECT * FROM USERS
365
+ SQL
366
+
367
+ query :find_user_by_id, <<-SQL
368
+ SELECT * FROM USERS WHERE $id = ?
154
369
  end
155
370
  end
156
371
  ```
372
+
373
+ #### 3.4.3 Lambda Query (--lambdas)
374
+ 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
+
376
+ Example:
377
+ ```ruby
378
+ class MyQuery < Db2Query::Base
379
+ query :all_users, -> args {
380
+ fetch("SELECT * FROM USERS", args)
381
+ }
382
+
383
+ query :find_user_by_id, -> args {
384
+ fetch("SELECT * FROM USERS WHERE $id = ?", args)
385
+ }
386
+ end
387
+ ```
388
+
389
+ Then you can call all three example with the same methods:
390
+
157
391
  ```bash
158
- irb(main):001:0> User.by_name_and_email first_name: "Strange", email: "strange@marvel.universe.com"
159
- SQL Load (3.28ms) SELECT * FROM LIBTEST.USERS WHERE first_name = ? AND last_name = ? [["first_name", Strange], ["email", strange@marvel.universe.com]]
160
- => #<DB2Query::Result @records=[#<Record id: 10000, first_name: "Strange", last_name: "Stephen", email: "strange@marvel.universe.com">]>
392
+ irb(main):001:0> MyQuery.all_users
393
+ SQL (2.7ms) SELECT * FROM USERS
394
+ => #<Db2Query::Result [#<Record id: 10000, first_name: Yohanes, ...]>
395
+
396
+ irb(main):001:0> MyQuery.find_user_by_id 10000
397
+ SQL (3.0ms) SELECT * FROM USERS WHERE id = ? [["id", 10000]]
398
+ => #<Db2Query::Result [#<Record id: 10004, first_name: Yohanes, ...]>
161
399
  ```
162
- ### SQL extention (`@extention`)
163
- 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.
400
+ If you pass a key-value argument into query, the key has to follow **Argument Key Convention**
401
+
402
+ ```bash
403
+ irb(main):001:0> MyQuery.find_user_by_id(id: 10000)
404
+ SQL (3.0ms) SELECT * FROM USERS WHERE id = ? [["id", 10000]]
405
+ => #<Db2Query::Result [#<Record id: 10004, first_name: Yohanes, ...]>
406
+
407
+ ```
408
+
409
+ And use it at your application
410
+ ```ruby
411
+ users = MyQuery.all
412
+ user_records = users.records
413
+ user_1 = user_records.first
414
+ user_1.id # => 10000
415
+ user_1.first_name # => "Yohanes"
416
+ user_1.last_name # => "Lumentut"
417
+ user_1.email # => "yohanes@github.com"
418
+
419
+ user_1 == users.record # => true
420
+
421
+ user = MyQuery.find_user_by_id id: 10000
422
+ user.id # => 10000
423
+ user.first_name # => "Yohanes"
424
+ user.last_name # => "Lumentut"
425
+ user.email # => "yohanes@github.com"
426
+ ```
427
+
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.
164
430
  ```ruby
165
- class User < Db2Query::Base
431
+ class MyQuery < Db2Query::Base
166
432
  # reusable SQL
167
433
  _SQL = -> extention {
168
- sql_with_extention("SELECT * FROM LIBTEST.USERS WHERE @extention", extention)
434
+ sql_with_extention("SELECT * FROM USERS WHERE @extention", extention)
169
435
  }
170
436
 
171
437
  # implementation
172
- query :by_email, _SQL.("$email = ?")
438
+ query :user_by_email, _SQL.("$email = ?")
173
439
  end
174
440
  ```
175
441
  ```bash
176
- irb(main):004:0> User.by_email "strange@marvel.universe.com"
177
- SQL (3.2ms) SELECT * FROM LIBTEST.USERS WHERE email = ? [["email", "strange@marvel.universe.com"]]
178
- => #<DB2Query::Result @records=[#<Record id: 10000, first_name: "Strange", last_name: "Stephen", email: "strange@marvel.universe.com">]>
442
+ irb(main):001:0> MyQuery.user_by_email
443
+ SQL (2.7ms) SELECT * FROM USERS email = ? [["email", "yohanes@github.com"]]
444
+ => #<Db2Query::Result [#<Record id: 10000, first_name: Yohanes, ...]>
179
445
  ```
180
- ### List input (`@list`)
446
+ ```ruby
447
+ user = MyQuery.user_by_email "yohanes@github.com"
448
+ user.id # => 10000
449
+ user.first_name # => "Yohanes"
450
+ user.last_name # => "Lumentut"
451
+ user.email # => "yohanes@github.com"
452
+ ```
453
+ ### 3.6 List input (`@list`)
181
454
  For an array consist list of inputs, we can use `fetch_list` method and `@list` pointer at the SQL statement.
182
455
 
183
456
  ```ruby
184
- class User < Db2Query
185
- query :by_ids, -> ids {
186
- fetch_list("SELECT * FROM LIBTEST.USERS WHERE ID IN (@list)", ids)
457
+ class MyQuery < Db2Query::Base
458
+ query :user_by_ids, -> args {
459
+ fetch_list("SELECT * FROM USERS WHERE ID IN (@list)", args)
187
460
  }
188
461
  end
189
462
  ```
190
463
  ```bash
191
- irb(main):007:0> User.by_ids [10000,10001,10002]
192
- SQL (2.8ms) SELECT * FROM LIBTEST.USERS WHERE ID IN ('10000', '10001', '10002')
464
+ irb(main):007:0> MyQuery.user_by_ids [10000,10001,10002]
465
+ SQL (2.8ms) SELECT * FROM USERS WHERE ID IN ('10000', '10001', '10002')
193
466
  => #<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">]>
194
467
 
195
468
  ```
196
-
197
- ### Formatter
198
- In order to get different result column format, a query result can be reformatted by adding a formatter class that inherits `DB2Query::AbstractFormatter` then register at `config\initializers\db2query.rb`
199
469
  ```ruby
200
- require "db2_query/formatter"
201
-
202
- # create a formatter class
203
- class FirstNameFormatter < Db2Query::AbstractFormatter
204
- def format(value)
205
- "Dr." + value
206
- end
207
- end
208
-
209
- # register the formatter class
210
- Db2Query::Formatter.registration do |format|
211
- format.register(:first_name_formatter, FirstNameFormatter)
212
- end
213
- ```
214
- Use it at query class
215
- ```ruby
216
- class Doctor < User
217
- attributes :first_name, :first_name_formatter
218
- end
219
- ```
220
- Check it at rails console
221
- ```bash
222
- Doctor.find_by id: 10000
223
- SQL Load (3.28ms) SELECT * FROM LIBTEST.USERS WHERE id = ? [["id", 10000]]
224
- => #<DB2Query::Result @records=[#<Record id: 10000, first_name: "Dr.Strange", last_name: "Stephen", email: "strange@marvel.universe.com">]>
470
+ users = MyQuery.user_by_ids [10000,10001,10002]
471
+ user = users.first
472
+ user == users.record # => true
473
+
474
+ user.id # => 10000
475
+ user.first_name # => "Carol"
476
+ user.last_name # => "Danvers"
477
+ user.email # => "captain.marvel@marvel.universe.com"
225
478
  ```
226
479
 
227
- For complete examples please see the basic examples [here](https://github.com/yohaneslumentut/db2_query/blob/master/test/dummy/app/queries/test_query.rb).
480
+ ### 3.7 Formatter
481
+ 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).
228
482
 
229
- ### Available Result Object methods
483
+ 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
+
485
+ ## 4. Available Result Object methods
230
486
  `Db2Query::Result` inherit all `ActiveRecord::Result` methods with additional custom methods:
231
- 1. `records` to convert query result into array of Record objects.
232
- 2. `to_h` to convert query result into hash with symbolized keys.
487
+ 1. `records` to convert query result into an array of Result query's Record objects.
488
+ 2. `record` to get the first Record Object of Result query.
489
+ 3. `to_h` to convert query result into an array of hashes with symbolized keys.
233
490
 
234
- ### Built-in methods
235
- These built-in methods are delegated to `Db2Query::Connection` methods
236
- 1. `query_rows(sql)`
237
- 2. `query_value(sql)`
238
- 3. `query_values(sql)`
239
- 4. `execute(sql)`
240
- 5. `exec_query(formatters, sql, args = [])`
241
- They behave just likely `ActiveRecords` connection's public methods.
491
+ ## 5. ActiveRecord Combination
242
492
 
243
- ### ActiveRecord Combination
493
+ Create an abstract class that inherits from `ActiveRecord::Base`. We have to implement `splat` operator correctly at the arguments to make it works.
244
494
 
245
- Create an abstract class that inherit from `ActiveRecord::Base`
246
495
  ```ruby
247
496
  class Db2Record < ActiveRecord::Base
248
497
  self.abstract_class = true
249
498
 
250
- def self.query(formatter, sql, args = [])
251
- Db2Query::Base.connection.exec_query(formatter, sql, args).to_a.map(&:deep_symbolize_keys)
499
+ def self.query(sql, args)
500
+ Db2Query::Base.query(sql, *args)
252
501
  end
253
502
  end
254
503
  ```
@@ -257,32 +506,35 @@ Utilize the goodness of rails model `scope`
257
506
  ```ruby
258
507
  class User < Db2Record
259
508
  scope :by_name, -> *args {
260
- query(
261
- {}, "SELECT * FROM LIBTEST.USERS WHERE $first_name = ? AND $last_name = ?", args
262
- )
509
+ query("SELECT * FROM USERS WHERE $first_name = ? AND $last_name = ?", args)
263
510
  }
264
511
  end
265
512
  ```
513
+
266
514
  ```bash
267
515
  User.by_name first_name: "Strange", last_name: "Stephen"
268
- SQL Load (3.28ms) SELECT * FROM LIBTEST.USERS WHERE first_name = ? AND last_name = ? [["first_name", Strange], ["last_name", Stephen]]
516
+ SQL Load (3.28ms) SELECT * FROM USERS WHERE first_name = ? AND last_name = ? [["first_name", Strange], ["last_name", Stephen]]
269
517
  => [{:id=> 10000, :first_name=> "Strange", :last_name=> "Stephen", :email=> "strange@marvel.universe.com"}]
270
518
  ```
271
519
 
272
520
  Another example:
273
521
  ```ruby
274
522
  class User < Db2Record
275
- scope :age_gt, -> age {
276
- query("SELECT * FROM LIBTEST.USERS WHERE age > #{age}")
523
+ scope :age_gt, -> *args {
524
+ query("SELECT * FROM USERS WHERE age > ?", args)
277
525
  }
278
526
  end
279
527
  ```
280
528
 
281
529
  ```bash
282
530
  User.age_gt 500
283
- SQL Load (3.28ms) SELECT * FROM LIBTEST.USERS WHERE age > 500
531
+ SQL Load (3.28ms) SELECT * FROM USERS WHERE age > 500
284
532
  => [{:id=> 99999, :first_name=> "Ancient", :last_name=> "One", :email=> "ancientone@marvel.universe.com"}]
285
533
  ```
286
534
 
287
- ## License
288
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
535
+ ## 6. Examples
536
+
537
+ For complete examples please see the basic examples [here](https://github.com/yohaneslumentut/db2_query/blob/master/test/dummy/app/queries/user_query.rb).
538
+
539
+ ## 7. License
540
+ The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).