db2_query 0.2.2 → 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/MIT-LICENSE +1 -1
- data/README.md +453 -110
- data/Rakefile +3 -2
- data/lib/db2_query.rb +41 -15
- data/lib/db2_query/base.rb +16 -5
- data/lib/db2_query/config.rb +20 -17
- data/lib/db2_query/core.rb +68 -55
- 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 +81 -0
- data/lib/db2_query/field_type.rb +31 -0
- data/lib/db2_query/helper.rb +49 -0
- data/lib/db2_query/logger.rb +52 -0
- data/lib/db2_query/query.rb +117 -0
- data/lib/db2_query/quoting.rb +102 -0
- data/lib/db2_query/railtie.rb +5 -7
- data/lib/db2_query/result.rb +51 -31
- 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 -50
- data/lib/db2_query/tasks/init.rake +1 -1
- data/lib/db2_query/tasks/initializer.rake +2 -34
- 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 +2 -2
- 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 +62 -49
- data/lib/db2_query/connection.rb +0 -163
- data/lib/db2_query/connection_handling.rb +0 -112
- data/lib/db2_query/database_statements.rb +0 -93
- data/lib/db2_query/formatter.rb +0 -27
- data/lib/db2_query/odbc_connector.rb +0 -40
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/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
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
|
|
5
|
-
A Rails
|
5
|
+
A Rails 5 & Rails 6 plugin for handling Db2 SQL database `SIUD` statement (`SELECT`, `INSERT`, `UPDATE`, `DELETE`) by using ODBC connection.
|
6
6
|
|
7
|
-
|
7
|
+
Note: Tested at Rails 5.2.6 and Rails 6.1.4
|
8
|
+
|
9
|
+
## 1. Installation
|
8
10
|
Add this line to your application's Gemfile:
|
9
11
|
|
10
12
|
```ruby
|
@@ -20,144 +22,482 @@ Or install it yourself as:
|
|
20
22
|
```bash
|
21
23
|
$ gem install db2_query
|
22
24
|
```
|
23
|
-
|
24
|
-
|
25
|
-
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.
|
26
27
|
```bash
|
27
28
|
$ rake db2query:init
|
29
|
+
create config/db2query.yml
|
30
|
+
create config/initializers/db2query.rb
|
28
31
|
```
|
29
|
-
DB2Query will generate two required files:
|
30
|
-
- `config/db2query_database.yml`
|
31
|
-
- `config/initializers/db2query.rb`
|
32
32
|
|
33
|
-
|
33
|
+
Complete the configurations by editing the files according to your application requirement.
|
34
34
|
|
35
|
-
|
35
|
+
### Database Configuration
|
36
|
+
File **config/db2query.yml** consist of DSN/database name and connection pool config:
|
37
|
+
```yml
|
38
|
+
development:
|
39
|
+
dsn: ARUNIT
|
40
|
+
idle: 5
|
41
|
+
pool: 5
|
42
|
+
timeout: 5
|
43
|
+
test:
|
44
|
+
dsn: ARUNIT
|
45
|
+
idle: 5
|
46
|
+
pool: 5
|
47
|
+
timeout: 5
|
48
|
+
production:
|
49
|
+
dsn: ARUNIT
|
50
|
+
idle: 5
|
51
|
+
pool: 5
|
52
|
+
timeout: 5
|
53
|
+
```
|
36
54
|
|
37
|
-
|
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.
|
38
56
|
|
39
|
-
|
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.
|
40
58
|
|
41
|
-
###
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
```yml
|
46
|
-
development:
|
47
|
-
primary: # Connection String Example
|
48
|
-
adapter: db2_query
|
49
|
-
conn_string:
|
50
|
-
driver: DB2
|
51
|
-
database: SAMPLE
|
52
|
-
dbalias: SAMPLE
|
53
|
-
hostname: LOCALHOST
|
54
|
-
currentschema: LIBTEST
|
55
|
-
port: "0"
|
56
|
-
protocol: IPC
|
57
|
-
uid: <%= ENV["DB2EC_UID"] %>
|
58
|
-
pwd: <%= ENV["DB2EC_PWD"] %>
|
59
|
-
secondary:
|
60
|
-
adapter: db2_query # DSN Example
|
61
|
-
dsn: iseries
|
62
|
-
uid: <%= ENV["ISERIES_UID"] %>
|
63
|
-
pwd: <%= ENV["ISERIES_PWD"] %>
|
64
|
-
```
|
65
|
-
|
66
|
-
Ensure that `unixodbc` have been installed and test your connection first by using `isql` commands.
|
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
|
67
63
|
|
68
|
-
|
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
|
+
}
|
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
|
120
|
+
|
121
|
+
```
|
122
|
+
|
123
|
+
## 3. Usage
|
124
|
+
|
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**.
|
126
|
+
|
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.**"**
|
135
|
+
|
136
|
+
|
137
|
+
```ruby
|
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
|
160
|
+
end
|
161
|
+
|
162
|
+
# Argument Key Convention Example
|
163
|
+
|
164
|
+
MyQuery.find_user_by_id id: 10000
|
165
|
+
|
166
|
+
```
|
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"}]
|
178
|
+
```
|
179
|
+
|
180
|
+
##### #query_rows(sql)
|
181
|
+
Execute the `SELECT Statement SQL` and returns collections of arrays consisting of row values.
|
182
|
+
```ruby
|
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
|
231
|
+
end
|
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:
|
69
264
|
|
70
|
-
Secondary database connection test
|
71
265
|
```bash
|
72
|
-
$
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
270
|
+
```
|
271
|
+
This will create `app/queries/name_space/name_query.rb` file in `app/queries` directory.
|
272
|
+
|
273
|
+
```ruby
|
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
|
288
|
+
end
|
289
|
+
```
|
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
|
313
|
+
```
|
314
|
+
|
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
|
+
|
321
|
+
```ruby
|
322
|
+
class MyQuery < Db2Query::Base
|
323
|
+
# 1. Plain Query (--defines)
|
324
|
+
def query_name_sql
|
325
|
+
"YOUR AMAZING SQL STATEMENT STRING"
|
326
|
+
end
|
327
|
+
|
328
|
+
# 2. String Query (--queries)
|
329
|
+
query :query_name, <<-SQL
|
330
|
+
YOUR AMAZING SQL STATEMENT
|
93
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
|
+
}
|
94
338
|
end
|
95
339
|
```
|
96
|
-
|
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:
|
97
345
|
```ruby
|
98
|
-
class
|
99
|
-
def
|
100
|
-
"SELECT * FROM
|
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 = ?"
|
101
353
|
end
|
102
354
|
end
|
103
355
|
```
|
104
|
-
|
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:
|
361
|
+
```ruby
|
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 = ?
|
369
|
+
end
|
370
|
+
end
|
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
|
+
|
105
391
|
```bash
|
106
|
-
|
107
|
-
SQL
|
108
|
-
=> #<
|
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, ...]>
|
109
399
|
```
|
110
|
-
|
400
|
+
If you pass a key-value argument into query, the key has to follow **Argument Key Convention**
|
401
|
+
|
111
402
|
```bash
|
112
|
-
|
113
|
-
SQL
|
114
|
-
=> #<
|
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
|
+
|
115
407
|
```
|
116
408
|
|
117
|
-
|
118
|
-
In order to get different result column format, a query result can be reformatted by add a formatter class that inherit `DB2Query::AbstractFormatter` then register at `config\initializers\db2query.rb`
|
409
|
+
And use it at your application
|
119
410
|
```ruby
|
120
|
-
|
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"
|
121
418
|
|
122
|
-
|
123
|
-
class FirstNameFormatter < DB2Query::AbstractFormatter
|
124
|
-
def format(value)
|
125
|
-
"Dr." + value
|
126
|
-
end
|
127
|
-
end
|
419
|
+
user_1 == users.record # => true
|
128
420
|
|
129
|
-
|
130
|
-
|
131
|
-
|
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.
|
430
|
+
```ruby
|
431
|
+
class MyQuery < Db2Query::Base
|
432
|
+
# reusable SQL
|
433
|
+
_SQL = -> extention {
|
434
|
+
sql_with_extention("SELECT * FROM USERS WHERE @extention", extention)
|
435
|
+
}
|
436
|
+
|
437
|
+
# implementation
|
438
|
+
query :user_by_email, _SQL.("$email = ?")
|
132
439
|
end
|
133
440
|
```
|
134
|
-
|
441
|
+
```bash
|
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, ...]>
|
445
|
+
```
|
135
446
|
```ruby
|
136
|
-
|
137
|
-
|
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`)
|
454
|
+
For an array consist list of inputs, we can use `fetch_list` method and `@list` pointer at the SQL statement.
|
455
|
+
|
456
|
+
```ruby
|
457
|
+
class MyQuery < Db2Query::Base
|
458
|
+
query :user_by_ids, -> args {
|
459
|
+
fetch_list("SELECT * FROM USERS WHERE ID IN (@list)", args)
|
460
|
+
}
|
138
461
|
end
|
139
462
|
```
|
140
|
-
Check it at rails console
|
141
463
|
```bash
|
142
|
-
|
143
|
-
SQL
|
144
|
-
=> #<
|
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')
|
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">]>
|
467
|
+
|
145
468
|
```
|
469
|
+
```ruby
|
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"
|
478
|
+
```
|
479
|
+
|
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).
|
146
482
|
|
147
|
-
|
148
|
-
`DB2Query::Result` inherit all `ActiveRecord::Result` methods with additional custom methods:
|
149
|
-
1. `records` to convert query result into array of Record objects.
|
150
|
-
2. `to_h` to convert query result into hash with symbolized keys.
|
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**.
|
151
484
|
|
152
|
-
|
485
|
+
## 4. Available Result Object methods
|
486
|
+
`Db2Query::Result` inherit all `ActiveRecord::Result` methods with additional custom methods:
|
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.
|
490
|
+
|
491
|
+
## 5. ActiveRecord Combination
|
492
|
+
|
493
|
+
Create an abstract class that inherits from `ActiveRecord::Base`. We have to implement `splat` operator correctly at the arguments to make it works.
|
153
494
|
|
154
|
-
Create an abstract class that inherit from `ActiveRecord::Base`
|
155
495
|
```ruby
|
156
496
|
class Db2Record < ActiveRecord::Base
|
157
497
|
self.abstract_class = true
|
158
498
|
|
159
|
-
def self.query(sql,
|
160
|
-
|
499
|
+
def self.query(sql, args)
|
500
|
+
Db2Query::Base.query(sql, *args)
|
161
501
|
end
|
162
502
|
end
|
163
503
|
```
|
@@ -166,32 +506,35 @@ Utilize the goodness of rails model `scope`
|
|
166
506
|
```ruby
|
167
507
|
class User < Db2Record
|
168
508
|
scope :by_name, -> *args {
|
169
|
-
query(
|
170
|
-
"SELECT * FROM LIBTEST.USERS WHERE first_name = ? AND last_name = ?", {}, args
|
171
|
-
)
|
509
|
+
query("SELECT * FROM USERS WHERE $first_name = ? AND $last_name = ?", args)
|
172
510
|
}
|
173
511
|
end
|
174
512
|
```
|
513
|
+
|
175
514
|
```bash
|
176
515
|
User.by_name first_name: "Strange", last_name: "Stephen"
|
177
|
-
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]]
|
178
517
|
=> [{:id=> 10000, :first_name=> "Strange", :last_name=> "Stephen", :email=> "strange@marvel.universe.com"}]
|
179
518
|
```
|
180
519
|
|
181
520
|
Another example:
|
182
521
|
```ruby
|
183
522
|
class User < Db2Record
|
184
|
-
scope :age_gt, ->
|
185
|
-
query("SELECT * FROM
|
523
|
+
scope :age_gt, -> *args {
|
524
|
+
query("SELECT * FROM USERS WHERE age > ?", args)
|
186
525
|
}
|
187
526
|
end
|
188
527
|
```
|
189
528
|
|
190
529
|
```bash
|
191
530
|
User.age_gt 500
|
192
|
-
SQL Load (3.28ms) SELECT * FROM
|
531
|
+
SQL Load (3.28ms) SELECT * FROM USERS WHERE age > 500
|
193
532
|
=> [{:id=> 99999, :first_name=> "Ancient", :last_name=> "One", :email=> "ancientone@marvel.universe.com"}]
|
194
533
|
```
|
195
534
|
|
196
|
-
##
|
197
|
-
|
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).
|