jdbc-helper 0.6.3 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|