sequel 4.9.0 → 4.10.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.
- checksums.yaml +4 -4
- data/CHANGELOG +79 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/Rakefile +2 -12
- data/bin/sequel +1 -0
- data/doc/advanced_associations.rdoc +82 -25
- data/doc/association_basics.rdoc +21 -22
- data/doc/core_extensions.rdoc +1 -1
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.10.0.txt +226 -0
- data/doc/security.rdoc +1 -0
- data/doc/testing.rdoc +7 -7
- data/doc/transactions.rdoc +8 -0
- data/lib/sequel/adapters/jdbc.rb +160 -168
- data/lib/sequel/adapters/jdbc/db2.rb +17 -18
- data/lib/sequel/adapters/jdbc/derby.rb +5 -28
- data/lib/sequel/adapters/jdbc/h2.rb +11 -22
- data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
- data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
- data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
- data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
- data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
- data/lib/sequel/adapters/openbase.rb +1 -7
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +3 -6
- data/lib/sequel/adapters/shared/cubrid.rb +24 -9
- data/lib/sequel/adapters/shared/db2.rb +13 -5
- data/lib/sequel/adapters/shared/firebird.rb +16 -16
- data/lib/sequel/adapters/shared/informix.rb +2 -5
- data/lib/sequel/adapters/shared/mssql.rb +72 -63
- data/lib/sequel/adapters/shared/mysql.rb +72 -40
- data/lib/sequel/adapters/shared/oracle.rb +27 -15
- data/lib/sequel/adapters/shared/postgres.rb +24 -44
- data/lib/sequel/adapters/shared/progress.rb +1 -5
- data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
- data/lib/sequel/adapters/shared/sqlite.rb +21 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
- data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
- data/lib/sequel/core.rb +14 -9
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +12 -0
- data/lib/sequel/database/query.rb +4 -1
- data/lib/sequel/database/schema_methods.rb +3 -2
- data/lib/sequel/database/transactions.rb +47 -17
- data/lib/sequel/dataset/features.rb +12 -2
- data/lib/sequel/dataset/mutation.rb +2 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/dataset/sql.rb +132 -70
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/null_dataset.rb +8 -4
- data/lib/sequel/extensions/pg_array.rb +4 -4
- data/lib/sequel/extensions/pg_row.rb +1 -0
- data/lib/sequel/model/associations.rb +468 -188
- data/lib/sequel/model/base.rb +88 -13
- data/lib/sequel/plugins/association_pks.rb +23 -64
- data/lib/sequel/plugins/auto_validations.rb +3 -2
- data/lib/sequel/plugins/dataset_associations.rb +1 -3
- data/lib/sequel/plugins/many_through_many.rb +18 -65
- data/lib/sequel/plugins/pg_array_associations.rb +97 -86
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
- data/lib/sequel/plugins/rcte_tree.rb +12 -16
- data/lib/sequel/plugins/sharding.rb +21 -3
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
- data/lib/sequel/plugins/subclasses.rb +1 -9
- data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
- data/lib/sequel/plugins/tree.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +57 -15
- data/spec/adapters/mysql_spec.rb +11 -0
- data/spec/bin_spec.rb +2 -2
- data/spec/core/database_spec.rb +38 -4
- data/spec/core/dataset_spec.rb +45 -7
- data/spec/core/placeholder_literalizer_spec.rb +17 -0
- data/spec/core/schema_spec.rb +6 -1
- data/spec/extensions/active_model_spec.rb +18 -9
- data/spec/extensions/association_pks_spec.rb +20 -18
- data/spec/extensions/association_proxies_spec.rb +9 -9
- data/spec/extensions/auto_validations_spec.rb +6 -0
- data/spec/extensions/columns_introspection_spec.rb +1 -0
- data/spec/extensions/constraint_validations_spec.rb +3 -1
- data/spec/extensions/many_through_many_spec.rb +191 -111
- data/spec/extensions/pg_array_associations_spec.rb +133 -103
- data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
- data/spec/extensions/rcte_tree_spec.rb +35 -27
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
- data/spec/extensions/sharding_spec.rb +2 -2
- data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
- data/spec/extensions/to_dot_spec.rb +1 -0
- data/spec/extensions/touch_spec.rb +2 -2
- data/spec/integration/associations_test.rb +130 -37
- data/spec/integration/dataset_test.rb +17 -0
- data/spec/integration/model_test.rb +17 -0
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/transaction_test.rb +25 -1
- data/spec/model/association_reflection_spec.rb +63 -24
- data/spec/model/associations_spec.rb +104 -57
- data/spec/model/base_spec.rb +14 -1
- data/spec/model/class_dataset_methods_spec.rb +1 -0
- data/spec/model/eager_loading_spec.rb +221 -74
- data/spec/model/model_spec.rb +119 -1
- metadata +4 -2
@@ -145,6 +145,14 @@ module Sequel
|
|
145
145
|
super && (server_version <= 50512 || server_version >= 50523)
|
146
146
|
end
|
147
147
|
|
148
|
+
# Support fractional timestamps on MySQL 5.6.5+ if the :fractional_seconds
|
149
|
+
# Database option is used. Technically, MySQL 5.6.4+ supports them, but
|
150
|
+
# automatic initialization of datetime values wasn't supported to 5.6.5+,
|
151
|
+
# and this is related to that.
|
152
|
+
def supports_timestamp_usecs?
|
153
|
+
@supports_timestamp_usecs ||= server_version >= 50605 && typecast_value_boolean(opts[:fractional_seconds])
|
154
|
+
end
|
155
|
+
|
148
156
|
# MySQL supports transaction isolation levels
|
149
157
|
def supports_transaction_isolation_levels?
|
150
158
|
true
|
@@ -185,7 +193,11 @@ module Sequel
|
|
185
193
|
sql = super
|
186
194
|
op[:table] = related
|
187
195
|
op[:key] ||= primary_key_from_schema(related)
|
188
|
-
sql << ", ADD
|
196
|
+
sql << ", ADD "
|
197
|
+
if constraint_name = op.delete(:foreign_key_constraint_name)
|
198
|
+
sql << "CONSTRAINT #{quote_identifier(constraint_name)} "
|
199
|
+
end
|
200
|
+
sql << "FOREIGN KEY (#{quote_identifier(op[:name])})#{column_references_sql(op)}"
|
189
201
|
else
|
190
202
|
super
|
191
203
|
end
|
@@ -292,9 +304,8 @@ module Sequel
|
|
292
304
|
# Use XA START to start a new prepared transaction if the :prepare
|
293
305
|
# option is given.
|
294
306
|
def begin_transaction(conn, opts=OPTS)
|
295
|
-
if (s = opts[:prepare]) && (
|
307
|
+
if (s = opts[:prepare]) && savepoint_level(conn) == 1
|
296
308
|
log_connection_execute(conn, "XA START #{literal(s)}")
|
297
|
-
th[:savepoint_level] += 1
|
298
309
|
else
|
299
310
|
super
|
300
311
|
end
|
@@ -315,7 +326,7 @@ module Sequel
|
|
315
326
|
# Prepare the XA transaction for a two-phase commit if the
|
316
327
|
# :prepare option is given.
|
317
328
|
def commit_transaction(conn, opts=OPTS)
|
318
|
-
if (s = opts[:prepare]) &&
|
329
|
+
if (s = opts[:prepare]) && savepoint_level(conn) <= 1
|
319
330
|
log_connection_execute(conn, "XA END #{literal(s)}")
|
320
331
|
log_connection_execute(conn, "XA PREPARE #{literal(s)}")
|
321
332
|
else
|
@@ -421,7 +432,7 @@ module Sequel
|
|
421
432
|
|
422
433
|
# Rollback the currently open XA transaction
|
423
434
|
def rollback_transaction(conn, opts=OPTS)
|
424
|
-
if (s = opts[:prepare]) &&
|
435
|
+
if (s = opts[:prepare]) && savepoint_level(conn) <= 1
|
425
436
|
log_connection_execute(conn, "XA END #{literal(s)}")
|
426
437
|
log_connection_execute(conn, "XA PREPARE #{literal(s)}")
|
427
438
|
log_connection_execute(conn, "XA ROLLBACK #{literal(s)}")
|
@@ -462,6 +473,12 @@ module Sequel
|
|
462
473
|
end
|
463
474
|
end
|
464
475
|
|
476
|
+
# Split DROP INDEX ops on MySQL 5.6+, as dropping them in the same
|
477
|
+
# statement as dropping a related foreign key causes an error.
|
478
|
+
def split_alter_table_op?(op)
|
479
|
+
server_version >= 50600 && (op[:op] == :drop_index || (op[:op] == :drop_constraint && op[:type] == :unique))
|
480
|
+
end
|
481
|
+
|
465
482
|
# MySQL can combine multiple alter table ops into a single query.
|
466
483
|
def supports_combining_alter_table_ops?
|
467
484
|
true
|
@@ -496,7 +513,9 @@ module Sequel
|
|
496
513
|
# MySQL has both datetime and timestamp classes, most people are going
|
497
514
|
# to want datetime
|
498
515
|
def type_literal_generic_datetime(column)
|
499
|
-
if
|
516
|
+
if supports_timestamp_usecs?
|
517
|
+
:'datetime(6)'
|
518
|
+
elsif column[:default] == Sequel::CURRENT_TIMESTAMP
|
500
519
|
:timestamp
|
501
520
|
else
|
502
521
|
:datetime
|
@@ -504,9 +523,17 @@ module Sequel
|
|
504
523
|
end
|
505
524
|
|
506
525
|
# MySQL has both datetime and timestamp classes, most people are going
|
507
|
-
# to want datetime
|
526
|
+
# to want datetime.
|
508
527
|
def type_literal_generic_time(column)
|
509
|
-
column[:only_time]
|
528
|
+
if column[:only_time]
|
529
|
+
if supports_timestamp_usecs?
|
530
|
+
:'time(6)'
|
531
|
+
else
|
532
|
+
:time
|
533
|
+
end
|
534
|
+
else
|
535
|
+
type_literal_generic_datetime(column)
|
536
|
+
end
|
510
537
|
end
|
511
538
|
|
512
539
|
# MySQL doesn't have a true boolean class, so it uses tinyint(1)
|
@@ -522,10 +549,6 @@ module Sequel
|
|
522
549
|
COMMA_SEPARATOR = ', '.freeze
|
523
550
|
FOR_SHARE = ' LOCK IN SHARE MODE'.freeze
|
524
551
|
SQL_CALC_FOUND_ROWS = ' SQL_CALC_FOUND_ROWS'.freeze
|
525
|
-
DELETE_CLAUSE_METHODS = Dataset.clause_methods(:delete, %w'delete from where order limit')
|
526
|
-
INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'insert ignore into columns values on_duplicate_key_update')
|
527
|
-
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'select distinct calc_found_rows columns from join where group having compounds order limit lock')
|
528
|
-
UPDATE_CLAUSE_METHODS = Dataset.clause_methods(:update, %w'update ignore table set where order limit')
|
529
552
|
APOS = Dataset::APOS
|
530
553
|
APOS_RE = Dataset::APOS_RE
|
531
554
|
DOUBLE_APOS = Dataset::DOUBLE_APOS
|
@@ -566,6 +589,15 @@ module Sequel
|
|
566
589
|
BLOB_START = "0x".freeze
|
567
590
|
EMPTY_BLOB = "''".freeze
|
568
591
|
HSTAR = "H*".freeze
|
592
|
+
CURRENT_TIMESTAMP_56 = 'CURRENT_TIMESTAMP(6)'.freeze
|
593
|
+
|
594
|
+
# Comes directly from MySQL's documentation, used for queries with limits without offsets
|
595
|
+
ONLY_OFFSET = ",18446744073709551615".freeze
|
596
|
+
|
597
|
+
Dataset.def_sql_method(self, :delete, %w'delete from where order limit')
|
598
|
+
Dataset.def_sql_method(self, :insert, %w'insert ignore into columns values on_duplicate_key_update')
|
599
|
+
Dataset.def_sql_method(self, :select, %w'select distinct calc_found_rows columns from join where group having compounds order limit lock')
|
600
|
+
Dataset.def_sql_method(self, :update, %w'update ignore table set where order limit')
|
569
601
|
|
570
602
|
include Sequel::Dataset::Replace
|
571
603
|
|
@@ -610,6 +642,18 @@ module Sequel
|
|
610
642
|
end
|
611
643
|
end
|
612
644
|
|
645
|
+
# MySQL's CURRENT_TIMESTAMP does not use fractional seconds,
|
646
|
+
# even if the database itself supports fractional seconds. If
|
647
|
+
# MySQL 5.6.4+ is being used, use a value that will return
|
648
|
+
# fractional seconds.
|
649
|
+
def constant_sql_append(sql, constant)
|
650
|
+
if constant == :CURRENT_TIMESTAMP && supports_timestamp_usecs?
|
651
|
+
sql << CURRENT_TIMESTAMP_56
|
652
|
+
else
|
653
|
+
super
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
613
657
|
# Use GROUP BY instead of DISTINCT ON if arguments are provided.
|
614
658
|
def distinct(*args)
|
615
659
|
args.empty? ? super : group(*args)
|
@@ -706,13 +750,6 @@ module Sequel
|
|
706
750
|
clone(:on_duplicate_key_update => args)
|
707
751
|
end
|
708
752
|
|
709
|
-
# MySQL specific syntax for inserting multiple values at once.
|
710
|
-
def multi_insert_sql(columns, values)
|
711
|
-
sql = LiteralString.new('VALUES ')
|
712
|
-
expression_list_append(sql, values.map{|r| Array(r)})
|
713
|
-
[insert_sql(columns, sql)]
|
714
|
-
end
|
715
|
-
|
716
753
|
# MySQL uses the nonstandard ` (backtick) for quoting identifiers.
|
717
754
|
def quoted_identifier_append(sql, c)
|
718
755
|
sql << BACKTICK << c.to_s.gsub(BACKTICK_RE, DOUBLE_BACKTICK) << BACKTICK
|
@@ -734,6 +771,11 @@ module Sequel
|
|
734
771
|
false
|
735
772
|
end
|
736
773
|
|
774
|
+
# MySQL does not support limits in correlated subqueries (or any subqueries that use IN).
|
775
|
+
def supports_limits_in_correlated_subqueries?
|
776
|
+
false
|
777
|
+
end
|
778
|
+
|
737
779
|
# MySQL supports modifying joined datasets
|
738
780
|
def supports_modifying_joins?
|
739
781
|
true
|
@@ -754,7 +796,7 @@ module Sequel
|
|
754
796
|
# ignores them. Also, using them seems to cause problems on 1.9. Since
|
755
797
|
# they are ignored anyway, not using them is probably best.
|
756
798
|
def supports_timestamp_usecs?
|
757
|
-
|
799
|
+
db.supports_timestamp_usecs?
|
758
800
|
end
|
759
801
|
|
760
802
|
# Sets up the update methods to use UPDATE IGNORE.
|
@@ -769,11 +811,6 @@ module Sequel
|
|
769
811
|
|
770
812
|
private
|
771
813
|
|
772
|
-
# MySQL supports the ORDER BY and LIMIT clauses for DELETE statements
|
773
|
-
def delete_clause_methods
|
774
|
-
DELETE_CLAUSE_METHODS
|
775
|
-
end
|
776
|
-
|
777
814
|
# Consider the first table in the joined dataset is the table to delete
|
778
815
|
# from, but include the others for the purposes of selecting rows.
|
779
816
|
def delete_from_sql(sql)
|
@@ -788,12 +825,6 @@ module Sequel
|
|
788
825
|
end
|
789
826
|
end
|
790
827
|
|
791
|
-
# MySQL supports the IGNORE and ON DUPLICATE KEY UPDATE clauses for INSERT statements
|
792
|
-
def insert_clause_methods
|
793
|
-
INSERT_CLAUSE_METHODS
|
794
|
-
end
|
795
|
-
alias replace_clause_methods insert_clause_methods
|
796
|
-
|
797
828
|
# MySQL doesn't use the SQL standard DEFAULT VALUES.
|
798
829
|
def insert_columns_sql(sql)
|
799
830
|
values = opts[:values]
|
@@ -905,11 +936,17 @@ module Sequel
|
|
905
936
|
BOOL_TRUE
|
906
937
|
end
|
907
938
|
|
908
|
-
# MySQL
|
909
|
-
def
|
910
|
-
|
939
|
+
# MySQL supports multiple rows in INSERT.
|
940
|
+
def multi_insert_sql_strategy
|
941
|
+
:values
|
911
942
|
end
|
912
|
-
|
943
|
+
|
944
|
+
def select_only_offset_sql(sql)
|
945
|
+
sql << LIMIT
|
946
|
+
literal_append(sql, @opts[:offset])
|
947
|
+
sql << ONLY_OFFSET
|
948
|
+
end
|
949
|
+
|
913
950
|
# Support FOR SHARE locking when using the :share lock style.
|
914
951
|
def select_lock_sql(sql)
|
915
952
|
@opts[:lock] == :share ? (sql << FOR_SHARE) : super
|
@@ -920,11 +957,6 @@ module Sequel
|
|
920
957
|
sql << SQL_CALC_FOUND_ROWS if opts[:calc_found_rows]
|
921
958
|
end
|
922
959
|
|
923
|
-
# MySQL supports the ORDER BY and LIMIT clauses for UPDATE statements
|
924
|
-
def update_clause_methods
|
925
|
-
UPDATE_CLAUSE_METHODS
|
926
|
-
end
|
927
|
-
|
928
960
|
# MySQL uses WITH ROLLUP syntax.
|
929
961
|
def uses_with_rollup?
|
930
962
|
true
|
@@ -247,7 +247,6 @@ module Sequel
|
|
247
247
|
end
|
248
248
|
|
249
249
|
module DatasetMethods
|
250
|
-
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'with select distinct columns from join where group having compounds order lock')
|
251
250
|
ROW_NUMBER_EXPRESSION = LiteralString.new('ROWNUM').freeze
|
252
251
|
SPACE = Dataset::SPACE
|
253
252
|
APOS = Dataset::APOS
|
@@ -259,9 +258,13 @@ module Sequel
|
|
259
258
|
BOOL_FALSE = "'N'".freeze
|
260
259
|
BOOL_TRUE = "'Y'".freeze
|
261
260
|
HSTAR = "H*".freeze
|
262
|
-
DUAL =
|
261
|
+
DUAL = ' FROM DUAL'.freeze
|
263
262
|
BITAND_PROC = lambda{|a, b| Sequel.lit(["CAST(BITAND(", ", ", ") AS INTEGER)"], a, b)}
|
264
263
|
|
264
|
+
include(Module.new do
|
265
|
+
Dataset.def_sql_method(self, :select, %w'with select distinct columns from join where group having compounds order lock')
|
266
|
+
end)
|
267
|
+
|
265
268
|
def complex_expression_sql_append(sql, op, args)
|
266
269
|
case op
|
267
270
|
when :&
|
@@ -334,7 +337,7 @@ module Sequel
|
|
334
337
|
def select_sql
|
335
338
|
return super if @opts[:sql]
|
336
339
|
if o = @opts[:offset]
|
337
|
-
columns = clone(:append_sql=>'').columns
|
340
|
+
columns = clone(:append_sql=>'', :placeholder_literal_null=>true).columns
|
338
341
|
dsa1 = dataset_alias(1)
|
339
342
|
rn = row_number_column
|
340
343
|
limit = @opts[:limit]
|
@@ -366,6 +369,10 @@ module Sequel
|
|
366
369
|
true
|
367
370
|
end
|
368
371
|
|
372
|
+
def supports_cte?(type=:select)
|
373
|
+
type == :select
|
374
|
+
end
|
375
|
+
|
369
376
|
# Oracle supports GROUP BY CUBE
|
370
377
|
def supports_group_cube?
|
371
378
|
true
|
@@ -386,6 +393,16 @@ module Sequel
|
|
386
393
|
false
|
387
394
|
end
|
388
395
|
|
396
|
+
# Oracle does not support limits in correlated subqueries.
|
397
|
+
def supports_limits_in_correlated_subqueries?
|
398
|
+
false
|
399
|
+
end
|
400
|
+
|
401
|
+
# Oracle does not support offsets in correlated subqueries.
|
402
|
+
def supports_offsets_in_correlated_subqueries?
|
403
|
+
false
|
404
|
+
end
|
405
|
+
|
389
406
|
# Oracle does not support SELECT *, column
|
390
407
|
def supports_select_all_and_column?
|
391
408
|
false
|
@@ -420,6 +437,10 @@ module Sequel
|
|
420
437
|
TIMESTAMP_FORMAT
|
421
438
|
end
|
422
439
|
|
440
|
+
def empty_from_sql
|
441
|
+
DUAL
|
442
|
+
end
|
443
|
+
|
423
444
|
# If this dataset is associated with a sequence, return the most recently
|
424
445
|
# inserted sequence value.
|
425
446
|
def execute_insert(sql, opts=OPTS)
|
@@ -457,18 +478,9 @@ module Sequel
|
|
457
478
|
BOOL_TRUE
|
458
479
|
end
|
459
480
|
|
460
|
-
#
|
461
|
-
def
|
462
|
-
|
463
|
-
end
|
464
|
-
|
465
|
-
# Modify the SQL to add the list of tables to select FROM
|
466
|
-
# Oracle doesn't support select without FROM clause
|
467
|
-
# so add the dummy DUAL table if the dataset doesn't select
|
468
|
-
# from a table.
|
469
|
-
def select_from_sql(sql)
|
470
|
-
sql << FROM
|
471
|
-
source_list_append(sql, @opts[:from] || DUAL)
|
481
|
+
# Oracle can insert multiple rows using a UNION
|
482
|
+
def multi_insert_sql_strategy
|
483
|
+
:union
|
472
484
|
end
|
473
485
|
|
474
486
|
# Oracle supports quoted function names.
|
@@ -410,6 +410,8 @@ module Sequel
|
|
410
410
|
# any named types.
|
411
411
|
def reset_conversion_procs
|
412
412
|
@conversion_procs = get_conversion_procs
|
413
|
+
conversion_procs_updated
|
414
|
+
@conversion_procs
|
413
415
|
end
|
414
416
|
|
415
417
|
# Reset the primary key sequence for the given table, basing it on the
|
@@ -540,6 +542,7 @@ module Sequel
|
|
540
542
|
convert_named_procs_to_procs(named_procs).each do |oid, pr|
|
541
543
|
procs[oid] ||= pr
|
542
544
|
end
|
545
|
+
conversion_procs_updated
|
543
546
|
end
|
544
547
|
end
|
545
548
|
|
@@ -596,7 +599,7 @@ module Sequel
|
|
596
599
|
# If the :prepare option is given and we aren't in a savepoint,
|
597
600
|
# prepare the transaction for a two-phase commit.
|
598
601
|
def commit_transaction(conn, opts=OPTS)
|
599
|
-
if (s = opts[:prepare]) &&
|
602
|
+
if (s = opts[:prepare]) && savepoint_level(conn) <= 1
|
600
603
|
log_connection_execute(conn, "PREPARE TRANSACTION #{literal(s)}")
|
601
604
|
else
|
602
605
|
super
|
@@ -658,6 +661,11 @@ module Sequel
|
|
658
661
|
end
|
659
662
|
end
|
660
663
|
|
664
|
+
# Callback used when conversion procs are updated.
|
665
|
+
def conversion_procs_updated
|
666
|
+
nil
|
667
|
+
end
|
668
|
+
|
661
669
|
# Convert the hash of named conversion procs into a hash a oid conversion procs.
|
662
670
|
def convert_named_procs_to_procs(named_procs)
|
663
671
|
h = {}
|
@@ -674,6 +682,7 @@ module Sequel
|
|
674
682
|
oids.each do |oid|
|
675
683
|
procs[oid] = PG_TYPES[oid]
|
676
684
|
end
|
685
|
+
conversion_procs_updated
|
677
686
|
end
|
678
687
|
|
679
688
|
EXCLUSION_CONSTRAINT_SQL_STATE = '23P01'.freeze
|
@@ -1094,27 +1103,19 @@ module Sequel
|
|
1094
1103
|
BOOL_FALSE = 'false'.freeze
|
1095
1104
|
BOOL_TRUE = 'true'.freeze
|
1096
1105
|
COMMA_SEPARATOR = ', '.freeze
|
1097
|
-
DELETE_CLAUSE_METHODS = Dataset.clause_methods(:delete, %w'delete from using where returning')
|
1098
|
-
DELETE_CLAUSE_METHODS_91 = Dataset.clause_methods(:delete, %w'with delete from using where returning')
|
1099
1106
|
EXCLUSIVE = 'EXCLUSIVE'.freeze
|
1100
1107
|
EXPLAIN = 'EXPLAIN '.freeze
|
1101
1108
|
EXPLAIN_ANALYZE = 'EXPLAIN ANALYZE '.freeze
|
1102
1109
|
FOR_SHARE = ' FOR SHARE'.freeze
|
1103
|
-
INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'insert into columns values returning')
|
1104
|
-
INSERT_CLAUSE_METHODS_91 = Dataset.clause_methods(:insert, %w'with insert into columns values returning')
|
1105
1110
|
NULL = LiteralString.new('NULL').freeze
|
1106
1111
|
PG_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
|
1107
1112
|
QUERY_PLAN = 'QUERY PLAN'.to_sym
|
1108
1113
|
ROW_EXCLUSIVE = 'ROW EXCLUSIVE'.freeze
|
1109
1114
|
ROW_SHARE = 'ROW SHARE'.freeze
|
1110
|
-
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
|
1111
|
-
SELECT_CLAUSE_METHODS_84 = Dataset.clause_methods(:select, %w'with select distinct columns from join where group having window compounds order limit lock')
|
1112
1115
|
SHARE = 'SHARE'.freeze
|
1113
1116
|
SHARE_ROW_EXCLUSIVE = 'SHARE ROW EXCLUSIVE'.freeze
|
1114
1117
|
SHARE_UPDATE_EXCLUSIVE = 'SHARE UPDATE EXCLUSIVE'.freeze
|
1115
1118
|
SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
|
1116
|
-
UPDATE_CLAUSE_METHODS = Dataset.clause_methods(:update, %w'update table set from where returning')
|
1117
|
-
UPDATE_CLAUSE_METHODS_91 = Dataset.clause_methods(:update, %w'with update table set from where returning')
|
1118
1119
|
SPACE = Dataset::SPACE
|
1119
1120
|
FROM = Dataset::FROM
|
1120
1121
|
APOS = Dataset::APOS
|
@@ -1133,6 +1134,11 @@ module Sequel
|
|
1133
1134
|
EMPTY_STRING = ''.freeze
|
1134
1135
|
LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each{|s| s.freeze}
|
1135
1136
|
|
1137
|
+
Dataset.def_sql_method(self, :delete, [['if server_version >= 90100', %w'with delete from using where returning'], ['else', %w'delete from using where returning']])
|
1138
|
+
Dataset.def_sql_method(self, :insert, [['if server_version >= 90100', %w'with insert into columns values returning'], ['else', %w'insert into columns values returning']])
|
1139
|
+
Dataset.def_sql_method(self, :select, [['if server_version >= 80400', %w'with select distinct columns from join where group having window compounds order limit lock'], ['else', %w'select distinct columns from join where group having compounds order limit lock']])
|
1140
|
+
Dataset.def_sql_method(self, :update, [['if server_version >= 90100', %w'with update table set from where returning'], ['else', %w'update table set from where returning']])
|
1141
|
+
|
1136
1142
|
# Shared methods for prepared statements when used with PostgreSQL databases.
|
1137
1143
|
module PreparedStatementMethods
|
1138
1144
|
# Override insert action to use RETURNING if the server supports it.
|
@@ -1279,11 +1285,12 @@ module Sequel
|
|
1279
1285
|
nil
|
1280
1286
|
end
|
1281
1287
|
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1288
|
+
def supports_cte?(type=:select)
|
1289
|
+
if type == :select
|
1290
|
+
server_version >= 80400
|
1291
|
+
else
|
1292
|
+
server_version >= 90100
|
1293
|
+
end
|
1287
1294
|
end
|
1288
1295
|
|
1289
1296
|
# PostgreSQL supports using the WITH clause in subqueries if it
|
@@ -1393,15 +1400,6 @@ module Sequel
|
|
1393
1400
|
raise(InvalidOperation, "Joined datasets cannot be truncated") if opts[:join]
|
1394
1401
|
end
|
1395
1402
|
|
1396
|
-
# PostgreSQL allows deleting from joined datasets
|
1397
|
-
def delete_clause_methods
|
1398
|
-
if server_version >= 90100
|
1399
|
-
DELETE_CLAUSE_METHODS_91
|
1400
|
-
else
|
1401
|
-
DELETE_CLAUSE_METHODS
|
1402
|
-
end
|
1403
|
-
end
|
1404
|
-
|
1405
1403
|
# Only include the primary table in the main delete clause
|
1406
1404
|
def delete_from_sql(sql)
|
1407
1405
|
sql << FROM
|
@@ -1413,15 +1411,6 @@ module Sequel
|
|
1413
1411
|
join_from_sql(:USING, sql)
|
1414
1412
|
end
|
1415
1413
|
|
1416
|
-
# PostgreSQL allows a RETURNING clause.
|
1417
|
-
def insert_clause_methods
|
1418
|
-
if server_version >= 90100
|
1419
|
-
INSERT_CLAUSE_METHODS_91
|
1420
|
-
else
|
1421
|
-
INSERT_CLAUSE_METHODS
|
1422
|
-
end
|
1423
|
-
end
|
1424
|
-
|
1425
1414
|
# Return the primary key to use for RETURNING in an INSERT statement
|
1426
1415
|
def insert_pk
|
1427
1416
|
if (f = opts[:from]) && !f.empty?
|
@@ -1479,9 +1468,9 @@ module Sequel
|
|
1479
1468
|
BOOL_TRUE
|
1480
1469
|
end
|
1481
1470
|
|
1482
|
-
#
|
1483
|
-
def
|
1484
|
-
|
1471
|
+
# PostgreSQL supports multiple rows in INSERT.
|
1472
|
+
def multi_insert_sql_strategy
|
1473
|
+
:values
|
1485
1474
|
end
|
1486
1475
|
|
1487
1476
|
# PostgreSQL requires parentheses around compound datasets if they use
|
@@ -1537,15 +1526,6 @@ module Sequel
|
|
1537
1526
|
SQL::StringExpression.new(:'||', *cols)
|
1538
1527
|
end
|
1539
1528
|
|
1540
|
-
# PostgreSQL splits the main table from the joined tables
|
1541
|
-
def update_clause_methods
|
1542
|
-
if server_version >= 90100
|
1543
|
-
UPDATE_CLAUSE_METHODS_91
|
1544
|
-
else
|
1545
|
-
UPDATE_CLAUSE_METHODS
|
1546
|
-
end
|
1547
|
-
end
|
1548
|
-
|
1549
1529
|
# Use FROM to specify additional tables in an update query
|
1550
1530
|
def update_from_sql(sql)
|
1551
1531
|
join_from_sql(:FROM, sql)
|