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.
- checksums.yaml +4 -4
- data/README.md +399 -147
- data/lib/db2_query.rb +36 -9
- data/lib/db2_query/base.rb +13 -0
- data/lib/db2_query/config.rb +14 -14
- data/lib/db2_query/core.rb +59 -118
- data/lib/db2_query/db_client.rb +56 -0
- data/lib/db2_query/db_connection.rb +67 -0
- data/lib/db2_query/db_statements.rb +87 -0
- data/lib/db2_query/definitions.rb +79 -0
- data/lib/db2_query/error.rb +71 -6
- data/lib/db2_query/field_type.rb +31 -0
- data/lib/db2_query/helper.rb +49 -0
- data/lib/db2_query/logger.rb +14 -4
- data/lib/db2_query/query.rb +117 -0
- data/lib/db2_query/quoting.rb +102 -0
- data/lib/db2_query/railtie.rb +5 -2
- data/lib/db2_query/result.rb +45 -33
- data/lib/db2_query/sql_statement.rb +34 -0
- data/lib/db2_query/tasks.rb +29 -0
- data/lib/db2_query/tasks/database.rake +2 -33
- data/lib/db2_query/tasks/init.rake +1 -1
- data/lib/db2_query/tasks/initializer.rake +2 -33
- data/lib/db2_query/tasks/templates/database.rb.tt +19 -0
- data/lib/db2_query/tasks/templates/initializer.rb.tt +8 -0
- data/lib/db2_query/type/binary.rb +19 -0
- data/lib/db2_query/type/boolean.rb +41 -0
- data/lib/db2_query/type/date.rb +34 -0
- data/lib/db2_query/type/decimal.rb +15 -0
- data/lib/db2_query/type/integer.rb +15 -0
- data/lib/db2_query/type/string.rb +30 -0
- data/lib/db2_query/type/text.rb +11 -0
- data/lib/db2_query/type/time.rb +30 -0
- data/lib/db2_query/type/timestamp.rb +30 -0
- data/lib/db2_query/type/value.rb +29 -0
- data/lib/db2_query/version.rb +1 -1
- data/lib/rails/generators/query/USAGE +15 -0
- data/lib/rails/generators/query/query_generator.rb +70 -0
- data/lib/rails/generators/query/templates/query.rb.tt +26 -0
- data/lib/rails/generators/query/templates/query_definitions.rb.tt +12 -0
- data/lib/rails/generators/query/templates/unit_test.rb.tt +9 -0
- metadata +49 -10
- data/lib/db2_query/connection.rb +0 -125
- data/lib/db2_query/formatter.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a863b9451d52ea28e71b1477cfd7275bb76b34c91a1302208f4052674dc7b901
|
4
|
+
data.tar.gz: 555eafaa282e3cab7a0d4231592a6d2a6d3087d0c194f98040dff1724f5da0f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 917d8a2a7a1eefbb85185d021642f42115e7fd51969b302752f1284e274799fca9d7b24c3f6a7fdc764fa9a79cfd6cac7245e4500b0005d5e498f1e718e63a5b
|
7
|
+
data.tar.gz: 353f50ef752eaaee361c939c21f6552e4fa5c8b5bc81a0face640aae420d889fcb1fb148bd0d7b74e8fec3b1867ffa31df9996cacb05465302e512ec0a5d2147
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
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
|
-
|
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
|
-
|
33
|
+
Complete the configurations by editing the files according to your application requirement.
|
36
34
|
|
37
35
|
### Database Configuration
|
38
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
-
|
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
|
-
|
81
|
-
Create query class that inherit from `DB2Query::Base` in `app/queries` folder.
|
123
|
+
## 3. Usage
|
82
124
|
|
83
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
-
|
179
|
+
|
180
|
+
##### #query_rows(sql)
|
181
|
+
Execute the `SELECT Statement SQL` and returns collections of arrays consisting of row values.
|
106
182
|
```ruby
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
271
|
+
This will create `app/queries/name_space/name_query.rb` file in `app/queries` directory.
|
272
|
+
|
119
273
|
```ruby
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
135
|
-
|
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
|
138
|
-
|
139
|
-
|
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
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
-
|
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
|
152
|
-
|
153
|
-
|
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>
|
159
|
-
SQL
|
160
|
-
=> #<
|
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
|
-
|
163
|
-
|
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
|
431
|
+
class MyQuery < Db2Query::Base
|
166
432
|
# reusable SQL
|
167
433
|
_SQL = -> extention {
|
168
|
-
sql_with_extention("SELECT * FROM
|
434
|
+
sql_with_extention("SELECT * FROM USERS WHERE @extention", extention)
|
169
435
|
}
|
170
436
|
|
171
437
|
# implementation
|
172
|
-
query :
|
438
|
+
query :user_by_email, _SQL.("$email = ?")
|
173
439
|
end
|
174
440
|
```
|
175
441
|
```bash
|
176
|
-
irb(main):
|
177
|
-
SQL (
|
178
|
-
=> #<
|
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
|
-
|
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
|
185
|
-
query :
|
186
|
-
fetch_list("SELECT * FROM
|
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>
|
192
|
-
SQL (2.8ms) SELECT * FROM
|
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
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
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
|
-
|
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
|
-
|
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. `
|
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
|
-
|
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
|
-
|
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(
|
251
|
-
Db2Query::Base.
|
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
|
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, ->
|
276
|
-
query("SELECT * FROM
|
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
|
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
|
-
##
|
288
|
-
|
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).
|