sequel 3.29.0 → 3.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/CHANGELOG +35 -3
  2. data/Rakefile +2 -1
  3. data/doc/association_basics.rdoc +11 -0
  4. data/doc/opening_databases.rdoc +2 -0
  5. data/doc/release_notes/3.30.0.txt +135 -0
  6. data/doc/testing.rdoc +17 -3
  7. data/lib/sequel/adapters/amalgalite.rb +2 -2
  8. data/lib/sequel/adapters/do/mysql.rb +5 -2
  9. data/lib/sequel/adapters/ibmdb.rb +2 -2
  10. data/lib/sequel/adapters/jdbc.rb +126 -43
  11. data/lib/sequel/adapters/jdbc/as400.rb +11 -3
  12. data/lib/sequel/adapters/jdbc/db2.rb +2 -1
  13. data/lib/sequel/adapters/jdbc/derby.rb +44 -19
  14. data/lib/sequel/adapters/jdbc/h2.rb +32 -19
  15. data/lib/sequel/adapters/jdbc/hsqldb.rb +21 -17
  16. data/lib/sequel/adapters/jdbc/jtds.rb +9 -4
  17. data/lib/sequel/adapters/jdbc/mssql.rb +3 -1
  18. data/lib/sequel/adapters/jdbc/mysql.rb +2 -1
  19. data/lib/sequel/adapters/jdbc/oracle.rb +21 -7
  20. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
  21. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -1
  22. data/lib/sequel/adapters/jdbc/sqlserver.rb +48 -18
  23. data/lib/sequel/adapters/mock.rb +2 -1
  24. data/lib/sequel/adapters/mysql.rb +4 -2
  25. data/lib/sequel/adapters/mysql2.rb +2 -2
  26. data/lib/sequel/adapters/odbc/mssql.rb +1 -1
  27. data/lib/sequel/adapters/openbase.rb +1 -1
  28. data/lib/sequel/adapters/oracle.rb +6 -6
  29. data/lib/sequel/adapters/postgres.rb +25 -12
  30. data/lib/sequel/adapters/shared/access.rb +14 -6
  31. data/lib/sequel/adapters/shared/db2.rb +36 -13
  32. data/lib/sequel/adapters/shared/firebird.rb +12 -5
  33. data/lib/sequel/adapters/shared/informix.rb +11 -3
  34. data/lib/sequel/adapters/shared/mssql.rb +94 -47
  35. data/lib/sequel/adapters/shared/mysql.rb +107 -49
  36. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +2 -2
  37. data/lib/sequel/adapters/shared/oracle.rb +54 -27
  38. data/lib/sequel/adapters/shared/postgres.rb +65 -26
  39. data/lib/sequel/adapters/shared/progress.rb +4 -1
  40. data/lib/sequel/adapters/shared/sqlite.rb +36 -20
  41. data/lib/sequel/adapters/sqlite.rb +2 -3
  42. data/lib/sequel/adapters/swift/mysql.rb +3 -2
  43. data/lib/sequel/adapters/swift/sqlite.rb +2 -2
  44. data/lib/sequel/adapters/tinytds.rb +14 -8
  45. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -4
  46. data/lib/sequel/database/misc.rb +6 -2
  47. data/lib/sequel/dataset/graph.rb +33 -7
  48. data/lib/sequel/dataset/prepared_statements.rb +19 -5
  49. data/lib/sequel/dataset/sql.rb +611 -201
  50. data/lib/sequel/model/associations.rb +12 -5
  51. data/lib/sequel/model/base.rb +20 -5
  52. data/lib/sequel/plugins/sharding.rb +9 -29
  53. data/lib/sequel/sql.rb +2 -1
  54. data/lib/sequel/timezones.rb +14 -4
  55. data/lib/sequel/version.rb +1 -1
  56. data/spec/adapters/mysql_spec.rb +10 -0
  57. data/spec/adapters/oracle_spec.rb +1 -1
  58. data/spec/core/core_sql_spec.rb +3 -1
  59. data/spec/core/database_spec.rb +42 -0
  60. data/spec/core/dataset_spec.rb +10 -3
  61. data/spec/core/mock_adapter_spec.rb +4 -0
  62. data/spec/core/object_graph_spec.rb +38 -0
  63. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  64. data/spec/extensions/association_dependencies_spec.rb +2 -12
  65. data/spec/extensions/association_pks_spec.rb +35 -39
  66. data/spec/extensions/caching_spec.rb +23 -50
  67. data/spec/extensions/class_table_inheritance_spec.rb +30 -82
  68. data/spec/extensions/composition_spec.rb +18 -13
  69. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  70. data/spec/extensions/identity_map_spec.rb +33 -103
  71. data/spec/extensions/instance_filters_spec.rb +10 -21
  72. data/spec/extensions/instance_hooks_spec.rb +6 -24
  73. data/spec/extensions/json_serializer_spec.rb +4 -5
  74. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  75. data/spec/extensions/list_spec.rb +17 -39
  76. data/spec/extensions/many_through_many_spec.rb +135 -277
  77. data/spec/extensions/migration_spec.rb +18 -15
  78. data/spec/extensions/named_timezones_spec.rb +1 -1
  79. data/spec/extensions/nested_attributes_spec.rb +97 -92
  80. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  81. data/spec/extensions/prepared_statements_associations_spec.rb +22 -37
  82. data/spec/extensions/prepared_statements_safe_spec.rb +9 -27
  83. data/spec/extensions/prepared_statements_spec.rb +11 -30
  84. data/spec/extensions/prepared_statements_with_pk_spec.rb +6 -13
  85. data/spec/extensions/pretty_table_spec.rb +1 -6
  86. data/spec/extensions/rcte_tree_spec.rb +41 -43
  87. data/spec/extensions/schema_dumper_spec.rb +3 -6
  88. data/spec/extensions/serialization_spec.rb +20 -32
  89. data/spec/extensions/sharding_spec.rb +66 -140
  90. data/spec/extensions/single_table_inheritance_spec.rb +14 -36
  91. data/spec/extensions/spec_helper.rb +10 -64
  92. data/spec/extensions/sql_expr_spec.rb +20 -60
  93. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  94. data/spec/extensions/timestamps_spec.rb +6 -6
  95. data/spec/extensions/to_dot_spec.rb +1 -2
  96. data/spec/extensions/touch_spec.rb +13 -14
  97. data/spec/extensions/tree_spec.rb +11 -26
  98. data/spec/extensions/update_primary_key_spec.rb +30 -24
  99. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  100. data/spec/extensions/validation_helpers_spec.rb +16 -35
  101. data/spec/integration/dataset_test.rb +16 -4
  102. data/spec/integration/prepared_statement_test.rb +4 -2
  103. data/spec/model/eager_loading_spec.rb +16 -0
  104. data/spec/model/model_spec.rb +15 -1
  105. data/spec/model/record_spec.rb +60 -0
  106. metadata +23 -40
@@ -39,6 +39,9 @@ module Sequel
39
39
  # Dataset class for AS400 datasets accessed via JDBC.
40
40
  class Dataset < JDBC::Dataset
41
41
  WILDCARD = Sequel::LiteralString.new('*').freeze
42
+ FETCH_FIRST_ROW_ONLY = " FETCH FIRST ROW ONLY".freeze
43
+ FETCH_FIRST = " FETCH FIRST ".freeze
44
+ ROWS_ONLY = " ROWS ONLY".freeze
42
45
 
43
46
  # AS400 needs to use a couple of subselects for queries with offsets.
44
47
  def select_sql
@@ -60,9 +63,14 @@ module Sequel
60
63
 
61
64
  # Modify the sql to limit the number of rows returned
62
65
  def select_limit_sql(sql)
63
- if @opts[:limit]
64
- sql << " FETCH FIRST ROW ONLY" if @opts[:limit] == 1
65
- sql << " FETCH FIRST #{@opts[:limit]} ROWS ONLY" if @opts[:limit] > 1
66
+ if l = @opts[:limit]
67
+ if l == 1
68
+ sql << FETCH_FIRST_ROW_ONLY
69
+ elsif l > 1
70
+ sql << FETCH_FIRST
71
+ literal_append(sql, l)
72
+ sql << ROWS_ONLY
73
+ end
66
74
  end
67
75
  end
68
76
 
@@ -18,6 +18,7 @@ module Sequel
18
18
  module DatabaseMethods
19
19
  include Sequel::DB2::DatabaseMethods
20
20
  include Sequel::JDBC::Transactions
21
+ IDENTITY_VAL_LOCAL = "SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1".freeze
21
22
 
22
23
  %w'schema_parse_table tables views indexes'.each do |s|
23
24
  class_eval("def #{s}(*a) jdbc_#{s}(*a) end", __FILE__, __LINE__)
@@ -27,7 +28,7 @@ module Sequel
27
28
 
28
29
  def last_insert_id(conn, opts={})
29
30
  statement(conn) do |stmt|
30
- sql = "SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1"
31
+ sql = IDENTITY_VAL_LOCAL
31
32
  rs = log_yield(sql){stmt.executeQuery(sql)}
32
33
  rs.next
33
34
  rs.getInt(1)
@@ -104,17 +104,31 @@ module Sequel
104
104
 
105
105
  # Dataset class for Derby datasets accessed via JDBC.
106
106
  class Dataset < JDBC::Dataset
107
+ PAREN_CLOSE = Dataset::PAREN_CLOSE
108
+ PAREN_OPEN = Dataset::PAREN_OPEN
109
+ OFFSET = Dataset::OFFSET
110
+ CAST_STRING_OPEN = "RTRIM(".freeze
111
+ BITCOMP_OPEN = "((0 - ".freeze
112
+ BITCOMP_CLOSE = ") - 1)".freeze
113
+ BLOB_OPEN = "CAST(X'".freeze
114
+ BLOB_CLOSE = "' AS BLOB)".freeze
115
+ HSTAR = "H*".freeze
116
+ TIME_FORMAT = "'%H:%M:%S'".freeze
117
+ DEFAULT_FROM = " FROM sysibm.sysdummy1".freeze
118
+ ROWS = " ROWS".freeze
119
+ FETCH_FIRST = " FETCH FIRST ".freeze
120
+ ROWS_ONLY = " ROWS ONLY".freeze
107
121
  BOOL_TRUE = '(1 = 1)'.freeze
108
122
  BOOL_FALSE = '(1 = 0)'.freeze
109
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit lock')
123
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
110
124
 
111
125
  # Derby doesn't support an expression between CASE and WHEN,
112
126
  # so emulate it by using an equality statement for all of the
113
127
  # conditions.
114
- def case_expression_sql(ce)
128
+ def case_expression_sql_append(sql, ce)
115
129
  if ce.expression?
116
130
  e = ce.expression
117
- literal(::Sequel::SQL::CaseExpression.new(ce.conditions.map{|c, r| [::Sequel::SQL::BooleanExpression.new(:'=', e, c), r]}, ce.default))
131
+ case_expression_sql_append(sql, ::Sequel::SQL::CaseExpression.new(ce.conditions.map{|c, r| [::Sequel::SQL::BooleanExpression.new(:'=', e, c), r]}, ce.default))
118
132
  else
119
133
  super
120
134
  end
@@ -123,27 +137,33 @@ module Sequel
123
137
  # If the type is String, trim the extra spaces since CHAR is used instead
124
138
  # of varchar. This can cause problems if you are casting a char/varchar to
125
139
  # a string and the ending whitespace is important.
126
- def cast_sql(expr, type)
140
+ def cast_sql_append(sql, expr, type)
127
141
  if type == String
128
- "RTRIM(#{super})"
142
+ sql << CAST_STRING_OPEN
143
+ super
144
+ sql << PAREN_CLOSE
129
145
  else
130
146
  super
131
147
  end
132
148
  end
133
149
 
134
150
  # Handle Derby specific LIKE, extract, and some bitwise compliment support.
135
- def complex_expression_sql(op, args)
151
+ def complex_expression_sql_append(sql, op, args)
136
152
  case op
137
153
  when :ILIKE
138
- super(:LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1)) ])
154
+ super(sql, :LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
139
155
  when :"NOT ILIKE"
140
- super(:"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1)) ])
156
+ super(sql, :"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
141
157
  when :&, :|, :^, :<<, :>>
142
158
  raise Error, "Derby doesn't support the #{op} operator"
143
159
  when :'B~'
144
- "((0 - #{literal(args.at(0))}) - 1)"
160
+ sql << BITCOMP_OPEN
161
+ literal_append(sql, args.at(0))
162
+ sql << BITCOMP_CLOSE
145
163
  when :extract
146
- "#{args.at(0)}(#{literal(args.at(1))})"
164
+ sql << args.at(0).to_s << PAREN_OPEN
165
+ literal_append(sql, args.at(1))
166
+ sql << PAREN_CLOSE
147
167
  else
148
168
  super
149
169
  end
@@ -162,11 +182,8 @@ module Sequel
162
182
  private
163
183
 
164
184
  # Derby needs a hex string casted to BLOB for blobs.
165
- def literal_blob(v)
166
- blob = "CAST(X'"
167
- v.each_byte{|x| blob << sprintf('%02x', x)}
168
- blob << "' AS BLOB)"
169
- blob
185
+ def literal_blob_append(sql, v)
186
+ sql << BLOB_OPEN << v.unpack(HSTAR).first << BLOB_CLOSE
170
187
  end
171
188
 
172
189
  # Derby needs the standard workaround to insert all default values into
@@ -183,7 +200,7 @@ module Sequel
183
200
 
184
201
  # Derby handles fractional seconds in timestamps, but not in times
185
202
  def literal_sqltime(v)
186
- v.strftime("'%H:%M:%S'")
203
+ v.strftime(TIME_FORMAT)
187
204
  end
188
205
 
189
206
  # Derby uses an expression yielding true for true values.
@@ -202,14 +219,22 @@ module Sequel
202
219
  if @opts[:from]
203
220
  super
204
221
  else
205
- sql << " FROM sysibm.sysdummy1"
222
+ sql << DEFAULT_FROM
206
223
  end
207
224
  end
208
225
 
209
226
  # Offset comes before limit in Derby
210
227
  def select_limit_sql(sql)
211
- sql << " OFFSET #{literal(@opts[:offset])} ROWS" if @opts[:offset]
212
- sql << " FETCH FIRST #{literal(@opts[:limit])} ROWS ONLY" if @opts[:limit]
228
+ if o = @opts[:offset]
229
+ sql << OFFSET
230
+ literal_append(sql, o)
231
+ sql << ROWS
232
+ end
233
+ if l = @opts[:limit]
234
+ sql << FETCH_FIRST
235
+ literal_append(sql, l)
236
+ sql << ROWS_ONLY
237
+ end
213
238
  end
214
239
  end
215
240
  end
@@ -104,26 +104,32 @@ module Sequel
104
104
 
105
105
  # Dataset class for H2 datasets accessed via JDBC.
106
106
  class Dataset < JDBC::Dataset
107
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit')
107
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit')
108
108
  BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
109
+ APOS = Dataset::APOS
110
+ HSTAR = "H*".freeze
111
+ BITCOMP_OPEN = "((0 - ".freeze
112
+ BITCOMP_CLOSE = ") - 1)".freeze
113
+ ILIKE_PLACEHOLDER = "CAST(? AS VARCHAR_IGNORECASE)".freeze
114
+ TIME_FORMAT = "'%H:%M:%S'".freeze
109
115
 
110
116
  # Emulate the case insensitive LIKE operator and the bitwise operators.
111
- def complex_expression_sql(op, args)
117
+ def complex_expression_sql_append(sql, op, args)
112
118
  case op
113
- when :ILIKE
114
- super(:LIKE, [SQL::PlaceholderLiteralString.new("CAST(? AS VARCHAR_IGNORECASE)", [args.at(0)]), args.at(1)])
115
- when :"NOT ILIKE"
116
- super(:"NOT LIKE", [SQL::PlaceholderLiteralString.new("CAST(? AS VARCHAR_IGNORECASE)", [args.at(0)]), args.at(1)])
119
+ when :ILIKE, :"NOT ILIKE"
120
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::PlaceholderLiteralString.new(ILIKE_PLACEHOLDER, [args.at(0)]), args.at(1)])
117
121
  when :&, :|, :^
118
- complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(BITWISE_METHOD_MAP[op], a, b))}
122
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(BITWISE_METHOD_MAP[op], a, b))}
119
123
  when :<<
120
- complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
124
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
121
125
  when :>>
122
- complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
126
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
123
127
  when :'B~'
124
- "((0 - #{literal(args.at(0))}) - 1)"
128
+ sql << BITCOMP_OPEN
129
+ literal_append(sql, args.at(0))
130
+ sql << BITCOMP_CLOSE
125
131
  else
126
- super(op, args)
132
+ super
127
133
  end
128
134
  end
129
135
 
@@ -148,25 +154,32 @@ module Sequel
148
154
  end
149
155
 
150
156
  private
157
+
158
+ #JAVA_H2_CLOB = Java::OrgH2Jdbc::JdbcClob
159
+
160
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
161
+ def h2_clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
162
+ end
163
+
164
+ H2_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:h2_clob)
151
165
 
152
166
  # Handle H2 specific clobs as strings.
153
- def convert_type(v)
154
- case v
155
- when Java::OrgH2Jdbc::JdbcClob
156
- convert_type(v.getSubString(1, v.length))
167
+ def convert_type_proc(v)
168
+ if v.is_a?(Java::OrgH2Jdbc::JdbcClob)
169
+ H2_CLOB_METHOD
157
170
  else
158
- super(v)
171
+ super
159
172
  end
160
173
  end
161
174
 
162
175
  # H2 expects hexadecimal strings for blob values
163
- def literal_blob(v)
164
- literal_string v.unpack("H*").first
176
+ def literal_blob_append(sql, v)
177
+ sql << APOS << v.unpack(HSTAR).first << APOS
165
178
  end
166
179
 
167
180
  # H2 handles fractional seconds in timestamps, but not in times
168
181
  def literal_sqltime(v)
169
- v.strftime("'%H:%M:%S'")
182
+ v.strftime(TIME_FORMAT)
170
183
  end
171
184
 
172
185
  def select_clause_methods
@@ -83,25 +83,32 @@ module Sequel
83
83
  # CTEs in earlier queries might take precedence over CTEs with the same name in later queries.
84
84
  # Also, if any CTE is recursive, all CTEs must be recursive.
85
85
  # If you want to use CTEs with HSQLDB, you'll have to manually modify the dataset to allow it.
86
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit lock')
86
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
87
87
  SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
88
+ APOS = Dataset::APOS
89
+ HSTAR = "H*".freeze
90
+ BLOB_OPEN = "X'".freeze
91
+ BITCOMP_OPEN = "((0 - ".freeze
92
+ BITCOMP_CLOSE = ") - 1)".freeze
93
+ DEFAULT_FROM = " FROM (VALUES (0))".freeze
94
+ TIME_FORMAT = "'%H:%M:%S'".freeze
88
95
 
89
96
  # Handle HSQLDB specific case insensitive LIKE and bitwise operator support.
90
- def complex_expression_sql(op, args)
97
+ def complex_expression_sql_append(sql, op, args)
91
98
  case op
92
- when :ILIKE
93
- super(:LIKE, [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
94
- when :"NOT ILIKE"
95
- super(:"NOT LIKE", [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
99
+ when :ILIKE, :"NOT ILIKE"
100
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
96
101
  when :&, :|, :^
97
102
  op = BITWISE_METHOD_MAP[op]
98
- complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
103
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
99
104
  when :<<
100
- complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
105
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
101
106
  when :>>
102
- complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
107
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
103
108
  when :'B~'
104
- "((0 - #{literal(args.at(0))}) - 1)"
109
+ sql << BITCOMP_OPEN
110
+ literal_append(sql, args.at(0))
111
+ sql << BITCOMP_CLOSE
105
112
  else
106
113
  super
107
114
  end
@@ -120,11 +127,8 @@ module Sequel
120
127
  private
121
128
 
122
129
  # Use string in hex format for blob data.
123
- def literal_blob(v)
124
- blob = "X'"
125
- v.each_byte{|x| blob << sprintf('%02x', x)}
126
- blob << "'"
127
- blob
130
+ def literal_blob_append(sql, v)
131
+ sql << BLOB_OPEN << v.unpack(HSTAR).first << APOS
128
132
  end
129
133
 
130
134
  # HSQLDB uses FALSE for false values.
@@ -134,7 +138,7 @@ module Sequel
134
138
 
135
139
  # HSQLDB handles fractional seconds in timestamps, but not in times
136
140
  def literal_sqltime(v)
137
- v.strftime("'%H:%M:%S'")
141
+ v.strftime(TIME_FORMAT)
138
142
  end
139
143
 
140
144
  # HSQLDB uses TRUE for true values.
@@ -152,7 +156,7 @@ module Sequel
152
156
  if @opts[:from]
153
157
  super
154
158
  else
155
- sql << " FROM (VALUES (0))"
159
+ sql << DEFAULT_FROM
156
160
  end
157
161
  end
158
162
 
@@ -14,11 +14,16 @@ module Sequel
14
14
  class Dataset < JDBC::Dataset
15
15
  include Sequel::MSSQL::DatasetMethods
16
16
 
17
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
18
+ def jtds_clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
19
+ end
20
+
21
+ JTDS_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:jtds_clob)
22
+
17
23
  # Handle CLOB types retrieved via JTDS.
18
- def convert_type(v)
19
- case v
20
- when Java::NetSourceforgeJtdsJdbc::ClobImpl
21
- convert_type(v.getSubString(1, v.length))
24
+ def convert_type_proc(v)
25
+ if v.is_a?(Java::NetSourceforgeJtdsJdbc::ClobImpl)
26
+ JTDS_CLOB_METHOD
22
27
  else
23
28
  super
24
29
  end
@@ -13,6 +13,8 @@ module Sequel
13
13
  # Database instance methods for MSSQL databases accessed via JDBC.
14
14
  module DatabaseMethods
15
15
  PRIMARY_KEY_INDEX_RE = /\Apk__/i.freeze
16
+ ATAT_IDENTITY = 'SELECT @@IDENTITY'.freeze
17
+ SCOPE_IDENTITY = 'SELECT SCOPE_IDENTITY()'.freeze
16
18
 
17
19
  include Sequel::MSSQL::DatabaseMethods
18
20
 
@@ -21,7 +23,7 @@ module Sequel
21
23
  # Get the last inserted id using SCOPE_IDENTITY().
22
24
  def last_insert_id(conn, opts={})
23
25
  statement(conn) do |stmt|
24
- sql = opts[:prepared] ? 'SELECT @@IDENTITY' : 'SELECT SCOPE_IDENTITY()'
26
+ sql = opts[:prepared] ? ATAT_IDENTITY : SCOPE_IDENTITY
25
27
  rs = log_yield(sql){stmt.executeQuery(sql)}
26
28
  rs.next
27
29
  rs.getInt(1)
@@ -8,6 +8,7 @@ module Sequel
8
8
  # Database instance methods for MySQL databases accessed via JDBC.
9
9
  module DatabaseMethods
10
10
  include Sequel::MySQL::DatabaseMethods
11
+ LAST_INSERT_ID = 'SELECT LAST_INSERT_ID()'.freeze
11
12
 
12
13
  private
13
14
 
@@ -34,7 +35,7 @@ module Sequel
34
35
  end
35
36
  else
36
37
  statement(conn) do |stmt|
37
- rs = stmt.executeQuery('SELECT LAST_INSERT_ID()')
38
+ rs = stmt.executeQuery(LAST_INSERT_ID)
38
39
  rs.next
39
40
  rs.getInt(1)
40
41
  end
@@ -67,21 +67,35 @@ module Sequel
67
67
 
68
68
  private
69
69
 
70
- def convert_type(v)
71
- case v
72
- when Java::JavaMath::BigDecimal
70
+ JAVA_BIG_DECIMAL = ::Sequel::JDBC::Dataset::JAVA_BIG_DECIMAL
71
+
72
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
73
+ def oracle_decimal(v)
73
74
  if v.scale == 0
74
75
  i = v.long_value
75
- if v.equals(Java::JavaMath::BigDecimal.new(i))
76
+ if v.equals(JAVA_BIG_DECIMAL.new(i))
76
77
  i
77
78
  else
78
- super
79
+ decimal(v)
79
80
  end
80
81
  else
81
- super
82
+ decimal(v)
82
83
  end
84
+ end
85
+ end
86
+
87
+ ORACLE_DECIMAL_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:oracle_decimal)
88
+
89
+ def convert_type_oracle_timestamp(v)
90
+ db.to_application_timestamp(v.to_string)
91
+ end
92
+
93
+ def convert_type_proc(v)
94
+ case v
95
+ when JAVA_BIG_DECIMAL
96
+ ORACLE_DECIMAL_METHOD
83
97
  when Java::OracleSql::TIMESTAMP
84
- db.to_application_timestamp(v.to_string)
98
+ method(:convert_type_oracle_timestamp)
85
99
  else
86
100
  super
87
101
  end
@@ -73,6 +73,7 @@ module Sequel
73
73
  # Dataset subclass used for datasets that connect to PostgreSQL via JDBC.
74
74
  class Dataset < JDBC::Dataset
75
75
  include Sequel::Postgres::DatasetMethods
76
+ APOS = Dataset::APOS
76
77
 
77
78
  # Add the shared PostgreSQL prepared statement methods
78
79
  def prepare(*args)
@@ -82,8 +83,8 @@ module Sequel
82
83
  end
83
84
 
84
85
  # Literalize strings similar to the native postgres adapter
85
- def literal_string(v)
86
- db.synchronize{|c| "'#{c.escape_string(v)}'"}
86
+ def literal_string_append(sql, v)
87
+ sql << APOS << db.synchronize{|c| c.escape_string(v)} << APOS
87
88
  end
88
89
  end
89
90
  end
@@ -7,13 +7,14 @@ module Sequel
7
7
  # Instance methods for SQLite Database objects accessed via JDBC.
8
8
  module DatabaseMethods
9
9
  include Sequel::SQLite::DatabaseMethods
10
+ LAST_INSERT_ROWID = 'SELECT last_insert_rowid()'.freeze
10
11
 
11
12
  private
12
13
 
13
14
  # Use last_insert_rowid() to get the last inserted id.
14
15
  def last_insert_id(conn, opts={})
15
16
  statement(conn) do |stmt|
16
- rs = stmt.executeQuery('SELECT last_insert_rowid()')
17
+ rs = stmt.executeQuery(LAST_INSERT_ROWID)
17
18
  rs.next
18
19
  rs.getInt(1)
19
20
  end