sequel 3.21.0 → 3.32.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 +539 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +293 -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/release_notes/3.32.0.txt +202 -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 +52 -0
- data/lib/sequel/adapters/jdbc/derby.rb +260 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +66 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -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 +88 -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 +339 -0
- data/lib/sequel/adapters/mysql.rb +85 -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 +355 -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 +328 -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 +278 -107
- data/lib/sequel/adapters/shared/mysql.rb +203 -65
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +237 -46
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +200 -50
- 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 +68 -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 +163 -59
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +240 -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 +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +59 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +676 -267
- 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/query.rb +1 -1
- 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 +1081 -344
- data/lib/sequel/model/base.rb +420 -133
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +20 -10
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +43 -10
- 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 +68 -7
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- 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 +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -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 +135 -30
- data/spec/adapters/mysql_spec.rb +244 -212
- data/spec/adapters/oracle_spec.rb +67 -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 +789 -512
- data/spec/core/dataset_spec.rb +1176 -1061
- 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/active_model_spec.rb +13 -0
- 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/query_spec.rb +6 -0
- 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 +72 -0
- data/spec/extensions/serialization_spec.rb +81 -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 +661 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +500 -67
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +367 -119
- data/spec/integration/prepared_statement_test.rb +222 -125
- data/spec/integration/schema_test.rb +217 -39
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +182 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +955 -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 +349 -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 +117 -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 ||= metadata_dataset.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
|
|
@@ -22,32 +30,53 @@ module Sequel
|
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
def tables(opts={})
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def table_exists?(name)
|
|
30
|
-
from(:tab).filter(:tname =>dataset.send(:input_identifier, name), :tabtype => 'TABLE').count > 0
|
|
33
|
+
m = output_identifier_meth
|
|
34
|
+
metadata_dataset.from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'TABLE').map{|r| m.call(r[:tname])}
|
|
31
35
|
end
|
|
32
36
|
|
|
33
37
|
def views(opts={})
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
m = output_identifier_meth
|
|
39
|
+
metadata_dataset.from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'VIEW').map{|r| m.call(r[:tname])}
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
def view_exists?(name)
|
|
39
|
-
|
|
43
|
+
m = input_identifier_meth
|
|
44
|
+
metadata_dataset.from(:tab).filter(:tname =>m.call(name), :tabtype => 'VIEW').count > 0
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
private
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
# Handle Oracle specific ALTER TABLE SQL
|
|
50
|
+
def alter_table_sql(table, op)
|
|
51
|
+
case op[:op]
|
|
52
|
+
when :add_column
|
|
53
|
+
if op[:primary_key]
|
|
54
|
+
sqls = []
|
|
55
|
+
sqls << alter_table_sql(table, op.merge(:primary_key=>nil))
|
|
56
|
+
if op[:auto_increment]
|
|
57
|
+
seq_name = default_sequence_name(table, op[:name])
|
|
58
|
+
sqls << drop_sequence_sql(seq_name)
|
|
59
|
+
sqls << create_sequence_sql(seq_name, op)
|
|
60
|
+
sqls << "UPDATE #{quote_schema_table(table)} SET #{quote_identifier(op[:name])} = #{seq_name}.nextval"
|
|
61
|
+
end
|
|
62
|
+
sqls << "ALTER TABLE #{quote_schema_table(table)} ADD PRIMARY KEY (#{quote_identifier(op[:name])})"
|
|
63
|
+
sqls
|
|
64
|
+
else
|
|
65
|
+
"ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
|
|
66
|
+
end
|
|
67
|
+
when :set_column_null
|
|
68
|
+
"ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} #{op[:null] ? 'NULL' : 'NOT NULL'}"
|
|
69
|
+
when :set_column_type
|
|
70
|
+
"ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} #{type_literal(op)}"
|
|
71
|
+
when :set_column_default
|
|
72
|
+
"ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} DEFAULT #{literal(op[:default])}"
|
|
73
|
+
else
|
|
74
|
+
super(table, op)
|
|
75
|
+
end
|
|
46
76
|
end
|
|
47
77
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
TEMPORARY
|
|
78
|
+
def auto_increment_sql
|
|
79
|
+
AUTOINCREMENT
|
|
51
80
|
end
|
|
52
81
|
|
|
53
82
|
def create_sequence_sql(name, opts={})
|
|
@@ -65,7 +94,7 @@ module Sequel
|
|
|
65
94
|
drop_seq_statement = nil
|
|
66
95
|
generator.columns.each do |c|
|
|
67
96
|
if c[:auto_increment]
|
|
68
|
-
c[:sequence_name] ||=
|
|
97
|
+
c[:sequence_name] ||= default_sequence_name(name, c[:name])
|
|
69
98
|
unless c[:create_sequence] == false
|
|
70
99
|
drop_seq_statement = drop_sequence_sql(c[:sequence_name])
|
|
71
100
|
statements << create_sequence_sql(c[:sequence_name], c)
|
|
@@ -97,13 +126,120 @@ module Sequel
|
|
|
97
126
|
sql
|
|
98
127
|
end
|
|
99
128
|
|
|
129
|
+
def default_sequence_name(table, column)
|
|
130
|
+
"seq_#{table}_#{column}"
|
|
131
|
+
end
|
|
132
|
+
|
|
100
133
|
def drop_sequence_sql(name)
|
|
101
134
|
"DROP SEQUENCE #{quote_identifier(name)}"
|
|
102
135
|
end
|
|
136
|
+
|
|
137
|
+
def remove_cached_schema(table)
|
|
138
|
+
@primary_key_sequences.delete(table)
|
|
139
|
+
super
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def sequence_for_table(table)
|
|
143
|
+
return nil unless autosequence
|
|
144
|
+
@primary_key_sequences.fetch(table) do |key|
|
|
145
|
+
pk = schema(table).select{|k, v| v[:primary_key]}
|
|
146
|
+
@primary_key_sequences[table] = if pk.length == 1
|
|
147
|
+
seq = "seq_#{table}_#{pk.first.first}"
|
|
148
|
+
seq.to_sym unless from(:user_sequences).filter(:sequence_name=>input_identifier_meth.call(seq)).empty?
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Oracle's integer/:number type handles larger values than
|
|
154
|
+
# most other databases's bigint types, so it should be
|
|
155
|
+
# safe to use for Bignum.
|
|
156
|
+
def type_literal_generic_bignum(column)
|
|
157
|
+
:integer
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Oracle doesn't have a time type, so use timestamp for all
|
|
161
|
+
# time columns.
|
|
162
|
+
def type_literal_generic_time(column)
|
|
163
|
+
:timestamp
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Oracle doesn't have a boolean type or even a reasonable
|
|
167
|
+
# facsimile. Using a char(1) seems to be the recommended way.
|
|
168
|
+
def type_literal_generic_trueclass(column)
|
|
169
|
+
:'char(1)'
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# SQL fragment for showing a table is temporary
|
|
173
|
+
def temporary_table_sql
|
|
174
|
+
TEMPORARY
|
|
175
|
+
end
|
|
103
176
|
end
|
|
104
177
|
|
|
105
178
|
module DatasetMethods
|
|
106
|
-
|
|
179
|
+
include EmulateOffsetWithRowNumber
|
|
180
|
+
|
|
181
|
+
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'with select distinct columns from join where group having compounds order lock')
|
|
182
|
+
ROW_NUMBER_EXPRESSION = 'ROWNUM'.lit.freeze
|
|
183
|
+
SPACE = Dataset::SPACE
|
|
184
|
+
APOS = Dataset::APOS
|
|
185
|
+
APOS_RE = Dataset::APOS_RE
|
|
186
|
+
DOUBLE_APOS = Dataset::DOUBLE_APOS
|
|
187
|
+
FROM = Dataset::FROM
|
|
188
|
+
BITCOMP_OPEN = "((0 - ".freeze
|
|
189
|
+
BITCOMP_CLOSE = ") - 1)".freeze
|
|
190
|
+
ILIKE_0 = "(UPPER(".freeze
|
|
191
|
+
ILIKE_1 = ") ".freeze
|
|
192
|
+
ILIKE_2 = ' UPPER('.freeze
|
|
193
|
+
ILIKE_3 = "))".freeze
|
|
194
|
+
LIKE = 'LIKE'.freeze
|
|
195
|
+
NOT_LIKE = 'NOT LIKE'.freeze
|
|
196
|
+
TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S%N %z'".freeze
|
|
197
|
+
TIMESTAMP_OFFSET_FORMAT = "%+03i:%02i".freeze
|
|
198
|
+
BOOL_FALSE = "'N'".freeze
|
|
199
|
+
BOOL_TRUE = "'Y'".freeze
|
|
200
|
+
HSTAR = "H*".freeze
|
|
201
|
+
DUAL = ['DUAL'.freeze].freeze
|
|
202
|
+
|
|
203
|
+
# Oracle needs to emulate bitwise operators and ILIKE/NOT ILIKE operators.
|
|
204
|
+
def complex_expression_sql_append(sql, op, args)
|
|
205
|
+
case op
|
|
206
|
+
when :&
|
|
207
|
+
sql << complex_expression_arg_pairs(args){|a, b| "CAST(BITAND(#{literal(a)}, #{literal(b)}) AS INTEGER)"}
|
|
208
|
+
when :|
|
|
209
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} - #{complex_expression_sql(:&, [a, b])} + #{literal(b)})"}
|
|
210
|
+
when :^
|
|
211
|
+
sql << complex_expression_arg_pairs(args){|*x| "(#{complex_expression_sql(:|, x)} - #{complex_expression_sql(:&, x)})"}
|
|
212
|
+
when :'B~'
|
|
213
|
+
sql << BITCOMP_OPEN
|
|
214
|
+
literal_append(sql, args.at(0))
|
|
215
|
+
sql << BITCOMP_CLOSE
|
|
216
|
+
when :<<
|
|
217
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * power(2, #{literal b}))"}
|
|
218
|
+
when :>>
|
|
219
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / power(2, #{literal b}))"}
|
|
220
|
+
when :ILIKE, :'NOT ILIKE'
|
|
221
|
+
sql << ILIKE_0
|
|
222
|
+
literal_append(sql, args.at(0))
|
|
223
|
+
sql << ILIKE_1
|
|
224
|
+
sql << (op == :ILIKE ? LIKE : NOT_LIKE)
|
|
225
|
+
sql<< ILIKE_2
|
|
226
|
+
literal_append(sql, args.at(1))
|
|
227
|
+
sql << ILIKE_3
|
|
228
|
+
else
|
|
229
|
+
super
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Oracle doesn't support CURRENT_TIME, as it doesn't have
|
|
234
|
+
# a type for storing just time values without a date, so
|
|
235
|
+
# use CURRENT_TIMESTAMP in its place.
|
|
236
|
+
def constant_sql_append(sql, c)
|
|
237
|
+
if c == :CURRENT_TIME
|
|
238
|
+
super(sql, :CURRENT_TIMESTAMP)
|
|
239
|
+
else
|
|
240
|
+
super
|
|
241
|
+
end
|
|
242
|
+
end
|
|
107
243
|
|
|
108
244
|
# Oracle uses MINUS instead of EXCEPT, and doesn't support EXCEPT ALL
|
|
109
245
|
def except(dataset, opts={})
|
|
@@ -112,19 +248,10 @@ module Sequel
|
|
|
112
248
|
compound_clone(:minus, dataset, opts)
|
|
113
249
|
end
|
|
114
250
|
|
|
251
|
+
# Use a custom expression with EXISTS to determine whether a dataset
|
|
252
|
+
# is empty.
|
|
115
253
|
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
|
|
254
|
+
db[:dual].where(@opts[:offset] ? exists : unordered.exists).get(1) == nil
|
|
128
255
|
end
|
|
129
256
|
|
|
130
257
|
# Oracle requires SQL standard datetimes
|
|
@@ -139,16 +266,61 @@ module Sequel
|
|
|
139
266
|
clone(:sequence=>s)
|
|
140
267
|
end
|
|
141
268
|
|
|
269
|
+
# Handle LIMIT by using a unlimited subselect filtered with ROWNUM.
|
|
270
|
+
def select_sql
|
|
271
|
+
if (limit = @opts[:limit]) && !@opts[:sql]
|
|
272
|
+
ds = clone(:limit=>nil)
|
|
273
|
+
# Lock doesn't work in subselects, so don't use a subselect when locking.
|
|
274
|
+
# Don't use a subselect if custom SQL is used, as it breaks somethings.
|
|
275
|
+
ds = ds.from_self unless @opts[:lock]
|
|
276
|
+
sql = @opts[:append_sql] || ''
|
|
277
|
+
subselect_sql_append(sql, ds.where(SQL::ComplexExpression.new(:<=, ROW_NUMBER_EXPRESSION, limit)))
|
|
278
|
+
sql
|
|
279
|
+
else
|
|
280
|
+
super
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Oracle requires recursive CTEs to have column aliases.
|
|
285
|
+
def recursive_cte_requires_column_aliases?
|
|
286
|
+
true
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Oracle supports GROUP BY CUBE
|
|
290
|
+
def supports_group_cube?
|
|
291
|
+
true
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Oracle supports GROUP BY ROLLUP
|
|
295
|
+
def supports_group_rollup?
|
|
296
|
+
true
|
|
297
|
+
end
|
|
298
|
+
|
|
142
299
|
# Oracle does not support INTERSECT ALL or EXCEPT ALL
|
|
143
300
|
def supports_intersect_except_all?
|
|
144
301
|
false
|
|
145
302
|
end
|
|
303
|
+
|
|
304
|
+
# Oracle does not support IS TRUE.
|
|
305
|
+
def supports_is_true?
|
|
306
|
+
false
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# Oracle does not support SELECT *, column
|
|
310
|
+
def supports_select_all_and_column?
|
|
311
|
+
false
|
|
312
|
+
end
|
|
146
313
|
|
|
147
314
|
# Oracle supports timezones in literal timestamps.
|
|
148
315
|
def supports_timestamp_timezones?
|
|
149
316
|
true
|
|
150
317
|
end
|
|
151
318
|
|
|
319
|
+
# Oracle does not support WHERE 'Y' for WHERE TRUE.
|
|
320
|
+
def supports_where_true?
|
|
321
|
+
false
|
|
322
|
+
end
|
|
323
|
+
|
|
152
324
|
# Oracle supports window functions
|
|
153
325
|
def supports_window_functions?
|
|
154
326
|
true
|
|
@@ -158,25 +330,54 @@ module Sequel
|
|
|
158
330
|
|
|
159
331
|
# Oracle doesn't support the use of AS when aliasing a dataset. It doesn't require
|
|
160
332
|
# the use of AS anywhere, so this disables it in all cases.
|
|
161
|
-
def
|
|
162
|
-
|
|
333
|
+
def as_sql_append(sql, aliaz)
|
|
334
|
+
sql << SPACE
|
|
335
|
+
quote_identifier_append(sql, aliaz)
|
|
163
336
|
end
|
|
164
337
|
|
|
165
338
|
# The strftime format to use when literalizing the time.
|
|
166
339
|
def default_timestamp_format
|
|
167
|
-
|
|
340
|
+
TIMESTAMP_FORMAT
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# If this dataset is associated with a sequence, return the most recently
|
|
344
|
+
# inserted sequence value.
|
|
345
|
+
def execute_insert(sql, opts={})
|
|
346
|
+
f = @opts[:from]
|
|
347
|
+
super(sql, {:table=>(f.first if f), :sequence=>@opts[:sequence]}.merge(opts))
|
|
168
348
|
end
|
|
169
349
|
|
|
170
350
|
# Use a colon for the timestamp offset, since Oracle appears to require it.
|
|
171
351
|
def format_timestamp_offset(hour, minute)
|
|
172
|
-
sprintf(
|
|
352
|
+
sprintf(TIMESTAMP_OFFSET_FORMAT, hour, minute)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Oracle doesn't support empty values when inserting.
|
|
356
|
+
def insert_supports_empty_values?
|
|
357
|
+
false
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Use string in hex format for blob data.
|
|
361
|
+
def literal_blob_append(sql, v)
|
|
362
|
+
sql << APOS << v.unpack(HSTAR).first << APOS
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
# Oracle uses 'N' for false values.
|
|
366
|
+
def literal_false
|
|
367
|
+
BOOL_FALSE
|
|
173
368
|
end
|
|
174
369
|
|
|
175
370
|
# Oracle uses the SQL standard of only doubling ' inside strings.
|
|
176
|
-
def
|
|
177
|
-
|
|
371
|
+
def literal_string_append(sql, v)
|
|
372
|
+
sql << APOS << v.gsub(APOS_RE, DOUBLE_APOS) << APOS
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# Oracle uses 'Y' for true values.
|
|
376
|
+
def literal_true
|
|
377
|
+
BOOL_TRUE
|
|
178
378
|
end
|
|
179
379
|
|
|
380
|
+
# Use the Oracle-specific SQL clauses (no limit, since it is emulated).
|
|
180
381
|
def select_clause_methods
|
|
181
382
|
SELECT_CLAUSE_METHODS
|
|
182
383
|
end
|
|
@@ -186,18 +387,8 @@ module Sequel
|
|
|
186
387
|
# so add the dummy DUAL table if the dataset doesn't select
|
|
187
388
|
# from a table.
|
|
188
389
|
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
|
|
390
|
+
sql << FROM
|
|
391
|
+
source_list_append(sql, @opts[:from] || DUAL)
|
|
201
392
|
end
|
|
202
393
|
end
|
|
203
394
|
end
|