sequel 5.39.0 → 5.63.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 +308 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +57 -25
- data/bin/sequel +11 -3
- data/doc/advanced_associations.rdoc +13 -13
- data/doc/association_basics.rdoc +89 -24
- data/doc/cheat_sheet.rdoc +11 -3
- data/doc/migration.rdoc +12 -6
- data/doc/model_hooks.rdoc +1 -1
- data/doc/object_model.rdoc +8 -8
- data/doc/opening_databases.rdoc +18 -11
- data/doc/postgresql.rdoc +16 -8
- data/doc/querying.rdoc +5 -3
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/release_notes/5.50.0.txt +78 -0
- data/doc/release_notes/5.51.0.txt +47 -0
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/release_notes/5.53.0.txt +23 -0
- data/doc/release_notes/5.54.0.txt +27 -0
- data/doc/release_notes/5.55.0.txt +21 -0
- data/doc/release_notes/5.56.0.txt +51 -0
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/release_notes/5.59.0.txt +73 -0
- data/doc/release_notes/5.60.0.txt +22 -0
- data/doc/release_notes/5.61.0.txt +43 -0
- data/doc/release_notes/5.62.0.txt +132 -0
- data/doc/release_notes/5.63.0.txt +33 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +9 -9
- data/doc/sql.rdoc +27 -15
- data/doc/testing.rdoc +22 -11
- data/doc/transactions.rdoc +6 -6
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +17 -17
- data/lib/sequel/adapters/amalgalite.rb +3 -5
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +8 -0
- data/lib/sequel/adapters/jdbc/h2.rb +60 -10
- data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -4
- data/lib/sequel/adapters/jdbc.rb +16 -18
- data/lib/sequel/adapters/mysql.rb +80 -67
- data/lib/sequel/adapters/mysql2.rb +54 -49
- data/lib/sequel/adapters/odbc.rb +6 -2
- data/lib/sequel/adapters/oracle.rb +3 -3
- data/lib/sequel/adapters/postgres.rb +83 -40
- data/lib/sequel/adapters/shared/access.rb +11 -1
- data/lib/sequel/adapters/shared/db2.rb +30 -0
- data/lib/sequel/adapters/shared/mssql.rb +58 -7
- data/lib/sequel/adapters/shared/mysql.rb +40 -2
- data/lib/sequel/adapters/shared/oracle.rb +76 -0
- data/lib/sequel/adapters/shared/postgres.rb +418 -174
- data/lib/sequel/adapters/shared/sqlanywhere.rb +10 -0
- data/lib/sequel/adapters/shared/sqlite.rb +102 -11
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +60 -18
- data/lib/sequel/adapters/tinytds.rb +1 -1
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -7
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -1
- data/lib/sequel/connection_pool/single.rb +6 -8
- data/lib/sequel/connection_pool/threaded.rb +8 -8
- data/lib/sequel/connection_pool/timed_queue.rb +257 -0
- data/lib/sequel/connection_pool.rb +47 -30
- data/lib/sequel/core.rb +28 -18
- data/lib/sequel/database/connecting.rb +26 -2
- data/lib/sequel/database/misc.rb +69 -14
- data/lib/sequel/database/query.rb +38 -1
- data/lib/sequel/database/schema_generator.rb +45 -52
- data/lib/sequel/database/schema_methods.rb +17 -1
- data/lib/sequel/dataset/actions.rb +107 -13
- data/lib/sequel/dataset/features.rb +20 -0
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +118 -16
- data/lib/sequel/dataset/sql.rb +177 -47
- data/lib/sequel/extensions/_model_pg_row.rb +0 -12
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/any_not_empty.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/core_refinements.rb +36 -11
- data/lib/sequel/extensions/date_arithmetic.rb +71 -31
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +5 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +9 -1
- data/lib/sequel/extensions/is_distinct_from.rb +141 -0
- data/lib/sequel/extensions/looser_typecasting.rb +3 -0
- data/lib/sequel/extensions/migration.rb +7 -2
- data/lib/sequel/extensions/named_timezones.rb +26 -6
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +23 -3
- data/lib/sequel/extensions/pg_array_ops.rb +2 -2
- data/lib/sequel/extensions/pg_auto_parameterize.rb +478 -0
- data/lib/sequel/extensions/pg_enum.rb +1 -1
- data/lib/sequel/extensions/pg_extended_date_support.rb +28 -25
- data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
- data/lib/sequel/extensions/pg_hstore.rb +6 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +53 -3
- data/lib/sequel/extensions/pg_inet.rb +10 -11
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +45 -19
- data/lib/sequel/extensions/pg_json.rb +13 -15
- data/lib/sequel/extensions/pg_json_ops.rb +73 -2
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_multirange.rb +367 -0
- data/lib/sequel/extensions/pg_range.rb +10 -23
- data/lib/sequel/extensions/pg_range_ops.rb +37 -9
- data/lib/sequel/extensions/pg_row.rb +19 -13
- data/lib/sequel/extensions/pg_row_ops.rb +1 -1
- data/lib/sequel/extensions/query.rb +2 -0
- data/lib/sequel/extensions/s.rb +2 -1
- data/lib/sequel/extensions/schema_dumper.rb +13 -2
- data/lib/sequel/extensions/server_block.rb +8 -12
- data/lib/sequel/extensions/sql_comments.rb +110 -3
- data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
- data/lib/sequel/extensions/string_agg.rb +1 -1
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/extensions/symbol_aref.rb +2 -0
- data/lib/sequel/model/associations.rb +325 -96
- data/lib/sequel/model/base.rb +51 -27
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +5 -0
- data/lib/sequel/plugins/association_proxies.rb +2 -0
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +87 -15
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +10 -4
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +1 -1
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/finder.rb +3 -1
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/instance_specific_default.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +39 -24
- data/lib/sequel/plugins/lazy_attributes.rb +3 -0
- data/lib/sequel/plugins/list.rb +3 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +12 -7
- data/lib/sequel/plugins/pg_array_associations.rb +56 -38
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +3 -1
- data/lib/sequel/plugins/prepared_statements.rb +10 -1
- data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
- data/lib/sequel/plugins/rcte_tree.rb +27 -19
- data/lib/sequel/plugins/require_valid_schema.rb +67 -0
- data/lib/sequel/plugins/serialization.rb +9 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +8 -0
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/tactical_eager_loading.rb +23 -10
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validate_associated.rb +22 -12
- data/lib/sequel/plugins/validation_helpers.rb +38 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/timezones.rb +12 -14
- data/lib/sequel/version.rb +1 -1
- metadata +97 -43
data/lib/sequel/dataset/query.rb
CHANGED
|
@@ -65,7 +65,7 @@ module Sequel
|
|
|
65
65
|
Sequel.synchronize{EXTENSIONS[ext] = block}
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
# On Ruby 2.4+, use clone(:
|
|
68
|
+
# On Ruby 2.4+, use clone(freeze: false) to create clones, because
|
|
69
69
|
# we use true freezing in that case, and we need to modify the opts
|
|
70
70
|
# in the frozen copy.
|
|
71
71
|
#
|
|
@@ -116,7 +116,7 @@ module Sequel
|
|
|
116
116
|
# DB[:items].order(:id).distinct(:id) # SQL: SELECT DISTINCT ON (id) * FROM items ORDER BY id
|
|
117
117
|
# DB[:items].order(:id).distinct{func(:id)} # SQL: SELECT DISTINCT ON (func(id)) * FROM items ORDER BY id
|
|
118
118
|
#
|
|
119
|
-
# There is support for
|
|
119
|
+
# There is support for emulating the DISTINCT ON support in MySQL, but it
|
|
120
120
|
# does not support the ORDER of the dataset, and also doesn't work in many
|
|
121
121
|
# cases if the ONLY_FULL_GROUP_BY sql_mode is used, which is the default on
|
|
122
122
|
# MySQL 5.7.5+.
|
|
@@ -508,6 +508,7 @@ module Sequel
|
|
|
508
508
|
# argument.
|
|
509
509
|
# :implicit_qualifier :: The name to use for qualifying implicit conditions. By default,
|
|
510
510
|
# the last joined or primary table is used.
|
|
511
|
+
# :join_using :: Force the using of JOIN USING, even if +expr+ is not an array of symbols.
|
|
511
512
|
# :reset_implicit_qualifier :: Can set to false to ignore this join when future joins determine qualifier
|
|
512
513
|
# for implicit conditions.
|
|
513
514
|
# :qualify :: Can be set to false to not do any implicit qualification. Can be set
|
|
@@ -541,7 +542,7 @@ module Sequel
|
|
|
541
542
|
return s.join_table(type, ds, expr, options, &block)
|
|
542
543
|
end
|
|
543
544
|
|
|
544
|
-
using_join = expr.is_a?(Array) && !expr.empty? && expr.all?{|x| x.is_a?(Symbol)}
|
|
545
|
+
using_join = options[:join_using] || (expr.is_a?(Array) && !expr.empty? && expr.all?{|x| x.is_a?(Symbol)})
|
|
545
546
|
if using_join && !supports_join_using?
|
|
546
547
|
h = {}
|
|
547
548
|
expr.each{|e| h[e] = e}
|
|
@@ -616,7 +617,7 @@ module Sequel
|
|
|
616
617
|
UNCONDITIONED_JOIN_TYPES.each do |jtype|
|
|
617
618
|
class_eval(<<-END, __FILE__, __LINE__+1)
|
|
618
619
|
def #{jtype}_join(table, opts=Sequel::OPTS)
|
|
619
|
-
raise(Sequel::Error, '#{jtype}_join does not accept join table blocks') if
|
|
620
|
+
raise(Sequel::Error, '#{jtype}_join does not accept join table blocks') if defined?(yield)
|
|
620
621
|
raise(Sequel::Error, '#{jtype}_join 2nd argument should be an options hash, not conditions') unless opts.is_a?(Hash)
|
|
621
622
|
join_table(:#{jtype}, table, nil, opts)
|
|
622
623
|
end
|
|
@@ -677,6 +678,56 @@ module Sequel
|
|
|
677
678
|
clone(:lock => style)
|
|
678
679
|
end
|
|
679
680
|
|
|
681
|
+
# Return a dataset with a WHEN MATCHED THEN DELETE clause added to the
|
|
682
|
+
# MERGE statement. If a block is passed, treat it as a virtual row and
|
|
683
|
+
# use it as additional conditions for the match.
|
|
684
|
+
#
|
|
685
|
+
# merge_delete
|
|
686
|
+
# # WHEN MATCHED THEN DELETE
|
|
687
|
+
#
|
|
688
|
+
# merge_delete{a > 30}
|
|
689
|
+
# # WHEN MATCHED AND (a > 30) THEN DELETE
|
|
690
|
+
def merge_delete(&block)
|
|
691
|
+
_merge_when(:type=>:delete, &block)
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
# Return a dataset with a WHEN NOT MATCHED THEN INSERT clause added to the
|
|
695
|
+
# MERGE statement. If a block is passed, treat it as a virtual row and
|
|
696
|
+
# use it as additional conditions for the match.
|
|
697
|
+
#
|
|
698
|
+
# The arguments provided can be any arguments that would be accepted by
|
|
699
|
+
# #insert.
|
|
700
|
+
#
|
|
701
|
+
# merge_insert(i1: :i2, a: Sequel[:b]+11)
|
|
702
|
+
# # WHEN NOT MATCHED THEN INSERT (i1, a) VALUES (i2, (b + 11))
|
|
703
|
+
#
|
|
704
|
+
# merge_insert(:i2, Sequel[:b]+11){a > 30}
|
|
705
|
+
# # WHEN NOT MATCHED AND (a > 30) THEN INSERT VALUES (i2, (b + 11))
|
|
706
|
+
def merge_insert(*values, &block)
|
|
707
|
+
_merge_when(:type=>:insert, :values=>values, &block)
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
# Return a dataset with a WHEN MATCHED THEN UPDATE clause added to the
|
|
711
|
+
# MERGE statement. If a block is passed, treat it as a virtual row and
|
|
712
|
+
# use it as additional conditions for the match.
|
|
713
|
+
#
|
|
714
|
+
# merge_update(i1: Sequel[:i1]+:i2+10, a: Sequel[:a]+:b+20)
|
|
715
|
+
# # WHEN MATCHED THEN UPDATE SET i1 = (i1 + i2 + 10), a = (a + b + 20)
|
|
716
|
+
#
|
|
717
|
+
# merge_update(i1: :i2){a > 30}
|
|
718
|
+
# # WHEN MATCHED AND (a > 30) THEN UPDATE SET i1 = i2
|
|
719
|
+
def merge_update(values, &block)
|
|
720
|
+
_merge_when(:type=>:update, :values=>values, &block)
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
# Return a dataset with the source and join condition to use for the MERGE statement.
|
|
724
|
+
#
|
|
725
|
+
# merge_using(:m2, i1: :i2)
|
|
726
|
+
# # USING m2 ON (i1 = i2)
|
|
727
|
+
def merge_using(source, join_condition)
|
|
728
|
+
clone(:merge_using => [source, join_condition].freeze)
|
|
729
|
+
end
|
|
730
|
+
|
|
680
731
|
# Returns a cloned dataset without a row_proc.
|
|
681
732
|
#
|
|
682
733
|
# ds = DB[:items].with_row_proc(:invert.to_proc)
|
|
@@ -699,7 +750,7 @@ module Sequel
|
|
|
699
750
|
end
|
|
700
751
|
|
|
701
752
|
# Returns a copy of the dataset with a specified order. Can be safely combined with limit.
|
|
702
|
-
# If you call limit with an offset, it will override
|
|
753
|
+
# If you call limit with an offset, it will override the offset if you've called
|
|
703
754
|
# offset first.
|
|
704
755
|
#
|
|
705
756
|
# DB[:items].offset(10) # SELECT * FROM items OFFSET 10
|
|
@@ -736,7 +787,7 @@ module Sequel
|
|
|
736
787
|
# DB[:items].order(Sequel.lit('a + b')) # SELECT * FROM items ORDER BY a + b
|
|
737
788
|
# DB[:items].order(Sequel[:a] + :b) # SELECT * FROM items ORDER BY (a + b)
|
|
738
789
|
# DB[:items].order(Sequel.desc(:name)) # SELECT * FROM items ORDER BY name DESC
|
|
739
|
-
# DB[:items].order(Sequel.asc(:name, :
|
|
790
|
+
# DB[:items].order(Sequel.asc(:name, nulls: :last)) # SELECT * FROM items ORDER BY name ASC NULLS LAST
|
|
740
791
|
# DB[:items].order{sum(name).desc} # SELECT * FROM items ORDER BY sum(name) DESC
|
|
741
792
|
# DB[:items].order(nil) # SELECT * FROM items
|
|
742
793
|
def order(*columns, &block)
|
|
@@ -806,13 +857,13 @@ module Sequel
|
|
|
806
857
|
# DB[:items].returning(nil) # RETURNING NULL
|
|
807
858
|
# DB[:items].returning(:id, :name) # RETURNING id, name
|
|
808
859
|
#
|
|
809
|
-
# DB[:items].returning.insert(:
|
|
860
|
+
# DB[:items].returning.insert(a: 1) do |hash|
|
|
810
861
|
# # hash for each row inserted, with values for all columns
|
|
811
862
|
# end
|
|
812
|
-
# DB[:items].returning.update(:
|
|
863
|
+
# DB[:items].returning.update(a: 1) do |hash|
|
|
813
864
|
# # hash for each row updated, with values for all columns
|
|
814
865
|
# end
|
|
815
|
-
# DB[:items].returning.delete(:
|
|
866
|
+
# DB[:items].returning.delete(a: 1) do |hash|
|
|
816
867
|
# # hash for each row deleted, with values for all columns
|
|
817
868
|
# end
|
|
818
869
|
def returning(*values)
|
|
@@ -1051,7 +1102,7 @@ module Sequel
|
|
|
1051
1102
|
# referenced in window functions. See Sequel::SQL::Window for a list of
|
|
1052
1103
|
# options that can be passed in. Example:
|
|
1053
1104
|
#
|
|
1054
|
-
# DB[:items].window(:w, :
|
|
1105
|
+
# DB[:items].window(:w, partition: :c1, order: :c2)
|
|
1055
1106
|
# # SELECT * FROM items WINDOW w AS (PARTITION BY c1 ORDER BY c2)
|
|
1056
1107
|
def window(name, opts)
|
|
1057
1108
|
clone(:window=>((@opts[:window]||EMPTY_ARRAY) + [[name, SQL::Window.new(opts)].freeze]).freeze)
|
|
@@ -1059,13 +1110,12 @@ module Sequel
|
|
|
1059
1110
|
|
|
1060
1111
|
# Add a common table expression (CTE) with the given name and a dataset that defines the CTE.
|
|
1061
1112
|
# A common table expression acts as an inline view for the query.
|
|
1113
|
+
#
|
|
1062
1114
|
# Options:
|
|
1063
1115
|
# :args :: Specify the arguments/columns for the CTE, should be an array of symbols.
|
|
1064
1116
|
# :recursive :: Specify that this is a recursive CTE
|
|
1065
|
-
#
|
|
1066
|
-
# PostgreSQL Specific Options:
|
|
1067
1117
|
# :materialized :: Set to false to force inlining of the CTE, or true to force not inlining
|
|
1068
|
-
# the CTE (PostgreSQL 12+).
|
|
1118
|
+
# the CTE (PostgreSQL 12+/SQLite 3.35+).
|
|
1069
1119
|
#
|
|
1070
1120
|
# DB[:items].with(:items, DB[:syx].where(Sequel[:name].like('A%')))
|
|
1071
1121
|
# # WITH items AS (SELECT * FROM syx WHERE (name LIKE 'A%' ESCAPE '\')) SELECT * FROM items
|
|
@@ -1081,20 +1131,60 @@ module Sequel
|
|
|
1081
1131
|
|
|
1082
1132
|
# Add a recursive common table expression (CTE) with the given name, a dataset that
|
|
1083
1133
|
# defines the nonrecursive part of the CTE, and a dataset that defines the recursive part
|
|
1084
|
-
# of the CTE.
|
|
1134
|
+
# of the CTE.
|
|
1135
|
+
#
|
|
1136
|
+
# Options:
|
|
1085
1137
|
# :args :: Specify the arguments/columns for the CTE, should be an array of symbols.
|
|
1086
1138
|
# :union_all :: Set to false to use UNION instead of UNION ALL combining the nonrecursive and recursive parts.
|
|
1087
1139
|
#
|
|
1140
|
+
# PostgreSQL 14+ Options:
|
|
1141
|
+
# :cycle :: Stop recursive searching when a cycle is detected. Includes two columns in the
|
|
1142
|
+
# result of the CTE, a cycle column indicating whether a cycle was detected for
|
|
1143
|
+
# the current row, and a path column for the path traversed to get to the current
|
|
1144
|
+
# row. If given, must be a hash with the following keys:
|
|
1145
|
+
# :columns :: (required) The column or array of columns to use to detect a cycle.
|
|
1146
|
+
# If the value of these columns match columns already traversed, then
|
|
1147
|
+
# a cycle is detected, and recursive searching will not traverse beyond
|
|
1148
|
+
# the cycle (the CTE will include the row where the cycle was detected).
|
|
1149
|
+
# :cycle_column :: The name of the cycle column in the output, defaults to :is_cycle.
|
|
1150
|
+
# :cycle_value :: The value of the cycle column in the output if the current row was
|
|
1151
|
+
# detected as a cycle, defaults to true.
|
|
1152
|
+
# :noncycle_value :: The value of the cycle column in the output if the current row
|
|
1153
|
+
# was not detected as a cycle, defaults to false. Only respected
|
|
1154
|
+
# if :cycle_value is given.
|
|
1155
|
+
# :path_column :: The name of the path column in the output, defaults to :path.
|
|
1156
|
+
# :search :: Include an order column in the result of the CTE that allows for breadth or
|
|
1157
|
+
# depth first searching. If given, must be a hash with the following keys:
|
|
1158
|
+
# :by :: (required) The column or array of columns to search by.
|
|
1159
|
+
# :order_column :: The name of the order column in the output, defaults to :ordercol.
|
|
1160
|
+
# :type :: Set to :breadth to use breadth-first searching (depth-first searching
|
|
1161
|
+
# is the default).
|
|
1162
|
+
#
|
|
1088
1163
|
# DB[:t].with_recursive(:t,
|
|
1089
1164
|
# DB[:i1].select(:id, :parent_id).where(parent_id: nil),
|
|
1090
1165
|
# DB[:i1].join(:t, id: :parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]),
|
|
1091
|
-
# :
|
|
1166
|
+
# args: [:id, :parent_id])
|
|
1092
1167
|
#
|
|
1093
1168
|
# # WITH RECURSIVE t(id, parent_id) AS (
|
|
1094
1169
|
# # SELECT id, parent_id FROM i1 WHERE (parent_id IS NULL)
|
|
1095
1170
|
# # UNION ALL
|
|
1096
1171
|
# # SELECT i1.id, i1.parent_id FROM i1 INNER JOIN t ON (t.id = i1.parent_id)
|
|
1097
1172
|
# # ) SELECT * FROM t
|
|
1173
|
+
#
|
|
1174
|
+
# DB[:t].with_recursive(:t,
|
|
1175
|
+
# DB[:i1].where(parent_id: nil),
|
|
1176
|
+
# DB[:i1].join(:t, id: :parent_id).select_all(:i1),
|
|
1177
|
+
# search: {by: :id, type: :breadth},
|
|
1178
|
+
# cycle: {columns: :id, cycle_value: 1, noncycle_value: 2})
|
|
1179
|
+
#
|
|
1180
|
+
# # WITH RECURSIVE t AS (
|
|
1181
|
+
# # SELECT * FROM i1 WHERE (parent_id IS NULL)
|
|
1182
|
+
# # UNION ALL
|
|
1183
|
+
# # (SELECT i1.* FROM i1 INNER JOIN t ON (t.id = i1.parent_id))
|
|
1184
|
+
# # )
|
|
1185
|
+
# # SEARCH BREADTH FIRST BY id SET ordercol
|
|
1186
|
+
# # CYCLE id SET is_cycle TO 1 DEFAULT 2 USING path
|
|
1187
|
+
# # SELECT * FROM t
|
|
1098
1188
|
def with_recursive(name, nonrecursive, recursive, opts=OPTS)
|
|
1099
1189
|
raise(Error, 'This dataset does not support common table expressions') unless supports_cte?
|
|
1100
1190
|
if hoist_cte?(nonrecursive)
|
|
@@ -1151,7 +1241,7 @@ module Sequel
|
|
|
1151
1241
|
#
|
|
1152
1242
|
# You can also provide a method name and arguments to call to get the SQL:
|
|
1153
1243
|
#
|
|
1154
|
-
# DB[:items].with_sql(:insert_sql, :
|
|
1244
|
+
# DB[:items].with_sql(:insert_sql, b: 1) # INSERT INTO items (b) VALUES (1)
|
|
1155
1245
|
#
|
|
1156
1246
|
# Note that datasets that specify custom SQL using this method will generally
|
|
1157
1247
|
# ignore future dataset methods that modify the SQL used, as specifying custom SQL
|
|
@@ -1247,6 +1337,18 @@ module Sequel
|
|
|
1247
1337
|
end
|
|
1248
1338
|
end
|
|
1249
1339
|
|
|
1340
|
+
# Append to the current MERGE WHEN clauses.
|
|
1341
|
+
# Mutates the hash to add the conditions, if a virtual row block is passed.
|
|
1342
|
+
def _merge_when(hash, &block)
|
|
1343
|
+
hash[:conditions] = Sequel.virtual_row(&block) if block
|
|
1344
|
+
|
|
1345
|
+
if merge_when = @opts[:merge_when]
|
|
1346
|
+
clone(:merge_when => (merge_when.dup << hash.freeze).freeze)
|
|
1347
|
+
else
|
|
1348
|
+
clone(:merge_when => [hash.freeze].freeze)
|
|
1349
|
+
end
|
|
1350
|
+
end
|
|
1351
|
+
|
|
1250
1352
|
# Add the given filter condition. Arguments:
|
|
1251
1353
|
# clause :: Symbol or which SQL clause to effect, should be :where or :having
|
|
1252
1354
|
# cond :: The filter condition to add
|
data/lib/sequel/dataset/sql.rb
CHANGED
|
@@ -22,31 +22,9 @@ module Sequel
|
|
|
22
22
|
def insert_sql(*values)
|
|
23
23
|
return static_sql(@opts[:sql]) if @opts[:sql]
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
columns = []
|
|
28
|
-
|
|
29
|
-
case values.size
|
|
30
|
-
when 0
|
|
31
|
-
return insert_sql(OPTS)
|
|
32
|
-
when 1
|
|
33
|
-
case vals = values[0]
|
|
34
|
-
when Hash
|
|
35
|
-
values = []
|
|
36
|
-
vals.each do |k,v|
|
|
37
|
-
columns << k
|
|
38
|
-
values << v
|
|
39
|
-
end
|
|
40
|
-
when Dataset, Array, LiteralString
|
|
41
|
-
values = vals
|
|
42
|
-
end
|
|
43
|
-
when 2
|
|
44
|
-
if (v0 = values[0]).is_a?(Array) && ((v1 = values[1]).is_a?(Array) || v1.is_a?(Dataset) || v1.is_a?(LiteralString))
|
|
45
|
-
columns, values = v0, v1
|
|
46
|
-
raise(Error, "Different number of values and columns given to insert_sql") if values.is_a?(Array) and columns.length != values.length
|
|
47
|
-
end
|
|
48
|
-
end
|
|
25
|
+
check_insert_allowed!
|
|
49
26
|
|
|
27
|
+
columns, values = _parse_insert_sql_args(values)
|
|
50
28
|
if values.is_a?(Array) && values.empty? && !insert_supports_empty_values?
|
|
51
29
|
columns, values = insert_empty_columns_values
|
|
52
30
|
elsif values.is_a?(Dataset) && hoist_cte?(values) && supports_cte?(:insert)
|
|
@@ -112,6 +90,31 @@ module Sequel
|
|
|
112
90
|
end
|
|
113
91
|
end
|
|
114
92
|
|
|
93
|
+
# The SQL to use for the MERGE statement.
|
|
94
|
+
def merge_sql
|
|
95
|
+
raise Error, "This database doesn't support MERGE" unless supports_merge?
|
|
96
|
+
if sql = opts[:sql]
|
|
97
|
+
return static_sql(sql)
|
|
98
|
+
end
|
|
99
|
+
if sql = cache_get(:_merge_sql)
|
|
100
|
+
return sql
|
|
101
|
+
end
|
|
102
|
+
source, join_condition = @opts[:merge_using]
|
|
103
|
+
raise Error, "No USING clause for MERGE" unless source
|
|
104
|
+
sql = @opts[:append_sql] || sql_string_origin
|
|
105
|
+
|
|
106
|
+
select_with_sql(sql)
|
|
107
|
+
sql << "MERGE INTO "
|
|
108
|
+
source_list_append(sql, @opts[:from])
|
|
109
|
+
sql << " USING "
|
|
110
|
+
identifier_append(sql, source)
|
|
111
|
+
sql << " ON "
|
|
112
|
+
literal_append(sql, join_condition)
|
|
113
|
+
_merge_when_sql(sql)
|
|
114
|
+
cache_set(:_merge_sql, sql) if cache_sql?
|
|
115
|
+
sql
|
|
116
|
+
end
|
|
117
|
+
|
|
115
118
|
# Returns an array of insert statements for inserting multiple records.
|
|
116
119
|
# This method is used by +multi_insert+ to format insert statements and
|
|
117
120
|
# expects a keys array and and an array of value arrays.
|
|
@@ -172,7 +175,7 @@ module Sequel
|
|
|
172
175
|
# than one table.
|
|
173
176
|
def update_sql(values = OPTS)
|
|
174
177
|
return static_sql(opts[:sql]) if opts[:sql]
|
|
175
|
-
|
|
178
|
+
check_update_allowed!
|
|
176
179
|
check_not_limited!(:update)
|
|
177
180
|
|
|
178
181
|
case values
|
|
@@ -215,7 +218,7 @@ module Sequel
|
|
|
215
218
|
lines << "def #{'_' if priv}#{type}_sql"
|
|
216
219
|
lines << 'if sql = opts[:sql]; return static_sql(sql) end' unless priv
|
|
217
220
|
lines << "if sql = cache_get(:_#{type}_sql); return sql end" if cacheable
|
|
218
|
-
lines << '
|
|
221
|
+
lines << 'check_delete_allowed!' << 'check_not_limited!(:delete)' if type == :delete
|
|
219
222
|
lines << 'sql = @opts[:append_sql] || sql_string_origin'
|
|
220
223
|
|
|
221
224
|
if clauses.all?{|c| c.is_a?(Array)}
|
|
@@ -559,11 +562,9 @@ module Sequel
|
|
|
559
562
|
# Append literalization of JOIN USING clause to SQL string.
|
|
560
563
|
def join_using_clause_sql_append(sql, jc)
|
|
561
564
|
join_clause_sql_append(sql, jc)
|
|
562
|
-
sql
|
|
563
|
-
column_list_append(sql, jc.using)
|
|
564
|
-
sql << ')'
|
|
565
|
+
join_using_clause_using_sql_append(sql, jc.using)
|
|
565
566
|
end
|
|
566
|
-
|
|
567
|
+
|
|
567
568
|
# Append literalization of negative boolean constant to SQL string.
|
|
568
569
|
def negative_boolean_constant_sql_append(sql, constant)
|
|
569
570
|
sql << 'NOT '
|
|
@@ -852,6 +853,83 @@ module Sequel
|
|
|
852
853
|
|
|
853
854
|
private
|
|
854
855
|
|
|
856
|
+
# Append the INSERT sql used in a MERGE
|
|
857
|
+
def _merge_insert_sql(sql, data)
|
|
858
|
+
sql << " THEN INSERT"
|
|
859
|
+
columns, values = _parse_insert_sql_args(data[:values])
|
|
860
|
+
_insert_columns_sql(sql, columns)
|
|
861
|
+
_insert_values_sql(sql, values)
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
def _merge_update_sql(sql, data)
|
|
865
|
+
sql << " THEN UPDATE SET "
|
|
866
|
+
update_sql_values_hash(sql, data[:values])
|
|
867
|
+
end
|
|
868
|
+
|
|
869
|
+
def _merge_delete_sql(sql, data)
|
|
870
|
+
sql << " THEN DELETE"
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
# Mapping of merge types to related SQL
|
|
874
|
+
MERGE_TYPE_SQL = {
|
|
875
|
+
:insert => ' WHEN NOT MATCHED',
|
|
876
|
+
:delete => ' WHEN MATCHED',
|
|
877
|
+
:update => ' WHEN MATCHED',
|
|
878
|
+
:matched => ' WHEN MATCHED',
|
|
879
|
+
:not_matched => ' WHEN NOT MATCHED',
|
|
880
|
+
}.freeze
|
|
881
|
+
private_constant :MERGE_TYPE_SQL
|
|
882
|
+
|
|
883
|
+
# Add the WHEN clauses to the MERGE SQL
|
|
884
|
+
def _merge_when_sql(sql)
|
|
885
|
+
raise Error, "no WHEN [NOT] MATCHED clauses provided for MERGE" unless merge_when = @opts[:merge_when]
|
|
886
|
+
merge_when.each do |data|
|
|
887
|
+
type = data[:type]
|
|
888
|
+
sql << MERGE_TYPE_SQL[type]
|
|
889
|
+
_merge_when_conditions_sql(sql, data)
|
|
890
|
+
send(:"_merge_#{type}_sql", sql, data)
|
|
891
|
+
end
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
# Append MERGE WHEN conditions, if there are conditions provided.
|
|
895
|
+
def _merge_when_conditions_sql(sql, data)
|
|
896
|
+
if data.has_key?(:conditions)
|
|
897
|
+
sql << " AND "
|
|
898
|
+
literal_append(sql, data[:conditions])
|
|
899
|
+
end
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
# Parse the values passed to insert_sql, returning columns and values
|
|
903
|
+
# to use for the INSERT. Returned columns is always an array, but can be empty
|
|
904
|
+
# for an INSERT without explicit column references. Returned values can be an
|
|
905
|
+
# array, dataset, or literal string.
|
|
906
|
+
def _parse_insert_sql_args(values)
|
|
907
|
+
columns = []
|
|
908
|
+
|
|
909
|
+
case values.size
|
|
910
|
+
when 0
|
|
911
|
+
values = []
|
|
912
|
+
when 1
|
|
913
|
+
case vals = values[0]
|
|
914
|
+
when Hash
|
|
915
|
+
values = []
|
|
916
|
+
vals.each do |k,v|
|
|
917
|
+
columns << k
|
|
918
|
+
values << v
|
|
919
|
+
end
|
|
920
|
+
when Dataset, Array, LiteralString
|
|
921
|
+
values = vals
|
|
922
|
+
end
|
|
923
|
+
when 2
|
|
924
|
+
if (v0 = values[0]).is_a?(Array) && ((v1 = values[1]).is_a?(Array) || v1.is_a?(Dataset) || v1.is_a?(LiteralString))
|
|
925
|
+
columns, values = v0, v1
|
|
926
|
+
raise(Error, "Different number of values and columns given to insert_sql") if values.is_a?(Array) and columns.length != values.length
|
|
927
|
+
end
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
[columns, values]
|
|
931
|
+
end
|
|
932
|
+
|
|
855
933
|
# Formats the truncate statement. Assumes the table given has already been
|
|
856
934
|
# literalized.
|
|
857
935
|
def _truncate_sql(table)
|
|
@@ -896,9 +974,10 @@ module Sequel
|
|
|
896
974
|
# Clone of this dataset usable in aggregate operations. Does
|
|
897
975
|
# a from_self if dataset contains any parameters that would
|
|
898
976
|
# affect normal aggregation, or just removes an existing
|
|
899
|
-
# order if not.
|
|
977
|
+
# order if not. Also removes the row_proc, which isn't needed
|
|
978
|
+
# for aggregate calculations.
|
|
900
979
|
def aggregate_dataset
|
|
901
|
-
options_overlap(COUNT_FROM_SELF_OPTS) ? from_self : unordered
|
|
980
|
+
(options_overlap(COUNT_FROM_SELF_OPTS) ? from_self : unordered).naked
|
|
902
981
|
end
|
|
903
982
|
|
|
904
983
|
# Append aliasing expression to SQL string.
|
|
@@ -918,10 +997,35 @@ module Sequel
|
|
|
918
997
|
!@opts[:no_cache_sql] && !cache_get(:_no_cache_sql)
|
|
919
998
|
end
|
|
920
999
|
|
|
921
|
-
# Raise an InvalidOperation exception if
|
|
1000
|
+
# Raise an InvalidOperation exception if modification is not allowed for this dataset.
|
|
1001
|
+
# Check whether it is allowed to insert into this dataset.
|
|
1002
|
+
# Only for backwards compatibility with older external adapters.
|
|
922
1003
|
def check_modification_allowed!
|
|
1004
|
+
# SEQUEL6: Remove
|
|
1005
|
+
Sequel::Deprecation.deprecate("Dataset#check_modification_allowed!", "Use check_{insert,delete,update,truncation}_allowed! instead")
|
|
1006
|
+
_check_modification_allowed!(supports_modifying_joins?)
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1009
|
+
# Check whether it is allowed to insert into this dataset.
|
|
1010
|
+
def check_insert_allowed!
|
|
1011
|
+
_check_modification_allowed!(false)
|
|
1012
|
+
end
|
|
1013
|
+
alias check_truncation_allowed! check_insert_allowed!
|
|
1014
|
+
|
|
1015
|
+
# Check whether it is allowed to delete from this dataset.
|
|
1016
|
+
def check_delete_allowed!
|
|
1017
|
+
_check_modification_allowed!(supports_deleting_joins?)
|
|
1018
|
+
end
|
|
1019
|
+
|
|
1020
|
+
# Check whether it is allowed to update this dataset.
|
|
1021
|
+
def check_update_allowed!
|
|
1022
|
+
_check_modification_allowed!(supports_updating_joins?)
|
|
1023
|
+
end
|
|
1024
|
+
|
|
1025
|
+
# Internals of the check_*_allowed! methods
|
|
1026
|
+
def _check_modification_allowed!(modifying_joins_supported)
|
|
923
1027
|
raise(InvalidOperation, "Grouped datasets cannot be modified") if opts[:group]
|
|
924
|
-
raise(InvalidOperation, "Joined datasets cannot be modified") if !
|
|
1028
|
+
raise(InvalidOperation, "Joined datasets cannot be modified") if !modifying_joins_supported && joined_dataset?
|
|
925
1029
|
end
|
|
926
1030
|
|
|
927
1031
|
# Raise error if the dataset uses limits or offsets.
|
|
@@ -930,11 +1034,6 @@ module Sequel
|
|
|
930
1034
|
raise InvalidOperation, "Dataset##{type} not supported on datasets with limits or offsets" if opts[:limit] || opts[:offset]
|
|
931
1035
|
end
|
|
932
1036
|
|
|
933
|
-
# Alias of check_modification_allowed!
|
|
934
|
-
def check_truncation_allowed!
|
|
935
|
-
check_modification_allowed!
|
|
936
|
-
end
|
|
937
|
-
|
|
938
1037
|
# Append column list to SQL string.
|
|
939
1038
|
# If the column list is empty, a wildcard (*) is appended.
|
|
940
1039
|
def column_list_append(sql, columns)
|
|
@@ -971,7 +1070,9 @@ module Sequel
|
|
|
971
1070
|
# operators unsupported by some databases. Used by adapters for databases
|
|
972
1071
|
# that don't support the operators natively.
|
|
973
1072
|
def complex_expression_emulate_append(sql, op, args)
|
|
1073
|
+
# :nocov:
|
|
974
1074
|
case op
|
|
1075
|
+
# :nocov:
|
|
975
1076
|
when :%
|
|
976
1077
|
complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.function(:MOD, a, b)}
|
|
977
1078
|
when :>>
|
|
@@ -1144,7 +1245,10 @@ module Sequel
|
|
|
1144
1245
|
end
|
|
1145
1246
|
|
|
1146
1247
|
def insert_columns_sql(sql)
|
|
1147
|
-
|
|
1248
|
+
_insert_columns_sql(sql, opts[:columns])
|
|
1249
|
+
end
|
|
1250
|
+
|
|
1251
|
+
def _insert_columns_sql(sql, columns)
|
|
1148
1252
|
if columns && !columns.empty?
|
|
1149
1253
|
sql << ' ('
|
|
1150
1254
|
identifier_list_append(sql, columns)
|
|
@@ -1163,7 +1267,11 @@ module Sequel
|
|
|
1163
1267
|
end
|
|
1164
1268
|
|
|
1165
1269
|
def insert_values_sql(sql)
|
|
1166
|
-
|
|
1270
|
+
_insert_values_sql(sql, opts[:values])
|
|
1271
|
+
end
|
|
1272
|
+
|
|
1273
|
+
def _insert_values_sql(sql, values)
|
|
1274
|
+
case values
|
|
1167
1275
|
when Array
|
|
1168
1276
|
if values.empty?
|
|
1169
1277
|
sql << " DEFAULT VALUES"
|
|
@@ -1196,6 +1304,13 @@ module Sequel
|
|
|
1196
1304
|
"#{join_type.to_s.gsub('_', ' ').upcase} JOIN"
|
|
1197
1305
|
end
|
|
1198
1306
|
|
|
1307
|
+
# Append USING clause for JOIN USING
|
|
1308
|
+
def join_using_clause_using_sql_append(sql, using_columns)
|
|
1309
|
+
sql << ' USING ('
|
|
1310
|
+
column_list_append(sql, using_columns)
|
|
1311
|
+
sql << ')'
|
|
1312
|
+
end
|
|
1313
|
+
|
|
1199
1314
|
# Append a literalization of the array to SQL string.
|
|
1200
1315
|
# Treats as an expression if an array of all two pairs, or as a SQL array otherwise.
|
|
1201
1316
|
def literal_array_append(sql, v)
|
|
@@ -1516,15 +1631,14 @@ module Sequel
|
|
|
1516
1631
|
|
|
1517
1632
|
def select_with_sql(sql)
|
|
1518
1633
|
return unless supports_cte?
|
|
1519
|
-
|
|
1520
|
-
return if !
|
|
1634
|
+
ctes = opts[:with]
|
|
1635
|
+
return if !ctes || ctes.empty?
|
|
1521
1636
|
sql << select_with_sql_base
|
|
1522
1637
|
c = false
|
|
1523
1638
|
comma = ', '
|
|
1524
|
-
|
|
1639
|
+
ctes.each do |cte|
|
|
1525
1640
|
sql << comma if c
|
|
1526
|
-
|
|
1527
|
-
literal_dataset_append(sql, w[:dataset])
|
|
1641
|
+
select_with_sql_cte(sql, cte)
|
|
1528
1642
|
c ||= true
|
|
1529
1643
|
end
|
|
1530
1644
|
sql << ' '
|
|
@@ -1537,6 +1651,11 @@ module Sequel
|
|
|
1537
1651
|
"WITH "
|
|
1538
1652
|
end
|
|
1539
1653
|
|
|
1654
|
+
def select_with_sql_cte(sql, cte)
|
|
1655
|
+
select_with_sql_prefix(sql, cte)
|
|
1656
|
+
literal_dataset_append(sql, cte[:dataset])
|
|
1657
|
+
end
|
|
1658
|
+
|
|
1540
1659
|
def select_with_sql_prefix(sql, w)
|
|
1541
1660
|
quote_identifier_append(sql, w[:name])
|
|
1542
1661
|
if args = w[:args]
|
|
@@ -1545,6 +1664,13 @@ module Sequel
|
|
|
1545
1664
|
sql << ')'
|
|
1546
1665
|
end
|
|
1547
1666
|
sql << ' AS '
|
|
1667
|
+
|
|
1668
|
+
case w[:materialized]
|
|
1669
|
+
when true
|
|
1670
|
+
sql << "MATERIALIZED "
|
|
1671
|
+
when false
|
|
1672
|
+
sql << "NOT MATERIALIZED "
|
|
1673
|
+
end
|
|
1548
1674
|
end
|
|
1549
1675
|
|
|
1550
1676
|
# Whether the symbol cache should be skipped when literalizing the dataset
|
|
@@ -1599,7 +1725,7 @@ module Sequel
|
|
|
1599
1725
|
# Append literalization of the subselect to SQL string.
|
|
1600
1726
|
def subselect_sql_append(sql, ds)
|
|
1601
1727
|
sds = subselect_sql_dataset(sql, ds)
|
|
1602
|
-
sds
|
|
1728
|
+
subselect_sql_append_sql(sql, sds)
|
|
1603
1729
|
unless sds.send(:cache_sql?)
|
|
1604
1730
|
# If subquery dataset does not allow caching SQL,
|
|
1605
1731
|
# then this dataset should not allow caching SQL.
|
|
@@ -1611,6 +1737,10 @@ module Sequel
|
|
|
1611
1737
|
ds.clone(:append_sql=>sql)
|
|
1612
1738
|
end
|
|
1613
1739
|
|
|
1740
|
+
def subselect_sql_append_sql(sql, ds)
|
|
1741
|
+
ds.sql
|
|
1742
|
+
end
|
|
1743
|
+
|
|
1614
1744
|
# The number of decimal digits of precision to use in timestamps.
|
|
1615
1745
|
def timestamp_precision
|
|
1616
1746
|
supports_timestamp_usecs? ? 6 : 0
|
|
@@ -23,18 +23,6 @@ module Sequel
|
|
|
23
23
|
super
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
# Handle Sequel::Model instances in bound variable arrays.
|
|
30
|
-
def bound_variable_array(arg)
|
|
31
|
-
case arg
|
|
32
|
-
when Sequel::Model
|
|
33
|
-
"\"(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(',').gsub(/("|\\)/, '\\\\\1')})\""
|
|
34
|
-
else
|
|
35
|
-
super
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
26
|
end
|
|
39
27
|
end
|
|
40
28
|
end
|