sequel 3.21.0 → 3.31.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/CHANGELOG +485 -3
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/association_basics.rdoc +249 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +89 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +45 -0
- data/lib/sequel/adapters/jdbc/derby.rb +247 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +56 -29
- data/lib/sequel/adapters/jdbc/hsqldb.rb +170 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +81 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +335 -0
- data/lib/sequel/adapters/mysql.rb +82 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +351 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +321 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +231 -106
- data/lib/sequel/adapters/shared/mysql.rb +181 -63
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +231 -41
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +4 -7
- data/lib/sequel/adapters/shared/sqlite.rb +201 -57
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +46 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +104 -19
- data/lib/sequel/database/query.rb +153 -58
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +231 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +5 -6
- data/lib/sequel/dataset/prepared_statements.rb +48 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +665 -253
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1020 -337
- data/lib/sequel/model/base.rb +414 -132
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +15 -8
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +65 -7
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +88 -44
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +111 -29
- data/spec/adapters/mysql_spec.rb +135 -123
- data/spec/adapters/oracle_spec.rb +49 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +21 -30
- data/spec/core/database_spec.rb +788 -512
- data/spec/core/dataset_spec.rb +1073 -1053
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
- data/spec/extensions/serialization_spec.rb +72 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +537 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +461 -65
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +304 -116
- data/spec/integration/prepared_statement_test.rb +212 -122
- data/spec/integration/schema_test.rb +161 -30
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +172 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +865 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +309 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +115 -73
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
Sequel.require 'adapters/utils/emulate_offset_with_row_number'
|
|
2
|
+
|
|
1
3
|
module Sequel
|
|
2
4
|
module Oracle
|
|
3
5
|
module DatabaseMethods
|
|
4
6
|
TEMPORARY = 'GLOBAL TEMPORARY '.freeze
|
|
5
7
|
AUTOINCREMENT = ''.freeze
|
|
6
8
|
|
|
9
|
+
attr_accessor :autosequence
|
|
10
|
+
|
|
7
11
|
def create_sequence(name, opts={})
|
|
8
12
|
self << create_sequence_sql(name, opts)
|
|
9
13
|
end
|
|
@@ -12,6 +16,10 @@ module Sequel
|
|
|
12
16
|
self << create_trigger_sql(*args)
|
|
13
17
|
end
|
|
14
18
|
|
|
19
|
+
def current_user
|
|
20
|
+
@current_user ||= get{sys_context('USERENV', 'CURRENT_USER')}
|
|
21
|
+
end
|
|
22
|
+
|
|
15
23
|
def drop_sequence(name)
|
|
16
24
|
self << drop_sequence_sql(name)
|
|
17
25
|
end
|
|
@@ -26,10 +34,6 @@ module Sequel
|
|
|
26
34
|
ds.map{|r| ds.send(:output_identifier, r[:tname])}
|
|
27
35
|
end
|
|
28
36
|
|
|
29
|
-
def table_exists?(name)
|
|
30
|
-
from(:tab).filter(:tname =>dataset.send(:input_identifier, name), :tabtype => 'TABLE').count > 0
|
|
31
|
-
end
|
|
32
|
-
|
|
33
37
|
def views(opts={})
|
|
34
38
|
ds = from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'VIEW')
|
|
35
39
|
ds.map{|r| ds.send(:output_identifier, r[:tname])}
|
|
@@ -41,13 +45,37 @@ module Sequel
|
|
|
41
45
|
|
|
42
46
|
private
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
# Handle Oracle specific ALTER TABLE SQL
|
|
49
|
+
def alter_table_sql(table, op)
|
|
50
|
+
case op[:op]
|
|
51
|
+
when :add_column
|
|
52
|
+
if op[:primary_key]
|
|
53
|
+
sqls = []
|
|
54
|
+
sqls << alter_table_sql(table, op.merge(:primary_key=>nil))
|
|
55
|
+
if op[:auto_increment]
|
|
56
|
+
seq_name = default_sequence_name(table, op[:name])
|
|
57
|
+
sqls << drop_sequence_sql(seq_name)
|
|
58
|
+
sqls << create_sequence_sql(seq_name, op)
|
|
59
|
+
sqls << "UPDATE #{quote_schema_table(table)} SET #{quote_identifier(op[:name])} = #{seq_name}.nextval"
|
|
60
|
+
end
|
|
61
|
+
sqls << "ALTER TABLE #{quote_schema_table(table)} ADD PRIMARY KEY (#{quote_identifier(op[:name])})"
|
|
62
|
+
sqls
|
|
63
|
+
else
|
|
64
|
+
"ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
|
|
65
|
+
end
|
|
66
|
+
when :set_column_null
|
|
67
|
+
"ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} #{op[:null] ? 'NULL' : 'NOT NULL'}"
|
|
68
|
+
when :set_column_type
|
|
69
|
+
"ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} #{type_literal(op)}"
|
|
70
|
+
when :set_column_default
|
|
71
|
+
"ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} DEFAULT #{literal(op[:default])}"
|
|
72
|
+
else
|
|
73
|
+
super(table, op)
|
|
74
|
+
end
|
|
46
75
|
end
|
|
47
76
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
TEMPORARY
|
|
77
|
+
def auto_increment_sql
|
|
78
|
+
AUTOINCREMENT
|
|
51
79
|
end
|
|
52
80
|
|
|
53
81
|
def create_sequence_sql(name, opts={})
|
|
@@ -65,7 +93,7 @@ module Sequel
|
|
|
65
93
|
drop_seq_statement = nil
|
|
66
94
|
generator.columns.each do |c|
|
|
67
95
|
if c[:auto_increment]
|
|
68
|
-
c[:sequence_name] ||=
|
|
96
|
+
c[:sequence_name] ||= default_sequence_name(name, c[:name])
|
|
69
97
|
unless c[:create_sequence] == false
|
|
70
98
|
drop_seq_statement = drop_sequence_sql(c[:sequence_name])
|
|
71
99
|
statements << create_sequence_sql(c[:sequence_name], c)
|
|
@@ -97,13 +125,120 @@ module Sequel
|
|
|
97
125
|
sql
|
|
98
126
|
end
|
|
99
127
|
|
|
128
|
+
def default_sequence_name(table, column)
|
|
129
|
+
"seq_#{table}_#{column}"
|
|
130
|
+
end
|
|
131
|
+
|
|
100
132
|
def drop_sequence_sql(name)
|
|
101
133
|
"DROP SEQUENCE #{quote_identifier(name)}"
|
|
102
134
|
end
|
|
135
|
+
|
|
136
|
+
def remove_cached_schema(table)
|
|
137
|
+
@primary_key_sequences.delete(table)
|
|
138
|
+
super
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def sequence_for_table(table)
|
|
142
|
+
return nil unless autosequence
|
|
143
|
+
@primary_key_sequences.fetch(table) do |key|
|
|
144
|
+
pk = schema(table).select{|k, v| v[:primary_key]}
|
|
145
|
+
@primary_key_sequences[table] = if pk.length == 1
|
|
146
|
+
seq = "seq_#{table}_#{pk.first.first}"
|
|
147
|
+
seq.to_sym unless from(:user_sequences).filter(:sequence_name=>input_identifier_meth.call(seq)).empty?
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Oracle's integer/:number type handles larger values than
|
|
153
|
+
# most other databases's bigint types, so it should be
|
|
154
|
+
# safe to use for Bignum.
|
|
155
|
+
def type_literal_generic_bignum(column)
|
|
156
|
+
:integer
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Oracle doesn't have a time type, so use timestamp for all
|
|
160
|
+
# time columns.
|
|
161
|
+
def type_literal_generic_time(column)
|
|
162
|
+
:timestamp
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Oracle doesn't have a boolean type or even a reasonable
|
|
166
|
+
# facsimile. Using a char(1) seems to be the recommended way.
|
|
167
|
+
def type_literal_generic_trueclass(column)
|
|
168
|
+
:'char(1)'
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# SQL fragment for showing a table is temporary
|
|
172
|
+
def temporary_table_sql
|
|
173
|
+
TEMPORARY
|
|
174
|
+
end
|
|
103
175
|
end
|
|
104
176
|
|
|
105
177
|
module DatasetMethods
|
|
106
|
-
|
|
178
|
+
include EmulateOffsetWithRowNumber
|
|
179
|
+
|
|
180
|
+
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'with select distinct columns from join where group having compounds order lock')
|
|
181
|
+
ROW_NUMBER_EXPRESSION = 'ROWNUM'.lit.freeze
|
|
182
|
+
SPACE = Dataset::SPACE
|
|
183
|
+
APOS = Dataset::APOS
|
|
184
|
+
APOS_RE = Dataset::APOS_RE
|
|
185
|
+
DOUBLE_APOS = Dataset::DOUBLE_APOS
|
|
186
|
+
FROM = Dataset::FROM
|
|
187
|
+
BITCOMP_OPEN = "((0 - ".freeze
|
|
188
|
+
BITCOMP_CLOSE = ") - 1)".freeze
|
|
189
|
+
ILIKE_0 = "(UPPER(".freeze
|
|
190
|
+
ILIKE_1 = ") ".freeze
|
|
191
|
+
ILIKE_2 = ' UPPER('.freeze
|
|
192
|
+
ILIKE_3 = "))".freeze
|
|
193
|
+
LIKE = 'LIKE'.freeze
|
|
194
|
+
NOT_LIKE = 'NOT LIKE'.freeze
|
|
195
|
+
TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S%N %z'".freeze
|
|
196
|
+
TIMESTAMP_OFFSET_FORMAT = "%+03i:%02i".freeze
|
|
197
|
+
BOOL_FALSE = "'N'".freeze
|
|
198
|
+
BOOL_TRUE = "'Y'".freeze
|
|
199
|
+
HSTAR = "H*".freeze
|
|
200
|
+
DUAL = ['DUAL'.freeze].freeze
|
|
201
|
+
|
|
202
|
+
# Oracle needs to emulate bitwise operators and ILIKE/NOT ILIKE operators.
|
|
203
|
+
def complex_expression_sql_append(sql, op, args)
|
|
204
|
+
case op
|
|
205
|
+
when :&
|
|
206
|
+
sql << complex_expression_arg_pairs(args){|a, b| "CAST(BITAND(#{literal(a)}, #{literal(b)}) AS INTEGER)"}
|
|
207
|
+
when :|
|
|
208
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} - #{complex_expression_sql(:&, [a, b])} + #{literal(b)})"}
|
|
209
|
+
when :^
|
|
210
|
+
sql << complex_expression_arg_pairs(args){|*x| "(#{complex_expression_sql(:|, x)} - #{complex_expression_sql(:&, x)})"}
|
|
211
|
+
when :'B~'
|
|
212
|
+
sql << BITCOMP_OPEN
|
|
213
|
+
literal_append(sql, args.at(0))
|
|
214
|
+
sql << BITCOMP_CLOSE
|
|
215
|
+
when :<<
|
|
216
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * power(2, #{literal b}))"}
|
|
217
|
+
when :>>
|
|
218
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / power(2, #{literal b}))"}
|
|
219
|
+
when :ILIKE, :'NOT ILIKE'
|
|
220
|
+
sql << ILIKE_0
|
|
221
|
+
literal_append(sql, args.at(0))
|
|
222
|
+
sql << ILIKE_1
|
|
223
|
+
sql << (op == :ILIKE ? LIKE : NOT_LIKE)
|
|
224
|
+
sql<< ILIKE_2
|
|
225
|
+
literal_append(sql, args.at(1))
|
|
226
|
+
sql << ILIKE_3
|
|
227
|
+
else
|
|
228
|
+
super
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Oracle doesn't support CURRENT_TIME, as it doesn't have
|
|
233
|
+
# a type for storing just time values without a date, so
|
|
234
|
+
# use CURRENT_TIMESTAMP in its place.
|
|
235
|
+
def constant_sql_append(sql, c)
|
|
236
|
+
if c == :CURRENT_TIME
|
|
237
|
+
super(sql, :CURRENT_TIMESTAMP)
|
|
238
|
+
else
|
|
239
|
+
super
|
|
240
|
+
end
|
|
241
|
+
end
|
|
107
242
|
|
|
108
243
|
# Oracle uses MINUS instead of EXCEPT, and doesn't support EXCEPT ALL
|
|
109
244
|
def except(dataset, opts={})
|
|
@@ -112,19 +247,10 @@ module Sequel
|
|
|
112
247
|
compound_clone(:minus, dataset, opts)
|
|
113
248
|
end
|
|
114
249
|
|
|
250
|
+
# Use a custom expression with EXISTS to determine whether a dataset
|
|
251
|
+
# is empty.
|
|
115
252
|
def empty?
|
|
116
|
-
db[:dual].where(exists).get(1) == nil
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
# If this dataset is associated with a sequence, return the most recently
|
|
120
|
-
# inserted sequence value.
|
|
121
|
-
def insert(*args)
|
|
122
|
-
r = super
|
|
123
|
-
if s = opts[:sequence]
|
|
124
|
-
with_sql("SELECT #{literal(s)}.currval FROM dual").single_value.to_i
|
|
125
|
-
else
|
|
126
|
-
r
|
|
127
|
-
end
|
|
253
|
+
db[:dual].where(@opts[:offset] ? exists : unordered.exists).get(1) == nil
|
|
128
254
|
end
|
|
129
255
|
|
|
130
256
|
# Oracle requires SQL standard datetimes
|
|
@@ -139,16 +265,61 @@ module Sequel
|
|
|
139
265
|
clone(:sequence=>s)
|
|
140
266
|
end
|
|
141
267
|
|
|
268
|
+
# Handle LIMIT by using a unlimited subselect filtered with ROWNUM.
|
|
269
|
+
def select_sql
|
|
270
|
+
if (limit = @opts[:limit]) && !@opts[:sql]
|
|
271
|
+
ds = clone(:limit=>nil)
|
|
272
|
+
# Lock doesn't work in subselects, so don't use a subselect when locking.
|
|
273
|
+
# Don't use a subselect if custom SQL is used, as it breaks somethings.
|
|
274
|
+
ds = ds.from_self unless @opts[:lock]
|
|
275
|
+
sql = @opts[:append_sql] || ''
|
|
276
|
+
subselect_sql_append(sql, ds.where(SQL::ComplexExpression.new(:<=, ROW_NUMBER_EXPRESSION, limit)))
|
|
277
|
+
sql
|
|
278
|
+
else
|
|
279
|
+
super
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Oracle requires recursive CTEs to have column aliases.
|
|
284
|
+
def recursive_cte_requires_column_aliases?
|
|
285
|
+
true
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Oracle supports GROUP BY CUBE
|
|
289
|
+
def supports_group_cube?
|
|
290
|
+
true
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# Oracle supports GROUP BY ROLLUP
|
|
294
|
+
def supports_group_rollup?
|
|
295
|
+
true
|
|
296
|
+
end
|
|
297
|
+
|
|
142
298
|
# Oracle does not support INTERSECT ALL or EXCEPT ALL
|
|
143
299
|
def supports_intersect_except_all?
|
|
144
300
|
false
|
|
145
301
|
end
|
|
302
|
+
|
|
303
|
+
# Oracle does not support IS TRUE.
|
|
304
|
+
def supports_is_true?
|
|
305
|
+
false
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Oracle does not support SELECT *, column
|
|
309
|
+
def supports_select_all_and_column?
|
|
310
|
+
false
|
|
311
|
+
end
|
|
146
312
|
|
|
147
313
|
# Oracle supports timezones in literal timestamps.
|
|
148
314
|
def supports_timestamp_timezones?
|
|
149
315
|
true
|
|
150
316
|
end
|
|
151
317
|
|
|
318
|
+
# Oracle does not support WHERE 'Y' for WHERE TRUE.
|
|
319
|
+
def supports_where_true?
|
|
320
|
+
false
|
|
321
|
+
end
|
|
322
|
+
|
|
152
323
|
# Oracle supports window functions
|
|
153
324
|
def supports_window_functions?
|
|
154
325
|
true
|
|
@@ -158,25 +329,54 @@ module Sequel
|
|
|
158
329
|
|
|
159
330
|
# Oracle doesn't support the use of AS when aliasing a dataset. It doesn't require
|
|
160
331
|
# the use of AS anywhere, so this disables it in all cases.
|
|
161
|
-
def
|
|
162
|
-
|
|
332
|
+
def as_sql_append(sql, aliaz)
|
|
333
|
+
sql << SPACE
|
|
334
|
+
quote_identifier_append(sql, aliaz)
|
|
163
335
|
end
|
|
164
336
|
|
|
165
337
|
# The strftime format to use when literalizing the time.
|
|
166
338
|
def default_timestamp_format
|
|
167
|
-
|
|
339
|
+
TIMESTAMP_FORMAT
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# If this dataset is associated with a sequence, return the most recently
|
|
343
|
+
# inserted sequence value.
|
|
344
|
+
def execute_insert(sql, opts={})
|
|
345
|
+
f = @opts[:from]
|
|
346
|
+
super(sql, {:table=>(f.first if f), :sequence=>@opts[:sequence]}.merge(opts))
|
|
168
347
|
end
|
|
169
348
|
|
|
170
349
|
# Use a colon for the timestamp offset, since Oracle appears to require it.
|
|
171
350
|
def format_timestamp_offset(hour, minute)
|
|
172
|
-
sprintf(
|
|
351
|
+
sprintf(TIMESTAMP_OFFSET_FORMAT, hour, minute)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Oracle doesn't support empty values when inserting.
|
|
355
|
+
def insert_supports_empty_values?
|
|
356
|
+
false
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# Use string in hex format for blob data.
|
|
360
|
+
def literal_blob_append(sql, v)
|
|
361
|
+
sql << APOS << v.unpack(HSTAR).first << APOS
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Oracle uses 'N' for false values.
|
|
365
|
+
def literal_false
|
|
366
|
+
BOOL_FALSE
|
|
173
367
|
end
|
|
174
368
|
|
|
175
369
|
# Oracle uses the SQL standard of only doubling ' inside strings.
|
|
176
|
-
def
|
|
177
|
-
|
|
370
|
+
def literal_string_append(sql, v)
|
|
371
|
+
sql << APOS << v.gsub(APOS_RE, DOUBLE_APOS) << APOS
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# Oracle uses 'Y' for true values.
|
|
375
|
+
def literal_true
|
|
376
|
+
BOOL_TRUE
|
|
178
377
|
end
|
|
179
378
|
|
|
379
|
+
# Use the Oracle-specific SQL clauses (no limit, since it is emulated).
|
|
180
380
|
def select_clause_methods
|
|
181
381
|
SELECT_CLAUSE_METHODS
|
|
182
382
|
end
|
|
@@ -186,18 +386,8 @@ module Sequel
|
|
|
186
386
|
# so add the dummy DUAL table if the dataset doesn't select
|
|
187
387
|
# from a table.
|
|
188
388
|
def select_from_sql(sql)
|
|
189
|
-
sql <<
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
# Oracle requires a subselect to do limit and offset
|
|
193
|
-
def select_limit_sql(sql)
|
|
194
|
-
if limit = @opts[:limit]
|
|
195
|
-
if (offset = @opts[:offset]) && (offset > 0)
|
|
196
|
-
sql.replace("SELECT * FROM (SELECT raw_sql_.*, ROWNUM raw_rnum_ FROM(#{sql}) raw_sql_ WHERE ROWNUM <= #{limit + offset}) WHERE raw_rnum_ > #{offset}")
|
|
197
|
-
else
|
|
198
|
-
sql.replace("SELECT * FROM (#{sql}) WHERE ROWNUM <= #{limit}")
|
|
199
|
-
end
|
|
200
|
-
end
|
|
389
|
+
sql << FROM
|
|
390
|
+
source_list_append(sql, @opts[:from] || DUAL)
|
|
201
391
|
end
|
|
202
392
|
end
|
|
203
393
|
end
|