jdbc-helper 0.6.3 → 0.7.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.markdown +39 -10
- data/lib/jdbc-helper/connection/type_map.rb +8 -8
- data/lib/jdbc-helper/connection.rb +6 -2
- data/lib/jdbc-helper/connector/postgres_connector.rb +37 -0
- data/lib/jdbc-helper/connector/sql_server_connector.rb +37 -0
- data/lib/jdbc-helper/connector.rb +2 -0
- data/lib/jdbc-helper/constants.rb +8 -2
- data/lib/jdbc-helper/sql/expression.rb +145 -0
- data/lib/jdbc-helper/{sql.rb → sql/sql.rb} +13 -45
- data/lib/jdbc-helper/{sql_prepared.rb → sql/sql_prepared.rb} +18 -9
- data/lib/jdbc-helper/wrapper/function_wrapper.rb +13 -2
- data/lib/jdbc-helper/wrapper/sequence_wrapper.rb +15 -2
- data/lib/jdbc-helper/wrapper/table_wrapper.rb +12 -0
- data/lib/jdbc-helper.rb +3 -2
- data/test/database.yml +11 -0
- data/test/database.yml.local +26 -13
- data/test/helper.rb +25 -0
- data/test/test_connection.rb +18 -13
- data/test/test_connectors.rb +40 -3
- data/test/test_object_wrapper.rb +63 -10
- data/test/test_sql.rb +89 -21
- metadata +12 -9
data/README.markdown
CHANGED
|
@@ -12,11 +12,13 @@
|
|
|
12
12
|
# jdbc-helper
|
|
13
13
|
|
|
14
14
|
A JDBC helper for Ruby/Database developers.
|
|
15
|
-
JDBCHelper::Connection object wraps around a JDBC connection and provides
|
|
15
|
+
JDBCHelper::Connection object wraps around a JDBC connection and provides far nicer interface to
|
|
16
16
|
crucial database operations from primitive selects and updates to more complex ones involving
|
|
17
17
|
batch updates, prepared statements and transactions.
|
|
18
18
|
As the name implies, this gem only works on JRuby.
|
|
19
19
|
|
|
20
|
+
Tested on MySQL 5.5, Oracle 11g R2, PostgreSQL 9.0.4 and MS SQL Server 2008 R2.
|
|
21
|
+
|
|
20
22
|
## Installation
|
|
21
23
|
### Install gem
|
|
22
24
|
```
|
|
@@ -55,12 +57,16 @@ conn.close
|
|
|
55
57
|
|
|
56
58
|
|
|
57
59
|
# MySQL shortcut connector
|
|
58
|
-
|
|
59
|
-
conn.close
|
|
60
|
+
JDBCHelper::MySQLConnector.connect('localhost', 'mysql', '', 'test')
|
|
60
61
|
|
|
61
62
|
# Oracle shortcut connector
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
JDBCHelper::OracleConnector.connect(host, user, password, service_name)
|
|
64
|
+
|
|
65
|
+
# PostgreSQL shortcut connector
|
|
66
|
+
JDBCHelper::PostgresConnector.connect(host, user, password, db)
|
|
67
|
+
|
|
68
|
+
# MS SQL Server shortcut connector
|
|
69
|
+
JDBCHelper::SqlServerConnector.connect(host, user, password, db)
|
|
64
70
|
```
|
|
65
71
|
|
|
66
72
|
### Querying database table
|
|
@@ -154,6 +160,7 @@ p_upd.close
|
|
|
154
160
|
### Using table wrappers (since 0.2.0)
|
|
155
161
|
```ruby
|
|
156
162
|
# For more complex examples, refer to test/test_object_wrapper.rb
|
|
163
|
+
SQL = JDBCHelper::SQL
|
|
157
164
|
|
|
158
165
|
# Creates a table wrapper
|
|
159
166
|
table = conn.table('test.data')
|
|
@@ -175,12 +182,10 @@ end
|
|
|
175
182
|
sql = table.select('a apple', :b).where(:c => (1..10)).order('b desc', 'a asc').sql
|
|
176
183
|
|
|
177
184
|
# Updates with conditions
|
|
178
|
-
table.update(:a => 'hello', :b =>
|
|
179
|
-
# Or equivalently,
|
|
180
|
-
table.where(:c => 3).update(:a => 'hello', :b => JDBCHelper::SQL('now()'))
|
|
185
|
+
table.where(:c => 3).update(:a => 'hello', :b => SQL.expr('now()'))
|
|
181
186
|
|
|
182
187
|
# Insert into the table
|
|
183
|
-
table.insert(:a => 10, :b => 20, :c =>
|
|
188
|
+
table.insert(:a => 10, :b => 20, :c => SQL.expr('10 + 20'))
|
|
184
189
|
table.insert_ignore(:a => 10, :b => 20, :c => 30)
|
|
185
190
|
table.replace(:a => 10, :b => 20, :c => 30)
|
|
186
191
|
|
|
@@ -190,7 +195,7 @@ with_defaults.insert(:c => 30)
|
|
|
190
195
|
with_defaults.where('a != 10 or b != 20').update # sets a => 10, b => 20
|
|
191
196
|
|
|
192
197
|
# Batch updates with batch method
|
|
193
|
-
table.batch.insert(:a => 10, :b => 20, :c =>
|
|
198
|
+
table.batch.insert(:a => 10, :b => 20, :c => SQL.expr('10 + 20'))
|
|
194
199
|
table.batch.insert_ignore(:a => 10, :b => 20, :c => 30)
|
|
195
200
|
conn.execute_batch
|
|
196
201
|
|
|
@@ -204,6 +209,30 @@ table.truncate!
|
|
|
204
209
|
table.drop!
|
|
205
210
|
```
|
|
206
211
|
|
|
212
|
+
#### Building complex where clauses
|
|
213
|
+
```ruby
|
|
214
|
+
SQL = JDBCHelper::SQL # Shortcut. Or you can just include JDBCHelper
|
|
215
|
+
|
|
216
|
+
# With Hash
|
|
217
|
+
scope = table.where(
|
|
218
|
+
:a => 'abc', # a = 'abc'
|
|
219
|
+
:b => (1..10), # and b >= 1 and b <= 10
|
|
220
|
+
:c => (1...10), # and c >= 1 and c < 10
|
|
221
|
+
:d => %w[a b c], # and d in ('a', 'b', 'c')
|
|
222
|
+
:e => SQL.expr('sysdate'), # and e = sysdate
|
|
223
|
+
:f => SQL.not_null, # and f is not null
|
|
224
|
+
:g => SQL.gt(100), # and g > 100
|
|
225
|
+
:h => SQL.lt(100), # and h < 100
|
|
226
|
+
:i => SQL.like('ABC%'), # and i like 'ABC%'
|
|
227
|
+
:j => SQL.not_like('ABC%'), # and j not like 'ABC%'
|
|
228
|
+
:k => SQL.le( SQL.expr('sysdate') ) # and k <= sysdate
|
|
229
|
+
)
|
|
230
|
+
scope.update(:a => 'xyz')
|
|
231
|
+
|
|
232
|
+
# With Array
|
|
233
|
+
scope = table.where(["a = ? or b > ?", 'abc', 10])
|
|
234
|
+
```
|
|
235
|
+
|
|
207
236
|
#### Invalid use of dynamic conditions
|
|
208
237
|
|
|
209
238
|
TableWrapper object internally creates JDBC PreparedStatements.
|
|
@@ -18,21 +18,21 @@ class Connection
|
|
|
18
18
|
java.sql.Types::INTEGER => :getInt,
|
|
19
19
|
java.sql.Types::BIGINT => :getLong,
|
|
20
20
|
|
|
21
|
-
java.sql.Types::CHAR
|
|
22
|
-
java.sql.Types::VARCHAR
|
|
21
|
+
java.sql.Types::CHAR => :getString,
|
|
22
|
+
java.sql.Types::VARCHAR => :getString,
|
|
23
23
|
java.sql.Types::LONGVARCHAR => :getString,
|
|
24
24
|
(java.sql.Types::NCHAR rescue nil) => :getString,
|
|
25
25
|
(java.sql.Types::NVARCHAR rescue nil) => :getString,
|
|
26
|
-
(java.sql.Types::LONGNVARCHAR rescue nil) => :
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
java.sql.Types::
|
|
26
|
+
(java.sql.Types::LONGNVARCHAR rescue nil) => :getString,
|
|
27
|
+
|
|
28
|
+
# !! MySQL function returns VARBINARY type
|
|
29
|
+
java.sql.Types::BINARY => :getBinaryStream,
|
|
30
|
+
java.sql.Types::VARBINARY => :getBinaryStream,
|
|
31
|
+
java.sql.Types::LONGVARBINARY => :getBinaryStream,
|
|
30
32
|
|
|
31
33
|
java.sql.Types::REAL => :getDouble,
|
|
32
34
|
java.sql.Types::FLOAT => :getFloat,
|
|
33
35
|
java.sql.Types::DOUBLE => :getDouble,
|
|
34
|
-
#java.sql.Types::NUMERIC => :getBigDecimal,
|
|
35
|
-
#java.sql.Types::DECIMAL => :getBigDecimal,
|
|
36
36
|
|
|
37
37
|
java.sql.Types::DATE => :getDate,
|
|
38
38
|
java.sql.Types::TIME => :getTime,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
# Junegunn Choi (junegunn.c@gmail.com)
|
|
3
3
|
|
|
4
|
-
require 'insensitive_hash'
|
|
4
|
+
require 'insensitive_hash/minimal'
|
|
5
5
|
|
|
6
6
|
require 'jdbc-helper/connection/type_map'
|
|
7
7
|
require 'jdbc-helper/connection/parameterized_statement'
|
|
@@ -147,7 +147,7 @@ class Connection
|
|
|
147
147
|
def initialize(args = {})
|
|
148
148
|
# Subsequent deletes should not affect the input
|
|
149
149
|
@args = Marshal.load(Marshal.dump(args))
|
|
150
|
-
args = Marshal.load(Marshal.dump(args))
|
|
150
|
+
args = InsensitiveHash[ Marshal.load(Marshal.dump(args)) ]
|
|
151
151
|
|
|
152
152
|
raise ArgumentError.new("driver not given") unless args.has_key? :driver
|
|
153
153
|
raise ArgumentError.new("url not given") unless args.has_key? :url
|
|
@@ -424,6 +424,10 @@ class Connection
|
|
|
424
424
|
JDBCHelper::ProcedureWrapper.new self, proc_name
|
|
425
425
|
end
|
|
426
426
|
|
|
427
|
+
def inspect
|
|
428
|
+
InsensitiveHash[@args].merge({ :closed? => closed? }).delete(:password).inspect
|
|
429
|
+
end
|
|
430
|
+
|
|
427
431
|
# Statistics
|
|
428
432
|
class Stat
|
|
429
433
|
attr_accessor :type, :elapsed, :success_count, :fail_count
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
|
3
|
+
|
|
4
|
+
module JDBCHelper
|
|
5
|
+
# Shortcut connector for PostgreSQL
|
|
6
|
+
class PostgresConnector < Connector
|
|
7
|
+
include Constants
|
|
8
|
+
include Constants::Connector
|
|
9
|
+
|
|
10
|
+
# @param [String] host
|
|
11
|
+
# @param [String] user
|
|
12
|
+
# @param [String] password
|
|
13
|
+
# @param [String] db
|
|
14
|
+
# @param [Fixnum] timeout
|
|
15
|
+
# @param [Hash] extra_params
|
|
16
|
+
# @return [JDBCHelper::Connection]
|
|
17
|
+
def self.connect(host, user, password, db,
|
|
18
|
+
timeout = DEFAULT_LOGIN_TIMEOUT,
|
|
19
|
+
extra_params = DEFAULT_PARAMETERS[:postgres], &block)
|
|
20
|
+
|
|
21
|
+
if extra_params && extra_params.is_a?(Hash) == false
|
|
22
|
+
raise ArgumentError.new('extra_params must be a hash')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
conn = Connection.new(
|
|
26
|
+
(extra_params || {}).merge(
|
|
27
|
+
:driver => JDBC_DRIVER[:postgres],
|
|
28
|
+
:url => "jdbc:postgresql://#{host}/#{db}",
|
|
29
|
+
:user => user,
|
|
30
|
+
:password => password,
|
|
31
|
+
:timeout => timeout))
|
|
32
|
+
|
|
33
|
+
block_given? ? ensure_close(conn, &block) : conn
|
|
34
|
+
end
|
|
35
|
+
end#PostgresConnector
|
|
36
|
+
end#JDBCHelper
|
|
37
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
|
3
|
+
|
|
4
|
+
module JDBCHelper
|
|
5
|
+
# Shortcut connector for MS SQL Server
|
|
6
|
+
class SqlServerConnector < Connector
|
|
7
|
+
include Constants
|
|
8
|
+
include Constants::Connector
|
|
9
|
+
|
|
10
|
+
# @param [String] host
|
|
11
|
+
# @param [String] user
|
|
12
|
+
# @param [String] password
|
|
13
|
+
# @param [String] db
|
|
14
|
+
# @param [Fixnum] timeout
|
|
15
|
+
# @param [Hash] extra_params
|
|
16
|
+
# @return [JDBCHelper::Connection]
|
|
17
|
+
def self.connect(host, user, password, db,
|
|
18
|
+
timeout = DEFAULT_LOGIN_TIMEOUT,
|
|
19
|
+
extra_params = DEFAULT_PARAMETERS[:sqlserver], &block)
|
|
20
|
+
|
|
21
|
+
if extra_params && extra_params.is_a?(Hash) == false
|
|
22
|
+
raise ArgumentError.new('extra_params must be a hash')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
conn = Connection.new(
|
|
26
|
+
(extra_params || {}).merge(
|
|
27
|
+
:driver => JDBC_DRIVER[:sqlserver],
|
|
28
|
+
:url => "jdbc:sqlserver://#{host};databaseName=#{db};",
|
|
29
|
+
:user => user,
|
|
30
|
+
:password => password,
|
|
31
|
+
:timeout => timeout))
|
|
32
|
+
|
|
33
|
+
block_given? ? ensure_close(conn, &block) : conn
|
|
34
|
+
end
|
|
35
|
+
end#SqlServerConnector
|
|
36
|
+
end#JDBCHelper
|
|
37
|
+
|
|
@@ -13,7 +13,9 @@ module Constants
|
|
|
13
13
|
module Connector
|
|
14
14
|
JDBC_DRIVER = {
|
|
15
15
|
:oracle => 'oracle.jdbc.driver.OracleDriver',
|
|
16
|
-
:mysql => 'com.mysql.jdbc.Driver'
|
|
16
|
+
:mysql => 'com.mysql.jdbc.Driver',
|
|
17
|
+
:postgres => 'org.postgresql.Driver',
|
|
18
|
+
:sqlserver => 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
DEFAULT_PARAMETERS = {
|
|
@@ -23,7 +25,11 @@ module Constants
|
|
|
23
25
|
# 'rewriteBatchedStatements' => 'true',
|
|
24
26
|
'useServerPrepStmts' => 'true',
|
|
25
27
|
'useCursorFetch' => 'true'
|
|
26
|
-
}
|
|
28
|
+
},
|
|
29
|
+
:postgres => {
|
|
30
|
+
'stringtype' => 'unspecified'
|
|
31
|
+
},
|
|
32
|
+
:sqlserver => {}
|
|
27
33
|
}
|
|
28
34
|
end#Connector
|
|
29
35
|
end#Constants
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
# Junegunn Choi (junegunn.c@gmail.com)
|
|
3
|
+
|
|
4
|
+
module JDBCHelper
|
|
5
|
+
# SQL generator class methods for prepared operations.
|
|
6
|
+
# WARNING: Does not perform SQL.check to minimize performance overhead
|
|
7
|
+
class SQL
|
|
8
|
+
# Generate SQL snippet, prevents the string from being quoted.
|
|
9
|
+
# @param [String] SQL snippet
|
|
10
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
11
|
+
# @since 0.7.0
|
|
12
|
+
def self.expr sql
|
|
13
|
+
ScalarExpression.new sql
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# "is not null" expression for where clauses
|
|
17
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
18
|
+
def self.not_nil
|
|
19
|
+
NotNullExpression.singleton
|
|
20
|
+
end
|
|
21
|
+
class << self
|
|
22
|
+
alias not_null not_nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Greater-than expression for where clauses
|
|
26
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
27
|
+
# @since 0.7.0
|
|
28
|
+
def self.gt v
|
|
29
|
+
CriterionExpression.new '>', v
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Less-than expression for where clauses
|
|
33
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
34
|
+
# @since 0.7.0
|
|
35
|
+
def self.lt v
|
|
36
|
+
CriterionExpression.new '<', v
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Less-than-or-equal-to expression for where clauses
|
|
40
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
41
|
+
# @since 0.7.0
|
|
42
|
+
def self.le v
|
|
43
|
+
CriterionExpression.new '<=', v
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Greater-than-or-equal-to expression for where clauses
|
|
47
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
48
|
+
# @since 0.7.0
|
|
49
|
+
def self.ge v
|
|
50
|
+
CriterionExpression.new '>=', v
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Not-equal expression for where clauses
|
|
54
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
55
|
+
# @since 0.7.0
|
|
56
|
+
def self.ne v
|
|
57
|
+
CriterionExpression.new '<>', v
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Like expression for where clauses
|
|
61
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
62
|
+
# @since 0.7.0
|
|
63
|
+
def self.like v
|
|
64
|
+
raise ArgumentError.new('Like expression must be given as a String') unless v.is_a?(String)
|
|
65
|
+
CriterionExpression.new 'like', v
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# "Not like" expression for where clauses
|
|
69
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
70
|
+
# @since 0.7.0
|
|
71
|
+
def self.not_like v
|
|
72
|
+
raise ArgumentError.new('Like expression must be given as a String') unless v.is_a?(String)
|
|
73
|
+
CriterionExpression.new 'not like', v
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @since 0.7.0
|
|
77
|
+
class Expression
|
|
78
|
+
def initialize
|
|
79
|
+
raise Exception.new("JDBCHelper::SQL::Expression is an abstract class")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def == other
|
|
83
|
+
self.to_s == other.to_s
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def eql? other
|
|
87
|
+
self.class == other.class && self.to_s == other.to_s
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def hash
|
|
91
|
+
[self.class, self.to_s].hash
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @since 0.7.0
|
|
96
|
+
class ScalarExpression < Expression
|
|
97
|
+
def initialize sql
|
|
98
|
+
@sql = SQL.check sql.to_s
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def to_s
|
|
102
|
+
@sql
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def to_bind
|
|
106
|
+
[@to_s, []]
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# @since 0.7.0
|
|
111
|
+
class NotNullExpression < Expression
|
|
112
|
+
def self.singleton
|
|
113
|
+
@@singleton ||= NotNullExpression.new
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def initialize
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def to_s
|
|
120
|
+
"is not null"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def to_bind
|
|
124
|
+
["is not null", []]
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# @since 0.7.0
|
|
129
|
+
class CriterionExpression < Expression
|
|
130
|
+
def initialize operator, param
|
|
131
|
+
@operator = operator
|
|
132
|
+
@param = param
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def to_s
|
|
136
|
+
[@operator, SQL.value(@param)].join(' ')
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def to_bind
|
|
140
|
+
[[@operator, '?'].join(' '), [@param]]
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end#SQL
|
|
144
|
+
end#JDBCHelper
|
|
145
|
+
|
|
@@ -5,38 +5,31 @@ module JDBCHelper
|
|
|
5
5
|
|
|
6
6
|
# Generate SQL snippet, prevents the string from being quoted.
|
|
7
7
|
# @param [String] SQL snippet
|
|
8
|
-
# @return [JDBCHelper::SQL]
|
|
8
|
+
# @return [JDBCHelper::SQL::Expression]
|
|
9
|
+
# @deprecated Use JDBCHelper::SQL.expr instead
|
|
9
10
|
def self.sql str
|
|
10
|
-
JDBCHelper::SQL.new str
|
|
11
|
+
JDBCHelper::SQL::ScalarExpression.new str
|
|
11
12
|
end
|
|
12
13
|
class << self
|
|
14
|
+
# @deprecated Use JDBCHelper::SQL.expr instead
|
|
13
15
|
alias_method :SQL, :sql
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
# Class representing an SQL snippet. Also has many SQL generator class methods.
|
|
17
19
|
class SQL
|
|
18
|
-
# Returns NotNilClass singleton object
|
|
19
|
-
# @return [JDBCHelper::SQL::NotNilClass]
|
|
20
|
-
def self.not_nil
|
|
21
|
-
NotNilClass.singleton
|
|
22
|
-
end
|
|
23
|
-
class << self
|
|
24
|
-
alias not_null not_nil
|
|
25
|
-
end
|
|
26
|
-
|
|
27
20
|
# Formats the given data so that it can be injected into SQL
|
|
28
21
|
def self.value data
|
|
29
22
|
case data
|
|
30
|
-
when NilClass
|
|
31
|
-
'null'
|
|
32
23
|
when BigDecimal
|
|
33
24
|
data.to_s("F")
|
|
34
25
|
when Numeric
|
|
35
26
|
data
|
|
36
|
-
when
|
|
37
|
-
data.to_s
|
|
38
|
-
when String
|
|
27
|
+
when String, Symbol
|
|
39
28
|
"'#{esc data}'"
|
|
29
|
+
when NilClass
|
|
30
|
+
'null'
|
|
31
|
+
when JDBCHelper::SQL::ScalarExpression
|
|
32
|
+
data.to_s
|
|
40
33
|
else
|
|
41
34
|
raise NotImplementedError.new("Unsupported datatype: #{data.class}")
|
|
42
35
|
end
|
|
@@ -124,18 +117,6 @@ class SQL
|
|
|
124
117
|
return expr
|
|
125
118
|
end
|
|
126
119
|
|
|
127
|
-
def to_s
|
|
128
|
-
@expr
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def == other
|
|
132
|
-
self.to_s == other.to_s
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def eql? other
|
|
136
|
-
self.class == other.class && self.to_s == other.to_s
|
|
137
|
-
end
|
|
138
|
-
|
|
139
120
|
protected
|
|
140
121
|
def self.esc str
|
|
141
122
|
str.to_s.gsub("'", "''")
|
|
@@ -150,7 +131,7 @@ protected
|
|
|
150
131
|
|
|
151
132
|
def self.where_unit conds
|
|
152
133
|
case conds
|
|
153
|
-
when String, JDBCHelper::SQL
|
|
134
|
+
when String, JDBCHelper::SQL::ScalarExpression
|
|
154
135
|
conds = conds.to_s.strip
|
|
155
136
|
conds.empty? ? '' : "(#{conds})"
|
|
156
137
|
when Hash
|
|
@@ -159,10 +140,10 @@ protected
|
|
|
159
140
|
case v
|
|
160
141
|
when NilClass
|
|
161
142
|
"is null"
|
|
162
|
-
when
|
|
163
|
-
"is not null"
|
|
164
|
-
when Numeric, JDBCHelper::SQL, String
|
|
143
|
+
when Numeric, String, JDBCHelper::SQL::ScalarExpression
|
|
165
144
|
"= #{value v}"
|
|
145
|
+
when JDBCHelper::SQL::Expression
|
|
146
|
+
v.to_s
|
|
166
147
|
when Range
|
|
167
148
|
">= #{v.first} and #{k} <#{'=' unless v.exclude_end?} #{v.last}"
|
|
168
149
|
when Array
|
|
@@ -192,19 +173,6 @@ protected
|
|
|
192
173
|
cols = data_hash.keys
|
|
193
174
|
check "#{cmd} into #{table} (#{cols.join ', '}) values (#{cols.map{|c|value data_hash[c]}.join ', '})"
|
|
194
175
|
end
|
|
195
|
-
|
|
196
|
-
def initialize str
|
|
197
|
-
@expr = JDBCHelper::SQL.check str
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
# Class to represent "(IS) NOT NULL" expression in SQL
|
|
201
|
-
class NotNilClass
|
|
202
|
-
# Returns the singleton object of NotNilClass
|
|
203
|
-
# @return [NotNilClass]
|
|
204
|
-
def self.singleton
|
|
205
|
-
@@singleton ||= NotNilClass.new
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
176
|
end#SQL
|
|
209
177
|
end#JDBCHelper
|
|
210
178
|
|
|
@@ -36,7 +36,7 @@ class SQLPrepared < JDBCHelper::SQL
|
|
|
36
36
|
col_binds = []
|
|
37
37
|
sql = ("update #{table} set " + data_hash.map { |k, v|
|
|
38
38
|
case v
|
|
39
|
-
when JDBCHelper::SQL
|
|
39
|
+
when JDBCHelper::SQL::ScalarExpression
|
|
40
40
|
"#{k} = #{v}"
|
|
41
41
|
else
|
|
42
42
|
col_binds << v
|
|
@@ -101,7 +101,7 @@ class SQLPrepared < JDBCHelper::SQL
|
|
|
101
101
|
binds = []
|
|
102
102
|
|
|
103
103
|
clause = case conds
|
|
104
|
-
when String
|
|
104
|
+
when String, JDBCHelper::SQL::ScalarExpression
|
|
105
105
|
conds = conds.strip
|
|
106
106
|
conds.empty? ? '' : "(#{conds})"
|
|
107
107
|
when Hash
|
|
@@ -110,13 +110,22 @@ class SQLPrepared < JDBCHelper::SQL
|
|
|
110
110
|
case v
|
|
111
111
|
when NilClass
|
|
112
112
|
"is null"
|
|
113
|
-
when
|
|
114
|
-
"is not null"
|
|
115
|
-
when JDBCHelper::SQL
|
|
116
|
-
"= #{v}"
|
|
117
|
-
when Fixnum, Bignum, Float
|
|
113
|
+
when Numeric
|
|
118
114
|
binds << v
|
|
119
115
|
"= ?"
|
|
116
|
+
when JDBCHelper::SQL::ScalarExpression
|
|
117
|
+
"= #{v.to_s}"
|
|
118
|
+
when JDBCHelper::SQL::NotNullExpression
|
|
119
|
+
v.to_s
|
|
120
|
+
when JDBCHelper::SQL::CriterionExpression
|
|
121
|
+
e, b = v.to_bind
|
|
122
|
+
case b.first
|
|
123
|
+
when JDBCHelper::SQL::ScalarExpression
|
|
124
|
+
v.to_s
|
|
125
|
+
else
|
|
126
|
+
binds += b
|
|
127
|
+
e
|
|
128
|
+
end
|
|
120
129
|
when Range
|
|
121
130
|
binds << v.begin << v.end
|
|
122
131
|
">= ? and #{k} <#{'=' unless v.exclude_end?} ?"
|
|
@@ -125,7 +134,7 @@ class SQLPrepared < JDBCHelper::SQL
|
|
|
125
134
|
v.map { |e|
|
|
126
135
|
case e
|
|
127
136
|
when String
|
|
128
|
-
|
|
137
|
+
SQL.value e
|
|
129
138
|
else
|
|
130
139
|
e.to_s
|
|
131
140
|
end }.join(', ') + ")"
|
|
@@ -151,7 +160,7 @@ class SQLPrepared < JDBCHelper::SQL
|
|
|
151
160
|
binds = []
|
|
152
161
|
values = data_hash.values.map { |v|
|
|
153
162
|
case v
|
|
154
|
-
when JDBCHelper::SQL
|
|
163
|
+
when JDBCHelper::SQL::ScalarExpression
|
|
155
164
|
v
|
|
156
165
|
else
|
|
157
166
|
binds << v
|
|
@@ -11,9 +11,21 @@ class FunctionWrapper < ObjectWrapper
|
|
|
11
11
|
# @return [String]
|
|
12
12
|
alias to_s name
|
|
13
13
|
|
|
14
|
+
def initialize conn, name
|
|
15
|
+
super conn, name
|
|
16
|
+
|
|
17
|
+
@suffix =
|
|
18
|
+
case conn.driver
|
|
19
|
+
when /oracle/
|
|
20
|
+
" from dual"
|
|
21
|
+
else
|
|
22
|
+
""
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
14
26
|
# Returns the result of the function call with the given parameters
|
|
15
27
|
def call(*args)
|
|
16
|
-
pstmt = @connection.prepare("select #{name}(#{args.map{'?'}.join ','})
|
|
28
|
+
pstmt = @connection.prepare("select #{name}(#{args.map{'?'}.join ','})#{@suffix}")
|
|
17
29
|
begin
|
|
18
30
|
pstmt.query(*args)[0][0]
|
|
19
31
|
ensure
|
|
@@ -23,4 +35,3 @@ class FunctionWrapper < ObjectWrapper
|
|
|
23
35
|
end#FunctionWrapper
|
|
24
36
|
end#JDBCHelper
|
|
25
37
|
|
|
26
|
-
|
|
@@ -15,16 +15,29 @@ class SequenceWrapper < ObjectWrapper
|
|
|
15
15
|
# @return [String]
|
|
16
16
|
alias to_s name
|
|
17
17
|
|
|
18
|
+
def initialize(conn, name)
|
|
19
|
+
super conn, name
|
|
20
|
+
|
|
21
|
+
case conn.driver
|
|
22
|
+
when /oracle/
|
|
23
|
+
@nextval_sql = "select #{name}.nextval from dual"
|
|
24
|
+
@currval_sql = "select #{name}.currval from dual"
|
|
25
|
+
else
|
|
26
|
+
@nextval_sql = "select nextval('#{name}')"
|
|
27
|
+
@currval_sql = "select currval('#{name}')"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
18
31
|
# Increments the sequence and returns the value
|
|
19
32
|
# @return [Fixnum]
|
|
20
33
|
def nextval
|
|
21
|
-
@connection.query(
|
|
34
|
+
@connection.query(@nextval_sql)[0][0].to_i
|
|
22
35
|
end
|
|
23
36
|
|
|
24
37
|
# Returns the incremented value of the sequence
|
|
25
38
|
# @return [Fixnum]
|
|
26
39
|
def currval
|
|
27
|
-
@connection.query(
|
|
40
|
+
@connection.query(@currval_sql)[0][0].to_i
|
|
28
41
|
end
|
|
29
42
|
|
|
30
43
|
# Recreates the sequence. Cannot be undone.
|
|
@@ -269,6 +269,18 @@ class TableWrapper < ObjectWrapper
|
|
|
269
269
|
@pstmts
|
|
270
270
|
end
|
|
271
271
|
|
|
272
|
+
def inspect
|
|
273
|
+
{
|
|
274
|
+
:conn => @connection,
|
|
275
|
+
:name => name,
|
|
276
|
+
:sqls => @pstmts.values.map(&:keys).flatten,
|
|
277
|
+
:where => @query_where,
|
|
278
|
+
:default => @query_default,
|
|
279
|
+
:order => @query_order,
|
|
280
|
+
:batch? => batch?
|
|
281
|
+
}.inspect
|
|
282
|
+
end
|
|
283
|
+
|
|
272
284
|
private
|
|
273
285
|
def prepare type, sql
|
|
274
286
|
sql = JDBCHelper::SQL.check(sql)
|
data/lib/jdbc-helper.rb
CHANGED
|
@@ -6,8 +6,9 @@ if RUBY_PLATFORM.match(/java/).nil?
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
require 'java'
|
|
9
|
-
require 'jdbc-helper/sql'
|
|
10
|
-
require 'jdbc-helper/sql_prepared'
|
|
9
|
+
require 'jdbc-helper/sql/sql'
|
|
10
|
+
require 'jdbc-helper/sql/sql_prepared'
|
|
11
|
+
require 'jdbc-helper/sql/expression'
|
|
11
12
|
require 'jdbc-helper/constants'
|
|
12
13
|
require 'jdbc-helper/connection'
|
|
13
14
|
require 'jdbc-helper/connector'
|