sequel 3.21.0 → 3.39.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 +1061 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +103 -63
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +67 -51
- data/doc/advanced_associations.rdoc +189 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +547 -0
- data/doc/opening_databases.rdoc +114 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- 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/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- 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 +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -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 +56 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +279 -97
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +125 -222
- data/lib/sequel/adapters/mysql2.rb +65 -56
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +368 -138
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +343 -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 +401 -116
- data/lib/sequel/adapters/shared/mysql.rb +424 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +257 -45
- data/lib/sequel/adapters/shared/postgres.rb +675 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +285 -96
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +28 -19
- data/lib/sequel/adapters/tinytds.rb +174 -22
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +43 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +190 -46
- data/lib/sequel/database/query.rb +272 -110
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +300 -67
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +305 -54
- data/lib/sequel/dataset/sql.rb +720 -292
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +537 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +313 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +208 -0
- data/lib/sequel/extensions/pg_range.rb +512 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -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 +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- 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 +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +55 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +649 -122
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +194 -66
- data/spec/adapters/mysql_spec.rb +475 -306
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +1982 -325
- data/spec/adapters/spec_helper.rb +9 -6
- data/spec/adapters/sqlite_spec.rb +203 -75
- data/spec/core/connection_pool_spec.rb +218 -93
- data/spec/core/database_spec.rb +956 -522
- data/spec/core/dataset_spec.rb +1631 -1242
- data/spec/core/expression_filters_spec.rb +690 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- 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/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +320 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +194 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- 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 +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -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 +8 -11
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +58 -67
- data/spec/extensions/validation_helpers_spec.rb +31 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +11 -5
- data/spec/integration/dataset_test.rb +717 -129
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +604 -147
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +367 -57
- data/spec/integration/spec_helper.rb +42 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +31 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +209 -80
- data/spec/core/core_sql_spec.rb +0 -451
data/lib/sequel/dataset/sql.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Dataset
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: User Methods relating to SQL Creation
|
|
4
|
+
# :section: 3 - User Methods relating to SQL Creation
|
|
5
5
|
# These are methods you can call to see what SQL will be generated by the dataset.
|
|
6
6
|
# ---------------------
|
|
7
7
|
|
|
@@ -20,7 +20,7 @@ module Sequel
|
|
|
20
20
|
# DB.select(1).where(DB[:items].exists)
|
|
21
21
|
# # SELECT 1 WHERE (EXISTS (SELECT * FROM items))
|
|
22
22
|
def exists
|
|
23
|
-
|
|
23
|
+
SQL::PlaceholderLiteralString.new(EXISTS, [self], true)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
# Returns an INSERT SQL query string. See +insert+.
|
|
@@ -49,10 +49,6 @@ module Sequel
|
|
|
49
49
|
end
|
|
50
50
|
when Dataset, Array, LiteralString
|
|
51
51
|
values = vals
|
|
52
|
-
else
|
|
53
|
-
if vals.respond_to?(:values) && (v = vals.values).is_a?(Hash)
|
|
54
|
-
return insert_sql(v)
|
|
55
|
-
end
|
|
56
52
|
end
|
|
57
53
|
when 2
|
|
58
54
|
if (v0 = values.at(0)).is_a?(Array) && ((v1 = values.at(1)).is_a?(Array) || v1.is_a?(Dataset) || v1.is_a?(LiteralString))
|
|
@@ -61,7 +57,10 @@ module Sequel
|
|
|
61
57
|
end
|
|
62
58
|
end
|
|
63
59
|
|
|
64
|
-
|
|
60
|
+
if values.is_a?(Array) && values.empty? && !insert_supports_empty_values?
|
|
61
|
+
columns = [columns().last]
|
|
62
|
+
values = [DEFAULT]
|
|
63
|
+
end
|
|
65
64
|
clone(:columns=>columns, :values=>values)._insert_sql
|
|
66
65
|
end
|
|
67
66
|
|
|
@@ -75,41 +74,47 @@ module Sequel
|
|
|
75
74
|
# DB[:items].literal(:x + 1 > :y) => "((x + 1) > y)"
|
|
76
75
|
#
|
|
77
76
|
# If an unsupported object is given, an +Error+ is raised.
|
|
78
|
-
def
|
|
77
|
+
def literal_append(sql, v)
|
|
79
78
|
case v
|
|
80
|
-
when String
|
|
81
|
-
return v if v.is_a?(LiteralString)
|
|
82
|
-
v.is_a?(SQL::Blob) ? literal_blob(v) : literal_string(v)
|
|
83
79
|
when Symbol
|
|
84
|
-
|
|
80
|
+
literal_symbol_append(sql, v)
|
|
81
|
+
when String
|
|
82
|
+
case v
|
|
83
|
+
when LiteralString
|
|
84
|
+
sql << v
|
|
85
|
+
when SQL::Blob
|
|
86
|
+
literal_blob_append(sql, v)
|
|
87
|
+
else
|
|
88
|
+
literal_string_append(sql, v)
|
|
89
|
+
end
|
|
85
90
|
when Integer
|
|
86
|
-
literal_integer(v)
|
|
91
|
+
sql << literal_integer(v)
|
|
87
92
|
when Hash
|
|
88
|
-
|
|
93
|
+
literal_hash_append(sql, v)
|
|
89
94
|
when SQL::Expression
|
|
90
|
-
|
|
95
|
+
literal_expression_append(sql, v)
|
|
91
96
|
when Float
|
|
92
|
-
literal_float(v)
|
|
97
|
+
sql << literal_float(v)
|
|
93
98
|
when BigDecimal
|
|
94
|
-
literal_big_decimal(v)
|
|
99
|
+
sql << literal_big_decimal(v)
|
|
95
100
|
when NilClass
|
|
96
|
-
literal_nil
|
|
101
|
+
sql << literal_nil
|
|
97
102
|
when TrueClass
|
|
98
|
-
literal_true
|
|
103
|
+
sql << literal_true
|
|
99
104
|
when FalseClass
|
|
100
|
-
literal_false
|
|
105
|
+
sql << literal_false
|
|
101
106
|
when Array
|
|
102
|
-
|
|
107
|
+
literal_array_append(sql, v)
|
|
103
108
|
when Time
|
|
104
|
-
literal_time(v)
|
|
109
|
+
sql << (v.is_a?(SQLTime) ? literal_sqltime(v) : literal_time(v))
|
|
105
110
|
when DateTime
|
|
106
|
-
literal_datetime(v)
|
|
111
|
+
sql << literal_datetime(v)
|
|
107
112
|
when Date
|
|
108
|
-
literal_date(v)
|
|
113
|
+
sql << literal_date(v)
|
|
109
114
|
when Dataset
|
|
110
|
-
|
|
115
|
+
literal_dataset_append(sql, v)
|
|
111
116
|
else
|
|
112
|
-
|
|
117
|
+
literal_other_append(sql, v)
|
|
113
118
|
end
|
|
114
119
|
end
|
|
115
120
|
|
|
@@ -143,8 +148,8 @@ module Sequel
|
|
|
143
148
|
if opts[:sql]
|
|
144
149
|
static_sql(opts[:sql])
|
|
145
150
|
else
|
|
146
|
-
|
|
147
|
-
raise(InvalidOperation, "Can't truncate filtered datasets") if opts[:where]
|
|
151
|
+
check_truncation_allowed!
|
|
152
|
+
raise(InvalidOperation, "Can't truncate filtered datasets") if opts[:where] || opts[:having]
|
|
148
153
|
_truncate_sql(source_list(opts[:from]))
|
|
149
154
|
end
|
|
150
155
|
end
|
|
@@ -163,7 +168,7 @@ module Sequel
|
|
|
163
168
|
end
|
|
164
169
|
|
|
165
170
|
# ---------------------
|
|
166
|
-
# :section: Internal Methods relating to SQL Creation
|
|
171
|
+
# :section: 9 - Internal Methods relating to SQL Creation
|
|
167
172
|
# These methods, while public, are not designed to be used directly by the end user.
|
|
168
173
|
# ---------------------
|
|
169
174
|
|
|
@@ -173,80 +178,239 @@ module Sequel
|
|
|
173
178
|
clauses.map{|clause| :"#{type}_#{clause}_sql"}.freeze
|
|
174
179
|
end
|
|
175
180
|
|
|
181
|
+
# Map of emulated function names to native function names.
|
|
182
|
+
EMULATED_FUNCTION_MAP = {}
|
|
183
|
+
|
|
184
|
+
WILDCARD = LiteralString.new('*').freeze
|
|
185
|
+
ALL = ' ALL'.freeze
|
|
176
186
|
AND_SEPARATOR = " AND ".freeze
|
|
187
|
+
APOS = "'".freeze
|
|
188
|
+
APOS_RE = /'/.freeze
|
|
189
|
+
ARRAY_EMPTY = '(NULL)'.freeze
|
|
190
|
+
AS = ' AS '.freeze
|
|
191
|
+
ASC = ' ASC'.freeze
|
|
177
192
|
BOOL_FALSE = "'f'".freeze
|
|
178
193
|
BOOL_TRUE = "'t'".freeze
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
194
|
+
BRACKET_CLOSE = ']'.freeze
|
|
195
|
+
BRACKET_OPEN = '['.freeze
|
|
196
|
+
CASE_ELSE = " ELSE ".freeze
|
|
197
|
+
CASE_END = " END)".freeze
|
|
198
|
+
CASE_OPEN = '(CASE'.freeze
|
|
199
|
+
CASE_THEN = " THEN ".freeze
|
|
200
|
+
CASE_WHEN = " WHEN ".freeze
|
|
201
|
+
CAST_OPEN = 'CAST('.freeze
|
|
202
|
+
COLUMN_REF_RE1 = Sequel::COLUMN_REF_RE1
|
|
203
|
+
COLUMN_REF_RE2 = Sequel::COLUMN_REF_RE2
|
|
204
|
+
COLUMN_REF_RE3 = Sequel::COLUMN_REF_RE3
|
|
205
|
+
COMMA = ', '.freeze
|
|
206
|
+
COMMA_SEPARATOR = COMMA
|
|
207
|
+
CONDITION_FALSE = '(1 = 0)'.freeze
|
|
208
|
+
CONDITION_TRUE = '(1 = 1)'.freeze
|
|
183
209
|
COUNT_FROM_SELF_OPTS = [:distinct, :group, :sql, :limit, :compounds]
|
|
184
|
-
COUNT_OF_ALL_AS_COUNT = SQL::Function.new(:count,
|
|
210
|
+
COUNT_OF_ALL_AS_COUNT = SQL::Function.new(:count, WILDCARD).as(:count)
|
|
185
211
|
DATASET_ALIAS_BASE_NAME = 't'.freeze
|
|
212
|
+
DEFAULT = LiteralString.new('DEFAULT').freeze
|
|
213
|
+
DEFAULT_VALUES = " DEFAULT VALUES".freeze
|
|
214
|
+
DELETE = 'DELETE'.freeze
|
|
215
|
+
DELETE_CLAUSE_METHODS = clause_methods(:delete, %w'delete from where')
|
|
216
|
+
DESC = ' DESC'.freeze
|
|
217
|
+
DISTINCT = " DISTINCT".freeze
|
|
218
|
+
DOT = '.'.freeze
|
|
219
|
+
DOUBLE_APOS = "''".freeze
|
|
220
|
+
DOUBLE_QUOTE = '""'.freeze
|
|
221
|
+
EQUAL = ' = '.freeze
|
|
222
|
+
EXTRACT = 'extract('.freeze
|
|
223
|
+
EXISTS = ['EXISTS '.freeze].freeze
|
|
186
224
|
FOR_UPDATE = ' FOR UPDATE'.freeze
|
|
225
|
+
FORMAT_DATE = "'%Y-%m-%d'".freeze
|
|
226
|
+
FORMAT_DATE_STANDARD = "DATE '%Y-%m-%d'".freeze
|
|
227
|
+
FORMAT_OFFSET = "%+03i%02i".freeze
|
|
228
|
+
FORMAT_TIMESTAMP_RE = /%[Nz]/.freeze
|
|
229
|
+
FORMAT_TIMESTAMP_USEC = ".%06d".freeze
|
|
230
|
+
FORMAT_USEC = '%N'.freeze
|
|
231
|
+
FRAME_ALL = "ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING".freeze
|
|
232
|
+
FRAME_ROWS = "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW".freeze
|
|
233
|
+
FROM = ' FROM '.freeze
|
|
234
|
+
FUNCTION_EMPTY = '()'.freeze
|
|
235
|
+
GROUP_BY = " GROUP BY ".freeze
|
|
236
|
+
HAVING = " HAVING ".freeze
|
|
237
|
+
INSERT = "INSERT".freeze
|
|
238
|
+
INSERT_CLAUSE_METHODS = clause_methods(:insert, %w'insert into columns values')
|
|
239
|
+
INTO = " INTO ".freeze
|
|
187
240
|
IS_LITERALS = {nil=>'NULL'.freeze, true=>'TRUE'.freeze, false=>'FALSE'.freeze}.freeze
|
|
188
241
|
IS_OPERATORS = ::Sequel::SQL::ComplexExpression::IS_OPERATORS
|
|
242
|
+
LIMIT = " LIMIT ".freeze
|
|
189
243
|
N_ARITY_OPERATORS = ::Sequel::SQL::ComplexExpression::N_ARITY_OPERATORS
|
|
244
|
+
NOT_SPACE = 'NOT '.freeze
|
|
190
245
|
NULL = "NULL".freeze
|
|
246
|
+
NULLS_FIRST = " NULLS FIRST".freeze
|
|
247
|
+
NULLS_LAST = " NULLS LAST".freeze
|
|
248
|
+
OFFSET = " OFFSET ".freeze
|
|
249
|
+
ON = ' ON '.freeze
|
|
250
|
+
ON_PAREN = " ON (".freeze
|
|
251
|
+
ORDER_BY = " ORDER BY ".freeze
|
|
252
|
+
ORDER_BY_NS = "ORDER BY ".freeze
|
|
253
|
+
OVER = ' OVER '.freeze
|
|
254
|
+
PAREN_CLOSE = ')'.freeze
|
|
255
|
+
PAREN_OPEN = '('.freeze
|
|
256
|
+
PAREN_SPACE_OPEN = ' ('.freeze
|
|
257
|
+
PARTITION_BY = "PARTITION BY ".freeze
|
|
191
258
|
QUALIFY_KEYS = [:select, :where, :having, :order, :group]
|
|
192
259
|
QUESTION_MARK = '?'.freeze
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
260
|
+
QUESTION_MARK_RE = /\?/.freeze
|
|
261
|
+
QUOTE = '"'.freeze
|
|
262
|
+
QUOTE_RE = /"/.freeze
|
|
263
|
+
RETURNING = " RETURNING ".freeze
|
|
264
|
+
SELECT = 'SELECT'.freeze
|
|
265
|
+
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'with select distinct columns from join where group having compounds order limit lock')
|
|
266
|
+
SET = ' SET '.freeze
|
|
267
|
+
SPACE = ' '.freeze
|
|
268
|
+
SQL_WITH = "WITH ".freeze
|
|
269
|
+
SPACE_WITH = " WITH ".freeze
|
|
270
|
+
TILDE = '~'.freeze
|
|
197
271
|
TIMESTAMP_FORMAT = "'%Y-%m-%d %H:%M:%S%N%z'".freeze
|
|
198
272
|
STANDARD_TIMESTAMP_FORMAT = "TIMESTAMP #{TIMESTAMP_FORMAT}".freeze
|
|
199
273
|
TWO_ARITY_OPERATORS = ::Sequel::SQL::ComplexExpression::TWO_ARITY_OPERATORS
|
|
200
|
-
|
|
201
|
-
|
|
274
|
+
REGEXP_OPERATORS = ::Sequel::SQL::ComplexExpression::REGEXP_OPERATORS
|
|
275
|
+
UNDERSCORE = '_'.freeze
|
|
276
|
+
UPDATE = 'UPDATE'.freeze
|
|
277
|
+
UPDATE_CLAUSE_METHODS = clause_methods(:update, %w'update table set where')
|
|
278
|
+
USING = ' USING ('.freeze
|
|
279
|
+
VALUES = " VALUES ".freeze
|
|
280
|
+
V190 = '1.9.0'.freeze
|
|
281
|
+
WHERE = " WHERE ".freeze
|
|
282
|
+
|
|
283
|
+
PUBLIC_APPEND_METHODS = (<<-END).split.map{|x| x.to_sym}
|
|
284
|
+
literal
|
|
285
|
+
aliased_expression_sql
|
|
286
|
+
array_sql
|
|
287
|
+
boolean_constant_sql
|
|
288
|
+
case_expression_sql
|
|
289
|
+
cast_sql
|
|
290
|
+
column_all_sql
|
|
291
|
+
complex_expression_sql
|
|
292
|
+
constant_sql
|
|
293
|
+
function_sql
|
|
294
|
+
join_clause_sql
|
|
295
|
+
join_on_clause_sql
|
|
296
|
+
join_using_clause_sql
|
|
297
|
+
negative_boolean_constant_sql
|
|
298
|
+
ordered_expression_sql
|
|
299
|
+
placeholder_literal_string_sql
|
|
300
|
+
qualified_identifier_sql
|
|
301
|
+
quote_identifier
|
|
302
|
+
quote_schema_table
|
|
303
|
+
quoted_identifier
|
|
304
|
+
subscript_sql
|
|
305
|
+
window_sql
|
|
306
|
+
window_function_sql
|
|
307
|
+
END
|
|
308
|
+
PRIVATE_APPEND_METHODS = (<<-END).split.map{|x| x.to_sym}
|
|
309
|
+
argument_list
|
|
310
|
+
as_sql
|
|
311
|
+
column_list
|
|
312
|
+
compound_dataset_sql
|
|
313
|
+
expression_list
|
|
314
|
+
literal_array
|
|
315
|
+
literal_blob
|
|
316
|
+
literal_dataset
|
|
317
|
+
literal_expression
|
|
318
|
+
literal_hash
|
|
319
|
+
literal_other
|
|
320
|
+
literal_string
|
|
321
|
+
literal_symbol
|
|
322
|
+
source_list
|
|
323
|
+
subselect_sql
|
|
324
|
+
table_ref
|
|
325
|
+
END
|
|
326
|
+
def self.def_append_methods(meths)
|
|
327
|
+
meths.each do |meth|
|
|
328
|
+
class_eval(<<-END, __FILE__, __LINE__ + 1)
|
|
329
|
+
def #{meth}(*args, &block)
|
|
330
|
+
s = ''
|
|
331
|
+
#{meth}_append(s, *args, &block)
|
|
332
|
+
s
|
|
333
|
+
end
|
|
334
|
+
END
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
def_append_methods(PUBLIC_APPEND_METHODS + PRIVATE_APPEND_METHODS)
|
|
338
|
+
private *PRIVATE_APPEND_METHODS
|
|
202
339
|
|
|
203
340
|
# SQL fragment for AliasedExpression
|
|
204
|
-
def
|
|
205
|
-
|
|
341
|
+
def aliased_expression_sql_append(sql, ae)
|
|
342
|
+
literal_append(sql, ae.expression)
|
|
343
|
+
as_sql_append(sql, ae.aliaz)
|
|
206
344
|
end
|
|
207
345
|
|
|
208
346
|
# SQL fragment for Array
|
|
209
|
-
def
|
|
210
|
-
a.empty?
|
|
347
|
+
def array_sql_append(sql, a)
|
|
348
|
+
if a.empty?
|
|
349
|
+
sql << ARRAY_EMPTY
|
|
350
|
+
else
|
|
351
|
+
sql << PAREN_OPEN
|
|
352
|
+
expression_list_append(sql, a)
|
|
353
|
+
sql << PAREN_CLOSE
|
|
354
|
+
end
|
|
211
355
|
end
|
|
212
356
|
|
|
213
357
|
# SQL fragment for BooleanConstants
|
|
214
|
-
def
|
|
215
|
-
|
|
358
|
+
def boolean_constant_sql_append(sql, constant)
|
|
359
|
+
if (constant == true || constant == false) && !supports_where_true?
|
|
360
|
+
sql << (constant == true ? CONDITION_TRUE : CONDITION_FALSE)
|
|
361
|
+
else
|
|
362
|
+
literal_append(sql, constant)
|
|
363
|
+
end
|
|
216
364
|
end
|
|
217
365
|
|
|
218
366
|
# SQL fragment for CaseExpression
|
|
219
|
-
def
|
|
220
|
-
sql
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
sql
|
|
224
|
-
|
|
225
|
-
|
|
367
|
+
def case_expression_sql_append(sql, ce)
|
|
368
|
+
sql << CASE_OPEN
|
|
369
|
+
if ce.expression?
|
|
370
|
+
sql << SPACE
|
|
371
|
+
literal_append(sql, ce.expression)
|
|
372
|
+
end
|
|
373
|
+
w = CASE_WHEN
|
|
374
|
+
t = CASE_THEN
|
|
375
|
+
ce.conditions.each do |c,r|
|
|
376
|
+
sql << w
|
|
377
|
+
literal_append(sql, c)
|
|
378
|
+
sql << t
|
|
379
|
+
literal_append(sql, r)
|
|
380
|
+
end
|
|
381
|
+
sql << CASE_ELSE
|
|
382
|
+
literal_append(sql, ce.default)
|
|
383
|
+
sql << CASE_END
|
|
226
384
|
end
|
|
227
385
|
|
|
228
386
|
# SQL fragment for the SQL CAST expression
|
|
229
|
-
def
|
|
230
|
-
|
|
387
|
+
def cast_sql_append(sql, expr, type)
|
|
388
|
+
sql << CAST_OPEN
|
|
389
|
+
literal_append(sql, expr)
|
|
390
|
+
sql << AS << db.cast_type_literal(type).to_s
|
|
391
|
+
sql << PAREN_CLOSE
|
|
231
392
|
end
|
|
232
393
|
|
|
233
394
|
# SQL fragment for specifying all columns in a given table
|
|
234
|
-
def
|
|
235
|
-
|
|
395
|
+
def column_all_sql_append(sql, ca)
|
|
396
|
+
qualified_identifier_sql_append(sql, ca.table, WILDCARD)
|
|
236
397
|
end
|
|
237
398
|
|
|
238
|
-
# SQL fragment for complex
|
|
239
|
-
def
|
|
399
|
+
# SQL fragment for the complex expression.
|
|
400
|
+
def complex_expression_sql_append(sql, op, args)
|
|
240
401
|
case op
|
|
241
402
|
when *IS_OPERATORS
|
|
242
403
|
r = args.at(1)
|
|
243
404
|
if r.nil? || supports_is_true?
|
|
244
405
|
raise(InvalidOperation, 'Invalid argument used for IS operator') unless v = IS_LITERALS[r]
|
|
245
|
-
|
|
406
|
+
sql << PAREN_OPEN
|
|
407
|
+
literal_append(sql, args.at(0))
|
|
408
|
+
sql << SPACE << op.to_s << SPACE
|
|
409
|
+
sql << v << PAREN_CLOSE
|
|
246
410
|
elsif op == :IS
|
|
247
|
-
|
|
411
|
+
complex_expression_sql_append(sql, :"=", args)
|
|
248
412
|
else
|
|
249
|
-
|
|
413
|
+
complex_expression_sql_append(sql, :OR, [SQL::BooleanExpression.new(:"!=", *args), SQL::BooleanExpression.new(:IS, args.at(0), nil)])
|
|
250
414
|
end
|
|
251
415
|
when :IN, :"NOT IN"
|
|
252
416
|
cols = args.at(0)
|
|
@@ -256,147 +420,214 @@ module Sequel
|
|
|
256
420
|
val_array = true
|
|
257
421
|
empty_val_array = vals == []
|
|
258
422
|
end
|
|
259
|
-
if
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
else
|
|
264
|
-
literal(1=>1)
|
|
265
|
-
end
|
|
266
|
-
elsif !supports_multiple_column_in?
|
|
423
|
+
if empty_val_array
|
|
424
|
+
literal_append(sql, empty_array_value(op, cols))
|
|
425
|
+
elsif col_array
|
|
426
|
+
if !supports_multiple_column_in?
|
|
267
427
|
if val_array
|
|
268
428
|
expr = SQL::BooleanExpression.new(:OR, *vals.to_a.map{|vs| SQL::BooleanExpression.from_value_pairs(cols.to_a.zip(vs).map{|c, v| [c, v]})})
|
|
269
|
-
|
|
429
|
+
literal_append(sql, op == :IN ? expr : ~expr)
|
|
270
430
|
else
|
|
271
431
|
old_vals = vals
|
|
432
|
+
vals = vals.naked if vals.is_a?(Sequel::Dataset)
|
|
272
433
|
vals = vals.to_a
|
|
273
434
|
val_cols = old_vals.columns
|
|
274
|
-
|
|
435
|
+
complex_expression_sql_append(sql, op, [cols, vals.map!{|x| x.values_at(*val_cols)}])
|
|
275
436
|
end
|
|
276
437
|
else
|
|
277
438
|
# If the columns and values are both arrays, use array_sql instead of
|
|
278
439
|
# literal so that if values is an array of two element arrays, it
|
|
279
440
|
# will be treated as a value list instead of a condition specifier.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
literal(SQL::BooleanExpression.from_value_pairs([[cols, cols]], :AND, true))
|
|
441
|
+
sql << PAREN_OPEN
|
|
442
|
+
literal_append(sql, cols)
|
|
443
|
+
sql << SPACE << op.to_s << SPACE
|
|
444
|
+
if val_array
|
|
445
|
+
array_sql_append(sql, vals)
|
|
286
446
|
else
|
|
287
|
-
|
|
447
|
+
literal_append(sql, vals)
|
|
288
448
|
end
|
|
289
|
-
|
|
290
|
-
"(#{literal(cols)} #{op} #{literal(vals)})"
|
|
449
|
+
sql << PAREN_CLOSE
|
|
291
450
|
end
|
|
451
|
+
else
|
|
452
|
+
sql << PAREN_OPEN
|
|
453
|
+
literal_append(sql, cols)
|
|
454
|
+
sql << SPACE << op.to_s << SPACE
|
|
455
|
+
literal_append(sql, vals)
|
|
456
|
+
sql << PAREN_CLOSE
|
|
292
457
|
end
|
|
293
458
|
when *TWO_ARITY_OPERATORS
|
|
294
|
-
|
|
459
|
+
if REGEXP_OPERATORS.include?(op) && !supports_regexp?
|
|
460
|
+
raise InvalidOperation, "Pattern matching via regular expressions is not supported on #{db.database_type}"
|
|
461
|
+
end
|
|
462
|
+
sql << PAREN_OPEN
|
|
463
|
+
literal_append(sql, args.at(0))
|
|
464
|
+
sql << SPACE << op.to_s << SPACE
|
|
465
|
+
literal_append(sql, args.at(1))
|
|
466
|
+
sql << PAREN_CLOSE
|
|
295
467
|
when *N_ARITY_OPERATORS
|
|
296
|
-
|
|
468
|
+
sql << PAREN_OPEN
|
|
469
|
+
c = false
|
|
470
|
+
op_str = " #{op} "
|
|
471
|
+
args.each do |a|
|
|
472
|
+
sql << op_str if c
|
|
473
|
+
literal_append(sql, a)
|
|
474
|
+
c ||= true
|
|
475
|
+
end
|
|
476
|
+
sql << PAREN_CLOSE
|
|
297
477
|
when :NOT
|
|
298
|
-
|
|
478
|
+
sql << NOT_SPACE
|
|
479
|
+
literal_append(sql, args.at(0))
|
|
299
480
|
when :NOOP
|
|
300
|
-
|
|
481
|
+
literal_append(sql, args.at(0))
|
|
301
482
|
when :'B~'
|
|
302
|
-
|
|
483
|
+
sql << TILDE
|
|
484
|
+
literal_append(sql, args.at(0))
|
|
485
|
+
when :extract
|
|
486
|
+
sql << EXTRACT << args.at(0).to_s << FROM
|
|
487
|
+
literal_append(sql, args.at(1))
|
|
488
|
+
sql << PAREN_CLOSE
|
|
303
489
|
else
|
|
304
490
|
raise(InvalidOperation, "invalid operator #{op}")
|
|
305
491
|
end
|
|
306
492
|
end
|
|
307
493
|
|
|
308
494
|
# SQL fragment for constants
|
|
309
|
-
def
|
|
310
|
-
constant.to_s
|
|
495
|
+
def constant_sql_append(sql, constant)
|
|
496
|
+
sql << constant.to_s
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
# SQL fragment specifying an emulated SQL function call.
|
|
500
|
+
# By default, assumes just the function name may need to
|
|
501
|
+
# be emulated, adapters should set an EMULATED_FUNCTION_MAP
|
|
502
|
+
# hash mapping emulated functions to native functions in
|
|
503
|
+
# their dataset class to setup the emulation.
|
|
504
|
+
def emulated_function_sql_append(sql, f)
|
|
505
|
+
_function_sql_append(sql, native_function_name(f.f), f.args)
|
|
311
506
|
end
|
|
312
507
|
|
|
313
|
-
# SQL fragment specifying an SQL function call
|
|
314
|
-
def
|
|
315
|
-
|
|
316
|
-
"#{f.f}#{args.empty? ? '()' : literal(args)}"
|
|
508
|
+
# SQL fragment specifying an SQL function call without emulation.
|
|
509
|
+
def function_sql_append(sql, f)
|
|
510
|
+
_function_sql_append(sql, f.f, f.args)
|
|
317
511
|
end
|
|
318
512
|
|
|
319
513
|
# SQL fragment specifying a JOIN clause without ON or USING.
|
|
320
|
-
def
|
|
514
|
+
def join_clause_sql_append(sql, jc)
|
|
321
515
|
table = jc.table
|
|
322
516
|
table_alias = jc.table_alias
|
|
323
517
|
table_alias = nil if table == table_alias
|
|
324
|
-
|
|
325
|
-
|
|
518
|
+
sql << SPACE << join_type_sql(jc.join_type) << SPACE
|
|
519
|
+
identifier_append(sql, table)
|
|
520
|
+
as_sql_append(sql, table_alias) if table_alias
|
|
326
521
|
end
|
|
327
522
|
|
|
328
523
|
# SQL fragment specifying a JOIN clause with ON.
|
|
329
|
-
def
|
|
330
|
-
|
|
524
|
+
def join_on_clause_sql_append(sql, jc)
|
|
525
|
+
join_clause_sql_append(sql, jc)
|
|
526
|
+
sql << ON
|
|
527
|
+
literal_append(sql, filter_expr(jc.on))
|
|
331
528
|
end
|
|
332
529
|
|
|
333
530
|
# SQL fragment specifying a JOIN clause with USING.
|
|
334
|
-
def
|
|
335
|
-
|
|
531
|
+
def join_using_clause_sql_append(sql, jc)
|
|
532
|
+
join_clause_sql_append(sql, jc)
|
|
533
|
+
sql << USING
|
|
534
|
+
column_list_append(sql, jc.using)
|
|
535
|
+
sql << PAREN_CLOSE
|
|
336
536
|
end
|
|
337
537
|
|
|
338
538
|
# SQL fragment for NegativeBooleanConstants
|
|
339
|
-
def
|
|
340
|
-
|
|
539
|
+
def negative_boolean_constant_sql_append(sql, constant)
|
|
540
|
+
sql << NOT_SPACE
|
|
541
|
+
boolean_constant_sql_append(sql, constant)
|
|
341
542
|
end
|
|
342
543
|
|
|
343
544
|
# SQL fragment for the ordered expression, used in the ORDER BY
|
|
344
545
|
# clause.
|
|
345
|
-
def
|
|
346
|
-
|
|
546
|
+
def ordered_expression_sql_append(sql, oe)
|
|
547
|
+
literal_append(sql, oe.expression)
|
|
548
|
+
sql << (oe.descending ? DESC : ASC)
|
|
347
549
|
case oe.nulls
|
|
348
550
|
when :first
|
|
349
|
-
|
|
551
|
+
sql << NULLS_FIRST
|
|
350
552
|
when :last
|
|
351
|
-
|
|
352
|
-
else
|
|
353
|
-
s
|
|
553
|
+
sql << NULLS_LAST
|
|
354
554
|
end
|
|
355
555
|
end
|
|
356
556
|
|
|
357
557
|
# SQL fragment for a literal string with placeholders
|
|
358
|
-
def
|
|
558
|
+
def placeholder_literal_string_sql_append(sql, pls)
|
|
359
559
|
args = pls.args
|
|
360
|
-
|
|
560
|
+
str = pls.str
|
|
561
|
+
sql << PAREN_OPEN if pls.parens
|
|
562
|
+
if args.is_a?(Hash)
|
|
361
563
|
re = /:(#{args.keys.map{|k| Regexp.escape(k.to_s)}.join('|')})\b/
|
|
362
|
-
|
|
564
|
+
loop do
|
|
565
|
+
previous, q, str = str.partition(re)
|
|
566
|
+
sql << previous
|
|
567
|
+
literal_append(sql, args[($1||q[1..-1].to_s).to_sym]) unless q.empty?
|
|
568
|
+
break if str.empty?
|
|
569
|
+
end
|
|
570
|
+
elsif str.is_a?(Array)
|
|
571
|
+
len = args.length
|
|
572
|
+
str.each_with_index do |s, i|
|
|
573
|
+
sql << s
|
|
574
|
+
literal_append(sql, args[i]) unless i == len
|
|
575
|
+
end
|
|
363
576
|
else
|
|
364
577
|
i = -1
|
|
365
|
-
|
|
578
|
+
loop do
|
|
579
|
+
previous, q, str = str.partition(QUESTION_MARK)
|
|
580
|
+
sql << previous
|
|
581
|
+
literal_append(sql, args.at(i+=1)) unless q.empty?
|
|
582
|
+
break if str.empty?
|
|
583
|
+
end
|
|
366
584
|
end
|
|
367
|
-
|
|
368
|
-
s
|
|
585
|
+
sql << PAREN_CLOSE if pls.parens
|
|
369
586
|
end
|
|
370
587
|
|
|
371
588
|
# SQL fragment for the qualifed identifier, specifying
|
|
372
589
|
# a table and a column (or schema and table).
|
|
373
|
-
|
|
374
|
-
|
|
590
|
+
# If 3 arguments are given, the 2nd should be the table/qualifier and the third should be
|
|
591
|
+
# column/qualified. If 2 arguments are given, the 2nd should be an SQL::QualifiedIdentifier.
|
|
592
|
+
def qualified_identifier_sql_append(sql, table, column=(c = table.column; table = table.table; c))
|
|
593
|
+
identifier_append(sql, table)
|
|
594
|
+
sql << DOT
|
|
595
|
+
identifier_append(sql, column)
|
|
375
596
|
end
|
|
376
597
|
|
|
377
598
|
# Adds quoting to identifiers (columns and tables). If identifiers are not
|
|
378
599
|
# being quoted, returns name as a string. If identifiers are being quoted
|
|
379
600
|
# quote the name with quoted_identifier.
|
|
380
|
-
def
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
601
|
+
def quote_identifier_append(sql, name)
|
|
602
|
+
if name.is_a?(LiteralString)
|
|
603
|
+
sql << name
|
|
604
|
+
else
|
|
605
|
+
name = name.value if name.is_a?(SQL::Identifier)
|
|
606
|
+
name = input_identifier(name)
|
|
607
|
+
if quote_identifiers?
|
|
608
|
+
quoted_identifier_append(sql, name)
|
|
609
|
+
else
|
|
610
|
+
sql << name
|
|
611
|
+
end
|
|
612
|
+
end
|
|
386
613
|
end
|
|
387
614
|
|
|
388
615
|
# Separates the schema from the table and returns a string with them
|
|
389
616
|
# quoted (if quoting identifiers)
|
|
390
|
-
def
|
|
617
|
+
def quote_schema_table_append(sql, table)
|
|
391
618
|
schema, table = schema_and_table(table)
|
|
392
|
-
|
|
619
|
+
if schema
|
|
620
|
+
quote_identifier_append(sql, schema)
|
|
621
|
+
sql << DOT
|
|
622
|
+
end
|
|
623
|
+
quote_identifier_append(sql, table)
|
|
393
624
|
end
|
|
394
625
|
|
|
395
626
|
# This method quotes the given name with the SQL standard double quote.
|
|
396
627
|
# should be overridden by subclasses to provide quoting not matching the
|
|
397
628
|
# SQL standard, such as backtick (used by MySQL and SQLite).
|
|
398
|
-
def
|
|
399
|
-
|
|
629
|
+
def quoted_identifier_append(sql, name)
|
|
630
|
+
sql << QUOTE << name.to_s.gsub(QUOTE_RE, DOUBLE_QUOTE) << QUOTE
|
|
400
631
|
end
|
|
401
632
|
|
|
402
633
|
# Split the schema information from the table
|
|
@@ -418,34 +649,59 @@ module Sequel
|
|
|
418
649
|
end
|
|
419
650
|
|
|
420
651
|
# SQL fragment for specifying subscripts (SQL array accesses)
|
|
421
|
-
def
|
|
422
|
-
|
|
652
|
+
def subscript_sql_append(sql, s)
|
|
653
|
+
literal_append(sql, s.f)
|
|
654
|
+
sql << BRACKET_OPEN
|
|
655
|
+
expression_list_append(sql, s.sub)
|
|
656
|
+
sql << BRACKET_CLOSE
|
|
423
657
|
end
|
|
424
658
|
|
|
425
659
|
# The SQL fragment for the given window's options.
|
|
426
|
-
def
|
|
660
|
+
def window_sql_append(sql, opts)
|
|
427
661
|
raise(Error, 'This dataset does not support window functions') unless supports_window_functions?
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
662
|
+
sql << PAREN_OPEN
|
|
663
|
+
window, part, order, frame = opts.values_at(:window, :partition, :order, :frame)
|
|
664
|
+
space = false
|
|
665
|
+
space_s = SPACE
|
|
666
|
+
if window
|
|
667
|
+
literal_append(sql, window)
|
|
668
|
+
space = true
|
|
669
|
+
end
|
|
670
|
+
if part
|
|
671
|
+
sql << space_s if space
|
|
672
|
+
sql << PARTITION_BY
|
|
673
|
+
expression_list_append(sql, Array(part))
|
|
674
|
+
space = true
|
|
675
|
+
end
|
|
676
|
+
if order
|
|
677
|
+
sql << space_s if space
|
|
678
|
+
sql << ORDER_BY_NS
|
|
679
|
+
expression_list_append(sql, Array(order))
|
|
680
|
+
space = true
|
|
681
|
+
end
|
|
682
|
+
case frame
|
|
432
683
|
when nil
|
|
433
|
-
|
|
684
|
+
# nothing
|
|
434
685
|
when :all
|
|
435
|
-
|
|
686
|
+
sql << space_s if space
|
|
687
|
+
sql << FRAME_ALL
|
|
436
688
|
when :rows
|
|
437
|
-
|
|
689
|
+
sql << space_s if space
|
|
690
|
+
sql << FRAME_ROWS
|
|
438
691
|
when String
|
|
439
|
-
|
|
692
|
+
sql << space_s if space
|
|
693
|
+
sql << frame
|
|
440
694
|
else
|
|
441
695
|
raise Error, "invalid window frame clause, should be :all, :rows, a string, or nil"
|
|
442
696
|
end
|
|
443
|
-
|
|
697
|
+
sql << PAREN_CLOSE
|
|
444
698
|
end
|
|
445
699
|
|
|
446
700
|
# The SQL fragment for the given window function's function and window.
|
|
447
|
-
def
|
|
448
|
-
|
|
701
|
+
def window_function_sql_append(sql, function, window)
|
|
702
|
+
literal_append(sql, function)
|
|
703
|
+
sql << OVER
|
|
704
|
+
literal_append(sql, window)
|
|
449
705
|
end
|
|
450
706
|
|
|
451
707
|
protected
|
|
@@ -468,6 +724,16 @@ module Sequel
|
|
|
468
724
|
|
|
469
725
|
private
|
|
470
726
|
|
|
727
|
+
# Backbone of function_sql_append and emulated_function_sql_append.
|
|
728
|
+
def _function_sql_append(sql, name, args)
|
|
729
|
+
sql << name.to_s
|
|
730
|
+
if args.empty?
|
|
731
|
+
sql << FUNCTION_EMPTY
|
|
732
|
+
else
|
|
733
|
+
literal_append(sql, args)
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
|
|
471
737
|
# Formats the truncate statement. Assumes the table given has already been
|
|
472
738
|
# literalized.
|
|
473
739
|
def _truncate_sql(table)
|
|
@@ -517,14 +783,20 @@ module Sequel
|
|
|
517
783
|
options_overlap(COUNT_FROM_SELF_OPTS) ? from_self : unordered
|
|
518
784
|
end
|
|
519
785
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
786
|
+
def argument_list_append(sql, args)
|
|
787
|
+
c = false
|
|
788
|
+
comma = COMMA
|
|
789
|
+
args.each do |a|
|
|
790
|
+
sql << comma if c
|
|
791
|
+
sql << a.to_s
|
|
792
|
+
c ||= true
|
|
793
|
+
end
|
|
523
794
|
end
|
|
524
795
|
|
|
525
796
|
# SQL fragment for specifying an alias. expression should already be literalized.
|
|
526
|
-
def
|
|
527
|
-
|
|
797
|
+
def as_sql_append(sql, aliaz)
|
|
798
|
+
sql << AS
|
|
799
|
+
quote_identifier_append(sql, aliaz)
|
|
528
800
|
end
|
|
529
801
|
|
|
530
802
|
# Raise an InvalidOperation exception if deletion is not allowed
|
|
@@ -534,38 +806,88 @@ module Sequel
|
|
|
534
806
|
raise(InvalidOperation, "Joined datasets cannot be modified") if !supports_modifying_joins? && joined_dataset?
|
|
535
807
|
end
|
|
536
808
|
|
|
809
|
+
# Alias of check_modification_allowed!
|
|
810
|
+
def check_truncation_allowed!
|
|
811
|
+
check_modification_allowed!
|
|
812
|
+
end
|
|
813
|
+
|
|
537
814
|
# Prepare an SQL statement by calling all clause methods for the given statement type.
|
|
538
815
|
def clause_sql(type)
|
|
539
|
-
sql =
|
|
816
|
+
sql = @opts[:append_sql] || sql_string_origin
|
|
540
817
|
send("#{type}_clause_methods").each{|x| send(x, sql)}
|
|
541
818
|
sql
|
|
542
819
|
end
|
|
543
820
|
|
|
544
821
|
# Converts an array of column names into a comma seperated string of
|
|
545
822
|
# column names. If the array is empty, a wildcard (*) is returned.
|
|
546
|
-
def
|
|
547
|
-
(columns.nil? || columns.empty?)
|
|
823
|
+
def column_list_append(sql, columns)
|
|
824
|
+
if (columns.nil? || columns.empty?)
|
|
825
|
+
sql << WILDCARD
|
|
826
|
+
else
|
|
827
|
+
expression_list_append(sql, columns)
|
|
828
|
+
end
|
|
548
829
|
end
|
|
549
|
-
|
|
830
|
+
|
|
831
|
+
# Yield each two pair of arguments to the block, which should
|
|
832
|
+
# return a string representing the SQL code for those
|
|
833
|
+
# two arguments. If more than 2 arguments are provided, all
|
|
834
|
+
# calls to the block # after the first will have a LiteralString
|
|
835
|
+
# as the first argument, representing the application of the block to
|
|
836
|
+
# the previous arguments.
|
|
837
|
+
def complex_expression_arg_pairs(args)
|
|
838
|
+
case args.length
|
|
839
|
+
when 1
|
|
840
|
+
literal(args.at(0))
|
|
841
|
+
when 2
|
|
842
|
+
yield args.at(0), args.at(1)
|
|
843
|
+
else
|
|
844
|
+
args.inject{|m, a| LiteralString.new(yield(m, a))}
|
|
845
|
+
end
|
|
846
|
+
end
|
|
847
|
+
|
|
848
|
+
# The SQL to use for the dataset used in a UNION/INTERSECT/EXCEPT clause.
|
|
849
|
+
def compound_dataset_sql_append(sql, ds)
|
|
850
|
+
subselect_sql_append(sql, ds)
|
|
851
|
+
end
|
|
852
|
+
|
|
550
853
|
# The alias to use for datasets, takes a number to make sure the name is unique.
|
|
551
854
|
def dataset_alias(number)
|
|
552
855
|
:"#{DATASET_ALIAS_BASE_NAME}#{number}"
|
|
553
856
|
end
|
|
554
857
|
|
|
858
|
+
# The strftime format to use when literalizing the time.
|
|
859
|
+
def default_timestamp_format
|
|
860
|
+
requires_sql_standard_datetimes? ? STANDARD_TIMESTAMP_FORMAT : TIMESTAMP_FORMAT
|
|
861
|
+
end
|
|
862
|
+
|
|
555
863
|
# The order of methods to call to build the DELETE SQL statement
|
|
556
864
|
def delete_clause_methods
|
|
557
865
|
DELETE_CLAUSE_METHODS
|
|
558
866
|
end
|
|
559
867
|
|
|
868
|
+
def delete_delete_sql(sql)
|
|
869
|
+
sql << DELETE
|
|
870
|
+
end
|
|
871
|
+
|
|
560
872
|
# Converts an array of expressions into a comma separated string of
|
|
561
873
|
# expressions.
|
|
562
|
-
def
|
|
563
|
-
|
|
874
|
+
def expression_list_append(sql, columns)
|
|
875
|
+
c = false
|
|
876
|
+
co = COMMA
|
|
877
|
+
columns.each do |col|
|
|
878
|
+
sql << co if c
|
|
879
|
+
literal_append(sql, col)
|
|
880
|
+
c ||= true
|
|
881
|
+
end
|
|
564
882
|
end
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
883
|
+
|
|
884
|
+
def empty_array_value(op, cols)
|
|
885
|
+
if Sequel.empty_array_handle_nulls
|
|
886
|
+
c = Array(cols)
|
|
887
|
+
SQL::BooleanExpression.from_value_pairs(c.zip(c), :AND, op == :IN)
|
|
888
|
+
else
|
|
889
|
+
{1 => ((op == :IN) ? 0 : 1)}
|
|
890
|
+
end
|
|
569
891
|
end
|
|
570
892
|
|
|
571
893
|
# Format the timestamp based on the default_timestamp_format, with a couple
|
|
@@ -573,10 +895,10 @@ module Sequel
|
|
|
573
895
|
# database supports them), and override %z to always use a numeric offset
|
|
574
896
|
# of hours and minutes.
|
|
575
897
|
def format_timestamp(v)
|
|
576
|
-
v2 =
|
|
577
|
-
fmt = default_timestamp_format.gsub(
|
|
578
|
-
if m ==
|
|
579
|
-
format_timestamp_usec(v.is_a?(DateTime) ? v.sec_fraction*(RUBY_VERSION <
|
|
898
|
+
v2 = db.from_application_timestamp(v)
|
|
899
|
+
fmt = default_timestamp_format.gsub(FORMAT_TIMESTAMP_RE) do |m|
|
|
900
|
+
if m == FORMAT_USEC
|
|
901
|
+
format_timestamp_usec(v.is_a?(DateTime) ? v.sec_fraction*(RUBY_VERSION < V190 ? 86400000000 : 1000000) : v.usec) if supports_timestamp_usecs?
|
|
580
902
|
else
|
|
581
903
|
if supports_timestamp_timezones?
|
|
582
904
|
# Would like to just use %z format, but it doesn't appear to work on Windows
|
|
@@ -591,15 +913,33 @@ module Sequel
|
|
|
591
913
|
|
|
592
914
|
# Return the SQL timestamp fragment to use for the timezone offset.
|
|
593
915
|
def format_timestamp_offset(hour, minute)
|
|
594
|
-
sprintf(
|
|
916
|
+
sprintf(FORMAT_OFFSET, hour, minute)
|
|
595
917
|
end
|
|
596
918
|
|
|
597
919
|
# Return the SQL timestamp fragment to use for the fractional time part.
|
|
598
920
|
# Should start with the decimal point. Uses 6 decimal places by default.
|
|
599
921
|
def format_timestamp_usec(usec)
|
|
600
|
-
sprintf(
|
|
922
|
+
sprintf(FORMAT_TIMESTAMP_USEC, usec)
|
|
923
|
+
end
|
|
924
|
+
|
|
925
|
+
# Append the value, but special case regular (non-literal, non-blob) strings
|
|
926
|
+
# so that they are considered as identifiers and not SQL strings.
|
|
927
|
+
def identifier_append(sql, v)
|
|
928
|
+
if v.is_a?(String)
|
|
929
|
+
case v
|
|
930
|
+
when LiteralString
|
|
931
|
+
sql << v
|
|
932
|
+
when SQL::Blob
|
|
933
|
+
literal_append(sql, v)
|
|
934
|
+
else
|
|
935
|
+
quote_identifier_append(sql, v)
|
|
936
|
+
end
|
|
937
|
+
else
|
|
938
|
+
literal_append(sql, v)
|
|
939
|
+
end
|
|
601
940
|
end
|
|
602
|
-
|
|
941
|
+
alias table_ref_append identifier_append
|
|
942
|
+
|
|
603
943
|
# Modify the identifier returned from the database based on the
|
|
604
944
|
# identifier_output_method.
|
|
605
945
|
def input_identifier(v)
|
|
@@ -608,7 +948,8 @@ module Sequel
|
|
|
608
948
|
|
|
609
949
|
# SQL fragment specifying the table to insert INTO
|
|
610
950
|
def insert_into_sql(sql)
|
|
611
|
-
sql <<
|
|
951
|
+
sql << INTO
|
|
952
|
+
source_list_append(sql, @opts[:from])
|
|
612
953
|
end
|
|
613
954
|
|
|
614
955
|
# The order of methods to call to build the INSERT SQL statement
|
|
@@ -619,27 +960,57 @@ module Sequel
|
|
|
619
960
|
# SQL fragment specifying the columns to insert into
|
|
620
961
|
def insert_columns_sql(sql)
|
|
621
962
|
columns = opts[:columns]
|
|
622
|
-
|
|
963
|
+
if columns && !columns.empty?
|
|
964
|
+
sql << PAREN_SPACE_OPEN
|
|
965
|
+
c = false
|
|
966
|
+
co = COMMA
|
|
967
|
+
columns.each do |col|
|
|
968
|
+
sql << co if c
|
|
969
|
+
identifier_append(sql, col)
|
|
970
|
+
c ||= true
|
|
971
|
+
end
|
|
972
|
+
sql << PAREN_CLOSE
|
|
973
|
+
end
|
|
974
|
+
end
|
|
975
|
+
|
|
976
|
+
def insert_insert_sql(sql)
|
|
977
|
+
sql << INSERT
|
|
623
978
|
end
|
|
624
979
|
|
|
625
980
|
# SQL fragment specifying the values to insert.
|
|
626
981
|
def insert_values_sql(sql)
|
|
627
982
|
case values = opts[:values]
|
|
628
983
|
when Array
|
|
629
|
-
|
|
984
|
+
if values.empty?
|
|
985
|
+
sql << DEFAULT_VALUES
|
|
986
|
+
else
|
|
987
|
+
sql << VALUES
|
|
988
|
+
literal_append(sql, values)
|
|
989
|
+
end
|
|
630
990
|
when Dataset
|
|
631
|
-
sql <<
|
|
991
|
+
sql << SPACE
|
|
992
|
+
subselect_sql_append(sql, values)
|
|
632
993
|
when LiteralString
|
|
633
|
-
sql <<
|
|
994
|
+
sql << SPACE << values
|
|
634
995
|
else
|
|
635
996
|
raise Error, "Unsupported INSERT values type, should be an Array or Dataset: #{values.inspect}"
|
|
636
997
|
end
|
|
637
998
|
end
|
|
638
999
|
|
|
1000
|
+
# SQL fragment specifying the values to return.
|
|
1001
|
+
def insert_returning_sql(sql)
|
|
1002
|
+
if opts.has_key?(:returning)
|
|
1003
|
+
sql << RETURNING
|
|
1004
|
+
column_list_append(sql, Array(opts[:returning]))
|
|
1005
|
+
end
|
|
1006
|
+
end
|
|
1007
|
+
alias delete_returning_sql insert_returning_sql
|
|
1008
|
+
alias update_returning_sql insert_returning_sql
|
|
1009
|
+
|
|
639
1010
|
# SQL fragment specifying a JOIN type, converts underscores to
|
|
640
1011
|
# spaces and upcases.
|
|
641
1012
|
def join_type_sql(join_type)
|
|
642
|
-
"#{join_type.to_s.gsub(
|
|
1013
|
+
"#{join_type.to_s.gsub(UNDERSCORE, SPACE).upcase} JOIN"
|
|
643
1014
|
end
|
|
644
1015
|
|
|
645
1016
|
# Whether this dataset is a joined dataset
|
|
@@ -648,8 +1019,12 @@ module Sequel
|
|
|
648
1019
|
end
|
|
649
1020
|
|
|
650
1021
|
# SQL fragment for Array. Treats as an expression if an array of all two pairs, or as a SQL array otherwise.
|
|
651
|
-
def
|
|
652
|
-
Sequel.condition_specifier?(v)
|
|
1022
|
+
def literal_array_append(sql, v)
|
|
1023
|
+
if Sequel.condition_specifier?(v)
|
|
1024
|
+
literal_expression_append(sql, SQL::BooleanExpression.from_value_pairs(v))
|
|
1025
|
+
else
|
|
1026
|
+
array_sql_append(sql, v)
|
|
1027
|
+
end
|
|
653
1028
|
end
|
|
654
1029
|
|
|
655
1030
|
# SQL fragment for BigDecimal
|
|
@@ -659,18 +1034,24 @@ module Sequel
|
|
|
659
1034
|
end
|
|
660
1035
|
|
|
661
1036
|
# SQL fragment for SQL::Blob
|
|
662
|
-
def
|
|
663
|
-
|
|
1037
|
+
def literal_blob_append(sql, v)
|
|
1038
|
+
literal_string_append(sql, v)
|
|
664
1039
|
end
|
|
665
1040
|
|
|
666
1041
|
# SQL fragment for Dataset. Does a subselect inside parantheses.
|
|
667
|
-
def
|
|
668
|
-
|
|
1042
|
+
def literal_dataset_append(sql, v)
|
|
1043
|
+
sql << PAREN_OPEN
|
|
1044
|
+
subselect_sql_append(sql, v)
|
|
1045
|
+
sql << PAREN_CLOSE
|
|
669
1046
|
end
|
|
670
1047
|
|
|
671
1048
|
# SQL fragment for Date, using the ISO8601 format.
|
|
672
1049
|
def literal_date(v)
|
|
673
|
-
|
|
1050
|
+
if requires_sql_standard_datetimes?
|
|
1051
|
+
v.strftime(FORMAT_DATE_STANDARD)
|
|
1052
|
+
else
|
|
1053
|
+
v.strftime(FORMAT_DATE)
|
|
1054
|
+
end
|
|
674
1055
|
end
|
|
675
1056
|
|
|
676
1057
|
# SQL fragment for DateTime
|
|
@@ -679,8 +1060,8 @@ module Sequel
|
|
|
679
1060
|
end
|
|
680
1061
|
|
|
681
1062
|
# SQL fragment for SQL::Expression, result depends on the specific type of expression.
|
|
682
|
-
def
|
|
683
|
-
v.
|
|
1063
|
+
def literal_expression_append(sql, v)
|
|
1064
|
+
v.to_s_append(self, sql)
|
|
684
1065
|
end
|
|
685
1066
|
|
|
686
1067
|
# SQL fragment for false
|
|
@@ -694,15 +1075,15 @@ module Sequel
|
|
|
694
1075
|
end
|
|
695
1076
|
|
|
696
1077
|
# SQL fragment for Hash, treated as an expression
|
|
697
|
-
def
|
|
698
|
-
|
|
1078
|
+
def literal_hash_append(sql, v)
|
|
1079
|
+
literal_expression_append(sql, SQL::BooleanExpression.from_value_pairs(v))
|
|
699
1080
|
end
|
|
700
1081
|
|
|
701
1082
|
# SQL fragment for Integer
|
|
702
1083
|
def literal_integer(v)
|
|
703
1084
|
v.to_s
|
|
704
1085
|
end
|
|
705
|
-
|
|
1086
|
+
|
|
706
1087
|
# SQL fragment for nil
|
|
707
1088
|
def literal_nil
|
|
708
1089
|
NULL
|
|
@@ -714,17 +1095,24 @@ module Sequel
|
|
|
714
1095
|
# provided and should add that method to Sequel::Dataset, allowing for adapters
|
|
715
1096
|
# to provide customized literalizations.
|
|
716
1097
|
# If a database specific type is allowed, this should be overriden in a subclass.
|
|
717
|
-
def
|
|
718
|
-
if v.respond_to?(:
|
|
719
|
-
v.
|
|
1098
|
+
def literal_other_append(sql, v)
|
|
1099
|
+
if v.respond_to?(:sql_literal_append)
|
|
1100
|
+
v.sql_literal_append(self, sql)
|
|
1101
|
+
elsif v.respond_to?(:sql_literal)
|
|
1102
|
+
sql << v.sql_literal(self)
|
|
720
1103
|
else
|
|
721
1104
|
raise Error, "can't express #{v.inspect} as a SQL literal"
|
|
722
1105
|
end
|
|
723
1106
|
end
|
|
724
1107
|
|
|
1108
|
+
# SQL fragment for Sequel::SQLTime, containing just the time part
|
|
1109
|
+
def literal_sqltime(v)
|
|
1110
|
+
v.strftime("'%H:%M:%S#{format_timestamp_usec(v.usec) if supports_timestamp_usecs?}'")
|
|
1111
|
+
end
|
|
1112
|
+
|
|
725
1113
|
# SQL fragment for String. Doubles \ and ' by default.
|
|
726
|
-
def
|
|
727
|
-
|
|
1114
|
+
def literal_string_append(sql, v)
|
|
1115
|
+
sql << APOS << v.gsub(APOS_RE, DOUBLE_APOS) << APOS
|
|
728
1116
|
end
|
|
729
1117
|
|
|
730
1118
|
# Converts a symbol into a column name. This method supports underscore
|
|
@@ -735,10 +1123,14 @@ module Sequel
|
|
|
735
1123
|
# dataset.literal(:abc___a) #=> "abc AS a"
|
|
736
1124
|
# dataset.literal(:items__abc) #=> "items.abc"
|
|
737
1125
|
# dataset.literal(:items__abc___a) #=> "items.abc AS a"
|
|
738
|
-
def
|
|
1126
|
+
def literal_symbol_append(sql, v)
|
|
739
1127
|
c_table, column, c_alias = split_symbol(v)
|
|
740
|
-
|
|
741
|
-
|
|
1128
|
+
if c_table
|
|
1129
|
+
quote_identifier_append(sql, c_table)
|
|
1130
|
+
sql << DOT
|
|
1131
|
+
end
|
|
1132
|
+
quote_identifier_append(sql, column)
|
|
1133
|
+
as_sql_append(sql, c_alias) if c_alias
|
|
742
1134
|
end
|
|
743
1135
|
|
|
744
1136
|
# SQL fragment for Time
|
|
@@ -751,6 +1143,11 @@ module Sequel
|
|
|
751
1143
|
BOOL_TRUE
|
|
752
1144
|
end
|
|
753
1145
|
|
|
1146
|
+
# Get the native function name given the emulated function name.
|
|
1147
|
+
def native_function_name(emulated_function)
|
|
1148
|
+
self.class.const_get(:EMULATED_FUNCTION_MAP).fetch(emulated_function, emulated_function)
|
|
1149
|
+
end
|
|
1150
|
+
|
|
754
1151
|
# Returns a qualified column name (including a table name) if the column
|
|
755
1152
|
# name isn't already qualified.
|
|
756
1153
|
def qualified_column_name(column, table)
|
|
@@ -774,59 +1171,7 @@ module Sequel
|
|
|
774
1171
|
|
|
775
1172
|
# Qualify the given expression e to the given table.
|
|
776
1173
|
def qualified_expression(e, table)
|
|
777
|
-
|
|
778
|
-
when Symbol
|
|
779
|
-
t, column, aliaz = split_symbol(e)
|
|
780
|
-
if t
|
|
781
|
-
e
|
|
782
|
-
elsif aliaz
|
|
783
|
-
SQL::AliasedExpression.new(SQL::QualifiedIdentifier.new(table, SQL::Identifier.new(column)), aliaz)
|
|
784
|
-
else
|
|
785
|
-
SQL::QualifiedIdentifier.new(table, e)
|
|
786
|
-
end
|
|
787
|
-
when Array
|
|
788
|
-
e.map{|a| qualified_expression(a, table)}
|
|
789
|
-
when Hash
|
|
790
|
-
h = {}
|
|
791
|
-
e.each{|k,v| h[qualified_expression(k, table)] = qualified_expression(v, table)}
|
|
792
|
-
h
|
|
793
|
-
when SQL::Identifier
|
|
794
|
-
SQL::QualifiedIdentifier.new(table, e)
|
|
795
|
-
when SQL::OrderedExpression
|
|
796
|
-
SQL::OrderedExpression.new(qualified_expression(e.expression, table), e.descending, :nulls=>e.nulls)
|
|
797
|
-
when SQL::AliasedExpression
|
|
798
|
-
SQL::AliasedExpression.new(qualified_expression(e.expression, table), e.aliaz)
|
|
799
|
-
when SQL::CaseExpression
|
|
800
|
-
args = [qualified_expression(e.conditions, table), qualified_expression(e.default, table)]
|
|
801
|
-
args << qualified_expression(e.expression, table) if e.expression?
|
|
802
|
-
SQL::CaseExpression.new(*args)
|
|
803
|
-
when SQL::Cast
|
|
804
|
-
SQL::Cast.new(qualified_expression(e.expr, table), e.type)
|
|
805
|
-
when SQL::Function
|
|
806
|
-
SQL::Function.new(e.f, *qualified_expression(e.args, table))
|
|
807
|
-
when SQL::ComplexExpression
|
|
808
|
-
SQL::ComplexExpression.new(e.op, *qualified_expression(e.args, table))
|
|
809
|
-
when SQL::Subscript
|
|
810
|
-
SQL::Subscript.new(qualified_expression(e.f, table), qualified_expression(e.sub, table))
|
|
811
|
-
when SQL::WindowFunction
|
|
812
|
-
SQL::WindowFunction.new(qualified_expression(e.function, table), qualified_expression(e.window, table))
|
|
813
|
-
when SQL::Window
|
|
814
|
-
o = e.opts.dup
|
|
815
|
-
o[:partition] = qualified_expression(o[:partition], table) if o[:partition]
|
|
816
|
-
o[:order] = qualified_expression(o[:order], table) if o[:order]
|
|
817
|
-
SQL::Window.new(o)
|
|
818
|
-
when SQL::PlaceholderLiteralString
|
|
819
|
-
args = if e.args.is_a?(Hash)
|
|
820
|
-
h = {}
|
|
821
|
-
e.args.each{|k,v| h[k] = qualified_expression(v, table)}
|
|
822
|
-
h
|
|
823
|
-
else
|
|
824
|
-
qualified_expression(e.args, table)
|
|
825
|
-
end
|
|
826
|
-
SQL::PlaceholderLiteralString.new(e.str, args, e.parens)
|
|
827
|
-
else
|
|
828
|
-
e
|
|
829
|
-
end
|
|
1174
|
+
Qualifier.new(self, table).transform(e)
|
|
830
1175
|
end
|
|
831
1176
|
|
|
832
1177
|
# The order of methods to call to build the SELECT SQL statement
|
|
@@ -836,13 +1181,19 @@ module Sequel
|
|
|
836
1181
|
|
|
837
1182
|
# Modify the sql to add the columns selected
|
|
838
1183
|
def select_columns_sql(sql)
|
|
839
|
-
sql <<
|
|
1184
|
+
sql << SPACE
|
|
1185
|
+
column_list_append(sql, @opts[:select])
|
|
840
1186
|
end
|
|
841
1187
|
|
|
842
1188
|
# Modify the sql to add the DISTINCT modifier
|
|
843
1189
|
def select_distinct_sql(sql)
|
|
844
1190
|
if distinct = @opts[:distinct]
|
|
845
|
-
sql <<
|
|
1191
|
+
sql << DISTINCT
|
|
1192
|
+
unless distinct.empty?
|
|
1193
|
+
sql << ON_PAREN
|
|
1194
|
+
expression_list_append(sql, distinct)
|
|
1195
|
+
sql << PAREN_CLOSE
|
|
1196
|
+
end
|
|
846
1197
|
end
|
|
847
1198
|
end
|
|
848
1199
|
|
|
@@ -850,60 +1201,100 @@ module Sequel
|
|
|
850
1201
|
# This uses a subselect for the compound datasets used, because using parantheses doesn't
|
|
851
1202
|
# work on all databases. I consider this an ugly hack, but can't I think of a better default.
|
|
852
1203
|
def select_compounds_sql(sql)
|
|
853
|
-
return unless @opts[:compounds]
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
sql <<
|
|
1204
|
+
return unless c = @opts[:compounds]
|
|
1205
|
+
c.each do |type, dataset, all|
|
|
1206
|
+
sql << SPACE << type.to_s.upcase
|
|
1207
|
+
sql << ALL if all
|
|
1208
|
+
sql << SPACE
|
|
1209
|
+
compound_dataset_sql_append(sql, dataset)
|
|
857
1210
|
end
|
|
858
1211
|
end
|
|
859
1212
|
|
|
860
1213
|
# Modify the sql to add the list of tables to select FROM
|
|
861
1214
|
def select_from_sql(sql)
|
|
862
|
-
|
|
1215
|
+
if f = @opts[:from]
|
|
1216
|
+
sql << FROM
|
|
1217
|
+
source_list_append(sql, f)
|
|
1218
|
+
end
|
|
863
1219
|
end
|
|
864
1220
|
alias delete_from_sql select_from_sql
|
|
865
1221
|
|
|
866
1222
|
# Modify the sql to add the expressions to GROUP BY
|
|
867
1223
|
def select_group_sql(sql)
|
|
868
|
-
|
|
1224
|
+
if group = @opts[:group]
|
|
1225
|
+
sql << GROUP_BY
|
|
1226
|
+
if go = @opts[:group_options]
|
|
1227
|
+
if uses_with_rollup?
|
|
1228
|
+
expression_list_append(sql, group)
|
|
1229
|
+
sql << SPACE_WITH << go.to_s.upcase
|
|
1230
|
+
else
|
|
1231
|
+
sql << go.to_s.upcase << PAREN_OPEN
|
|
1232
|
+
expression_list_append(sql, group)
|
|
1233
|
+
sql << PAREN_CLOSE
|
|
1234
|
+
end
|
|
1235
|
+
else
|
|
1236
|
+
expression_list_append(sql, group)
|
|
1237
|
+
end
|
|
1238
|
+
end
|
|
869
1239
|
end
|
|
870
1240
|
|
|
871
1241
|
# Modify the sql to add the filter criteria in the HAVING clause
|
|
872
1242
|
def select_having_sql(sql)
|
|
873
|
-
|
|
1243
|
+
if having = @opts[:having]
|
|
1244
|
+
sql << HAVING
|
|
1245
|
+
literal_append(sql, having)
|
|
1246
|
+
end
|
|
874
1247
|
end
|
|
875
1248
|
|
|
876
1249
|
# Modify the sql to add the list of tables to JOIN to
|
|
877
1250
|
def select_join_sql(sql)
|
|
878
|
-
|
|
1251
|
+
if js = @opts[:join]
|
|
1252
|
+
js.each{|j| literal_append(sql, j)}
|
|
1253
|
+
end
|
|
879
1254
|
end
|
|
880
1255
|
|
|
881
1256
|
# Modify the sql to limit the number of rows returned and offset
|
|
882
1257
|
def select_limit_sql(sql)
|
|
883
|
-
|
|
884
|
-
|
|
1258
|
+
if l = @opts[:limit]
|
|
1259
|
+
sql << LIMIT
|
|
1260
|
+
literal_append(sql, l)
|
|
1261
|
+
end
|
|
1262
|
+
if o = @opts[:offset]
|
|
1263
|
+
sql << OFFSET
|
|
1264
|
+
literal_append(sql, o)
|
|
1265
|
+
end
|
|
885
1266
|
end
|
|
886
1267
|
|
|
887
1268
|
# Modify the sql to support the different types of locking modes.
|
|
888
1269
|
def select_lock_sql(sql)
|
|
889
|
-
case @opts[:lock]
|
|
1270
|
+
case l = @opts[:lock]
|
|
890
1271
|
when :update
|
|
891
1272
|
sql << FOR_UPDATE
|
|
892
1273
|
when String
|
|
893
|
-
sql <<
|
|
1274
|
+
sql << SPACE << l
|
|
894
1275
|
end
|
|
895
1276
|
end
|
|
896
1277
|
|
|
897
1278
|
# Modify the sql to add the expressions to ORDER BY
|
|
898
1279
|
def select_order_sql(sql)
|
|
899
|
-
|
|
1280
|
+
if o = @opts[:order]
|
|
1281
|
+
sql << ORDER_BY
|
|
1282
|
+
expression_list_append(sql, o)
|
|
1283
|
+
end
|
|
900
1284
|
end
|
|
901
1285
|
alias delete_order_sql select_order_sql
|
|
902
1286
|
alias update_order_sql select_order_sql
|
|
903
1287
|
|
|
1288
|
+
def select_select_sql(sql)
|
|
1289
|
+
sql << SELECT
|
|
1290
|
+
end
|
|
1291
|
+
|
|
904
1292
|
# Modify the sql to add the filter criteria in the WHERE clause
|
|
905
1293
|
def select_where_sql(sql)
|
|
906
|
-
|
|
1294
|
+
if w = @opts[:where]
|
|
1295
|
+
sql << WHERE
|
|
1296
|
+
literal_append(sql, w)
|
|
1297
|
+
end
|
|
907
1298
|
end
|
|
908
1299
|
alias delete_where_sql select_where_sql
|
|
909
1300
|
alias update_where_sql select_where_sql
|
|
@@ -912,8 +1303,26 @@ module Sequel
|
|
|
912
1303
|
def select_with_sql(sql)
|
|
913
1304
|
ws = opts[:with]
|
|
914
1305
|
return if !ws || ws.empty?
|
|
915
|
-
sql
|
|
1306
|
+
sql << select_with_sql_base
|
|
1307
|
+
c = false
|
|
1308
|
+
comma = COMMA
|
|
1309
|
+
ws.each do |w|
|
|
1310
|
+
sql << comma if c
|
|
1311
|
+
quote_identifier_append(sql, w[:name])
|
|
1312
|
+
if args = w[:args]
|
|
1313
|
+
sql << PAREN_OPEN
|
|
1314
|
+
argument_list_append(sql, args)
|
|
1315
|
+
sql << PAREN_CLOSE
|
|
1316
|
+
end
|
|
1317
|
+
sql << AS
|
|
1318
|
+
literal_dataset_append(sql, w[:dataset])
|
|
1319
|
+
c ||= true
|
|
1320
|
+
end
|
|
1321
|
+
sql << SPACE
|
|
916
1322
|
end
|
|
1323
|
+
alias delete_with_sql select_with_sql
|
|
1324
|
+
alias insert_with_sql select_with_sql
|
|
1325
|
+
alias update_with_sql select_with_sql
|
|
917
1326
|
|
|
918
1327
|
# The base keyword to use for the SQL WITH clause
|
|
919
1328
|
def select_with_sql_base
|
|
@@ -921,46 +1330,52 @@ module Sequel
|
|
|
921
1330
|
end
|
|
922
1331
|
|
|
923
1332
|
# Converts an array of source names into into a comma separated list.
|
|
924
|
-
def
|
|
925
|
-
raise(Error, 'No source specified for query') if
|
|
926
|
-
|
|
1333
|
+
def source_list_append(sql, sources)
|
|
1334
|
+
raise(Error, 'No source specified for query') if sources.nil? || sources == []
|
|
1335
|
+
c = false
|
|
1336
|
+
co = COMMA
|
|
1337
|
+
sources.each do |s|
|
|
1338
|
+
sql << co if c
|
|
1339
|
+
identifier_append(sql, s)
|
|
1340
|
+
c ||= true
|
|
1341
|
+
end
|
|
927
1342
|
end
|
|
928
1343
|
|
|
929
|
-
#
|
|
930
|
-
# either be a string or nil.
|
|
931
|
-
#
|
|
932
|
-
# For columns, these parts are the table, column, and alias.
|
|
933
|
-
# For tables, these parts are the schema, table, and alias.
|
|
1344
|
+
# Delegate to Sequel.split_symbol.
|
|
934
1345
|
def split_symbol(sym)
|
|
935
|
-
|
|
936
|
-
if m = COLUMN_REF_RE1.match(s)
|
|
937
|
-
[m[1], m[3], m[5]]
|
|
938
|
-
elsif m = COLUMN_REF_RE2.match(s)
|
|
939
|
-
[nil, m[1], m[3]]
|
|
940
|
-
elsif m = COLUMN_REF_RE3.match(s)
|
|
941
|
-
[m[1], m[3], nil]
|
|
942
|
-
else
|
|
943
|
-
[nil, s, nil]
|
|
944
|
-
end
|
|
1346
|
+
Sequel.split_symbol(sym)
|
|
945
1347
|
end
|
|
946
1348
|
|
|
1349
|
+
# The string that is appended to to create the SQL query, the empty
|
|
1350
|
+
# string by default
|
|
1351
|
+
def sql_string_origin
|
|
1352
|
+
''
|
|
1353
|
+
end
|
|
1354
|
+
|
|
947
1355
|
# SQL to use if this dataset uses static SQL. Since static SQL
|
|
948
1356
|
# can be a PlaceholderLiteralString in addition to a String,
|
|
949
1357
|
# we literalize nonstrings.
|
|
950
1358
|
def static_sql(sql)
|
|
951
|
-
|
|
1359
|
+
if append_sql = @opts[:append_sql]
|
|
1360
|
+
if sql.is_a?(String)
|
|
1361
|
+
append_sql << sql
|
|
1362
|
+
else
|
|
1363
|
+
literal_append(append_sql, sql)
|
|
1364
|
+
end
|
|
1365
|
+
else
|
|
1366
|
+
if sql.is_a?(String)
|
|
1367
|
+
sql
|
|
1368
|
+
else
|
|
1369
|
+
literal(sql)
|
|
1370
|
+
end
|
|
1371
|
+
end
|
|
952
1372
|
end
|
|
953
1373
|
|
|
954
1374
|
# SQL fragment for a subselect using the given database's SQL.
|
|
955
|
-
def
|
|
956
|
-
ds.sql
|
|
1375
|
+
def subselect_sql_append(sql, ds)
|
|
1376
|
+
ds.clone(:append_sql=>sql).sql
|
|
957
1377
|
end
|
|
958
1378
|
|
|
959
|
-
# SQL fragment specifying a table name.
|
|
960
|
-
def table_ref(t)
|
|
961
|
-
t.is_a?(String) ? quote_identifier(t) : literal(t)
|
|
962
|
-
end
|
|
963
|
-
|
|
964
1379
|
# The order of methods to call to build the UPDATE SQL statement
|
|
965
1380
|
def update_clause_methods
|
|
966
1381
|
UPDATE_CLAUSE_METHODS
|
|
@@ -969,25 +1384,38 @@ module Sequel
|
|
|
969
1384
|
# SQL fragment specifying the tables from with to delete.
|
|
970
1385
|
# Includes join table if modifying joins is allowed.
|
|
971
1386
|
def update_table_sql(sql)
|
|
972
|
-
sql <<
|
|
1387
|
+
sql << SPACE
|
|
1388
|
+
source_list_append(sql, @opts[:from])
|
|
973
1389
|
select_join_sql(sql) if supports_modifying_joins?
|
|
974
1390
|
end
|
|
975
1391
|
|
|
976
1392
|
# The SQL fragment specifying the columns and values to SET.
|
|
977
1393
|
def update_set_sql(sql)
|
|
978
1394
|
values = opts[:values]
|
|
979
|
-
|
|
1395
|
+
sql << SET
|
|
1396
|
+
if values.is_a?(Hash)
|
|
980
1397
|
values = opts[:defaults].merge(values) if opts[:defaults]
|
|
981
1398
|
values = values.merge(opts[:overrides]) if opts[:overrides]
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1399
|
+
c = false
|
|
1400
|
+
eq = EQUAL
|
|
1401
|
+
values.each do |k, v|
|
|
1402
|
+
sql << COMMA if c
|
|
1403
|
+
if k.is_a?(String) && !k.is_a?(LiteralString)
|
|
1404
|
+
quote_identifier_append(sql, k)
|
|
1405
|
+
else
|
|
1406
|
+
literal_append(sql, k)
|
|
1407
|
+
end
|
|
1408
|
+
sql << eq
|
|
1409
|
+
literal_append(sql, v)
|
|
1410
|
+
c ||= true
|
|
1411
|
+
end
|
|
986
1412
|
else
|
|
987
|
-
|
|
988
|
-
values
|
|
1413
|
+
sql << values
|
|
989
1414
|
end
|
|
990
|
-
|
|
1415
|
+
end
|
|
1416
|
+
|
|
1417
|
+
def update_update_sql(sql)
|
|
1418
|
+
sql << UPDATE
|
|
991
1419
|
end
|
|
992
1420
|
end
|
|
993
1421
|
end
|