sequel 4.39.0 → 4.40.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +34 -0
- data/README.rdoc +8 -4
- data/doc/active_record.rdoc +1 -1
- data/doc/advanced_associations.rdoc +7 -7
- data/doc/association_basics.rdoc +7 -7
- data/doc/cheat_sheet.rdoc +5 -3
- data/doc/core_extensions.rdoc +3 -3
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/object_model.rdoc +16 -7
- data/doc/postgresql.rdoc +3 -3
- data/doc/querying.rdoc +3 -3
- data/doc/release_notes/4.40.0.txt +179 -0
- data/doc/security.rdoc +2 -1
- data/doc/sql.rdoc +34 -18
- data/doc/testing.rdoc +1 -0
- data/doc/virtual_rows.rdoc +11 -2
- data/lib/sequel/adapters/jdbc/derby.rb +7 -1
- data/lib/sequel/adapters/jdbc/h2.rb +15 -1
- data/lib/sequel/adapters/oracle.rb +9 -5
- data/lib/sequel/adapters/postgres.rb +0 -1
- data/lib/sequel/adapters/shared/cubrid.rb +11 -11
- data/lib/sequel/adapters/shared/db2.rb +4 -8
- data/lib/sequel/adapters/shared/mssql.rb +41 -28
- data/lib/sequel/adapters/shared/mysql.rb +9 -6
- data/lib/sequel/adapters/shared/oracle.rb +16 -5
- data/lib/sequel/adapters/shared/postgres.rb +84 -45
- data/lib/sequel/adapters/shared/sqlanywhere.rb +29 -15
- data/lib/sequel/adapters/shared/sqlite.rb +6 -6
- data/lib/sequel/core.rb +61 -10
- data/lib/sequel/database/connecting.rb +2 -1
- data/lib/sequel/database/features.rb +7 -0
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +30 -3
- data/lib/sequel/database/transactions.rb +4 -2
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/dataset/graph.rb +6 -1
- data/lib/sequel/dataset/query.rb +14 -7
- data/lib/sequel/dataset/sql.rb +2 -2
- data/lib/sequel/extensions/core_extensions.rb +2 -1
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/s.rb +57 -0
- data/lib/sequel/extensions/set_overrides.rb +5 -1
- data/lib/sequel/extensions/sql_expr.rb +1 -0
- data/lib/sequel/extensions/symbol_aref.rb +71 -0
- data/lib/sequel/extensions/symbol_aref_refinement.rb +41 -0
- data/lib/sequel/extensions/symbol_as.rb +23 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +35 -0
- data/lib/sequel/model/base.rb +3 -3
- data/lib/sequel/plugins/class_table_inheritance.rb +14 -3
- data/lib/sequel/plugins/column_select.rb +4 -2
- data/lib/sequel/plugins/dataset_associations.rb +12 -4
- data/lib/sequel/plugins/insert_returning_select.rb +1 -1
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/sql.rb +40 -8
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +3 -3
- data/spec/adapters/mssql_spec.rb +40 -40
- data/spec/adapters/mysql_spec.rb +5 -5
- data/spec/adapters/oracle_spec.rb +4 -4
- data/spec/adapters/postgres_spec.rb +135 -124
- data/spec/adapters/spec_helper.rb +1 -0
- data/spec/adapters/sqlite_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +2 -2
- data/spec/core/expression_filters_spec.rb +43 -2
- data/spec/core/schema_spec.rb +35 -1
- data/spec/core_extensions_spec.rb +27 -0
- data/spec/extensions/class_table_inheritance_spec.rb +8 -0
- data/spec/extensions/column_select_spec.rb +8 -0
- data/spec/extensions/core_refinements_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +9 -0
- data/spec/extensions/insert_returning_select_spec.rb +20 -0
- data/spec/extensions/prepared_statements_spec.rb +7 -0
- data/spec/extensions/s_spec.rb +60 -0
- data/spec/extensions/symbol_aref_refinement_spec.rb +28 -0
- data/spec/extensions/symbol_as_refinement_spec.rb +21 -0
- data/spec/integration/associations_test.rb +62 -57
- data/spec/integration/dataset_test.rb +54 -54
- data/spec/integration/eager_loader_test.rb +7 -7
- data/spec/integration/plugin_test.rb +20 -20
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +21 -0
- data/spec/integration/spec_helper.rb +1 -0
- metadata +12 -2
data/doc/security.rdoc
CHANGED
@@ -242,7 +242,8 @@ derived from user input unless absolutely necessary.
|
|
242
242
|
|
243
243
|
Sequel also allows you to create identifiers using
|
244
244
|
Sequel.identifier[rdoc-ref:Sequel::SQL::Builders#identifier] for plain identifiers,
|
245
|
-
Sequel.qualify[rdoc-ref:Sequel::SQL::Builders#qualify]
|
245
|
+
Sequel.qualify[rdoc-ref:Sequel::SQL::Builders#qualify] and
|
246
|
+
Sequel::SQL::Indentifier#[][rdoc-ref:Sequel::SQL::QualifyingMethods#[]] for qualified identifiers, and
|
246
247
|
Sequel.as[rdoc-ref:Sequel::SQL::Builders#as] for aliased expressions. So if you
|
247
248
|
pass any of those values derived from user input, you are dealing with the same scenario.
|
248
249
|
|
data/doc/sql.rdoc
CHANGED
@@ -125,6 +125,8 @@ A plain symbol is usually treated as an unqualified identifier. However, if you
|
|
125
125
|
|
126
126
|
:table__column # "table"."column"
|
127
127
|
|
128
|
+
This works by default, but it is possible to turn off by setting <tt>Sequel.split_symbols = false</tt>.
|
129
|
+
|
128
130
|
Note that you can't use a period to separate them:
|
129
131
|
|
130
132
|
:table.column # calls the column method on the symbol
|
@@ -133,14 +135,21 @@ Also note that specifying the period inside the symbol doesn't work if you are q
|
|
133
135
|
|
134
136
|
:"table.column" # "table.column"
|
135
137
|
|
136
|
-
|
138
|
+
A couple other ways two create a qualified identifier are to use <tt>Sequel.[]</tt> to create an identifier,
|
139
|
+
and call <tt>[]</tt> or +qualify+ on that, or to use the <tt>Sequel.qualify</tt> with the table and column symbols:
|
137
140
|
|
141
|
+
Sequel[:table][:column] # "table"."column"
|
142
|
+
Sequel[:column].qualify(:table) # "table"."column"
|
138
143
|
Sequel.qualify(:table, :column) # "table"."column"
|
139
144
|
|
140
145
|
Another way to generate identifiers is to use Sequel's {virtual row support}[rdoc-ref:doc/virtual_rows.rdoc]:
|
141
146
|
|
142
147
|
DB[:albums].select{name} # SELECT "name" FROM "albums"
|
143
|
-
DB[:albums].select{
|
148
|
+
DB[:albums].select{albums[:name]} # SELECT "albums"."name" FROM "albums"
|
149
|
+
|
150
|
+
You can also use the symbol_aref extension for creating qualified identifiers:
|
151
|
+
|
152
|
+
:table[:column] # "table"."column"
|
144
153
|
|
145
154
|
=== Numbers
|
146
155
|
|
@@ -173,10 +182,17 @@ You can combine this with implicit qualification:
|
|
173
182
|
|
174
183
|
:table__column___alias # "table"."column" AS "alias"
|
175
184
|
|
185
|
+
As with creating qualified identifiers via a double underscore, This works by default, but it is possible to turn off by setting <tt>Sequel.split_symbols = false</tt>.
|
186
|
+
|
176
187
|
You can also use the <tt>Sequel.as</tt> method to create an alias, and the +as+ method on most Sequel-specific expression objects:
|
177
188
|
|
178
|
-
Sequel.as(:column, :alias)
|
179
|
-
Sequel
|
189
|
+
Sequel.as(:column, :alias) # "column" AS "alias"
|
190
|
+
Sequel[:column].as(:alias) # "column" AS "alias"
|
191
|
+
Sequel[:table][:column].as(:alias) # "table"."column" AS "alias"
|
192
|
+
|
193
|
+
You can also use the symbol_as extension for creating aliased identifiers:
|
194
|
+
|
195
|
+
:column.as(:alias) # "column" AS "alias"
|
180
196
|
|
181
197
|
If you want to use a derived column list, you can provide an array of column aliases:
|
182
198
|
|
@@ -231,10 +247,10 @@ If the database supports window functions, Sequel can handle them by calling the
|
|
231
247
|
|
232
248
|
If the database supports schema qualified functions, Sequel can handle them by calling the function method on a QuailfiedIdentifier:
|
233
249
|
|
234
|
-
DB[:albums].select{
|
250
|
+
DB[:albums].select{schema[:function].function}
|
235
251
|
# SELECT schema.function() FROM albums
|
236
252
|
|
237
|
-
DB[:albums].select{
|
253
|
+
DB[:albums].select{schema[:function].function(col, 2, "a")}
|
238
254
|
# SELECT schema.function(col, 2, 'a') FROM albums
|
239
255
|
|
240
256
|
=== Portable/Emulated Functions
|
@@ -347,8 +363,8 @@ produces <tt>(column != 1)</tt> instead of <tt>NOT (column = 1)</tt>.
|
|
347
363
|
|
348
364
|
Sequel defines the inequality operators directly on most Sequel-specific expression objects:
|
349
365
|
|
350
|
-
Sequel
|
351
|
-
Sequel
|
366
|
+
Sequel[:table][:column] > 1 # ("table"."column" > 1)
|
367
|
+
Sequel[:table][:column] < 1 # ("table"."column" < 1)
|
352
368
|
Sequel.function(:func) >= 1 # (func() >= 1)
|
353
369
|
Sequel.function(:func, :column) <= 1 # (func("column") <= 1)
|
354
370
|
|
@@ -365,23 +381,23 @@ A common use of virtual rows is to handle inequality operators:
|
|
365
381
|
The standard mathematical operates are defined on most Sequel-specific expression objects:
|
366
382
|
|
367
383
|
Sequel[:column] + 1 # "column" + 1
|
368
|
-
Sequel[:
|
369
|
-
Sequel
|
384
|
+
Sequel[:table][:column] - 1 # "table"."column" - 1
|
385
|
+
Sequel[:table][:column] * 1 # "table"."column" * 1
|
370
386
|
Sequel[:column] / 1 # "column" / 1
|
371
387
|
Sequel[:column] ** 1 # power("column", 1)
|
372
388
|
|
373
389
|
You can also call the operator methods directly on the Sequel module:
|
374
390
|
|
375
391
|
Sequel.+(:column, 1) # "column" + 1
|
376
|
-
Sequel.-(:
|
377
|
-
Sequel.*(Sequel
|
392
|
+
Sequel.-(Sequel[:table][:column], 1) # "table"."column" - 1
|
393
|
+
Sequel.*(Sequel[:table][:column], 1) # "table"."column" * 1
|
378
394
|
Sequel./(:column, 1) # "column" / 1
|
379
395
|
Sequel.**(:column, 1) # power("column", 1)
|
380
396
|
|
381
397
|
Note that since Sequel implements support for ruby's coercion protocol, the following also works:
|
382
398
|
|
383
399
|
1 + Sequel[:column]
|
384
|
-
1 - Sequel
|
400
|
+
1 - Sequel[:table][:column]
|
385
401
|
|
386
402
|
=== Boolean Operators (AND OR)
|
387
403
|
|
@@ -432,7 +448,7 @@ Casting in Sequel is done with the +cast+ method, which is available on most of
|
|
432
448
|
|
433
449
|
Sequel[:name].cast(:text) # CAST("name" AS text)
|
434
450
|
Sequel['1'].cast(:integer) # CAST('1' AS integer)
|
435
|
-
Sequel
|
451
|
+
Sequel[:table][:column].cast(:date) # CAST("table"."column" AS date)
|
436
452
|
|
437
453
|
You can also use the <tt>Sequel.cast</tt> method:
|
438
454
|
|
@@ -516,17 +532,17 @@ Note that using +ilike+ with a regular expression will always make the regexp ca
|
|
516
532
|
Sequel supports specifying ascending or descending order using the +asc+ and +desc+ method on most Sequel-specific expression objects:
|
517
533
|
|
518
534
|
Sequel[:column].asc # "column" ASC
|
519
|
-
Sequel[:column].
|
535
|
+
Sequel[:table][:column].desc # "table"."column" DESC
|
520
536
|
|
521
537
|
You can also use the <tt>Sequel.asc</tt> and <tt>Sequel.desc</tt> methods:
|
522
538
|
|
523
539
|
Sequel.asc(:column) # "column" ASC
|
524
|
-
Sequel.desc(Sequel[:column]
|
540
|
+
Sequel.desc(Sequel[:table][:column]) # "table"."column" DESC
|
525
541
|
|
526
542
|
On some databases, you can specify null ordering:
|
527
543
|
|
528
544
|
Sequel.asc(:column, :nulls=>:first) # "column" ASC NULLS FIRST
|
529
|
-
Sequel.desc(Sequel[:column]
|
545
|
+
Sequel.desc(Sequel[:table][:column], :nulls=>:last) # "table"."column" DESC NULLS LAST
|
530
546
|
|
531
547
|
=== All Columns (.*)
|
532
548
|
|
@@ -556,7 +572,7 @@ If you provide a 3rd argument to <tt>Sequel.case</tt>, it goes between CASE and
|
|
556
572
|
Sequel supports SQL subscripts using the +sql_subscript+ method on most Sequel-specific expression objects:
|
557
573
|
|
558
574
|
Sequel[:column].sql_subscript(3) # column[3]
|
559
|
-
Sequel[:column].
|
575
|
+
Sequel[:table][:column].sql_subscript(3) # table.column[3]
|
560
576
|
|
561
577
|
You can also use the <tt>Sequel.subscript</tt> method:
|
562
578
|
|
data/doc/testing.rdoc
CHANGED
@@ -159,5 +159,6 @@ SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
|
|
159
159
|
SEQUEL_NO_AUTO_LITERAL_STRINGS :: Use the no_auto_string_literals extension when running the specs
|
160
160
|
SEQUEL_NO_CACHE_ASSOCIATIONS :: Don't cache association metadata when running the specs
|
161
161
|
SEQUEL_NO_CHECK_SQLS :: Don't check for specific SQL syntax when running the specs
|
162
|
+
SEQUEL_NO_SPLIT_SYMBOLS :: Turn off symbol splitting when running the specs
|
162
163
|
SEQUEL_NO_PENDING :: Don't skip any specs, try running all specs (note, can cause lockups for some adapters)
|
163
164
|
SKIPPED_TEST_WARN :: Warn when skipping any tests because libraries aren't available
|
data/doc/virtual_rows.rdoc
CHANGED
@@ -121,8 +121,17 @@ in the method name:
|
|
121
121
|
# WHERE table.column > 1
|
122
122
|
|
123
123
|
Using the double underscore for SQL::QualifiedIdentifiers was done to make
|
124
|
-
usage very similar to using symbols, which also translate the
|
125
|
-
into a qualified column.
|
124
|
+
usage very similar to using symbols, which by default also translate the
|
125
|
+
double underscore into a qualified column.
|
126
|
+
|
127
|
+
Note that when <tt>Sequel.split_symbols = false</tt> is used, then virtual
|
128
|
+
rows do not split symbols either. If you need to create qualified identifers
|
129
|
+
when disabling symbol splitting, it is easy to do by calling #[] on the
|
130
|
+
SQL::Identifiers returned by regular methods calls:
|
131
|
+
|
132
|
+
ds.where{|o| o.table[:column] > 1}
|
133
|
+
ds.where{table[:column] > 1}
|
134
|
+
# WHERE table.column > 1
|
126
135
|
|
127
136
|
== SQL::Functions - SQL function calls
|
128
137
|
|
@@ -82,9 +82,15 @@ module Sequel
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
# Derby does not allow adding primary key constraints to NULLable columns.
|
86
|
+
def can_add_primary_key_constraint_on_nullable_columns?
|
87
|
+
false
|
88
|
+
end
|
89
|
+
|
85
90
|
# Derby doesn't allow specifying NULL for columns, only NOT NULL.
|
86
91
|
def column_definition_null_sql(sql, column)
|
87
|
-
|
92
|
+
null = column.fetch(:null, column[:allow_null])
|
93
|
+
sql << " NOT NULL" if null == false || (null.nil? && column[:primary_key])
|
88
94
|
end
|
89
95
|
|
90
96
|
# Add NOT LOGGED for temporary tables to improve performance.
|
@@ -58,6 +58,11 @@ module Sequel
|
|
58
58
|
|
59
59
|
private
|
60
60
|
|
61
|
+
# H2 does not allow adding primary key constraints to NULLable columns.
|
62
|
+
def can_add_primary_key_constraint_on_nullable_columns?
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
61
66
|
# If the :prepare option is given and we aren't in a savepoint,
|
62
67
|
# prepare the transaction for a two-phase commit.
|
63
68
|
def commit_transaction(conn, opts=OPTS)
|
@@ -73,12 +78,21 @@ module Sequel
|
|
73
78
|
case op[:op]
|
74
79
|
when :add_column
|
75
80
|
if (pk = op.delete(:primary_key)) || (ref = op.delete(:table))
|
81
|
+
if pk
|
82
|
+
op[:null] = false
|
83
|
+
end
|
84
|
+
|
76
85
|
sqls = [super(table, op)]
|
77
|
-
|
86
|
+
|
87
|
+
if pk && op[:type] != :identity
|
88
|
+
sqls << "ALTER TABLE #{quote_schema_table(table)} ADD PRIMARY KEY (#{quote_identifier(op[:name])})"
|
89
|
+
end
|
90
|
+
|
78
91
|
if ref
|
79
92
|
op[:table] = ref
|
80
93
|
sqls << "ALTER TABLE #{quote_schema_table(table)} ADD FOREIGN KEY (#{quote_identifier(op[:name])}) #{column_references_sql(op)}"
|
81
94
|
end
|
95
|
+
|
82
96
|
sqls
|
83
97
|
else
|
84
98
|
super(table, op)
|
@@ -264,11 +264,15 @@ module Sequel
|
|
264
264
|
im = input_identifier_meth(ds)
|
265
265
|
|
266
266
|
# Primary Keys
|
267
|
-
ds = metadata_dataset.
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
267
|
+
ds = metadata_dataset.
|
268
|
+
from{[all_constraints.as(:cons), all_cons_columns.as(:cols)]}.
|
269
|
+
where{{
|
270
|
+
cols[:table_name]=>im.call(table),
|
271
|
+
cons[:constraint_type]=>'P',
|
272
|
+
cons[:constraint_name]=>cols[:constraint_name],
|
273
|
+
cons[:owner]=>cols[:owner]}}
|
274
|
+
ds = ds.where{{cons[:owner]=>im.call(schema)}} if schema
|
275
|
+
pks = ds.select_map{cols[:column_name]}
|
272
276
|
|
273
277
|
# Default values
|
274
278
|
defaults = begin
|
@@ -23,11 +23,11 @@ module Sequel
|
|
23
23
|
m2 = input_identifier_meth
|
24
24
|
indexes = {}
|
25
25
|
metadata_dataset.
|
26
|
-
from
|
27
|
-
join(:
|
28
|
-
where
|
29
|
-
order
|
30
|
-
select
|
26
|
+
from{db_index[:i]}.
|
27
|
+
join(Sequel[:db_index_key].as(:k), :index_name=>:index_name, :class_name=>:class_name).
|
28
|
+
where{{i[:class_name]=>m2.call(table), :is_primary_key=>'NO'}}.
|
29
|
+
order{k[:key_order]}.
|
30
|
+
select{[i[:index_name], k[:key_attr_name].as(:column), :is_unique]}.
|
31
31
|
each do |row|
|
32
32
|
index = indexes[m.call(row[:index_name])] ||= {:columns=>[], :unique=>row[:is_unique]=='YES'}
|
33
33
|
index[:columns] << m.call(row[:column])
|
@@ -44,18 +44,18 @@ module Sequel
|
|
44
44
|
m2 = input_identifier_meth(opts[:dataset])
|
45
45
|
|
46
46
|
pks = metadata_dataset.
|
47
|
-
from
|
48
|
-
join(:
|
49
|
-
where
|
50
|
-
order
|
51
|
-
select_map
|
47
|
+
from{db_index[:i]}.
|
48
|
+
join(Sequel[:db_index_key].as(:k), :index_name=>:index_name, :class_name=>:class_name).
|
49
|
+
where{{i[:class_name]=>m2.call(table_name), :is_primary_key=>'YES'}}.
|
50
|
+
order{k[:key_order]}.
|
51
|
+
select_map{k[:key_attr_name]}.
|
52
52
|
map{|c| m.call(c)}
|
53
53
|
|
54
54
|
metadata_dataset.
|
55
55
|
from(:db_attribute).
|
56
56
|
where(:class_name=>m2.call(table_name)).
|
57
57
|
order(:def_order).
|
58
|
-
select
|
58
|
+
select{[:attr_name, data_type.as(:db_type), default_value.as(:default), is_nullable.as(:allow_null), :prec]}.
|
59
59
|
map do |row|
|
60
60
|
name = m.call(row.delete(:attr_name))
|
61
61
|
row[:allow_null] = row[:allow_null] == 'YES'
|
@@ -76,7 +76,7 @@ module Sequel
|
|
76
76
|
m = output_identifier_meth
|
77
77
|
indexes = {}
|
78
78
|
metadata_dataset.
|
79
|
-
from(:
|
79
|
+
from(Sequel[:syscat][:indexes]).
|
80
80
|
select(:indname, :uniquerule, :colnames).
|
81
81
|
where(:tabname=>input_identifier_meth.call(table), :system_required=>0).
|
82
82
|
each do |r|
|
@@ -160,13 +160,9 @@ module Sequel
|
|
160
160
|
AUTOINCREMENT
|
161
161
|
end
|
162
162
|
|
163
|
-
#
|
164
|
-
def
|
165
|
-
|
166
|
-
null = false if column[:primary_key]
|
167
|
-
|
168
|
-
sql << NOT_NULL if null == false
|
169
|
-
sql << NULL if null == true
|
163
|
+
# DB2 does not allow adding primary key constraints to NULLable columns.
|
164
|
+
def can_add_primary_key_constraint_on_nullable_columns?
|
165
|
+
false
|
170
166
|
end
|
171
167
|
|
172
168
|
# Supply columns with NOT NULL if they are part of a composite
|
@@ -3,7 +3,6 @@
|
|
3
3
|
Sequel.require %w'emulate_offset_with_row_number split_alter_table', 'adapters/utils'
|
4
4
|
|
5
5
|
module Sequel
|
6
|
-
Dataset::NON_SQL_OPTIONS << :disable_insert_output
|
7
6
|
module MSSQL
|
8
7
|
Sequel::Database.set_shared_adapter_scheme(:mssql, self)
|
9
8
|
|
@@ -141,20 +140,22 @@ module Sequel
|
|
141
140
|
schema, table = schema_and_table(table)
|
142
141
|
current_schema = m.call(get(Sequel.function('schema_name')))
|
143
142
|
fk_action_map = FOREIGN_KEY_ACTION_MAP
|
143
|
+
fk = Sequel[:fk]
|
144
|
+
fkc = Sequel[:fkc]
|
144
145
|
ds = metadata_dataset.from(Sequel.lit('[sys].[foreign_keys]').as(:fk)).
|
145
146
|
join(Sequel.lit('[sys].[foreign_key_columns]').as(:fkc), :constraint_object_id => :object_id).
|
146
|
-
join(Sequel.lit('[sys].[all_columns]').as(:pc), :object_id => :
|
147
|
-
join(Sequel.lit('[sys].[all_columns]').as(:rc), :object_id => :
|
148
|
-
where{{object_schema_name(:
|
149
|
-
where{{object_name(:
|
150
|
-
select{[:
|
151
|
-
:
|
152
|
-
:
|
153
|
-
:
|
154
|
-
:
|
155
|
-
object_schema_name(:
|
156
|
-
object_name(:
|
157
|
-
order(:
|
147
|
+
join(Sequel.lit('[sys].[all_columns]').as(:pc), :object_id => fkc[:parent_object_id], :column_id => fkc[:parent_column_id]).
|
148
|
+
join(Sequel.lit('[sys].[all_columns]').as(:rc), :object_id => fkc[:referenced_object_id], :column_id => fkc[:referenced_column_id]).
|
149
|
+
where{{object_schema_name(fk[:parent_object_id]) => im.call(schema || current_schema)}}.
|
150
|
+
where{{object_name(fk[:parent_object_id]) => im.call(table)}}.
|
151
|
+
select{[fk[:name],
|
152
|
+
fk[:delete_referential_action],
|
153
|
+
fk[:update_referential_action],
|
154
|
+
pc[:name].as(:column),
|
155
|
+
rc[:name].as(:referenced_column),
|
156
|
+
object_schema_name(fk[:referenced_object_id]).as(:schema),
|
157
|
+
object_name(fk[:referenced_object_id]).as(:table)]}.
|
158
|
+
order(fk[:name], fkc[:constraint_column_id])
|
158
159
|
h = {}
|
159
160
|
ds.each do |row|
|
160
161
|
if r = h[row[:name]]
|
@@ -179,17 +180,18 @@ module Sequel
|
|
179
180
|
m = output_identifier_meth
|
180
181
|
im = input_identifier_meth
|
181
182
|
indexes = {}
|
183
|
+
i = Sequel[:i]
|
182
184
|
ds = metadata_dataset.from(Sequel.lit('[sys].[tables]').as(:t)).
|
183
185
|
join(Sequel.lit('[sys].[indexes]').as(:i), :object_id=>:object_id).
|
184
186
|
join(Sequel.lit('[sys].[index_columns]').as(:ic), :object_id=>:object_id, :index_id=>:index_id).
|
185
187
|
join(Sequel.lit('[sys].[columns]').as(:c), :object_id=>:object_id, :column_id=>:column_id).
|
186
|
-
select(:
|
187
|
-
where{{
|
188
|
-
where(:
|
189
|
-
order(:
|
188
|
+
select(i[:name], i[:is_unique], Sequel[:c][:name].as(:column)).
|
189
|
+
where{{t[:name]=>im.call(table)}}.
|
190
|
+
where(i[:is_primary_key]=>0, i[:is_disabled]=>0).
|
191
|
+
order(i[:name], Sequel[:ic][:index_column_id])
|
190
192
|
|
191
193
|
if supports_partial_indexes?
|
192
|
-
ds = ds.where(:
|
194
|
+
ds = ds.where(i[:has_filter]=>0)
|
193
195
|
end
|
194
196
|
|
195
197
|
ds.each do |r|
|
@@ -313,6 +315,11 @@ module Sequel
|
|
313
315
|
SQL_BEGIN
|
314
316
|
end
|
315
317
|
|
318
|
+
# MSSQL does not allow adding primary key constraints to NULLable columns.
|
319
|
+
def can_add_primary_key_constraint_on_nullable_columns?
|
320
|
+
false
|
321
|
+
end
|
322
|
+
|
316
323
|
# Handle MSSQL specific default format.
|
317
324
|
def column_schema_normalize_default(default, type)
|
318
325
|
if m = MSSQL_DEFAULT_RE.match(default)
|
@@ -365,7 +372,7 @@ module Sequel
|
|
365
372
|
def default_constraint_name(table, column_name)
|
366
373
|
if server_version >= 9000000
|
367
374
|
table_name = schema_and_table(table).compact.join('.')
|
368
|
-
self[:
|
375
|
+
self[Sequel[:sys][:default_constraints]].
|
369
376
|
where{{:parent_object_id => Sequel::SQL::Function.new(:object_id, table_name), col_name(:parent_object_id, :parent_column_id) => column_name.to_s}}.
|
370
377
|
get(:name)
|
371
378
|
end
|
@@ -390,7 +397,7 @@ module Sequel
|
|
390
397
|
# Backbone of the tables and views support.
|
391
398
|
def information_schema_tables(type, opts)
|
392
399
|
m = output_identifier_meth
|
393
|
-
metadata_dataset.from(:
|
400
|
+
metadata_dataset.from(Sequel[:information_schema][:tables].as(:t)).
|
394
401
|
select(:table_name).
|
395
402
|
filter(:table_type=>type, :table_schema=>(opts[:schema]||'dbo').to_s).
|
396
403
|
map{|x| m.call(x[:table_name])}
|
@@ -453,17 +460,17 @@ module Sequel
|
|
453
460
|
get(:indid)
|
454
461
|
pk_cols = metadata_dataset.from(sys_qual.call(Sequel.lit('sysindexkeys')).as(:sik)).
|
455
462
|
join(sys_qual.call(Sequel.lit('syscolumns')).as(:sc), :id=>:id, :colid=>:colid).
|
456
|
-
where
|
457
|
-
select_order_map
|
463
|
+
where{{sik[:id]=>table_id, sik[:indid]=>pk_index_id}}.
|
464
|
+
select_order_map{sc[:name]}
|
458
465
|
|
459
|
-
ds = metadata_dataset.from(inf_sch_qual.call(:
|
460
|
-
join(inf_sch_qual.call(:
|
466
|
+
ds = metadata_dataset.from(inf_sch_qual.call(Sequel[:information_schema][:tables]).as(:t)).
|
467
|
+
join(inf_sch_qual.call(Sequel[:information_schema][:columns]).as(:c), :table_catalog=>:table_catalog,
|
461
468
|
:table_schema => :table_schema, :table_name => :table_name).
|
462
|
-
select(:
|
463
|
-
|
469
|
+
select{[column_name.as(:column), data_type.as(:db_type), character_maximum_length.as(:max_chars), column_default.as(:default), is_nullable.as(:allow_null), numeric_precision.as(:column_size), numeric_scale.as(:scale)]}.
|
470
|
+
where{{c[:table_name]=>tn}}
|
464
471
|
|
465
472
|
if schema = opts[:schema]
|
466
|
-
ds.
|
473
|
+
ds = ds.where{{c[:table_schema]=>schema}}
|
467
474
|
end
|
468
475
|
|
469
476
|
ds.map do |row|
|
@@ -567,12 +574,13 @@ module Sequel
|
|
567
574
|
ROWS_ONLY = " ROWS ONLY".freeze
|
568
575
|
FETCH_NEXT = " FETCH NEXT ".freeze
|
569
576
|
|
577
|
+
NON_SQL_OPTIONS = (Dataset::NON_SQL_OPTIONS + [:disable_insert_output]).freeze
|
578
|
+
|
570
579
|
Dataset.def_mutation_method(:disable_insert_output, :output, :module=>self)
|
571
580
|
Dataset.def_sql_method(self, :delete, %w'with delete from output from2 where')
|
572
581
|
Dataset.def_sql_method(self, :insert, %w'with insert into columns output values')
|
573
582
|
Dataset.def_sql_method(self, :update, [['if is_2005_or_later?', %w'with update limit table set output from where'], ['else', %w'update table set output from where']])
|
574
583
|
|
575
|
-
|
576
584
|
# Allow overriding of the mssql_unicode_strings option at the dataset level.
|
577
585
|
attr_writer :mssql_unicode_strings
|
578
586
|
|
@@ -953,6 +961,11 @@ module Sequel
|
|
953
961
|
is_2008_or_later? ? :values : :union
|
954
962
|
end
|
955
963
|
|
964
|
+
# Dataset options that do not affect the generated SQL.
|
965
|
+
def non_sql_options
|
966
|
+
NON_SQL_OPTIONS
|
967
|
+
end
|
968
|
+
|
956
969
|
def select_into_sql(sql)
|
957
970
|
if i = @opts[:into]
|
958
971
|
sql << INTO
|