jdbc-helper 0.7.7 → 0.8.0

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.
@@ -12,31 +12,31 @@ module JDBCHelper
12
12
  #
13
13
  # # Counting the records in the table
14
14
  # table.count
15
- # table.count(:a => 10)
16
- # table.where(:a => 10).count
15
+ # table.count(a: 10)
16
+ # table.where(a: 10).count
17
17
  #
18
18
  # table.empty?
19
- # table.where(:a => 10).empty?
19
+ # table.where(a: 10).empty?
20
20
  #
21
21
  # # Selects the table by combining select, where, and order methods
22
- # table.select('a apple', :b).where(:c => (1..10)).order('b desc', 'a asc') do |row|
22
+ # table.select('a apple', :b).where(c: (1..10)).order('b desc', 'a asc') do |row|
23
23
  # puts row.apple
24
24
  # end
25
25
  #
26
26
  # # Updates with conditions
27
- # table.update(:a => 'hello', :b => JDBCHelper::SQL('now()'), :where => { :c => 3 })
27
+ # table.update(a: 'hello', b: { sql: 'now()' }, where: { c: 3 })
28
28
  # # Or equivalently,
29
- # table.where(:c => 3).update(:a => 'hello', :b => JDBCHelper::SQL('now()'))
29
+ # table.where(c: 3).update(a: 'hello', b: { sql: 'now()' })
30
30
  #
31
31
  # # Insert into the table
32
- # table.insert(:a => 10, :b => 20, :c => JDBCHelper::SQL('10 + 20'))
33
- # table.insert_ignore(:a => 10, :b => 20, :c => 30)
34
- # table.replace(:a => 10, :b => 20, :c => 30)
32
+ # table.insert(a: 10, b: 20, c: { sql: '10 + 20' })
33
+ # table.insert_ignore(a: 10, b: 20, c: 30)
34
+ # table.replace(a: 10, b: 20, c: 30)
35
35
  #
36
36
  # # Delete with conditions
37
- # table.delete(:c => 3)
37
+ # table.delete(c: 3)
38
38
  # # Or equivalently,
39
- # table.where(:c => 3).delete
39
+ # table.where(c: 3).delete
40
40
  #
41
41
  # # Truncate or drop table (Cannot be undone)
42
42
  # table.truncate_table!
@@ -50,9 +50,9 @@ class TableWrapper < ObjectWrapper
50
50
  # @param [List of Hash/String] where Filter conditions
51
51
  # @return [Fixnum] Count of the records.
52
52
  def count *where
53
- sql, binds = JDBCHelper::SQLPrepared.count(name, @query_where + where)
53
+ sql, *binds = SQLHelper.count :table => name, :where => @query_where + where, :prepared => true
54
54
  pstmt = prepare :count, sql
55
- pstmt.query(*binds)[0][0].to_i
55
+ pstmt.query(*binds).to_a[0][0].to_i
56
56
  end
57
57
 
58
58
  # Sees if the table is empty
@@ -66,7 +66,9 @@ class TableWrapper < ObjectWrapper
66
66
  # @param [Hash] data_hash Column values in Hash
67
67
  # @return [Fixnum] Number of affected records
68
68
  def insert data_hash = {}
69
- sql, binds = JDBCHelper::SQLPrepared.insert(name, @query_default.merge(data_hash))
69
+ sql, *binds = SQLHelper.insert :table => name,
70
+ :data => @query_default.merge(data_hash),
71
+ :prepared => true
70
72
  pstmt = prepare :insert, sql
71
73
  pstmt.send @update_method, *binds
72
74
  end
@@ -77,7 +79,9 @@ class TableWrapper < ObjectWrapper
77
79
  # @param [Hash] data_hash Column values in Hash
78
80
  # @return [Fixnum] Number of affected records
79
81
  def insert_ignore data_hash = {}
80
- sql, binds = JDBCHelper::SQLPrepared.insert_ignore(name, @query_default.merge(data_hash))
82
+ sql, *binds = SQLHelper.insert_ignore :table => name,
83
+ :data => @query_default.merge(data_hash),
84
+ :prepared => true
81
85
  pstmt = prepare :insert, sql
82
86
  pstmt.set_fetch_size @fetch_size if @fetch_size
83
87
  pstmt.send @update_method, *binds
@@ -88,7 +92,9 @@ class TableWrapper < ObjectWrapper
88
92
  # @param [Hash] data_hash Column values in Hash
89
93
  # @return [Fixnum] Number of affected records
90
94
  def replace data_hash = {}
91
- sql, binds = JDBCHelper::SQLPrepared.replace(name, @query_default.merge(data_hash))
95
+ sql, *binds = SQLHelper.replace :table => name,
96
+ :data => @query_default.merge(data_hash),
97
+ :prepared => true
92
98
  pstmt = prepare :insert, sql
93
99
  pstmt.send @update_method, *binds
94
100
  end
@@ -101,9 +107,11 @@ class TableWrapper < ObjectWrapper
101
107
  def update data_hash_with_where = {}
102
108
  where_ext = data_hash_with_where.delete(:where)
103
109
  where_ext = [where_ext] unless where_ext.is_a? Array
104
- sql, binds = JDBCHelper::SQLPrepared.update(name,
105
- @query_default.merge(data_hash_with_where),
106
- @query_where + where_ext.compact)
110
+ sql, *binds = SQLHelper.update(
111
+ :prepared => true,
112
+ :table => name,
113
+ :data => @query_default.merge(data_hash_with_where),
114
+ :where => @query_where + where_ext.compact)
107
115
  pstmt = prepare :update, sql
108
116
  pstmt.send @update_method, *binds
109
117
  end
@@ -112,7 +120,7 @@ class TableWrapper < ObjectWrapper
112
120
  # @param [List of Hash/String] where Delete filters
113
121
  # @return [Fixnum] Number of affected records
114
122
  def delete *where
115
- sql, binds = JDBCHelper::SQLPrepared.delete(name, @query_where + where)
123
+ sql, *binds = SQLHelper.delete(:table => name, :where => @query_where + where, :prepared => true)
116
124
  pstmt = prepare :delete, sql
117
125
  pstmt.send @update_method, *binds
118
126
  end
@@ -121,7 +129,7 @@ class TableWrapper < ObjectWrapper
121
129
  # @note This operation cannot be undone
122
130
  # @return [JDBCHelper::TableWrapper] Self.
123
131
  def truncate!
124
- @connection.update(JDBCHelper::SQL.check "truncate table #{name}")
132
+ @connection.update("truncate table #{name}")
125
133
  self
126
134
  end
127
135
  alias truncate_table! truncate!
@@ -130,7 +138,7 @@ class TableWrapper < ObjectWrapper
130
138
  # @note This operation cannot be undone
131
139
  # @return [JDBCHelper::TableWrapper] Self.
132
140
  def drop!
133
- @connection.update(JDBCHelper::SQL.check "drop table #{name}")
141
+ @connection.update("drop table #{name}")
134
142
  self
135
143
  end
136
144
  alias drop_table! drop!
@@ -149,6 +157,7 @@ class TableWrapper < ObjectWrapper
149
157
  obj.instance_variable_set :@query_select, fields unless fields.empty?
150
158
  ret obj, &block
151
159
  end
160
+ alias project select
152
161
 
153
162
  # Returns a new TableWrapper object which can be used to execute a select
154
163
  # statement for the table with the specified filter conditions.
@@ -164,6 +173,16 @@ class TableWrapper < ObjectWrapper
164
173
  ret obj, &block
165
174
  end
166
175
 
176
+ # @overload limit(offset, limit)
177
+ # @overload limit(limit)
178
+ # @return [JDBCHelper::TableWrapper]
179
+ # @since 0.8.0
180
+ def limit *args, &block
181
+ obj = self.dup
182
+ obj.instance_variable_set :@query_limit, args
183
+ ret obj, &block
184
+ end
185
+
167
186
  # Returns a new TableWrapper object which can be used to execute a select
168
187
  # statement for the table with the given sorting criteria.
169
188
  # If a block is given, executes the select statement and yields each row to the block.
@@ -203,14 +222,16 @@ class TableWrapper < ObjectWrapper
203
222
 
204
223
  # Executes a select SQL for the table and returns an Enumerable object,
205
224
  # or yields each row if block is given.
206
- # @return [JDBCHelper::Connection::ResultSetEnumerator]
225
+ # @return [JDBCHelper::Connection::ResultSet]
207
226
  # @since 0.4.0
208
227
  def each &block
209
- sql, binds = JDBCHelper::SQLPrepared.select(
210
- name,
211
- :select => @query_select,
212
- :where => @query_where,
213
- :order => @query_order)
228
+ sql, *binds = SQLHelper.select(
229
+ :prepared => true,
230
+ :table => name,
231
+ :project => @query_select,
232
+ :where => @query_where,
233
+ :order => @query_order,
234
+ :limit => @query_limit)
214
235
  pstmt = prepare :select, sql
215
236
  pstmt.enumerate(*binds, &block)
216
237
  end
@@ -276,25 +297,28 @@ class TableWrapper < ObjectWrapper
276
297
  # @return [String] Select SQL
277
298
  # @since 0.4.0
278
299
  def sql
279
- JDBCHelper::SQL.select(
280
- name,
281
- :select => @query_select,
282
- :where => @query_where,
283
- :order => @query_order)
300
+ SQLHelper.select(
301
+ :prepared => false,
302
+ :table => name,
303
+ :project => @query_select,
304
+ :where => @query_where,
305
+ :limit => @query_limit,
306
+ :order => @query_order)
284
307
  end
285
308
 
286
309
  def initialize connection, table_name
287
310
  super connection, table_name
288
311
  @update_method = :update
289
312
  @query_default = {}
290
- @query_where = []
291
- @query_order = nil
292
- @query_select = nil
313
+ @query_where = []
314
+ @query_order = nil
315
+ @query_limit = nil
316
+ @query_select = nil
293
317
  @pstmts = {
294
318
  :select => {},
295
319
  :insert => {},
296
320
  :delete => {},
297
- :count => {},
321
+ :count => {},
298
322
  :update => {}
299
323
  }
300
324
  @fetch_size = nil
@@ -319,13 +343,14 @@ class TableWrapper < ObjectWrapper
319
343
 
320
344
  def inspect
321
345
  {
322
- :conn => @connection,
323
- :name => name,
324
- :sqls => @pstmts.values.map(&:keys).flatten,
325
- :where => @query_where,
346
+ :conn => @connection,
347
+ :name => name,
348
+ :sqls => @pstmts.values.map(&:keys).flatten,
349
+ :where => @query_where,
326
350
  :default => @query_default,
327
- :order => @query_order,
328
- :batch? => batch?
351
+ :order => @query_order,
352
+ :limit => @query_limit,
353
+ :batch? => batch?
329
354
  }.inspect
330
355
  end
331
356
 
data/lib/jdbc-helper.rb CHANGED
@@ -12,4 +12,5 @@ require 'jdbc-helper/sql'
12
12
  require 'jdbc-helper/constants'
13
13
  require 'jdbc-helper/connection'
14
14
  require 'jdbc-helper/connector'
15
+ require 'sql_helper'
15
16
 
data/test/helper.rb CHANGED
@@ -84,7 +84,7 @@ module JDBCHelperTestHelper
84
84
  config.each do | db, conn_info |
85
85
  # Just for quick and dirty testing
86
86
  @type = case conn_info[:driver]
87
- when /mysql/i
87
+ when /mysql/i, /maria/i
88
88
  :mysql
89
89
  when /oracle/i
90
90
  :oracle
@@ -187,9 +187,10 @@ class TestConnection < Test::Unit::TestCase
187
187
 
188
188
  def test_query_enumerate
189
189
  each_connection do | conn |
190
- # Query without a block => Array
190
+ # Query without a block => ResultSet
191
191
  query_result = conn.query get_one_two
192
- assert query_result.is_a? Array
192
+ assert query_result.is_a? JDBCHelper::Connection::ResultSet
193
+ query_result = query_result.to_a
193
194
  assert_equal 2, query_result.length
194
195
  check_one_two(query_result.first)
195
196
  assert_equal query_result.first, query_result.last
@@ -203,13 +204,64 @@ class TestConnection < Test::Unit::TestCase
203
204
  assert_equal 2, count
204
205
 
205
206
  # Enumerate
206
- enum = conn.enumerate(get_one_two)
207
+ enum = conn.query(get_one_two)
207
208
  assert enum.is_a? Enumerable
208
209
  assert enum.closed? == false
209
210
  a = enum.to_a
210
211
  assert_equal 2, a.length
211
212
  check_one_two a.first
212
213
  assert enum.closed? == true
214
+
215
+ # Enumerator chain
216
+ cnt = 0
217
+ enum = conn.query(get_one_two)
218
+ assert_equal false, enum.closed?
219
+ enum.each.each.each.each_slice(1) do |slice|
220
+ assert_equal Array, slice.class
221
+ assert_equal 1, slice.length
222
+ cnt += 1
223
+ assert_equal cnt == 2, enum.closed?
224
+ end
225
+ assert_equal true, enum.closed?
226
+ assert_equal 2, cnt
227
+
228
+ # Enumerator chain 2
229
+ cnt = 0
230
+ enum = conn.query(get_one_two)
231
+ assert_equal false, enum.closed?
232
+ enum.each.each.each.with_index.each_slice(2).each do |slice|
233
+ assert_equal Array, slice.class
234
+ assert_equal 2, slice.length
235
+ assert_equal Array, slice[0].class
236
+ assert_equal 2, slice[0].length
237
+ assert_equal cnt, slice[0][1]
238
+ assert_equal cnt + 1, slice[1][1]
239
+ cnt += 2
240
+ assert_equal cnt == 2, enum.closed?
241
+ end
242
+ assert_equal true, enum.closed?
243
+ assert_equal 2, cnt
244
+ assert_equal 0, enum.to_a.length
245
+
246
+ enum = conn.query('
247
+ select 1 a from dual union all
248
+ select 2 a from dual union all
249
+ select 3 a from dual')
250
+
251
+ row = enum.take(1).first
252
+ assert_equal 0, row.rownum
253
+ assert_equal false, enum.closed?
254
+
255
+ row = enum.take(1).first
256
+ assert_equal 1, row.rownum
257
+ assert_equal false, enum.closed?
258
+
259
+ row = enum.take(1).first
260
+ assert_equal 2, row.rownum
261
+ assert_equal true, enum.closed?
262
+
263
+ assert_equal [], enum.take(1)
264
+ assert_equal true, enum.closed?
213
265
  end
214
266
  end
215
267
 
@@ -217,17 +269,18 @@ class TestConnection < Test::Unit::TestCase
217
269
  each_connection do |conn|
218
270
  # On error, Statement object must be returned to the StatementPool
219
271
  (JDBCHelper::Constants::MAX_STATEMENT_NESTING_LEVEL * 2).times do |i|
220
- conn.enumerate('xxx') rescue nil
272
+ conn.query('xxx') rescue nil
221
273
  end
222
- assert_equal 'OK', conn.query("select 'OK' from dual")[0][0]
274
+ assert_equal 'OK', conn.query("select 'OK' from dual").to_a[0][0]
223
275
  end
224
276
  end
225
277
 
226
278
  def test_deep_nesting
227
279
  nest = lambda { |str, lev|
228
280
  if lev > 0
229
- "conn.query('select 1 from dual') do |r#{lev}|
281
+ "conn.query('select 1 a from dual union all select 2 a from dual') do |r#{lev}|
230
282
  #{nest.call str, lev - 1}
283
+ break
231
284
  end"
232
285
  else
233
286
  str
@@ -323,7 +376,8 @@ class TestConnection < Test::Unit::TestCase
323
376
 
324
377
  # Query without a block => Array
325
378
  query_result = sel.query
326
- assert query_result.is_a? Array
379
+ assert query_result.is_a? JDBCHelper::Connection::ResultSet
380
+ query_result = query_result.to_a
327
381
  assert_equal 2, query_result.length
328
382
  check_one_two(query_result.first)
329
383
 
@@ -336,7 +390,7 @@ class TestConnection < Test::Unit::TestCase
336
390
  assert_equal 2, count
337
391
 
338
392
  # Enumerate
339
- enum = sel.enumerate
393
+ enum = sel.query
340
394
  assert enum.is_a? Enumerable
341
395
  assert enum.closed? == false
342
396
  a = enum.to_a
@@ -475,13 +529,13 @@ class TestConnection < Test::Unit::TestCase
475
529
  if @type == :mysql
476
530
  conn.prepare("insert into #{TEST_TABLE} (a, b, c) values (?, ?, ?)").update(ts, d, t)
477
531
  # MySQL doesn't have subsecond precision
478
- assert [lt, lt / 1000 * 1000].include?(conn.query("select a from #{TEST_TABLE}")[0][0].getTime)
532
+ assert [lt, (lt * 0.001).round * 1000].include?(conn.query("select a from #{TEST_TABLE}").to_a[0][0].getTime)
479
533
  # The JDBC spec states that java.sql.Dates have _no_ time component
480
534
  # http://bugs.mysql.com/bug.php?id=2876
481
- assert_equal d.getTime, conn.query("select b from #{TEST_TABLE}")[0][0].getTime
535
+ assert_equal d.getTime, conn.query("select b from #{TEST_TABLE}").to_a[0][0].getTime
482
536
 
483
537
  # http://stackoverflow.com/questions/907170/java-getminutes-and-gethours
484
- t2 = conn.query("select c from #{TEST_TABLE}")[0][0]
538
+ t2 = conn.query("select c from #{TEST_TABLE}").to_a[0][0]
485
539
  cal = java.util.Calendar.getInstance
486
540
  cal.setTime(t)
487
541
  cal2 = java.util.Calendar.getInstance
@@ -498,9 +552,10 @@ class TestConnection < Test::Unit::TestCase
498
552
  reset_test_table_ts conn
499
553
  ts = Time.now
500
554
  conn.prepare("insert into #{TEST_TABLE} (a) values (?)").update(ts)
501
- got = conn.query("select a from #{TEST_TABLE}")[0][0]
555
+ got = conn.query("select a from #{TEST_TABLE}").to_a[0][0]
502
556
  arr = [
503
557
  ts.to_i * 1000,
558
+ (ts.to_f.round) * 1000, # MySQL
504
559
  (ts.to_f * 1000).to_i,
505
560
  # SQL Server seems to round up the millisecond precision
506
561
  (ts.to_f * 1000).to_i / 10 * 10
@@ -611,7 +666,7 @@ class TestConnection < Test::Unit::TestCase
611
666
  each_connection do | conn |
612
667
  reset_test_table conn
613
668
 
614
- rse_class = JDBCHelper::Connection::ResultSetEnumerator
669
+ rse_class = JDBCHelper::Connection::ResultSet
615
670
 
616
671
  # Connection#execute
617
672
  assert_equal 1, conn.execute("insert into #{TEST_TABLE} values (0, 'A')")
@@ -659,8 +714,8 @@ class TestConnection < Test::Unit::TestCase
659
714
 
660
715
  assert_equal 20, 20.times.select {
661
716
  conn.execute(q).close
662
- conn.enumerate(q).close
663
- conn.query q
717
+ conn.query(q).close
718
+ conn.query(q).to_a
664
719
  conn.update u
665
720
 
666
721
  conn.execute(q).count == 1
@@ -119,11 +119,10 @@ class TestObjectWrapper < Test::Unit::TestCase
119
119
  end
120
120
  end
121
121
 
122
-
123
122
  def insert_params
124
123
  {
125
124
  :alpha => 100,
126
- :beta => JDBCHelper::SQL('0.1 + 0.2'),
125
+ :beta => { :sql => '0.1 + 0.2' },
127
126
  :num_f => 1234567890.12345, # 16 digits
128
127
  :num_fstr => BigDecimal.new("12345678901234567890.12345"),
129
128
  :num_int => 123456789,
@@ -272,7 +271,7 @@ class TestObjectWrapper < Test::Unit::TestCase
272
271
  params = {
273
272
  :id => 1,
274
273
  :alpha => 100,
275
- :beta => JDBCHelper::SQL('0.1 + 0.2'),
274
+ :beta => { :sql => '0.1 + 0.2' },
276
275
  :gamma => 'hello world' }
277
276
 
278
277
  100.times do
@@ -291,7 +290,7 @@ class TestObjectWrapper < Test::Unit::TestCase
291
290
  table = conn.table(@table_name)
292
291
  params = {
293
292
  :id => 1,
294
- :beta => JDBCHelper::SQL('0.1 + 0.2'),
293
+ :beta => { :sql => '0.1 + 0.2' },
295
294
  :gamma => 'hello world' }
296
295
 
297
296
  100.times do |i|
@@ -355,7 +354,7 @@ class TestObjectWrapper < Test::Unit::TestCase
355
354
  # SQL Server seems to have a bug in getBinaryStream (FIXME)
356
355
  # http://www.herongyang.com/JDBC/SQL-Server-BLOB-getBinaryStream.html
357
356
  assert_equal @blob, get_blob_data(blob) unless @type == :sqlserver
358
- assert_equal Float, row.num_f.class
357
+ assert_equal BigDecimal, row.num_f.class
359
358
  assert_equal BigDecimal, row.num_fstr.class
360
359
  assert_equal Fixnum, row.num_int.class
361
360
  assert_equal Fixnum, row.num_long.class
@@ -382,13 +381,13 @@ class TestObjectWrapper < Test::Unit::TestCase
382
381
  assert_equal 10, cnt
383
382
 
384
383
  assert_equal "select a, b, c cc from tmp_jdbc_helper " +
385
- "where id >= 11 and id <= 20 order by id desc, name asc",
384
+ "where id between 11 and 20 order by id desc, name asc",
386
385
  table.where(:id => 11..20).
387
386
  select(:a, :b, 'c cc').
388
387
  order('id desc', 'name asc').sql
389
388
 
390
389
  assert_equal "select a, b, c cc from tmp_jdbc_helper " +
391
- "where (id != 15) and id >= 11 and id <= 20 order by id desc, name asc",
390
+ "where (id != 15) and id between 11 and 20 order by id desc, name asc",
392
391
  table.where("id != 15", :id => 11..20).
393
392
  select(:a, :b, 'c cc').
394
393
  order('id desc', 'name asc').sql
@@ -499,7 +498,7 @@ class TestObjectWrapper < Test::Unit::TestCase
499
498
  table.clear_batch
500
499
  assert_equal 50, table.count
501
500
 
502
- table.batch.update(:alpha => JDBCHelper::SQL('alpha * 2'))
501
+ table.batch.update(:alpha => { :sql => 'alpha * 2' })
503
502
  assert_equal 100, table.select(:alpha).to_a.first.alpha.to_i
504
503
 
505
504
  # Independent update inbetween
@@ -517,7 +516,7 @@ class TestObjectWrapper < Test::Unit::TestCase
517
516
  assert_equal 200, table.select(:alpha).to_a.first.alpha.to_i
518
517
 
519
518
  # Order of execution
520
- table.batch.update(:alpha => JDBCHelper::SQL('alpha * 4'))
519
+ table.batch.update(:alpha => { :sql => 'alpha * 4' })
521
520
  insert table.batch, 50, 2000
522
521
  table.batch.delete
523
522
  ret = table.execute_batch :delete, :insert, :update
@@ -733,5 +732,19 @@ class TestObjectWrapper < Test::Unit::TestCase
733
732
  conn.table(@table_name).fetch_size("No").count
734
733
  end
735
734
  end
735
+
736
+ def test_limit
737
+ each_connection do |conn|
738
+ next unless [:mysql].include?(@type)
739
+
740
+ create_table conn
741
+ t = conn.table(@table_name)
742
+ insert t, 100
743
+ assert_equal 100, t.to_a.count
744
+
745
+ assert_equal 30, t.limit(30).to_a.count
746
+ assert_equal 100, t.limit(30).count
747
+ end
748
+ end
736
749
  end
737
750