activerecord-jdbc-adapter 1.3.7 → 1.3.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +33 -3
- data/Appraisals +11 -5
- data/Gemfile +21 -15
- data/History.md +31 -1
- data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
- data/lib/arel/visitors/firebird.rb +7 -10
- data/lib/arel/visitors/h2.rb +9 -0
- data/lib/arel/visitors/sql_server.rb +21 -2
- data/lib/arjdbc/h2/adapter.rb +31 -2
- data/lib/arjdbc/h2/connection_methods.rb +1 -1
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +2 -1
- data/lib/arjdbc/mssql/adapter.rb +40 -23
- data/lib/arjdbc/mssql/column.rb +4 -4
- data/lib/arjdbc/mysql/adapter.rb +36 -10
- data/lib/arjdbc/mysql/column.rb +12 -7
- data/lib/arjdbc/mysql/connection_methods.rb +53 -21
- data/lib/arjdbc/oracle/adapter.rb +22 -5
- data/lib/arjdbc/postgresql/adapter.rb +54 -18
- data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
- data/lib/arjdbc/postgresql/base/oid.rb +460 -0
- data/lib/arjdbc/postgresql/column.rb +50 -15
- data/lib/arjdbc/postgresql/oid_types.rb +126 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +4 -2
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/02-test.rake +3 -30
- data/src/java/arjdbc/derby/DerbyModule.java +0 -8
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +1 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +2 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +8 -8
- data/src/java/arjdbc/mssql/MSSQLModule.java +50 -19
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +1 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +6 -6
- data/src/java/arjdbc/oracle/OracleModule.java +1 -1
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +66 -2
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +23 -10
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +1 -0
- data/src/java/arjdbc/util/CallResultSet.java +826 -0
- data/src/java/arjdbc/util/QuotingUtils.java +14 -7
- metadata +8 -3
- data/lib/arjdbc/postgresql/array_parser.rb +0 -89
@@ -24,8 +24,8 @@ module ArJdbc
|
|
24
24
|
require 'pg_array_parser'
|
25
25
|
include PgArrayParser
|
26
26
|
rescue LoadError
|
27
|
-
require 'arjdbc/postgresql/array_parser'
|
28
|
-
include ArrayParser
|
27
|
+
require 'arjdbc/postgresql/base/array_parser'
|
28
|
+
include ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser
|
29
29
|
end if AR4_COMPAT
|
30
30
|
|
31
31
|
include Cast
|
@@ -33,8 +33,21 @@ module ArJdbc
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
# @private
|
37
|
+
def oid_type
|
38
|
+
@oid_type ||= begin
|
39
|
+
raise "oid not defined" unless oid = (@oid ||= nil)
|
40
|
+
@adapter.get_oid_type(oid.to_i, @fmod.to_i, name)
|
41
|
+
end
|
42
|
+
end if AR4_COMPAT
|
43
|
+
|
44
|
+
def accessor; oid_type.accessor end if AR4_COMPAT
|
45
|
+
|
36
46
|
( attr_accessor :array; def array?; array; end ) if AR4_COMPAT
|
37
47
|
|
48
|
+
def number?; !array && super end if AR4_COMPAT
|
49
|
+
def text?; !array && super end if AR4_COMPAT
|
50
|
+
|
38
51
|
# Extracts the value from a PostgreSQL column default definition.
|
39
52
|
#
|
40
53
|
# @override JdbcColumn#default_value
|
@@ -354,7 +367,7 @@ module ArJdbc
|
|
354
367
|
when 'infinity' then 1.0 / 0.0
|
355
368
|
when '-infinity' then -1.0 / 0.0
|
356
369
|
when / BC$/
|
357
|
-
super("
|
370
|
+
super("-#{string.sub(/ BC$/, "")}")
|
358
371
|
else
|
359
372
|
super
|
360
373
|
end
|
@@ -376,9 +389,11 @@ module ArJdbc
|
|
376
389
|
end
|
377
390
|
end if AR4_COMPAT
|
378
391
|
|
379
|
-
def hstore_to_string(object)
|
392
|
+
def hstore_to_string(object, array_member = false)
|
380
393
|
if Hash === object
|
381
|
-
object.map { |k,v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
|
394
|
+
string = object.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
|
395
|
+
string = escape_hstore(string) if array_member
|
396
|
+
string
|
382
397
|
else
|
383
398
|
object
|
384
399
|
end
|
@@ -388,10 +403,10 @@ module ArJdbc
|
|
388
403
|
if string.nil?
|
389
404
|
nil
|
390
405
|
elsif String === string
|
391
|
-
Hash[string.scan(HstorePair).map { |k,v|
|
392
|
-
v = v.upcase == 'NULL' ? nil : v.gsub(
|
393
|
-
k = k.gsub(
|
394
|
-
[k,v]
|
406
|
+
Hash[string.scan(HstorePair).map { |k, v|
|
407
|
+
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
408
|
+
k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
409
|
+
[k, v]
|
395
410
|
}]
|
396
411
|
else
|
397
412
|
string
|
@@ -406,7 +421,7 @@ module ArJdbc
|
|
406
421
|
end
|
407
422
|
end
|
408
423
|
|
409
|
-
def array_to_string(value, column, adapter
|
424
|
+
def array_to_string(value, column, adapter)
|
410
425
|
casted_values = value.map do |val|
|
411
426
|
if String === val
|
412
427
|
if val == "NULL"
|
@@ -439,7 +454,11 @@ module ArJdbc
|
|
439
454
|
if string.nil?
|
440
455
|
nil
|
441
456
|
elsif String === string
|
442
|
-
|
457
|
+
begin
|
458
|
+
IPAddr.new(string)
|
459
|
+
rescue ArgumentError
|
460
|
+
nil
|
461
|
+
end
|
443
462
|
else
|
444
463
|
string
|
445
464
|
end
|
@@ -454,9 +473,9 @@ module ArJdbc
|
|
454
473
|
end
|
455
474
|
|
456
475
|
# @note Only used for default values - we get a "parsed" array from JDBC.
|
457
|
-
def string_to_array(string,
|
476
|
+
def string_to_array(string, column_or_oid)
|
458
477
|
return string unless String === string
|
459
|
-
parse_pg_array(string).map { |val|
|
478
|
+
parse_pg_array(string).map { |val| type_cast_array(column_or_oid, val) }
|
460
479
|
end
|
461
480
|
|
462
481
|
private
|
@@ -480,12 +499,28 @@ module ArJdbc
|
|
480
499
|
end
|
481
500
|
end
|
482
501
|
|
502
|
+
ARRAY_ESCAPE = "\\" * 2 * 2 # escape the backslash twice for PG arrays
|
503
|
+
|
483
504
|
def quote_and_escape(value)
|
484
505
|
case value
|
485
|
-
when "NULL"
|
506
|
+
when "NULL", Numeric
|
486
507
|
value
|
487
508
|
else
|
488
|
-
|
509
|
+
value = value.gsub(/\\/, ARRAY_ESCAPE)
|
510
|
+
value.gsub!(/"/,"\\\"")
|
511
|
+
"\"#{value}\""
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
def type_cast_array(oid, value)
|
516
|
+
if ::Array === value
|
517
|
+
value.map { |item| type_cast_array(oid, item) }
|
518
|
+
else
|
519
|
+
if oid.is_a?(Column)
|
520
|
+
oid.type_cast value, oid.type # column.type
|
521
|
+
else
|
522
|
+
oid.type_cast value
|
523
|
+
end
|
489
524
|
end
|
490
525
|
end
|
491
526
|
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'arjdbc/postgresql/base/oid' # 'active_record/connection_adapters/postgresql/oid'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module ArJdbc
|
5
|
+
module PostgreSQL
|
6
|
+
module OIDTypes
|
7
|
+
|
8
|
+
OID = ActiveRecord::ConnectionAdapters::PostgreSQL::OID
|
9
|
+
|
10
|
+
def get_oid_type(oid, fmod, column_name)
|
11
|
+
type_map.fetch(oid, fmod) {
|
12
|
+
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
13
|
+
type_map[oid] = OID::Identity.new
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
# @override
|
18
|
+
def enable_extension(name)
|
19
|
+
result = super(name)
|
20
|
+
@extensions = nil
|
21
|
+
reload_type_map
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
# @override
|
26
|
+
def disable_extension(name)
|
27
|
+
result = super(name)
|
28
|
+
@extensions = nil
|
29
|
+
reload_type_map
|
30
|
+
result
|
31
|
+
end
|
32
|
+
|
33
|
+
# @override
|
34
|
+
def extensions
|
35
|
+
@extensions ||= super
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
@@type_map_cache = {}
|
41
|
+
@@type_map_cache_lock = Mutex.new
|
42
|
+
|
43
|
+
# @private
|
44
|
+
class OID::TypeMap
|
45
|
+
def dup
|
46
|
+
dup = super # make sure @mapping is not shared
|
47
|
+
dup.instance_variable_set(:@mapping, @mapping.dup)
|
48
|
+
dup
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def type_map
|
53
|
+
# NOTE: our type_map is lazy since it's only used for `adapter.accessor`
|
54
|
+
@type_map ||= begin
|
55
|
+
if type_map = @@type_map_cache[ type_cache_key ]
|
56
|
+
type_map.dup
|
57
|
+
else
|
58
|
+
type_map = OID::TypeMap.new
|
59
|
+
initialize_type_map(type_map)
|
60
|
+
cache_type_map(type_map)
|
61
|
+
type_map
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def reload_type_map
|
67
|
+
if ( @type_map ||= nil )
|
68
|
+
@type_map.clear
|
69
|
+
initialize_type_map(@type_map)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def cache_type_map(type_map)
|
74
|
+
@@type_map_cache_lock.synchronize do
|
75
|
+
@@type_map_cache[ type_cache_key ] = type_map
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def type_cache_key
|
80
|
+
config.hash + ( 7 * extensions.hash )
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_oid(row, records_by_oid, type_map)
|
84
|
+
return type_map if type_map.key? row['type_elem'].to_i
|
85
|
+
|
86
|
+
if OID.registered_type? typname = row['typname']
|
87
|
+
# this composite type is explicitly registered
|
88
|
+
vector = OID::NAMES[ typname ]
|
89
|
+
else
|
90
|
+
# use the default for composite types
|
91
|
+
unless type_map.key? typelem = row['typelem'].to_i
|
92
|
+
add_oid records_by_oid[ row['typelem'] ], records_by_oid, type_map
|
93
|
+
end
|
94
|
+
|
95
|
+
vector = OID::Vector.new row['typdelim'], type_map[typelem]
|
96
|
+
end
|
97
|
+
|
98
|
+
type_map[ row['oid'].to_i ] = vector
|
99
|
+
type_map
|
100
|
+
end
|
101
|
+
|
102
|
+
def initialize_type_map(type_map)
|
103
|
+
result = execute('SELECT oid, typname, typelem, typdelim, typinput FROM pg_type', 'SCHEMA')
|
104
|
+
leaves, nodes = result.partition { |row| row['typelem'].to_s == '0' }
|
105
|
+
# populate the leaf nodes
|
106
|
+
leaves.find_all { |row| OID.registered_type? row['typname'] }.each do |row|
|
107
|
+
type_map[ row['oid'].to_i ] = OID::NAMES[ row['typname'] ]
|
108
|
+
end
|
109
|
+
|
110
|
+
records_by_oid = result.group_by { |row| row['oid'] }
|
111
|
+
|
112
|
+
arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' }
|
113
|
+
|
114
|
+
# populate composite types
|
115
|
+
nodes.each { |row| add_oid row, records_by_oid, type_map }
|
116
|
+
|
117
|
+
# populate array types
|
118
|
+
arrays.find_all { |row| type_map.key? row['typelem'].to_i }.each do |row|
|
119
|
+
array = OID::Array.new type_map[ row['typelem'].to_i ]
|
120
|
+
type_map[ row['oid'].to_i ] = array
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -20,8 +20,10 @@ module ArJdbc
|
|
20
20
|
# @override
|
21
21
|
def delete_database_files(config)
|
22
22
|
return unless db_base = database_base_name(config)
|
23
|
-
|
24
|
-
|
23
|
+
for suffix in [ '.h2,db', '.mv.db', '.lock.db', '.trace.db' ]
|
24
|
+
db_file = "#{db_base}#{suffix}"
|
25
|
+
File.delete(db_file) if File.exist?(db_file)
|
26
|
+
end
|
25
27
|
end
|
26
28
|
|
27
29
|
end
|
data/lib/arjdbc/version.rb
CHANGED
data/rakelib/02-test.rake
CHANGED
@@ -47,16 +47,6 @@ task 'test_appraisal_hint' do
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
desc "Run unit tests (not connecting to a DB)."
|
51
|
-
Rake::TestTask.new(:test_unit) do |test_task|
|
52
|
-
test_task.test_files = FileList["test/unit*_test.rb"] + FileList["test/unit/*_test.rb"]
|
53
|
-
test_task.libs << 'lib' if defined?(JRUBY_VERSION)
|
54
|
-
test_task.libs << 'test'
|
55
|
-
test_task.verbose = true if $VERBOSE
|
56
|
-
set_test_task_compat_version test_task
|
57
|
-
end
|
58
|
-
task :test_units => :test_unit # alias
|
59
|
-
|
60
50
|
Rake::TestTask.class_eval { attr_reader :test_files }
|
61
51
|
|
62
52
|
def test_task_for(adapter, options = {})
|
@@ -95,12 +85,14 @@ test_task_for :H2, :desc => 'Run tests against H2 database engine'
|
|
95
85
|
test_task_for :HSQLDB, :desc => 'Run tests against HyperSQL (Java) database'
|
96
86
|
test_task_for :MSSQL, :driver => :jtds, :database_name => 'MS-SQL (SQLServer)'
|
97
87
|
test_task_for :MySQL, :prereqs => 'db:mysql'
|
98
|
-
test_task_for :PostgreSQL, :
|
88
|
+
test_task_for :PostgreSQL, :driver => 'postgres', :prereqs => 'db:postgresql'
|
99
89
|
task :test_postgres => :test_postgresql # alias
|
100
90
|
test_task_for :SQLite3
|
101
91
|
task :test_sqlite => :test_sqlite3 # alias
|
102
92
|
test_task_for :Firebird
|
103
93
|
|
94
|
+
test_task_for :MariaDB, :prereqs => 'db:mysql', :files => FileList["test/db/mysql/*_test.rb"]
|
95
|
+
|
104
96
|
# ensure driver for these DBs is on your class-path
|
105
97
|
[ :Oracle, :DB2, :Informix, :CacheDB ].each do |adapter|
|
106
98
|
test_task_for adapter, :desc => "Run tests against #{adapter} (ensure driver is on class-path)"
|
@@ -136,22 +128,3 @@ end
|
|
136
128
|
#task :test_sybase_jtds => :test_sybase # alias
|
137
129
|
#test_task_for :Sybase, :name => 'sybase_jconnect',
|
138
130
|
# :desc => "Run tests against Sybase (ensure jConnect driver is on class-path)"
|
139
|
-
|
140
|
-
Rake::TraceOutput.module_eval do
|
141
|
-
|
142
|
-
# NOTE: avoid TypeError: String can't be coerced into Fixnum
|
143
|
-
# due this method getting some strings == [ 1 ] argument ...
|
144
|
-
def trace_on(out, *strings)
|
145
|
-
sep = $\ || "\n"
|
146
|
-
if strings.empty?
|
147
|
-
output = sep
|
148
|
-
else
|
149
|
-
output = strings.map { |s|
|
150
|
-
next if s.nil?; s = s.to_s
|
151
|
-
s =~ /#{sep}$/ ? s : s + sep
|
152
|
-
}.join
|
153
|
-
end
|
154
|
-
out.print(output)
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
@@ -171,14 +171,6 @@ public class DerbyModule {
|
|
171
171
|
return RubyString.newString(context.getRuntime(), BYTES_0);
|
172
172
|
}
|
173
173
|
|
174
|
-
private static RubyString quoteBoolean(final Ruby runtime, final IRubyObject value) {
|
175
|
-
return value.isTrue() ? runtime.newString(BYTES_1) : runtime.newString(BYTES_0);
|
176
|
-
}
|
177
|
-
|
178
|
-
private static boolean isMultibyteChars(final Ruby runtime, final IRubyObject value) {
|
179
|
-
return getMultibyteChars(runtime).isInstance(value);
|
180
|
-
}
|
181
|
-
|
182
174
|
private static RubyModule getMultibyteChars(final Ruby runtime) {
|
183
175
|
return (RubyModule) ((RubyModule) runtime.getModule("ActiveSupport").
|
184
176
|
getConstant("Multibyte")).getConstantAt("Chars");
|
@@ -46,6 +46,7 @@ import org.jruby.util.ByteList;
|
|
46
46
|
* @author kares
|
47
47
|
*/
|
48
48
|
public class DerbyRubyJdbcConnection extends RubyJdbcConnection {
|
49
|
+
private static final long serialVersionUID = 4809475910953623325L;
|
49
50
|
|
50
51
|
protected DerbyRubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
|
51
52
|
super(runtime, metaClass);
|
@@ -37,6 +37,8 @@ import org.jruby.runtime.builtin.IRubyObject;
|
|
37
37
|
* @author nicksieger
|
38
38
|
*/
|
39
39
|
public class H2RubyJdbcConnection extends RubyJdbcConnection {
|
40
|
+
private static final long serialVersionUID = -2652911264521657428L;
|
41
|
+
|
40
42
|
protected H2RubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
|
41
43
|
super(runtime, metaClass);
|
42
44
|
}
|
@@ -1300,7 +1300,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1300
1300
|
final boolean binary = // column.type == :binary
|
1301
1301
|
column.callMethod(context, "type").toString() == (Object) "binary";
|
1302
1302
|
|
1303
|
-
final
|
1303
|
+
final IRubyObject recordClass = record.callMethod(context, "class");
|
1304
1304
|
final IRubyObject adapter = recordClass.callMethod(context, "connection");
|
1305
1305
|
|
1306
1306
|
IRubyObject columnName = column.callMethod(context, "name");
|
@@ -1314,7 +1314,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1314
1314
|
|
1315
1315
|
final IRubyObject id = record.callMethod(context, "id"); // record.id
|
1316
1316
|
|
1317
|
-
int count = updateLobValue(context,
|
1317
|
+
final int count = updateLobValue(context,
|
1318
1318
|
tableName.toString(), columnName.toString(), column,
|
1319
1319
|
idKey.toString(), id, idColumn, value, binary
|
1320
1320
|
);
|
@@ -2860,12 +2860,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2860
2860
|
final Ruby runtime = context.getRuntime();
|
2861
2861
|
final IRubyObject jdbcColumn = getJdbcColumnClass(context);
|
2862
2862
|
|
2863
|
-
final List<String>
|
2863
|
+
final List<String> primaryKeyNames = new ArrayList<String>(4);
|
2864
2864
|
while ( primaryKeys.next() ) {
|
2865
|
-
|
2865
|
+
primaryKeyNames.add( primaryKeys.getString(COLUMN_NAME) );
|
2866
2866
|
}
|
2867
2867
|
|
2868
|
-
final
|
2868
|
+
final RubyArray columns = runtime.newArray();
|
2869
2869
|
final IRubyObject config = getInstanceVariable("@config");
|
2870
2870
|
while ( results.next() ) {
|
2871
2871
|
final String colName = results.getString(COLUMN_NAME);
|
@@ -2877,13 +2877,13 @@ public class RubyJdbcConnection extends RubyObject {
|
|
2877
2877
|
RubyString.newUnicodeString( runtime, typeFromResultSet(results) ),
|
2878
2878
|
runtime.newBoolean( ! results.getString(IS_NULLABLE).trim().equals("NO") )
|
2879
2879
|
});
|
2880
|
-
columns.
|
2880
|
+
columns.append(column);
|
2881
2881
|
|
2882
|
-
if (
|
2882
|
+
if ( primaryKeyNames.contains(colName) ) {
|
2883
2883
|
column.callMethod(context, "primary=", runtime.getTrue());
|
2884
2884
|
}
|
2885
2885
|
}
|
2886
|
-
return
|
2886
|
+
return columns;
|
2887
2887
|
}
|
2888
2888
|
|
2889
2889
|
protected IRubyObject mapGeneratedKeys(
|
@@ -25,47 +25,78 @@ package arjdbc.mssql;
|
|
25
25
|
|
26
26
|
import static arjdbc.util.QuotingUtils.BYTES_0;
|
27
27
|
import static arjdbc.util.QuotingUtils.BYTES_1;
|
28
|
+
import static arjdbc.util.QuotingUtils.quoteCharWith;
|
28
29
|
import static arjdbc.util.QuotingUtils.quoteSingleQuotesWithFallback;
|
29
30
|
|
30
31
|
import org.jruby.RubyModule;
|
31
32
|
import org.jruby.RubyString;
|
32
33
|
import org.jruby.anno.JRubyMethod;
|
33
34
|
import org.jruby.runtime.ThreadContext;
|
35
|
+
import org.jruby.runtime.Visibility;
|
34
36
|
import org.jruby.runtime.builtin.IRubyObject;
|
37
|
+
import org.jruby.util.ByteList;
|
35
38
|
|
36
39
|
/**
|
37
40
|
* ArJdbc::MSSQL
|
38
|
-
*
|
41
|
+
*
|
39
42
|
* @author kares
|
40
43
|
*/
|
41
44
|
public class MSSQLModule {
|
42
|
-
|
45
|
+
|
43
46
|
public static RubyModule load(final RubyModule arJdbc) {
|
44
47
|
RubyModule mssql = arJdbc.defineModuleUnder("MSSQL");
|
45
48
|
mssql.defineAnnotatedMethods( MSSQLModule.class );
|
46
49
|
return mssql;
|
47
50
|
}
|
48
|
-
|
49
|
-
@JRubyMethod(name = "quote_string", required = 1
|
50
|
-
public static IRubyObject quote_string(
|
51
|
-
|
52
|
-
final IRubyObject self,
|
53
|
-
final IRubyObject string) {
|
51
|
+
|
52
|
+
@JRubyMethod(name = "quote_string", required = 1)
|
53
|
+
public static IRubyObject quote_string(final ThreadContext context,
|
54
|
+
final IRubyObject self, final IRubyObject string) {
|
54
55
|
return quoteSingleQuotesWithFallback(context, string);
|
55
56
|
}
|
56
|
-
|
57
|
-
@JRubyMethod(name = "quoted_true", required = 0
|
58
|
-
public static IRubyObject quoted_true(
|
59
|
-
|
60
|
-
final IRubyObject self) {
|
57
|
+
|
58
|
+
@JRubyMethod(name = "quoted_true", required = 0)
|
59
|
+
public static IRubyObject quoted_true(final ThreadContext context,
|
60
|
+
final IRubyObject self) {
|
61
61
|
return RubyString.newString(context.getRuntime(), BYTES_1);
|
62
62
|
}
|
63
|
-
|
64
|
-
@JRubyMethod(name = "quoted_false", required = 0
|
65
|
-
public static IRubyObject quoted_false(
|
66
|
-
|
67
|
-
final IRubyObject self) {
|
63
|
+
|
64
|
+
@JRubyMethod(name = "quoted_false", required = 0)
|
65
|
+
public static IRubyObject quoted_false(final ThreadContext context,
|
66
|
+
final IRubyObject self) {
|
68
67
|
return RubyString.newString(context.getRuntime(), BYTES_0);
|
69
68
|
}
|
70
|
-
|
69
|
+
|
70
|
+
// part =~ /^\[.*\]$/ ? part : "[#{part.gsub(']', ']]')}]"
|
71
|
+
@SuppressWarnings("deprecation")
|
72
|
+
@JRubyMethod(required = 1, visibility = Visibility.PRIVATE)
|
73
|
+
public static IRubyObject quote_name_part(final ThreadContext context,
|
74
|
+
final IRubyObject self, final IRubyObject part) {
|
75
|
+
|
76
|
+
final RubyString partString = ((RubyString) part);
|
77
|
+
final ByteList str = partString.getByteList();
|
78
|
+
if ( str.charAt(0) == '[' && str.charAt(str.length() - 1) == ']' ) {
|
79
|
+
return part; // part =~ /^\[.*\]$/ ? part
|
80
|
+
}
|
81
|
+
final RubyString quotedString = // part.gsub(']', ']]')
|
82
|
+
quoteCharWith(context, partString, ']', ']', 1, 4 + 1);
|
83
|
+
if ( quotedString == partString ) {
|
84
|
+
final int realSize = str.getRealSize();
|
85
|
+
final ByteList quoted = new ByteList(
|
86
|
+
new byte[realSize + 2], partString.getEncoding(), false
|
87
|
+
);
|
88
|
+
quoted.begin = 0; quoted.realSize = 0;
|
89
|
+
quoted.append('[');
|
90
|
+
quoted.append(str.unsafeBytes(), str.getBegin(), realSize);
|
91
|
+
quoted.append(']');
|
92
|
+
return context.getRuntime().newString(quoted);
|
93
|
+
}
|
94
|
+
// we got a new string with a reserve of 1 byte front and back :
|
95
|
+
final ByteList quoted = quotedString.getByteList();
|
96
|
+
quoted.begin = 0; // setBegin invalidates
|
97
|
+
quoted.bytes[0] = '['; quoted.realSize++;
|
98
|
+
quoted.append(']');
|
99
|
+
return quotedString;
|
100
|
+
}
|
101
|
+
|
71
102
|
}
|