jdbc-helper 0.1.3 → 0.2.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.
- data/README.rdoc +17 -1
- data/lib/jdbc-helper/connection/prepared_statement.rb +28 -16
- data/lib/jdbc-helper/connection/row.rb +37 -9
- data/lib/jdbc-helper/connection/statement_pool.rb +4 -3
- data/lib/jdbc-helper/connection.rb +57 -19
- data/lib/jdbc-helper/connector/mysql_connector.rb +7 -0
- data/lib/jdbc-helper/connector/oracle_connector.rb +12 -0
- data/lib/jdbc-helper/object_wrapper.rb +126 -0
- data/lib/jdbc-helper/sql.rb +168 -0
- data/lib/jdbc-helper.rb +2 -0
- data/test/database.yml +4 -2
- data/test/helper.rb +22 -0
- data/test/{test_jdbc-helper.rb → test_connection.rb} +5 -39
- data/test/test_connectors.rb +34 -0
- data/test/test_object_wrapper.rb +221 -0
- data/test/test_performance.rb +105 -0
- data/test/test_sql.rb +77 -0
- metadata +94 -89
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
3
|
+
|
4
|
+
module JDBCHelper
|
5
|
+
# Abstract base class for wrappers for various database objects.
|
6
|
+
# @abstract
|
7
|
+
# @since 0.2.0
|
8
|
+
# @todo Need to add more subclasses (such as for functions and procedures)
|
9
|
+
class ObjectWrapper
|
10
|
+
# Underlying JDBCHelper::Connection object
|
11
|
+
# @return [JDBCHelper::Connection]
|
12
|
+
attr_reader :connection
|
13
|
+
|
14
|
+
# Object name (or expression)
|
15
|
+
# @return [String]
|
16
|
+
attr_reader :name
|
17
|
+
|
18
|
+
# Base constructor.
|
19
|
+
# @param [JDBCHelper::Connection] conn JDBCHelper::Connection object
|
20
|
+
# @param [String] name Name of the object to be wrapped
|
21
|
+
def initialize(conn, name)
|
22
|
+
raise Exception.new(
|
23
|
+
"JDBCHelper::ObjectWrapper is an abstract class") if
|
24
|
+
self.instance_of? ObjectWrapper
|
25
|
+
|
26
|
+
@connection = conn
|
27
|
+
@name = name.to_s
|
28
|
+
JDBCHelper::SQL.check @name
|
29
|
+
end
|
30
|
+
end#ObjectWrapper
|
31
|
+
|
32
|
+
# A wrapper object representing a database table. Allows you to perform table operations easily.
|
33
|
+
# @since 0.2.0
|
34
|
+
# @example Usage
|
35
|
+
# # For more complex examples, refer to test/test_object_wrapper.rb
|
36
|
+
#
|
37
|
+
# conn.table('test.data').count
|
38
|
+
# conn.table('test.data').empty?
|
39
|
+
# conn.table('test.data').select(:c => 3) do |row|
|
40
|
+
# puts row.a
|
41
|
+
# end
|
42
|
+
# conn.table('test.data').update(:a => 1, :b => 2, :where => { :c => 3 })
|
43
|
+
# conn.table('test.data').insert(:a => 10, :b => 20, :c => 30)
|
44
|
+
# conn.table('test.data').insert_ignore(:a => 10, :b => 20, :c => 30)
|
45
|
+
# conn.table('test.data').insert_replace(:a => 10, :b => 20, :c => 30)
|
46
|
+
# conn.table('test.data').delete(:c => 3)
|
47
|
+
# conn.table('test.data').truncate_table!
|
48
|
+
# conn.table('test.data').drop_table!
|
49
|
+
class TableWrapper < ObjectWrapper
|
50
|
+
# Retrieves the count of the table
|
51
|
+
# @return [Fixnum] Count of the records.
|
52
|
+
def count(where = nil)
|
53
|
+
@connection.query(JDBCHelper::SQL.count name, where)[0][0]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Sees if the table is empty
|
57
|
+
# @return [boolean]
|
58
|
+
def empty?
|
59
|
+
count == 0
|
60
|
+
end
|
61
|
+
|
62
|
+
# Select * with optional conditions
|
63
|
+
# @param [Hash/String] where Select filters
|
64
|
+
# @return [Array] Array is returned if block is not given
|
65
|
+
# @yield [JDBCHelper::Connection::Row]
|
66
|
+
def select where = nil, &block
|
67
|
+
@connection.query(JDBCHelper::SQL.select(name, where), &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Inserts a record into the table with the given hash
|
71
|
+
# @param [Hash] data_hash Column values in Hash
|
72
|
+
# @return [Fixnum] Number of affected records
|
73
|
+
def insert data_hash
|
74
|
+
@connection.update(JDBCHelper::SQL.insert name, data_hash)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Inserts a record into the table with the given hash.
|
78
|
+
# Skip insertion when duplicate record is found.
|
79
|
+
# @note This is not SQL standard. Only works if the database supports insert ignore syntax.
|
80
|
+
# @param [Hash] data_hash Column values in Hash
|
81
|
+
# @return [Fixnum] Number of affected records
|
82
|
+
def insert_ignore data_hash
|
83
|
+
@connection.update(JDBCHelper::SQL.insert_ignore name, data_hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Replaces a record in the table with the new one with the same unique key.
|
87
|
+
# @note This is not SQL standard. Only works if the database supports replace syntax.
|
88
|
+
# @param [Hash] data_hash Column values in Hash
|
89
|
+
# @return [Fixnum] Number of affected records
|
90
|
+
def replace data_hash
|
91
|
+
@connection.update(JDBCHelper::SQL.replace name, data_hash)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Executes update with the given hash.
|
95
|
+
# :where element of the hash is taken out to generate where clause of the update SQL.
|
96
|
+
# @param [Hash] data_hash_with_where Column values in Hash.
|
97
|
+
# :where element of the given hash can (usually should) point to another Hash representing update filters.
|
98
|
+
# @return [Fixnum] Number of affected records
|
99
|
+
def update data_hash_with_where
|
100
|
+
@connection.update(JDBCHelper::SQL.update name, data_hash_with_where)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Deletes records matching given condtion
|
104
|
+
# @param [Hash] where Delete filters
|
105
|
+
# @return [Fixnum] Number of affected records
|
106
|
+
def delete where = nil
|
107
|
+
@connection.update(JDBCHelper::SQL.delete name, where)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Empties the table.
|
111
|
+
# @note This operation cannot be undone
|
112
|
+
# @return [Fixnum] executeUpdate return value
|
113
|
+
def truncate_table!
|
114
|
+
@connection.update(JDBCHelper::SQL.check "truncate table #{name}")
|
115
|
+
end
|
116
|
+
|
117
|
+
# Drops the table.
|
118
|
+
# @note This operation cannot be undone
|
119
|
+
# @return [Fixnum] executeUpdate return value
|
120
|
+
def drop_table!
|
121
|
+
@connection.update(JDBCHelper::SQL.check "drop table #{name}")
|
122
|
+
end
|
123
|
+
end#TableWrapper
|
124
|
+
|
125
|
+
end#JDBCHelper
|
126
|
+
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
3
|
+
|
4
|
+
module JDBCHelper
|
5
|
+
module SQL
|
6
|
+
# Prevents a string from being quoted
|
7
|
+
def self.expr str
|
8
|
+
Expr.new str
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns NotNilClass singleton object
|
12
|
+
def self.not_nil
|
13
|
+
NotNilClass.singleton
|
14
|
+
end
|
15
|
+
|
16
|
+
# Formats the given data so that it can be injected into SQL
|
17
|
+
def self.value data
|
18
|
+
case data
|
19
|
+
when NilClass
|
20
|
+
'null'
|
21
|
+
when Fixnum, Bignum, Float
|
22
|
+
data
|
23
|
+
when JDBCHelper::SQL::Expr
|
24
|
+
data.to_s
|
25
|
+
when String
|
26
|
+
"'#{esc data}'"
|
27
|
+
else
|
28
|
+
raise NotImplementedError.new("Unsupported datatype: #{data.class}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Generates SQL where cluase with the given conditions.
|
33
|
+
# Parameter can be either Hash of String.
|
34
|
+
def self.where conds
|
35
|
+
check(where_internal conds)
|
36
|
+
end
|
37
|
+
|
38
|
+
# SQL Helpers
|
39
|
+
# ===========
|
40
|
+
|
41
|
+
# Generates insert SQL with hash
|
42
|
+
def self.insert table, data_hash
|
43
|
+
insert_internal 'insert', table, data_hash
|
44
|
+
end
|
45
|
+
|
46
|
+
# Generates insert ignore SQL (Non-standard syntax)
|
47
|
+
def self.insert_ignore table, data_hash
|
48
|
+
insert_internal 'insert ignore', table, data_hash
|
49
|
+
end
|
50
|
+
|
51
|
+
# Generates replace SQL (Non-standard syntax)
|
52
|
+
def self.replace table, data_hash
|
53
|
+
insert_internal 'replace', table, data_hash
|
54
|
+
end
|
55
|
+
|
56
|
+
# Generates update SQL with hash.
|
57
|
+
# :where element of the given hash is taken out to generate where clause.
|
58
|
+
def self.update table, data_hash
|
59
|
+
where_clause = make_where(data_hash.delete :where)
|
60
|
+
updates = data_hash.map { |k, v| "#{k} = #{value v}" }.join(', ')
|
61
|
+
check "update #{table} set #{updates}#{where_clause}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Generates select * SQL with the given conditions
|
65
|
+
def self.select table, conds = nil
|
66
|
+
check "select * from #{table}#{make_where conds}"
|
67
|
+
end
|
68
|
+
|
69
|
+
# Generates count SQL with the given conditions
|
70
|
+
def self.count table, conds = nil
|
71
|
+
check "select count(*) from #{table}#{make_where conds}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# Generates delete SQL with the given conditions
|
75
|
+
def self.delete table, conds = nil
|
76
|
+
check "delete from #{table}#{make_where conds}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# FIXME: Naive protection for SQL Injection
|
80
|
+
def self.check expr
|
81
|
+
return nil if expr.nil?
|
82
|
+
|
83
|
+
test = expr.gsub(/'[^']*'/, '').gsub(/`[^`]*`/, '').gsub(/"[^"]*"/, '')
|
84
|
+
raise ArgumentError.new("Expression cannot contain semi-colons: #{test}") if test.include?(';')
|
85
|
+
raise ArgumentError.new("Expression cannot contain comments: #{test}") if test.match(%r{--|/\*|\*/})
|
86
|
+
raise ArgumentError.new("Unclosed quotation mark: #{test}") if test.match(/['"`]/)
|
87
|
+
|
88
|
+
return expr
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
def self.esc str
|
93
|
+
str.gsub("'", "''")
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.make_where conds
|
97
|
+
str = where_internal conds
|
98
|
+
str = ' where ' + str if str
|
99
|
+
str
|
100
|
+
end
|
101
|
+
|
102
|
+
# No check
|
103
|
+
def self.where_internal conds
|
104
|
+
return nil if conds.nil?
|
105
|
+
|
106
|
+
case conds
|
107
|
+
when String
|
108
|
+
return nil if conds.strip.empty?
|
109
|
+
conds
|
110
|
+
when Hash
|
111
|
+
return nil if conds.empty?
|
112
|
+
conds.map { |k, v|
|
113
|
+
"#{k} " +
|
114
|
+
case v
|
115
|
+
when NilClass
|
116
|
+
"is null"
|
117
|
+
when NotNilClass
|
118
|
+
"is not null"
|
119
|
+
when Fixnum, Bignum, Float, JDBCHelper::SQL::Expr
|
120
|
+
"= #{v}"
|
121
|
+
when Range
|
122
|
+
">= #{v.first} and #{k} <#{'=' unless v.exclude_end?} #{v.last}"
|
123
|
+
when Array
|
124
|
+
"in (" +
|
125
|
+
v.map { |e|
|
126
|
+
case e
|
127
|
+
when String
|
128
|
+
"'#{esc e}'"
|
129
|
+
else
|
130
|
+
e
|
131
|
+
end }.join(', ') + ")"
|
132
|
+
when String
|
133
|
+
"= '#{esc v}'"
|
134
|
+
else
|
135
|
+
raise NotImplementedError.new("Unsupported class: #{v.class}")
|
136
|
+
end
|
137
|
+
}.join(' and ')
|
138
|
+
else
|
139
|
+
raise NotImplementedError.new("Parameter to where must be either Hash or String")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.insert_internal cmd, table, data_hash
|
144
|
+
cols = data_hash.keys
|
145
|
+
check "#{cmd} into #{table} (#{cols.join ', '}) values (#{cols.map{|c|value data_hash[c]}.join ', '})"
|
146
|
+
end
|
147
|
+
|
148
|
+
class Expr
|
149
|
+
def initialize str
|
150
|
+
@expr = str
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_s
|
154
|
+
@expr
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Class to represent "(IS) NOT NULL" expression in SQL
|
159
|
+
class NotNilClass
|
160
|
+
# Returns the singleton object of NotNilClass
|
161
|
+
# @return [NotNilClass]
|
162
|
+
def self.singleton
|
163
|
+
@@singleton ||= NotNilClass.new
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end#SQL
|
167
|
+
end#JDBCHelper
|
168
|
+
|
data/lib/jdbc-helper.rb
CHANGED
data/test/database.yml
CHANGED
@@ -4,10 +4,12 @@ mysql:
|
|
4
4
|
url: jdbc:mysql://localhost/test
|
5
5
|
user: mysql
|
6
6
|
password:
|
7
|
+
database: test
|
7
8
|
|
8
9
|
# oracle:
|
9
10
|
# driver: com.mysql.jdbc.Driver
|
10
|
-
# url: jdbc:
|
11
|
-
# user:
|
11
|
+
# url: jdbc:oracle:thin:@localhost/test
|
12
|
+
# user: test
|
12
13
|
# password:
|
14
|
+
# database: test
|
13
15
|
|
data/test/helper.rb
CHANGED
@@ -15,3 +15,25 @@ require 'jdbc-helper'
|
|
15
15
|
|
16
16
|
class Test::Unit::TestCase
|
17
17
|
end
|
18
|
+
|
19
|
+
module JDBCHelperTestHelper
|
20
|
+
require 'yaml'
|
21
|
+
def config
|
22
|
+
@db_config ||= YAML.load File.read(File.dirname(__FILE__) + '/database.yml')
|
23
|
+
end
|
24
|
+
|
25
|
+
def each_connection(&block)
|
26
|
+
config.each do | db, conn_info |
|
27
|
+
conn = JDBCHelper::Connection.new(conn_info)
|
28
|
+
begin
|
29
|
+
if block.arity == 1
|
30
|
+
yield conn
|
31
|
+
else
|
32
|
+
yield conn, conn_info
|
33
|
+
end
|
34
|
+
ensure
|
35
|
+
conn.close
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,28 +1,16 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class TestConnection < Test::Unit::TestCase
|
4
|
+
include JDBCHelperTestHelper
|
5
|
+
|
4
6
|
def setup
|
5
|
-
require 'yaml'
|
6
|
-
@config = YAML.load File.read(File.dirname(__FILE__) + '/database.yml')
|
7
7
|
end
|
8
8
|
|
9
9
|
def teardown
|
10
|
-
|
11
10
|
end
|
12
11
|
|
13
12
|
TEST_TABLE = 'tmp_jdbc_helper_test'
|
14
13
|
|
15
|
-
def each_connection
|
16
|
-
@config.each do | db, conn_info |
|
17
|
-
conn = JDBCHelper::Connection.new(conn_info)
|
18
|
-
begin
|
19
|
-
yield conn
|
20
|
-
ensure
|
21
|
-
conn.close
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
14
|
def get_one_two
|
27
15
|
"
|
28
16
|
select 1 one, 'two' two from dual
|
@@ -42,7 +30,7 @@ class TestJdbcHelper < Test::Unit::TestCase
|
|
42
30
|
assert_equal 'two', rec[1]
|
43
31
|
assert_equal 'two', rec['two']
|
44
32
|
|
45
|
-
assert_raise(
|
33
|
+
assert_raise(NoMethodError) { rec.three }
|
46
34
|
assert_raise(NameError) { rec['three'] }
|
47
35
|
assert_raise(RangeError) { rec[3] }
|
48
36
|
end
|
@@ -69,7 +57,7 @@ class TestJdbcHelper < Test::Unit::TestCase
|
|
69
57
|
# ---------------------------------------------------------------
|
70
58
|
|
71
59
|
def test_connect_and_close
|
72
|
-
|
60
|
+
config.each do | db, conn_info |
|
73
61
|
4.times do | i |
|
74
62
|
# With or without timeout parameter
|
75
63
|
conn_info['timeout'] = 60 if i % 2 == 1
|
@@ -276,28 +264,6 @@ class TestJdbcHelper < Test::Unit::TestCase
|
|
276
264
|
end
|
277
265
|
end
|
278
266
|
|
279
|
-
def test_connectors
|
280
|
-
@config.each do | db, conn_info |
|
281
|
-
if db == 'mysql'
|
282
|
-
host = conn_info['url'].match(%r{//(.*?)/})[1]
|
283
|
-
db = conn_info['url'].match(%r{/([^/?]*?)(\?.*)?$})[1]
|
284
|
-
conn = JDBCHelper::MySQLConnector.connect(host, conn_info['user'], conn_info['password'], db)
|
285
|
-
|
286
|
-
assert conn.closed? == false
|
287
|
-
conn.close
|
288
|
-
assert conn.closed?
|
289
|
-
elsif db == 'oracle'
|
290
|
-
host = conn_info['url'].match(%r{//(.*?)/})[1]
|
291
|
-
svc = conn_info['url'].match(%r{/([^/?]*?)(\?.*)?$})[1]
|
292
|
-
conn = JDBCHelper::OracleConnector.connect(host, conn_info['user'], conn_info['password'], svc)
|
293
|
-
|
294
|
-
assert conn.closed? == false
|
295
|
-
conn.close
|
296
|
-
assert conn.closed?
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
267
|
def test_setter_timestamp
|
302
268
|
each_connection do | conn |
|
303
269
|
# Java timestamp
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestConnectors < Test::Unit::TestCase
|
4
|
+
include JDBCHelperTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_connectors
|
13
|
+
config.each do | db, conn_info |
|
14
|
+
if db == 'mysql'
|
15
|
+
host = conn_info['url'].match(%r{//(.*?)/})[1]
|
16
|
+
db = conn_info['url'].match(%r{/([^/?]*?)(\?.*)?$})[1]
|
17
|
+
conn = JDBCHelper::MySQLConnector.connect(host, conn_info['user'], conn_info['password'], db)
|
18
|
+
|
19
|
+
assert conn.closed? == false
|
20
|
+
conn.close
|
21
|
+
assert conn.closed?
|
22
|
+
elsif db == 'oracle'
|
23
|
+
host = conn_info['url'].match(%r{//(.*?)/})[1]
|
24
|
+
svc = conn_info['url'].match(%r{/([^/?]*?)(\?.*)?$})[1]
|
25
|
+
conn = JDBCHelper::OracleConnector.connect(host, conn_info['user'], conn_info['password'], svc)
|
26
|
+
|
27
|
+
assert conn.closed? == false
|
28
|
+
conn.close
|
29
|
+
assert conn.closed?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestObjectWrapper < Test::Unit::TestCase
|
4
|
+
include JDBCHelperTestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@table_name = "tmp_jdbc_helper"
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
each_connection do |conn|
|
12
|
+
drop_table conn
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_table conn
|
17
|
+
drop_table conn
|
18
|
+
conn.update "
|
19
|
+
create table #{@table_name} (
|
20
|
+
id int primary key,
|
21
|
+
alpha int,
|
22
|
+
beta float,
|
23
|
+
gamma varchar(100)
|
24
|
+
)
|
25
|
+
"
|
26
|
+
end
|
27
|
+
|
28
|
+
def drop_table conn
|
29
|
+
begin
|
30
|
+
conn.update "drop table #{@table_name}"
|
31
|
+
return true
|
32
|
+
rescue Exception
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_wrapper
|
38
|
+
each_connection do |conn|
|
39
|
+
# With symbol
|
40
|
+
assert_kind_of JDBCHelper::ObjectWrapper, conn.table(:some_table)
|
41
|
+
assert_instance_of JDBCHelper::TableWrapper, conn.table(:some_table)
|
42
|
+
assert_equal 'some_table', conn.table(:some_table).name
|
43
|
+
|
44
|
+
# With string
|
45
|
+
assert_kind_of JDBCHelper::ObjectWrapper, conn.table('db.table')
|
46
|
+
assert_instance_of JDBCHelper::TableWrapper, conn.table('db.table')
|
47
|
+
assert_equal 'db.table', conn.table('db.table').name
|
48
|
+
|
49
|
+
# Invalid table name
|
50
|
+
assert_raise(ArgumentError) { conn.table('table;') }
|
51
|
+
assert_raise(ArgumentError) { conn.table('table -- ') }
|
52
|
+
assert_raise(ArgumentError) { conn.table("tab'le") }
|
53
|
+
assert_raise(ArgumentError) { conn.table('tab"le') }
|
54
|
+
assert_raise(ArgumentError) { conn.table("tab`le") }
|
55
|
+
|
56
|
+
# Abstract class
|
57
|
+
assert_raise(Exception) { JDBCHelper::ObjectWrapper.new(conn, 'table') }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def insert table
|
62
|
+
params = {
|
63
|
+
:alpha => 100,
|
64
|
+
:beta => JDBCHelper::SQL.expr('0.1 + 0.2'),
|
65
|
+
:gamma => 'hello world' }
|
66
|
+
|
67
|
+
(1..100).each do |pk|
|
68
|
+
icnt = table.insert(params.merge(:id => pk))
|
69
|
+
assert_equal icnt, 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_empty
|
74
|
+
each_connection do |conn|
|
75
|
+
create_table conn
|
76
|
+
table = conn.table(@table_name)
|
77
|
+
|
78
|
+
assert table.empty?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_insert_count
|
83
|
+
each_connection do |conn|
|
84
|
+
create_table conn
|
85
|
+
table = conn.table(@table_name)
|
86
|
+
|
87
|
+
# Count
|
88
|
+
assert_equal 0, table.count
|
89
|
+
assert table.empty?
|
90
|
+
|
91
|
+
# Insert
|
92
|
+
insert table
|
93
|
+
|
94
|
+
# Count
|
95
|
+
assert_equal 100, table.count
|
96
|
+
assert_equal 100, table.count(:alpha => 100)
|
97
|
+
assert_equal 0, table.count(:beta => nil)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# This will fail if the database doesn't support insert ignore syntax
|
102
|
+
def test_insert_ignore
|
103
|
+
each_connection do |conn|
|
104
|
+
create_table conn
|
105
|
+
table = conn.table(@table_name)
|
106
|
+
params = {
|
107
|
+
:id => 1,
|
108
|
+
:alpha => 100,
|
109
|
+
:beta => JDBCHelper::SQL.expr('0.1 + 0.2'),
|
110
|
+
:gamma => 'hello world' }
|
111
|
+
|
112
|
+
100.times do
|
113
|
+
table.insert_ignore(params)
|
114
|
+
end
|
115
|
+
|
116
|
+
assert_equal 1, table.count
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# This will fail if the database doesn't support replace syntax
|
121
|
+
def test_replace
|
122
|
+
each_connection do |conn|
|
123
|
+
create_table conn
|
124
|
+
table = conn.table(@table_name)
|
125
|
+
params = {
|
126
|
+
:id => 1,
|
127
|
+
:beta => JDBCHelper::SQL.expr('0.1 + 0.2'),
|
128
|
+
:gamma => 'hello world' }
|
129
|
+
|
130
|
+
100.times do |i|
|
131
|
+
table.replace(params.merge(:alpha => i))
|
132
|
+
end
|
133
|
+
|
134
|
+
assert_equal 1, table.count
|
135
|
+
assert_equal 99, table.select.first.alpha
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_select
|
140
|
+
each_connection do |conn|
|
141
|
+
create_table conn
|
142
|
+
table = conn.table(@table_name)
|
143
|
+
insert table
|
144
|
+
assert_equal 100, table.count
|
145
|
+
|
146
|
+
cnt = 0
|
147
|
+
table.select do |row|
|
148
|
+
cnt += 1
|
149
|
+
assert_equal 100, row.alpha
|
150
|
+
assert_equal 'hello world', row.gamma
|
151
|
+
end
|
152
|
+
assert_equal 100, cnt
|
153
|
+
|
154
|
+
cnt = 0
|
155
|
+
table.select(:id => 11..20) do |row|
|
156
|
+
cnt += 1
|
157
|
+
assert_equal 100, row.alpha
|
158
|
+
assert_equal 'hello world', row.gamma
|
159
|
+
end
|
160
|
+
assert_equal 10, cnt
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_delete
|
165
|
+
each_connection do |conn|
|
166
|
+
create_table conn
|
167
|
+
table = conn.table(@table_name)
|
168
|
+
insert table
|
169
|
+
|
170
|
+
# Count
|
171
|
+
assert_equal 100, table.count
|
172
|
+
|
173
|
+
# Delete
|
174
|
+
assert_equal 10, table.delete(:id => (1...11))
|
175
|
+
assert_equal 10, table.delete(:id => (11..20))
|
176
|
+
assert_equal 1, table.delete(:id => 21)
|
177
|
+
assert_equal 4, table.delete(:id => [22, 23, 24, 25])
|
178
|
+
assert_equal 5, table.delete("id <= 30")
|
179
|
+
|
180
|
+
# Could be dangerous (XXX)
|
181
|
+
assert_equal 70, table.delete
|
182
|
+
|
183
|
+
# Count
|
184
|
+
assert_equal 0, table.count
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_update
|
189
|
+
each_connection do |conn|
|
190
|
+
create_table conn
|
191
|
+
table = conn.table(@table_name)
|
192
|
+
insert table
|
193
|
+
|
194
|
+
assert_equal 10, table.update(:beta => 0, :where => { :id => (1..10) })
|
195
|
+
assert_equal 10, table.count(:beta => 0)
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_truncate_table
|
201
|
+
each_connection do |conn|
|
202
|
+
create_table conn
|
203
|
+
table = conn.table(@table_name)
|
204
|
+
insert table
|
205
|
+
|
206
|
+
table.truncate_table!
|
207
|
+
assert table.empty?
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_drop_table
|
212
|
+
each_connection do |conn|
|
213
|
+
create_table conn
|
214
|
+
table = conn.table(@table_name)
|
215
|
+
table.drop_table!
|
216
|
+
|
217
|
+
assert_equal false, drop_table(conn)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|