sql-maker 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 32ac24cfad827c72f15a9d677d0c7ea6a68317a2
4
- data.tar.gz: 51e81c781768b04148522f9408777dd532b4c62b
3
+ metadata.gz: 32d150cb48d1dafd939ac1562fc6e7a31195172d
4
+ data.tar.gz: 749f497d5f5a1f5d38a1f1855e575725b862bf9a
5
5
  SHA512:
6
- metadata.gz: 029d20d44324f0e04c82a68556301dfb31b18e09c3f2e633e9e00f3ab450dddccd8b04fb715af57e489d5bdb2aa81b5dc32980484037170cc2b6d9dfc381965b
7
- data.tar.gz: 30e4544a8d797d4b36dd0bde3bd6d342ce9b1d7ca9e63c510930b5d97d5aef298a5f92752d49ac877879f82eacbf86ae1fe0bc5c840f05ca04401e6139961b85
6
+ metadata.gz: a474871843140b6871e998e583bfe4222a89dc43db85f4a121379438eaf80bb648a36749166f91da4fffa69e8eff9d103f278a39860bf78960eb06e7916c2405
7
+ data.tar.gz: 994cf90b1c734b301f7fb4c09bdedfe55a8c00bb5ec38530874be625c3f939d7f94c33cea071dae1b6062868d6e4dbcf21decd932978f86c10b8456e1ea517a3
data/.gitignore CHANGED
@@ -7,7 +7,7 @@ Gemfile.lock
7
7
  InstalledFiles
8
8
  _yardoc
9
9
  coverage
10
- doc/
10
+ #doc/
11
11
  lib/bundler/man
12
12
  pkg
13
13
  rdoc
@@ -0,0 +1,6 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1
5
+ gemfile:
6
+ - Gemfile
@@ -1,3 +1,9 @@
1
+ ## 0.0.3 (2014/06/21)
2
+
3
+ Fixes:
4
+
5
+ * require BigDecimal for quoting
6
+
1
7
  ## 0.0.2 (2014/06/18)
2
8
 
3
9
  Enhancements:
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in sql-maker.gemspec
4
4
  gemspec
5
+ gem 'coveralls', :require => false
data/README.md CHANGED
@@ -5,10 +5,51 @@
5
5
 
6
6
  SQL Builder for Ruby
7
7
 
8
+ ## Installation
9
+
10
+ Add the following to your `Gemfile`:
11
+
12
+ ```ruby
13
+ gem 'sql-maker'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ ```plain
19
+ $ bundle
20
+ ```
21
+
22
+ ## Example
23
+
24
+ ```ruby
25
+ require 'sql-maker'
26
+ builder = SQL::Maker::Select.new(:quote_char => '"', :auto_bind => true)
27
+ builder.add_select('id').add_from('books').add_where('books.id' => 1).as_sql
28
+ #=> SELECT "id" FROM "books" WHERE "books"."id" = 1
29
+ ```
30
+
31
+ To avoid quoting the column name, use `sql_raw`.
32
+
33
+ ```ruby
34
+ require 'sql-maker'
35
+ include SQL::Maker::Helper # adds sql_raw, etc
36
+ builder = SQL::Maker::Select.new(:quote_char => '"', :auto_bind => true)
37
+ builder.add_select(sql_raw('COUNT(*)')).add_from('books').as_sql
38
+ # => SELECT COUNT(*) FROM "books"
39
+ ```
40
+
41
+ ## Further Reading
42
+
43
+ Please see the [doc](./doc) directory.
44
+
8
45
  ## ChangeLog
9
46
 
10
47
  See [CHANGELOG.md](CHANGELOG.md) for details.
11
48
 
49
+ ## ToDo
50
+
51
+ 1. Support plugins
52
+
12
53
  ## Contributing
13
54
 
14
55
  1. Fork it
@@ -21,3 +62,11 @@ See [CHANGELOG.md](CHANGELOG.md) for details.
21
62
 
22
63
  Copyright (c) 2014 Naotoshi Seo. See [LICENSE.txt](LICENSE.txt) for details.
23
64
 
65
+ ## Acknowledgement
66
+
67
+ Ruby SQL::Maker is a ruby port of following perl modules:
68
+
69
+ 1. https://github.com/tokuhirom/SQL-Maker
70
+ 2. https://github.com/kazuho/SQL-QueryMaker
71
+
72
+ Thank you very much!!!
@@ -0,0 +1,8 @@
1
+ # SQL::Maker - Index
2
+
3
+ * [sql/maker.md](./sql/maker.md)
4
+ * [sql/maker/select.md](./sql/maker/select.md)
5
+ * [sql/maker/condition.md](./sql/maker/condition.md)
6
+ * [sql/maker/helper.md](./sql/maker/helper.md)
7
+ * [sql/maker/select_set.md](./sql/maker/select_set.md)
8
+ * [sql/queyr_maker.md](./sql/maker.md)
@@ -0,0 +1,314 @@
1
+ # NAME
2
+
3
+ SQL::Maker - Yet another SQL builder
4
+
5
+ # SYNOPSIS
6
+
7
+ use SQL::Maker
8
+
9
+ builder = SQL::Maker.new(
10
+ :driver => 'SQLite', # or your favorite driver
11
+ )
12
+
13
+ # SELECT
14
+ sql, bind = builder.select(table, fields, where, opt)
15
+
16
+ # INSERT
17
+ sql, bind = builder.insert(table, values, opt)
18
+
19
+ # DELETE
20
+ sql, bind = builder.delete(table, where, opt)
21
+
22
+ # UPDATE
23
+ sql, bind = builder.update(table, set, where)
24
+ sql, bind = builder.update(table, set, where)
25
+
26
+ # DESCRIPTION
27
+
28
+ SQL::Maker is yet another SQL builder class.
29
+
30
+ # METHODS
31
+
32
+
33
+
34
+ ## builder = SQL::Maker.new(args)
35
+
36
+ Create new instance of SQL::Maker.
37
+
38
+ Attributes are the following:
39
+
40
+
41
+
42
+ ### driver: Str
43
+
44
+ Driver name is required. The driver type is needed to create SQL string.
45
+
46
+ ### quote_char: Str
47
+
48
+ This is the character that a table or column name will be quoted with.
49
+
50
+ Default: auto detect from driver.
51
+
52
+ ### name_sep: Str
53
+
54
+ This is the character that separates a table and column name.
55
+
56
+ Default: '.'
57
+
58
+ ### new_line: Str
59
+
60
+ This is the character that separates a part of statements.
61
+
62
+ Default: '\n'
63
+
64
+ ### strict: Bool
65
+
66
+ In strict mode, all the expressions must be declared by using instances of SQL::QueryMaker
67
+
68
+ Default: false
69
+
70
+
71
+
72
+ ## sql, bind = builder.select(table|tables, fields, where, opt)
73
+
74
+ sql, bind = builder.select('user', ['*'], {:name => 'john'}, {:order_by => 'user_id DESC'})
75
+ # =>
76
+ # SELECT * FROM `user` WHERE (`name` = ?) ORDER BY user_id DESC
77
+ # ['john']
78
+
79
+ This method returns the SQL string and bind variables for a SELECT statement.
80
+
81
+
82
+
83
+ ### table
84
+
85
+ Table name for the FROM clause as scalar or arrayref. You can specify the instance of SQL::Maker::Select for a sub-query.
86
+
87
+ If you are using opt[:joins] >> this should be I<< undef since it's passed via the first join.
88
+
89
+ ### fields
90
+
91
+ This is a list for retrieving fields from database.
92
+
93
+ Each element of the fields is normally an array of column names.
94
+ If you want to specify an alias of the field, you can use an array of hashes containing a pair
95
+ of column and alias names (e.g. ['foo.id' => 'foo_id']).
96
+
97
+ ### where
98
+
99
+ where clause from hash or array via SQL::Maker::Condition, or SQL::Maker::Condition object.
100
+
101
+ ### opt
102
+
103
+ These are the options for the SELECT statement
104
+
105
+
106
+
107
+ ### opt[:prefix]
108
+
109
+ This is a prefix for the SELECT statement.
110
+
111
+ For example, you can provide the 'SELECT SQL_CALC_FOUND_ROWS '. It's useful for MySQL.
112
+
113
+ Default Value: 'SELECT '
114
+
115
+ ### opt[:limit]
116
+
117
+ This option adds a 'LIMIT n' clause.
118
+
119
+ ### opt[:offset]
120
+
121
+ This option adds an 'OFFSET n' clause.
122
+
123
+ ### opt[:order_by]
124
+
125
+ This option adds an ORDER BY clause
126
+
127
+ You can write it in any of the following forms:
128
+
129
+ builder.select(..., {:order_by => 'foo DESC, bar ASC'})
130
+ builder.select(..., {:order_by => ['foo DESC', 'bar ASC']})
131
+ builder.select(..., {:order_by => {:foo => 'DESC'}})
132
+ builder.select(..., {:order_by => [{:foo => 'DESC'}, {:bar => 'ASC'}]})
133
+
134
+ ### opt[:group_by]
135
+
136
+ This option adds a GROUP BY clause
137
+
138
+ You can write it in any of the following forms:
139
+
140
+ builder.select(..., {:group_by => 'foo DESC, bar ASC'})
141
+ builder.select(..., {:group_by => ['foo DESC', 'bar ASC']})
142
+ builder.select(..., {:group_by => {:foo => 'DESC'}})
143
+ builder.select(..., {:group_by => [{:foo => 'DESC'}, {:bar => 'ASC'}]})
144
+
145
+ ### opt[:having]
146
+
147
+ This option adds a HAVING clause
148
+
149
+ ### opt[:for_update]
150
+
151
+ This option adds a 'FOR UPDATE" clause.
152
+
153
+ ### opt[:joins]
154
+
155
+ This option adds a 'JOIN' via SQL::Maker::Select.
156
+
157
+ You can write it as follows:
158
+
159
+ builder.select(nil, ..., {:joins => [[:user => {:table => 'group', :condition => 'user.gid = group.gid'}], ...]})
160
+
161
+ ### opt[:index_hint]
162
+
163
+ This option adds an INDEX HINT like as 'USE INDEX' clause for MySQL via SQL::Maker::Select.
164
+
165
+ You can write it as follows:
166
+
167
+ builder.select(..., { :index_hint => 'foo' })
168
+ builder.select(..., { :index_hint => ['foo', 'bar'] })
169
+ builder.select(..., { :index_hint => { :list => 'foo' })
170
+ builder.select(..., { :index_hint => { :type => 'FORCE', :list => ['foo', 'bar'] })
171
+
172
+
173
+
174
+
175
+
176
+ ## sql, bind = builder.insert(table, values, opt);
177
+
178
+ sql, bind = builder.insert(:user, {:name => 'john'})
179
+ # =>
180
+ # INSERT INTO `user` (`name`) VALUES (?)
181
+ # ['john']
182
+
183
+ Generate an INSERT query.
184
+
185
+
186
+
187
+ ### table
188
+
189
+ Table name
190
+
191
+ ### values
192
+
193
+ These are the values for the INSERT statement.
194
+
195
+ ### opt
196
+
197
+ These are the options for the INSERT statement
198
+
199
+
200
+
201
+ ### opt[:prefix]
202
+
203
+ This is a prefix for the INSERT statement.
204
+
205
+ For example, you can provide 'INSERT IGNORE INTO' for MySQL.
206
+
207
+ Default Value: 'INSERT INTO'
208
+
209
+
210
+
211
+
212
+
213
+ ## sql, bind = builder.delete(table, where, opt)
214
+
215
+ sql, bind = builder.delete(table, where)
216
+ # =>
217
+ # DELETE FROM `user` WHERE (`name` = ?)
218
+ # ['john']
219
+
220
+ Generate a DELETE query.
221
+
222
+
223
+
224
+ ### table
225
+
226
+ Table name
227
+
228
+ ### where
229
+
230
+ where clause from hash or array, or SQL::Maker::Condition object.
231
+
232
+ ### opt
233
+
234
+ These are the options for the DELETE statement
235
+
236
+
237
+
238
+ ### opt[:using]
239
+
240
+ This option adds a USING clause. It takes a scalar or an arrayref of table names as argument:
241
+
242
+ (sql, bind) = bulder.delete(table, where, { :using => 'group' })
243
+ # =>
244
+ # DELETE FROM `user` USING `group` WHERE (`group`.`name` = ?)
245
+ # ['doe']
246
+ bulder.delete(..., { :using => ['bar', 'qux'] })
247
+
248
+
249
+
250
+
251
+
252
+ ## sql, bind = builder.update(table, set, where)
253
+
254
+ Generate a UPDATE query.
255
+
256
+ sql, bind = builder.update('user', ['name' => 'john', :email => 'john@example.com'], {:user_id => 3})
257
+ # =>
258
+ # 'UPDATE `user` SET `name` = ?, `email` = ? WHERE (`user_id` = ?)'
259
+ # ['john','john@example.com',3]
260
+
261
+
262
+
263
+ ### table
264
+
265
+ Table name
266
+
267
+ ### set
268
+
269
+ Setting values.
270
+
271
+ ### where
272
+
273
+ where clause from a hash or array, or SQL::Maker::Condition object.
274
+
275
+
276
+
277
+ ## select = builder.new_select(args)
278
+
279
+ Create new instance of SQL::Maker::Select using the settings from builder.
280
+
281
+ This method returns an instance of SQL::Maker::Select.
282
+
283
+ ## builder.new_condition()
284
+
285
+ Create new SQL::Maker::Condition object from builder settings.
286
+
287
+ ## sql, bind = builder.where(where)
288
+
289
+ Where clause from a hash or array, or SQL::Maker::Condition object.
290
+
291
+
292
+
293
+ # PLUGINS
294
+
295
+ SQL::Maker features a plugin system. Write the code as follows:
296
+
297
+ require 'sql/maker'
298
+ SQL::Maker.load_plugin('insert_multi')
299
+
300
+ # FAQ
301
+
302
+
303
+
304
+ ### Why don't you use Arel or ActiveRecord?
305
+
306
+ I wanted a query builder rather than ORM.
307
+
308
+ I wanted simpler one than Arel.
309
+
310
+
311
+
312
+ # SEE ALSO
313
+
314
+ Perl version is located at https://github.com/tokuhirom/SQL-Maker
@@ -0,0 +1,186 @@
1
+ # NAME
2
+
3
+ SQL::Maker::Condition - condition object for SQL::Maker
4
+
5
+ # SYNOPSIS
6
+
7
+ my condition = SQL::Maker::Condition.new(
8
+ name_sep => '.',
9
+ quote_char => '`',
10
+ )
11
+ condition.add('foo_id' => 3)
12
+ condition.add('bar_id' => 4)
13
+ sql = condition.as_sql # (`foo_id`=?) AND (`bar_id`=?)
14
+ bind = condition.bind # (3, 4)
15
+
16
+ # add_raw
17
+ my condition = SQL::Maker::Condition.new(
18
+ name_sep => '.',
19
+ quote_char => '`',
20
+ )
21
+ condition.add_raw('EXISTS(SELECT * FROM bar WHERE name = ?)' => ['john'])
22
+ condition.add_raw('type IS NOT NULL')
23
+ sql = condition.as_sql # (EXISTS(SELECT * FROM bar WHERE name = ?)) AND (type IS NOT NULL)
24
+ bind = condition.bind # ('john')
25
+
26
+ # composite and
27
+ my other = SQL::Maker::Condition.new(
28
+ name_sep => '.',
29
+ quote_char => '`',
30
+ )
31
+ other.add('name' => 'john')
32
+ comp_and = condition & other
33
+ sql = comp_and.as_sql # ((`foo_id`=?) AND (`bar_id`=?)) AND (`name`=?)
34
+ bind = comp_and.bind # (3, 4, 'john')
35
+
36
+ # composite or
37
+ comp_or = condition | other
38
+ sql = comp_and.as_sql # ((`foo_id`=?) AND (`bar_id`=?)) OR (`name`=?)
39
+ bind = comp_and.bind # (3, 4, 'john')
40
+
41
+
42
+ # CONDITION CHEAT SHEET
43
+
44
+ Here is a cheat sheet for conditions.
45
+
46
+ IN: {'foo'=>'bar'}
47
+ OUT QUERY: '`foo` = ?'
48
+ OUT BIND: ['bar']
49
+
50
+ IN: {'foo'=>['bar','baz']}
51
+ OUT QUERY: '`foo` IN (?, ?)'
52
+ OUT BIND: ['bar','baz']
53
+
54
+ IN: {'foo'=>{'IN' => ['bar','baz']}}
55
+ OUT QUERY: '`foo` IN (?, ?)'
56
+ OUT BIND: ['bar','baz']
57
+
58
+ IN: {'foo'=>{'not IN' => ['bar','baz']}}
59
+ OUT QUERY: '`foo` NOT IN (?, ?)'
60
+ OUT BIND: ['bar','baz']
61
+
62
+ IN: {'foo'=>{'!=' => 'bar'}}
63
+ OUT QUERY: '`foo` != ?'
64
+ OUT BIND: ['bar']
65
+
66
+ IN: {'foo'=>{'between' => ['1','2']}}
67
+ OUT QUERY: '`foo` BETWEEN ? AND ?'
68
+ OUT BIND: ['1','2']
69
+
70
+ IN: {'foo'=>{'like' => 'xaic%'}}
71
+ OUT QUERY: '`foo` LIKE ?'
72
+ OUT BIND: ['xaic%']
73
+
74
+ IN: {'foo'=>[{'>' => 'bar'},{'<' => 'baz'}]}
75
+ OUT QUERY: '(`foo` > ?) OR (`foo` < ?)'
76
+ OUT BIND: ['bar','baz']
77
+
78
+ IN: {'foo'=>{:AND => [{'>' => 'bar'},{'<' => 'baz'}]}}
79
+ OUT QUERY: '(`foo` > ?) AND (`foo` < ?)'
80
+ OUT BIND: ['bar','baz']
81
+
82
+ IN: {'foo'=>{:AND => ['foo','bar','baz']}}
83
+ OUT QUERY: '(`foo` = ?) AND (`foo` = ?) AND (`foo` = ?)'
84
+ OUT BIND: ['foo','bar','baz']
85
+
86
+ IN: {'foo_id'=>{'IN' => sql_raw('SELECT foo_id FROM bar WHERE t=?',44)}}
87
+ OUT QUERY: '`foo_id` IN (SELECT foo_id FROM bar WHERE t=?)'
88
+ OUT BIND: [44]
89
+
90
+ IN: {'foo_id'=>nil}
91
+ OUT QUERY: '`foo_id` IS NULL'
92
+ OUT BIND: []
93
+
94
+ IN: {'foo_id'=>{'IN' => []}}
95
+ OUT QUERY: '0=1'
96
+ OUT BIND: []
97
+
98
+ IN: {'foo_id'=>{'NOT IN' => []}}
99
+ OUT QUERY: '1=1'
100
+ OUT BIND: []
101
+
102
+ # IN: ['foo_id',\['MATCH (col1, col2) AGAINST (?)','apples']]
103
+ # OUT QUERY: '`foo_id` MATCH (col1, col2) AGAINST (?)'
104
+ # OUT BIND: ['apples']
105
+
106
+ # IN: ['foo_id', [123,sql_type(\3, SQL_INTEGER)]]
107
+ # OUT QUERY: '`foo_id` IN (?, ?)'
108
+ # OUT BIND: (123, sql_type(\3, SQL_INTEGER))
109
+
110
+ # IN: ['foo_id', sql_type(\3, SQL_INTEGER)]
111
+ # OUT QUERY: '`foo_id` = ?'
112
+ # OUT BIND: sql_type(\3, SQL_INTEGER)
113
+
114
+ # IN: ['created_on', { '>', \'DATE_SUB(NOW(), INTERVAL 1 DAY)' }]
115
+ # OUT QUERY: '`created_on` > DATE_SUB(NOW(), INTERVAL 1 DAY)'
116
+ # OUT BIND:
117
+
118
+ It is also possible to use the functions exported by SQL::Maker::Helper to define the conditions.
119
+
120
+ IN: {'foo' => sql_in(['bar','baz'])}
121
+ OUT QUERY: '`foo` IN (?,?)'
122
+ OUT BIND: ['bar','baz']
123
+
124
+ IN: {'foo' => sql_lt(3)}
125
+ OUT QUERY: '`foo` < ?'
126
+ OUT BIND: [3]
127
+
128
+ IN: {'foo' => sql_not_in(['bar','baz'])}
129
+ OUT QUERY: '`foo` NOT IN (?,?)'
130
+ OUT BIND: ['bar','baz']
131
+
132
+ IN: {'foo' => sql_ne('bar')}
133
+ OUT QUERY: '`foo` != ?'
134
+ OUT BIND: ['bar']
135
+
136
+ IN: {'foo' => sql_is_not_null}
137
+ OUT QUERY: '`foo` IS NOT NULL'
138
+ OUT BIND: []
139
+
140
+ IN: {'foo' => sql_between('1','2')}
141
+ OUT QUERY: '`foo` BETWEEN ? AND ?'
142
+ OUT BIND: ['1','2']
143
+
144
+ IN: {'foo' => sql_like('xaic%')}
145
+ OUT QUERY: '`foo` LIKE ?'
146
+ OUT BIND: ['xaic%']
147
+
148
+ IN: {'foo' => sql_or([sql_gt('bar'), sql_lt('baz')])}
149
+ OUT QUERY: '(`foo` > ?) OR (`foo` < ?)'
150
+ OUT BIND: ['bar','baz']
151
+
152
+ IN: {'foo' => sql_and([sql_gt('bar'), sql_lt('baz')])}
153
+ OUT QUERY: '(`foo` > ?) AND (`foo` < ?)'
154
+ OUT BIND: ['bar','baz']
155
+
156
+ IN: {'foo_id' => sql_op('IN (SELECT foo_id FROM bar WHERE t=?)',[44])}
157
+ OUT QUERY: '`foo_id` IN (SELECT foo_id FROM bar WHERE t=?)'
158
+ OUT BIND: [44]
159
+
160
+ IN: {'foo_id' => sql_in([sql_raw('SELECT foo_id FROM bar WHERE t=?',44)])}
161
+ OUT QUERY: '`foo_id` IN ((SELECT foo_id FROM bar WHERE t=?))'
162
+ OUT BIND: [44]
163
+
164
+ IN: {'foo_id' => sql_op('MATCH (@) AGAINST (?)',['apples'])}
165
+ OUT QUERY: 'MATCH (`foo_id`) AGAINST (?)'
166
+ OUT BIND: ['apples']
167
+
168
+ IN: {'foo_id'=>sql_in([])}
169
+ OUT QUERY: '0=1'
170
+ OUT BIND: []
171
+
172
+ IN: {'foo_id'=>sql_not_in([])}
173
+ OUT QUERY: '1=1'
174
+ OUT BIND: []
175
+
176
+ # IN: ['foo_id', sql_type(\3, SQL_INTEGER)]
177
+ # OUT QUERY: '`foo_id` = ?'
178
+ # OUT BIND: sql_type(\3, SQL_INTEGER)
179
+
180
+ # IN: ['foo_id', sql_in([sql_type(\3, SQL_INTEGER)])]
181
+ # OUT QUERY: '`foo_id` IN (?)'
182
+ # OUT BIND: sql_type(\3, SQL_INTEGER)
183
+
184
+ # IN: ['created_on', sql_gt(sql_raw('DATE_SUB(NOW(), INTERVAL 1 DAY)')) ]
185
+ # OUT QUERY: '`created_on` > DATE_SUB(NOW(), INTERVAL 1 DAY)'
186
+ # OUT BIND: