sql-maker 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: