sequel 3.21.0 → 3.41.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 +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- 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 +576 -0
- data/doc/opening_databases.rdoc +121 -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/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -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/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- 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 +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -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 +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -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 +16 -28
- 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 +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- 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 +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- 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/split_alter_table.rb +36 -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 +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- 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 +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- 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 +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- 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/connection_validator.rb +109 -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 +539 -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 +334 -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 +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -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 +137 -16
- 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 +77 -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 +168 -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 +57 -12
- 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/touch.rb +18 -6
- 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 +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- 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 +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -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 +227 -33
- 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/connection_validator_spec.rb +118 -0
- 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 +324 -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 +200 -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 +340 -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 +65 -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 +53 -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 +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -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 +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- 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 +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -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 +223 -81
- 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
|
+
delayed_evaluation_sql
|
|
294
|
+
function_sql
|
|
295
|
+
join_clause_sql
|
|
296
|
+
join_on_clause_sql
|
|
297
|
+
join_using_clause_sql
|
|
298
|
+
negative_boolean_constant_sql
|
|
299
|
+
ordered_expression_sql
|
|
300
|
+
placeholder_literal_string_sql
|
|
301
|
+
qualified_identifier_sql
|
|
302
|
+
quote_identifier
|
|
303
|
+
quote_schema_table
|
|
304
|
+
quoted_identifier
|
|
305
|
+
subscript_sql
|
|
306
|
+
window_sql
|
|
307
|
+
window_function_sql
|
|
308
|
+
END
|
|
309
|
+
PRIVATE_APPEND_METHODS = (<<-END).split.map{|x| x.to_sym}
|
|
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,220 @@ 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 for delayed evaluations, evaluating the
|
|
500
|
+
# object and literalizing the returned value.
|
|
501
|
+
def delayed_evaluation_sql_append(sql, callable)
|
|
502
|
+
literal_append(sql, callable.call)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
# SQL fragment specifying an emulated SQL function call.
|
|
506
|
+
# By default, assumes just the function name may need to
|
|
507
|
+
# be emulated, adapters should set an EMULATED_FUNCTION_MAP
|
|
508
|
+
# hash mapping emulated functions to native functions in
|
|
509
|
+
# their dataset class to setup the emulation.
|
|
510
|
+
def emulated_function_sql_append(sql, f)
|
|
511
|
+
_function_sql_append(sql, native_function_name(f.f), f.args)
|
|
311
512
|
end
|
|
312
513
|
|
|
313
|
-
# SQL fragment specifying an SQL function call
|
|
314
|
-
def
|
|
315
|
-
|
|
316
|
-
"#{f.f}#{args.empty? ? '()' : literal(args)}"
|
|
514
|
+
# SQL fragment specifying an SQL function call without emulation.
|
|
515
|
+
def function_sql_append(sql, f)
|
|
516
|
+
_function_sql_append(sql, f.f, f.args)
|
|
317
517
|
end
|
|
318
518
|
|
|
319
519
|
# SQL fragment specifying a JOIN clause without ON or USING.
|
|
320
|
-
def
|
|
520
|
+
def join_clause_sql_append(sql, jc)
|
|
321
521
|
table = jc.table
|
|
322
522
|
table_alias = jc.table_alias
|
|
323
523
|
table_alias = nil if table == table_alias
|
|
324
|
-
|
|
325
|
-
|
|
524
|
+
sql << SPACE << join_type_sql(jc.join_type) << SPACE
|
|
525
|
+
identifier_append(sql, table)
|
|
526
|
+
as_sql_append(sql, table_alias) if table_alias
|
|
326
527
|
end
|
|
327
528
|
|
|
328
529
|
# SQL fragment specifying a JOIN clause with ON.
|
|
329
|
-
def
|
|
330
|
-
|
|
530
|
+
def join_on_clause_sql_append(sql, jc)
|
|
531
|
+
join_clause_sql_append(sql, jc)
|
|
532
|
+
sql << ON
|
|
533
|
+
literal_append(sql, filter_expr(jc.on))
|
|
331
534
|
end
|
|
332
535
|
|
|
333
536
|
# SQL fragment specifying a JOIN clause with USING.
|
|
334
|
-
def
|
|
335
|
-
|
|
537
|
+
def join_using_clause_sql_append(sql, jc)
|
|
538
|
+
join_clause_sql_append(sql, jc)
|
|
539
|
+
sql << USING
|
|
540
|
+
column_list_append(sql, jc.using)
|
|
541
|
+
sql << PAREN_CLOSE
|
|
336
542
|
end
|
|
337
543
|
|
|
338
544
|
# SQL fragment for NegativeBooleanConstants
|
|
339
|
-
def
|
|
340
|
-
|
|
545
|
+
def negative_boolean_constant_sql_append(sql, constant)
|
|
546
|
+
sql << NOT_SPACE
|
|
547
|
+
boolean_constant_sql_append(sql, constant)
|
|
341
548
|
end
|
|
342
549
|
|
|
343
550
|
# SQL fragment for the ordered expression, used in the ORDER BY
|
|
344
551
|
# clause.
|
|
345
|
-
def
|
|
346
|
-
|
|
552
|
+
def ordered_expression_sql_append(sql, oe)
|
|
553
|
+
literal_append(sql, oe.expression)
|
|
554
|
+
sql << (oe.descending ? DESC : ASC)
|
|
347
555
|
case oe.nulls
|
|
348
556
|
when :first
|
|
349
|
-
|
|
557
|
+
sql << NULLS_FIRST
|
|
350
558
|
when :last
|
|
351
|
-
|
|
352
|
-
else
|
|
353
|
-
s
|
|
559
|
+
sql << NULLS_LAST
|
|
354
560
|
end
|
|
355
561
|
end
|
|
356
562
|
|
|
357
563
|
# SQL fragment for a literal string with placeholders
|
|
358
|
-
def
|
|
564
|
+
def placeholder_literal_string_sql_append(sql, pls)
|
|
359
565
|
args = pls.args
|
|
360
|
-
|
|
566
|
+
str = pls.str
|
|
567
|
+
sql << PAREN_OPEN if pls.parens
|
|
568
|
+
if args.is_a?(Hash)
|
|
361
569
|
re = /:(#{args.keys.map{|k| Regexp.escape(k.to_s)}.join('|')})\b/
|
|
362
|
-
|
|
570
|
+
loop do
|
|
571
|
+
previous, q, str = str.partition(re)
|
|
572
|
+
sql << previous
|
|
573
|
+
literal_append(sql, args[($1||q[1..-1].to_s).to_sym]) unless q.empty?
|
|
574
|
+
break if str.empty?
|
|
575
|
+
end
|
|
576
|
+
elsif str.is_a?(Array)
|
|
577
|
+
len = args.length
|
|
578
|
+
str.each_with_index do |s, i|
|
|
579
|
+
sql << s
|
|
580
|
+
literal_append(sql, args[i]) unless i == len
|
|
581
|
+
end
|
|
363
582
|
else
|
|
364
583
|
i = -1
|
|
365
|
-
|
|
584
|
+
loop do
|
|
585
|
+
previous, q, str = str.partition(QUESTION_MARK)
|
|
586
|
+
sql << previous
|
|
587
|
+
literal_append(sql, args.at(i+=1)) unless q.empty?
|
|
588
|
+
break if str.empty?
|
|
589
|
+
end
|
|
366
590
|
end
|
|
367
|
-
|
|
368
|
-
s
|
|
591
|
+
sql << PAREN_CLOSE if pls.parens
|
|
369
592
|
end
|
|
370
593
|
|
|
371
594
|
# SQL fragment for the qualifed identifier, specifying
|
|
372
595
|
# a table and a column (or schema and table).
|
|
373
|
-
|
|
374
|
-
|
|
596
|
+
# If 3 arguments are given, the 2nd should be the table/qualifier and the third should be
|
|
597
|
+
# column/qualified. If 2 arguments are given, the 2nd should be an SQL::QualifiedIdentifier.
|
|
598
|
+
def qualified_identifier_sql_append(sql, table, column=(c = table.column; table = table.table; c))
|
|
599
|
+
identifier_append(sql, table)
|
|
600
|
+
sql << DOT
|
|
601
|
+
identifier_append(sql, column)
|
|
375
602
|
end
|
|
376
603
|
|
|
377
604
|
# Adds quoting to identifiers (columns and tables). If identifiers are not
|
|
378
605
|
# being quoted, returns name as a string. If identifiers are being quoted
|
|
379
606
|
# quote the name with quoted_identifier.
|
|
380
|
-
def
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
607
|
+
def quote_identifier_append(sql, name)
|
|
608
|
+
if name.is_a?(LiteralString)
|
|
609
|
+
sql << name
|
|
610
|
+
else
|
|
611
|
+
name = name.value if name.is_a?(SQL::Identifier)
|
|
612
|
+
name = input_identifier(name)
|
|
613
|
+
if quote_identifiers?
|
|
614
|
+
quoted_identifier_append(sql, name)
|
|
615
|
+
else
|
|
616
|
+
sql << name
|
|
617
|
+
end
|
|
618
|
+
end
|
|
386
619
|
end
|
|
387
620
|
|
|
388
621
|
# Separates the schema from the table and returns a string with them
|
|
389
622
|
# quoted (if quoting identifiers)
|
|
390
|
-
def
|
|
623
|
+
def quote_schema_table_append(sql, table)
|
|
391
624
|
schema, table = schema_and_table(table)
|
|
392
|
-
|
|
625
|
+
if schema
|
|
626
|
+
quote_identifier_append(sql, schema)
|
|
627
|
+
sql << DOT
|
|
628
|
+
end
|
|
629
|
+
quote_identifier_append(sql, table)
|
|
393
630
|
end
|
|
394
631
|
|
|
395
632
|
# This method quotes the given name with the SQL standard double quote.
|
|
396
633
|
# should be overridden by subclasses to provide quoting not matching the
|
|
397
634
|
# SQL standard, such as backtick (used by MySQL and SQLite).
|
|
398
|
-
def
|
|
399
|
-
|
|
635
|
+
def quoted_identifier_append(sql, name)
|
|
636
|
+
sql << QUOTE << name.to_s.gsub(QUOTE_RE, DOUBLE_QUOTE) << QUOTE
|
|
400
637
|
end
|
|
401
638
|
|
|
402
639
|
# Split the schema information from the table
|
|
@@ -418,34 +655,59 @@ module Sequel
|
|
|
418
655
|
end
|
|
419
656
|
|
|
420
657
|
# SQL fragment for specifying subscripts (SQL array accesses)
|
|
421
|
-
def
|
|
422
|
-
|
|
658
|
+
def subscript_sql_append(sql, s)
|
|
659
|
+
literal_append(sql, s.f)
|
|
660
|
+
sql << BRACKET_OPEN
|
|
661
|
+
expression_list_append(sql, s.sub)
|
|
662
|
+
sql << BRACKET_CLOSE
|
|
423
663
|
end
|
|
424
664
|
|
|
425
665
|
# The SQL fragment for the given window's options.
|
|
426
|
-
def
|
|
666
|
+
def window_sql_append(sql, opts)
|
|
427
667
|
raise(Error, 'This dataset does not support window functions') unless supports_window_functions?
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
668
|
+
sql << PAREN_OPEN
|
|
669
|
+
window, part, order, frame = opts.values_at(:window, :partition, :order, :frame)
|
|
670
|
+
space = false
|
|
671
|
+
space_s = SPACE
|
|
672
|
+
if window
|
|
673
|
+
literal_append(sql, window)
|
|
674
|
+
space = true
|
|
675
|
+
end
|
|
676
|
+
if part
|
|
677
|
+
sql << space_s if space
|
|
678
|
+
sql << PARTITION_BY
|
|
679
|
+
expression_list_append(sql, Array(part))
|
|
680
|
+
space = true
|
|
681
|
+
end
|
|
682
|
+
if order
|
|
683
|
+
sql << space_s if space
|
|
684
|
+
sql << ORDER_BY_NS
|
|
685
|
+
expression_list_append(sql, Array(order))
|
|
686
|
+
space = true
|
|
687
|
+
end
|
|
688
|
+
case frame
|
|
432
689
|
when nil
|
|
433
|
-
|
|
690
|
+
# nothing
|
|
434
691
|
when :all
|
|
435
|
-
|
|
692
|
+
sql << space_s if space
|
|
693
|
+
sql << FRAME_ALL
|
|
436
694
|
when :rows
|
|
437
|
-
|
|
695
|
+
sql << space_s if space
|
|
696
|
+
sql << FRAME_ROWS
|
|
438
697
|
when String
|
|
439
|
-
|
|
698
|
+
sql << space_s if space
|
|
699
|
+
sql << frame
|
|
440
700
|
else
|
|
441
701
|
raise Error, "invalid window frame clause, should be :all, :rows, a string, or nil"
|
|
442
702
|
end
|
|
443
|
-
|
|
703
|
+
sql << PAREN_CLOSE
|
|
444
704
|
end
|
|
445
705
|
|
|
446
706
|
# The SQL fragment for the given window function's function and window.
|
|
447
|
-
def
|
|
448
|
-
|
|
707
|
+
def window_function_sql_append(sql, function, window)
|
|
708
|
+
literal_append(sql, function)
|
|
709
|
+
sql << OVER
|
|
710
|
+
literal_append(sql, window)
|
|
449
711
|
end
|
|
450
712
|
|
|
451
713
|
protected
|
|
@@ -468,6 +730,16 @@ module Sequel
|
|
|
468
730
|
|
|
469
731
|
private
|
|
470
732
|
|
|
733
|
+
# Backbone of function_sql_append and emulated_function_sql_append.
|
|
734
|
+
def _function_sql_append(sql, name, args)
|
|
735
|
+
sql << name.to_s
|
|
736
|
+
if args.empty?
|
|
737
|
+
sql << FUNCTION_EMPTY
|
|
738
|
+
else
|
|
739
|
+
literal_append(sql, args)
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
|
|
471
743
|
# Formats the truncate statement. Assumes the table given has already been
|
|
472
744
|
# literalized.
|
|
473
745
|
def _truncate_sql(table)
|
|
@@ -517,14 +789,10 @@ module Sequel
|
|
|
517
789
|
options_overlap(COUNT_FROM_SELF_OPTS) ? from_self : unordered
|
|
518
790
|
end
|
|
519
791
|
|
|
520
|
-
# Do a simple join of the arguments (which should be strings or symbols) separated by commas
|
|
521
|
-
def argument_list(args)
|
|
522
|
-
args.join(COMMA_SEPARATOR)
|
|
523
|
-
end
|
|
524
|
-
|
|
525
792
|
# SQL fragment for specifying an alias. expression should already be literalized.
|
|
526
|
-
def
|
|
527
|
-
|
|
793
|
+
def as_sql_append(sql, aliaz)
|
|
794
|
+
sql << AS
|
|
795
|
+
quote_identifier_append(sql, aliaz)
|
|
528
796
|
end
|
|
529
797
|
|
|
530
798
|
# Raise an InvalidOperation exception if deletion is not allowed
|
|
@@ -534,38 +802,88 @@ module Sequel
|
|
|
534
802
|
raise(InvalidOperation, "Joined datasets cannot be modified") if !supports_modifying_joins? && joined_dataset?
|
|
535
803
|
end
|
|
536
804
|
|
|
805
|
+
# Alias of check_modification_allowed!
|
|
806
|
+
def check_truncation_allowed!
|
|
807
|
+
check_modification_allowed!
|
|
808
|
+
end
|
|
809
|
+
|
|
537
810
|
# Prepare an SQL statement by calling all clause methods for the given statement type.
|
|
538
811
|
def clause_sql(type)
|
|
539
|
-
sql =
|
|
812
|
+
sql = @opts[:append_sql] || sql_string_origin
|
|
540
813
|
send("#{type}_clause_methods").each{|x| send(x, sql)}
|
|
541
814
|
sql
|
|
542
815
|
end
|
|
543
816
|
|
|
544
817
|
# Converts an array of column names into a comma seperated string of
|
|
545
818
|
# column names. If the array is empty, a wildcard (*) is returned.
|
|
546
|
-
def
|
|
547
|
-
(columns.nil? || columns.empty?)
|
|
819
|
+
def column_list_append(sql, columns)
|
|
820
|
+
if (columns.nil? || columns.empty?)
|
|
821
|
+
sql << WILDCARD
|
|
822
|
+
else
|
|
823
|
+
expression_list_append(sql, columns)
|
|
824
|
+
end
|
|
548
825
|
end
|
|
549
|
-
|
|
826
|
+
|
|
827
|
+
# Yield each two pair of arguments to the block, which should
|
|
828
|
+
# return a string representing the SQL code for those
|
|
829
|
+
# two arguments. If more than 2 arguments are provided, all
|
|
830
|
+
# calls to the block # after the first will have a LiteralString
|
|
831
|
+
# as the first argument, representing the application of the block to
|
|
832
|
+
# the previous arguments.
|
|
833
|
+
def complex_expression_arg_pairs(args)
|
|
834
|
+
case args.length
|
|
835
|
+
when 1
|
|
836
|
+
literal(args.at(0))
|
|
837
|
+
when 2
|
|
838
|
+
yield args.at(0), args.at(1)
|
|
839
|
+
else
|
|
840
|
+
args.inject{|m, a| LiteralString.new(yield(m, a))}
|
|
841
|
+
end
|
|
842
|
+
end
|
|
843
|
+
|
|
844
|
+
# The SQL to use for the dataset used in a UNION/INTERSECT/EXCEPT clause.
|
|
845
|
+
def compound_dataset_sql_append(sql, ds)
|
|
846
|
+
subselect_sql_append(sql, ds)
|
|
847
|
+
end
|
|
848
|
+
|
|
550
849
|
# The alias to use for datasets, takes a number to make sure the name is unique.
|
|
551
850
|
def dataset_alias(number)
|
|
552
851
|
:"#{DATASET_ALIAS_BASE_NAME}#{number}"
|
|
553
852
|
end
|
|
554
853
|
|
|
854
|
+
# The strftime format to use when literalizing the time.
|
|
855
|
+
def default_timestamp_format
|
|
856
|
+
requires_sql_standard_datetimes? ? STANDARD_TIMESTAMP_FORMAT : TIMESTAMP_FORMAT
|
|
857
|
+
end
|
|
858
|
+
|
|
555
859
|
# The order of methods to call to build the DELETE SQL statement
|
|
556
860
|
def delete_clause_methods
|
|
557
861
|
DELETE_CLAUSE_METHODS
|
|
558
862
|
end
|
|
559
863
|
|
|
864
|
+
def delete_delete_sql(sql)
|
|
865
|
+
sql << DELETE
|
|
866
|
+
end
|
|
867
|
+
|
|
560
868
|
# Converts an array of expressions into a comma separated string of
|
|
561
869
|
# expressions.
|
|
562
|
-
def
|
|
563
|
-
|
|
870
|
+
def expression_list_append(sql, columns)
|
|
871
|
+
c = false
|
|
872
|
+
co = COMMA
|
|
873
|
+
columns.each do |col|
|
|
874
|
+
sql << co if c
|
|
875
|
+
literal_append(sql, col)
|
|
876
|
+
c ||= true
|
|
877
|
+
end
|
|
564
878
|
end
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
879
|
+
|
|
880
|
+
def empty_array_value(op, cols)
|
|
881
|
+
if Sequel.empty_array_handle_nulls
|
|
882
|
+
c = Array(cols)
|
|
883
|
+
SQL::BooleanExpression.from_value_pairs(c.zip(c), :AND, op == :IN)
|
|
884
|
+
else
|
|
885
|
+
{1 => ((op == :IN) ? 0 : 1)}
|
|
886
|
+
end
|
|
569
887
|
end
|
|
570
888
|
|
|
571
889
|
# Format the timestamp based on the default_timestamp_format, with a couple
|
|
@@ -573,10 +891,10 @@ module Sequel
|
|
|
573
891
|
# database supports them), and override %z to always use a numeric offset
|
|
574
892
|
# of hours and minutes.
|
|
575
893
|
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 <
|
|
894
|
+
v2 = db.from_application_timestamp(v)
|
|
895
|
+
fmt = default_timestamp_format.gsub(FORMAT_TIMESTAMP_RE) do |m|
|
|
896
|
+
if m == FORMAT_USEC
|
|
897
|
+
format_timestamp_usec(v.is_a?(DateTime) ? v.sec_fraction*(RUBY_VERSION < V190 ? 86400000000 : 1000000) : v.usec) if supports_timestamp_usecs?
|
|
580
898
|
else
|
|
581
899
|
if supports_timestamp_timezones?
|
|
582
900
|
# Would like to just use %z format, but it doesn't appear to work on Windows
|
|
@@ -591,13 +909,42 @@ module Sequel
|
|
|
591
909
|
|
|
592
910
|
# Return the SQL timestamp fragment to use for the timezone offset.
|
|
593
911
|
def format_timestamp_offset(hour, minute)
|
|
594
|
-
sprintf(
|
|
912
|
+
sprintf(FORMAT_OFFSET, hour, minute)
|
|
595
913
|
end
|
|
596
914
|
|
|
597
915
|
# Return the SQL timestamp fragment to use for the fractional time part.
|
|
598
916
|
# Should start with the decimal point. Uses 6 decimal places by default.
|
|
599
917
|
def format_timestamp_usec(usec)
|
|
600
|
-
sprintf(
|
|
918
|
+
sprintf(FORMAT_TIMESTAMP_USEC, usec)
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
# Append the value, but special case regular (non-literal, non-blob) strings
|
|
922
|
+
# so that they are considered as identifiers and not SQL strings.
|
|
923
|
+
def identifier_append(sql, v)
|
|
924
|
+
if v.is_a?(String)
|
|
925
|
+
case v
|
|
926
|
+
when LiteralString
|
|
927
|
+
sql << v
|
|
928
|
+
when SQL::Blob
|
|
929
|
+
literal_append(sql, v)
|
|
930
|
+
else
|
|
931
|
+
quote_identifier_append(sql, v)
|
|
932
|
+
end
|
|
933
|
+
else
|
|
934
|
+
literal_append(sql, v)
|
|
935
|
+
end
|
|
936
|
+
end
|
|
937
|
+
alias table_ref_append identifier_append
|
|
938
|
+
|
|
939
|
+
# Append all identifiers in args interspersed by commas.
|
|
940
|
+
def identifier_list_append(sql, args)
|
|
941
|
+
c = false
|
|
942
|
+
comma = COMMA
|
|
943
|
+
args.each do |a|
|
|
944
|
+
sql << comma if c
|
|
945
|
+
identifier_append(sql, a)
|
|
946
|
+
c ||= true
|
|
947
|
+
end
|
|
601
948
|
end
|
|
602
949
|
|
|
603
950
|
# Modify the identifier returned from the database based on the
|
|
@@ -608,7 +955,8 @@ module Sequel
|
|
|
608
955
|
|
|
609
956
|
# SQL fragment specifying the table to insert INTO
|
|
610
957
|
def insert_into_sql(sql)
|
|
611
|
-
sql <<
|
|
958
|
+
sql << INTO
|
|
959
|
+
source_list_append(sql, @opts[:from])
|
|
612
960
|
end
|
|
613
961
|
|
|
614
962
|
# The order of methods to call to build the INSERT SQL statement
|
|
@@ -619,27 +967,51 @@ module Sequel
|
|
|
619
967
|
# SQL fragment specifying the columns to insert into
|
|
620
968
|
def insert_columns_sql(sql)
|
|
621
969
|
columns = opts[:columns]
|
|
622
|
-
|
|
970
|
+
if columns && !columns.empty?
|
|
971
|
+
sql << PAREN_SPACE_OPEN
|
|
972
|
+
identifier_list_append(sql, columns)
|
|
973
|
+
sql << PAREN_CLOSE
|
|
974
|
+
end
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
def insert_insert_sql(sql)
|
|
978
|
+
sql << INSERT
|
|
623
979
|
end
|
|
624
980
|
|
|
625
981
|
# SQL fragment specifying the values to insert.
|
|
626
982
|
def insert_values_sql(sql)
|
|
627
983
|
case values = opts[:values]
|
|
628
984
|
when Array
|
|
629
|
-
|
|
985
|
+
if values.empty?
|
|
986
|
+
sql << DEFAULT_VALUES
|
|
987
|
+
else
|
|
988
|
+
sql << VALUES
|
|
989
|
+
literal_append(sql, values)
|
|
990
|
+
end
|
|
630
991
|
when Dataset
|
|
631
|
-
sql <<
|
|
992
|
+
sql << SPACE
|
|
993
|
+
subselect_sql_append(sql, values)
|
|
632
994
|
when LiteralString
|
|
633
|
-
sql <<
|
|
995
|
+
sql << SPACE << values
|
|
634
996
|
else
|
|
635
997
|
raise Error, "Unsupported INSERT values type, should be an Array or Dataset: #{values.inspect}"
|
|
636
998
|
end
|
|
637
999
|
end
|
|
638
1000
|
|
|
1001
|
+
# SQL fragment specifying the values to return.
|
|
1002
|
+
def insert_returning_sql(sql)
|
|
1003
|
+
if opts.has_key?(:returning)
|
|
1004
|
+
sql << RETURNING
|
|
1005
|
+
column_list_append(sql, Array(opts[:returning]))
|
|
1006
|
+
end
|
|
1007
|
+
end
|
|
1008
|
+
alias delete_returning_sql insert_returning_sql
|
|
1009
|
+
alias update_returning_sql insert_returning_sql
|
|
1010
|
+
|
|
639
1011
|
# SQL fragment specifying a JOIN type, converts underscores to
|
|
640
1012
|
# spaces and upcases.
|
|
641
1013
|
def join_type_sql(join_type)
|
|
642
|
-
"#{join_type.to_s.gsub(
|
|
1014
|
+
"#{join_type.to_s.gsub(UNDERSCORE, SPACE).upcase} JOIN"
|
|
643
1015
|
end
|
|
644
1016
|
|
|
645
1017
|
# Whether this dataset is a joined dataset
|
|
@@ -648,8 +1020,12 @@ module Sequel
|
|
|
648
1020
|
end
|
|
649
1021
|
|
|
650
1022
|
# 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)
|
|
1023
|
+
def literal_array_append(sql, v)
|
|
1024
|
+
if Sequel.condition_specifier?(v)
|
|
1025
|
+
literal_expression_append(sql, SQL::BooleanExpression.from_value_pairs(v))
|
|
1026
|
+
else
|
|
1027
|
+
array_sql_append(sql, v)
|
|
1028
|
+
end
|
|
653
1029
|
end
|
|
654
1030
|
|
|
655
1031
|
# SQL fragment for BigDecimal
|
|
@@ -659,18 +1035,24 @@ module Sequel
|
|
|
659
1035
|
end
|
|
660
1036
|
|
|
661
1037
|
# SQL fragment for SQL::Blob
|
|
662
|
-
def
|
|
663
|
-
|
|
1038
|
+
def literal_blob_append(sql, v)
|
|
1039
|
+
literal_string_append(sql, v)
|
|
664
1040
|
end
|
|
665
1041
|
|
|
666
1042
|
# SQL fragment for Dataset. Does a subselect inside parantheses.
|
|
667
|
-
def
|
|
668
|
-
|
|
1043
|
+
def literal_dataset_append(sql, v)
|
|
1044
|
+
sql << PAREN_OPEN
|
|
1045
|
+
subselect_sql_append(sql, v)
|
|
1046
|
+
sql << PAREN_CLOSE
|
|
669
1047
|
end
|
|
670
1048
|
|
|
671
1049
|
# SQL fragment for Date, using the ISO8601 format.
|
|
672
1050
|
def literal_date(v)
|
|
673
|
-
|
|
1051
|
+
if requires_sql_standard_datetimes?
|
|
1052
|
+
v.strftime(FORMAT_DATE_STANDARD)
|
|
1053
|
+
else
|
|
1054
|
+
v.strftime(FORMAT_DATE)
|
|
1055
|
+
end
|
|
674
1056
|
end
|
|
675
1057
|
|
|
676
1058
|
# SQL fragment for DateTime
|
|
@@ -679,8 +1061,8 @@ module Sequel
|
|
|
679
1061
|
end
|
|
680
1062
|
|
|
681
1063
|
# SQL fragment for SQL::Expression, result depends on the specific type of expression.
|
|
682
|
-
def
|
|
683
|
-
v.
|
|
1064
|
+
def literal_expression_append(sql, v)
|
|
1065
|
+
v.to_s_append(self, sql)
|
|
684
1066
|
end
|
|
685
1067
|
|
|
686
1068
|
# SQL fragment for false
|
|
@@ -694,15 +1076,15 @@ module Sequel
|
|
|
694
1076
|
end
|
|
695
1077
|
|
|
696
1078
|
# SQL fragment for Hash, treated as an expression
|
|
697
|
-
def
|
|
698
|
-
|
|
1079
|
+
def literal_hash_append(sql, v)
|
|
1080
|
+
literal_expression_append(sql, SQL::BooleanExpression.from_value_pairs(v))
|
|
699
1081
|
end
|
|
700
1082
|
|
|
701
1083
|
# SQL fragment for Integer
|
|
702
1084
|
def literal_integer(v)
|
|
703
1085
|
v.to_s
|
|
704
1086
|
end
|
|
705
|
-
|
|
1087
|
+
|
|
706
1088
|
# SQL fragment for nil
|
|
707
1089
|
def literal_nil
|
|
708
1090
|
NULL
|
|
@@ -714,17 +1096,24 @@ module Sequel
|
|
|
714
1096
|
# provided and should add that method to Sequel::Dataset, allowing for adapters
|
|
715
1097
|
# to provide customized literalizations.
|
|
716
1098
|
# If a database specific type is allowed, this should be overriden in a subclass.
|
|
717
|
-
def
|
|
718
|
-
if v.respond_to?(:
|
|
719
|
-
v.
|
|
1099
|
+
def literal_other_append(sql, v)
|
|
1100
|
+
if v.respond_to?(:sql_literal_append)
|
|
1101
|
+
v.sql_literal_append(self, sql)
|
|
1102
|
+
elsif v.respond_to?(:sql_literal)
|
|
1103
|
+
sql << v.sql_literal(self)
|
|
720
1104
|
else
|
|
721
1105
|
raise Error, "can't express #{v.inspect} as a SQL literal"
|
|
722
1106
|
end
|
|
723
1107
|
end
|
|
724
1108
|
|
|
1109
|
+
# SQL fragment for Sequel::SQLTime, containing just the time part
|
|
1110
|
+
def literal_sqltime(v)
|
|
1111
|
+
v.strftime("'%H:%M:%S#{format_timestamp_usec(v.usec) if supports_timestamp_usecs?}'")
|
|
1112
|
+
end
|
|
1113
|
+
|
|
725
1114
|
# SQL fragment for String. Doubles \ and ' by default.
|
|
726
|
-
def
|
|
727
|
-
|
|
1115
|
+
def literal_string_append(sql, v)
|
|
1116
|
+
sql << APOS << v.gsub(APOS_RE, DOUBLE_APOS) << APOS
|
|
728
1117
|
end
|
|
729
1118
|
|
|
730
1119
|
# Converts a symbol into a column name. This method supports underscore
|
|
@@ -735,10 +1124,14 @@ module Sequel
|
|
|
735
1124
|
# dataset.literal(:abc___a) #=> "abc AS a"
|
|
736
1125
|
# dataset.literal(:items__abc) #=> "items.abc"
|
|
737
1126
|
# dataset.literal(:items__abc___a) #=> "items.abc AS a"
|
|
738
|
-
def
|
|
1127
|
+
def literal_symbol_append(sql, v)
|
|
739
1128
|
c_table, column, c_alias = split_symbol(v)
|
|
740
|
-
|
|
741
|
-
|
|
1129
|
+
if c_table
|
|
1130
|
+
quote_identifier_append(sql, c_table)
|
|
1131
|
+
sql << DOT
|
|
1132
|
+
end
|
|
1133
|
+
quote_identifier_append(sql, column)
|
|
1134
|
+
as_sql_append(sql, c_alias) if c_alias
|
|
742
1135
|
end
|
|
743
1136
|
|
|
744
1137
|
# SQL fragment for Time
|
|
@@ -751,6 +1144,11 @@ module Sequel
|
|
|
751
1144
|
BOOL_TRUE
|
|
752
1145
|
end
|
|
753
1146
|
|
|
1147
|
+
# Get the native function name given the emulated function name.
|
|
1148
|
+
def native_function_name(emulated_function)
|
|
1149
|
+
self.class.const_get(:EMULATED_FUNCTION_MAP).fetch(emulated_function, emulated_function)
|
|
1150
|
+
end
|
|
1151
|
+
|
|
754
1152
|
# Returns a qualified column name (including a table name) if the column
|
|
755
1153
|
# name isn't already qualified.
|
|
756
1154
|
def qualified_column_name(column, table)
|
|
@@ -774,59 +1172,7 @@ module Sequel
|
|
|
774
1172
|
|
|
775
1173
|
# Qualify the given expression e to the given table.
|
|
776
1174
|
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
|
|
1175
|
+
Qualifier.new(self, table).transform(e)
|
|
830
1176
|
end
|
|
831
1177
|
|
|
832
1178
|
# The order of methods to call to build the SELECT SQL statement
|
|
@@ -836,13 +1182,19 @@ module Sequel
|
|
|
836
1182
|
|
|
837
1183
|
# Modify the sql to add the columns selected
|
|
838
1184
|
def select_columns_sql(sql)
|
|
839
|
-
sql <<
|
|
1185
|
+
sql << SPACE
|
|
1186
|
+
column_list_append(sql, @opts[:select])
|
|
840
1187
|
end
|
|
841
1188
|
|
|
842
1189
|
# Modify the sql to add the DISTINCT modifier
|
|
843
1190
|
def select_distinct_sql(sql)
|
|
844
1191
|
if distinct = @opts[:distinct]
|
|
845
|
-
sql <<
|
|
1192
|
+
sql << DISTINCT
|
|
1193
|
+
unless distinct.empty?
|
|
1194
|
+
sql << ON_PAREN
|
|
1195
|
+
expression_list_append(sql, distinct)
|
|
1196
|
+
sql << PAREN_CLOSE
|
|
1197
|
+
end
|
|
846
1198
|
end
|
|
847
1199
|
end
|
|
848
1200
|
|
|
@@ -850,60 +1202,100 @@ module Sequel
|
|
|
850
1202
|
# This uses a subselect for the compound datasets used, because using parantheses doesn't
|
|
851
1203
|
# work on all databases. I consider this an ugly hack, but can't I think of a better default.
|
|
852
1204
|
def select_compounds_sql(sql)
|
|
853
|
-
return unless @opts[:compounds]
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
sql <<
|
|
1205
|
+
return unless c = @opts[:compounds]
|
|
1206
|
+
c.each do |type, dataset, all|
|
|
1207
|
+
sql << SPACE << type.to_s.upcase
|
|
1208
|
+
sql << ALL if all
|
|
1209
|
+
sql << SPACE
|
|
1210
|
+
compound_dataset_sql_append(sql, dataset)
|
|
857
1211
|
end
|
|
858
1212
|
end
|
|
859
1213
|
|
|
860
1214
|
# Modify the sql to add the list of tables to select FROM
|
|
861
1215
|
def select_from_sql(sql)
|
|
862
|
-
|
|
1216
|
+
if f = @opts[:from]
|
|
1217
|
+
sql << FROM
|
|
1218
|
+
source_list_append(sql, f)
|
|
1219
|
+
end
|
|
863
1220
|
end
|
|
864
1221
|
alias delete_from_sql select_from_sql
|
|
865
1222
|
|
|
866
1223
|
# Modify the sql to add the expressions to GROUP BY
|
|
867
1224
|
def select_group_sql(sql)
|
|
868
|
-
|
|
1225
|
+
if group = @opts[:group]
|
|
1226
|
+
sql << GROUP_BY
|
|
1227
|
+
if go = @opts[:group_options]
|
|
1228
|
+
if uses_with_rollup?
|
|
1229
|
+
expression_list_append(sql, group)
|
|
1230
|
+
sql << SPACE_WITH << go.to_s.upcase
|
|
1231
|
+
else
|
|
1232
|
+
sql << go.to_s.upcase << PAREN_OPEN
|
|
1233
|
+
expression_list_append(sql, group)
|
|
1234
|
+
sql << PAREN_CLOSE
|
|
1235
|
+
end
|
|
1236
|
+
else
|
|
1237
|
+
expression_list_append(sql, group)
|
|
1238
|
+
end
|
|
1239
|
+
end
|
|
869
1240
|
end
|
|
870
1241
|
|
|
871
1242
|
# Modify the sql to add the filter criteria in the HAVING clause
|
|
872
1243
|
def select_having_sql(sql)
|
|
873
|
-
|
|
1244
|
+
if having = @opts[:having]
|
|
1245
|
+
sql << HAVING
|
|
1246
|
+
literal_append(sql, having)
|
|
1247
|
+
end
|
|
874
1248
|
end
|
|
875
1249
|
|
|
876
1250
|
# Modify the sql to add the list of tables to JOIN to
|
|
877
1251
|
def select_join_sql(sql)
|
|
878
|
-
|
|
1252
|
+
if js = @opts[:join]
|
|
1253
|
+
js.each{|j| literal_append(sql, j)}
|
|
1254
|
+
end
|
|
879
1255
|
end
|
|
880
1256
|
|
|
881
1257
|
# Modify the sql to limit the number of rows returned and offset
|
|
882
1258
|
def select_limit_sql(sql)
|
|
883
|
-
|
|
884
|
-
|
|
1259
|
+
if l = @opts[:limit]
|
|
1260
|
+
sql << LIMIT
|
|
1261
|
+
literal_append(sql, l)
|
|
1262
|
+
end
|
|
1263
|
+
if o = @opts[:offset]
|
|
1264
|
+
sql << OFFSET
|
|
1265
|
+
literal_append(sql, o)
|
|
1266
|
+
end
|
|
885
1267
|
end
|
|
886
1268
|
|
|
887
1269
|
# Modify the sql to support the different types of locking modes.
|
|
888
1270
|
def select_lock_sql(sql)
|
|
889
|
-
case @opts[:lock]
|
|
1271
|
+
case l = @opts[:lock]
|
|
890
1272
|
when :update
|
|
891
1273
|
sql << FOR_UPDATE
|
|
892
1274
|
when String
|
|
893
|
-
sql <<
|
|
1275
|
+
sql << SPACE << l
|
|
894
1276
|
end
|
|
895
1277
|
end
|
|
896
1278
|
|
|
897
1279
|
# Modify the sql to add the expressions to ORDER BY
|
|
898
1280
|
def select_order_sql(sql)
|
|
899
|
-
|
|
1281
|
+
if o = @opts[:order]
|
|
1282
|
+
sql << ORDER_BY
|
|
1283
|
+
expression_list_append(sql, o)
|
|
1284
|
+
end
|
|
900
1285
|
end
|
|
901
1286
|
alias delete_order_sql select_order_sql
|
|
902
1287
|
alias update_order_sql select_order_sql
|
|
903
1288
|
|
|
1289
|
+
def select_select_sql(sql)
|
|
1290
|
+
sql << SELECT
|
|
1291
|
+
end
|
|
1292
|
+
|
|
904
1293
|
# Modify the sql to add the filter criteria in the WHERE clause
|
|
905
1294
|
def select_where_sql(sql)
|
|
906
|
-
|
|
1295
|
+
if w = @opts[:where]
|
|
1296
|
+
sql << WHERE
|
|
1297
|
+
literal_append(sql, w)
|
|
1298
|
+
end
|
|
907
1299
|
end
|
|
908
1300
|
alias delete_where_sql select_where_sql
|
|
909
1301
|
alias update_where_sql select_where_sql
|
|
@@ -912,8 +1304,26 @@ module Sequel
|
|
|
912
1304
|
def select_with_sql(sql)
|
|
913
1305
|
ws = opts[:with]
|
|
914
1306
|
return if !ws || ws.empty?
|
|
915
|
-
sql
|
|
1307
|
+
sql << select_with_sql_base
|
|
1308
|
+
c = false
|
|
1309
|
+
comma = COMMA
|
|
1310
|
+
ws.each do |w|
|
|
1311
|
+
sql << comma if c
|
|
1312
|
+
quote_identifier_append(sql, w[:name])
|
|
1313
|
+
if args = w[:args]
|
|
1314
|
+
sql << PAREN_OPEN
|
|
1315
|
+
identifier_list_append(sql, args)
|
|
1316
|
+
sql << PAREN_CLOSE
|
|
1317
|
+
end
|
|
1318
|
+
sql << AS
|
|
1319
|
+
literal_dataset_append(sql, w[:dataset])
|
|
1320
|
+
c ||= true
|
|
1321
|
+
end
|
|
1322
|
+
sql << SPACE
|
|
916
1323
|
end
|
|
1324
|
+
alias delete_with_sql select_with_sql
|
|
1325
|
+
alias insert_with_sql select_with_sql
|
|
1326
|
+
alias update_with_sql select_with_sql
|
|
917
1327
|
|
|
918
1328
|
# The base keyword to use for the SQL WITH clause
|
|
919
1329
|
def select_with_sql_base
|
|
@@ -921,46 +1331,46 @@ module Sequel
|
|
|
921
1331
|
end
|
|
922
1332
|
|
|
923
1333
|
# Converts an array of source names into into a comma separated list.
|
|
924
|
-
def
|
|
925
|
-
raise(Error, 'No source specified for query') if
|
|
926
|
-
|
|
1334
|
+
def source_list_append(sql, sources)
|
|
1335
|
+
raise(Error, 'No source specified for query') if sources.nil? || sources == []
|
|
1336
|
+
identifier_list_append(sql, sources)
|
|
927
1337
|
end
|
|
928
1338
|
|
|
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.
|
|
1339
|
+
# Delegate to Sequel.split_symbol.
|
|
934
1340
|
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
|
|
1341
|
+
Sequel.split_symbol(sym)
|
|
945
1342
|
end
|
|
946
1343
|
|
|
1344
|
+
# The string that is appended to to create the SQL query, the empty
|
|
1345
|
+
# string by default
|
|
1346
|
+
def sql_string_origin
|
|
1347
|
+
''
|
|
1348
|
+
end
|
|
1349
|
+
|
|
947
1350
|
# SQL to use if this dataset uses static SQL. Since static SQL
|
|
948
1351
|
# can be a PlaceholderLiteralString in addition to a String,
|
|
949
1352
|
# we literalize nonstrings.
|
|
950
1353
|
def static_sql(sql)
|
|
951
|
-
|
|
1354
|
+
if append_sql = @opts[:append_sql]
|
|
1355
|
+
if sql.is_a?(String)
|
|
1356
|
+
append_sql << sql
|
|
1357
|
+
else
|
|
1358
|
+
literal_append(append_sql, sql)
|
|
1359
|
+
end
|
|
1360
|
+
else
|
|
1361
|
+
if sql.is_a?(String)
|
|
1362
|
+
sql
|
|
1363
|
+
else
|
|
1364
|
+
literal(sql)
|
|
1365
|
+
end
|
|
1366
|
+
end
|
|
952
1367
|
end
|
|
953
1368
|
|
|
954
1369
|
# SQL fragment for a subselect using the given database's SQL.
|
|
955
|
-
def
|
|
956
|
-
ds.sql
|
|
1370
|
+
def subselect_sql_append(sql, ds)
|
|
1371
|
+
ds.clone(:append_sql=>sql).sql
|
|
957
1372
|
end
|
|
958
1373
|
|
|
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
1374
|
# The order of methods to call to build the UPDATE SQL statement
|
|
965
1375
|
def update_clause_methods
|
|
966
1376
|
UPDATE_CLAUSE_METHODS
|
|
@@ -969,25 +1379,38 @@ module Sequel
|
|
|
969
1379
|
# SQL fragment specifying the tables from with to delete.
|
|
970
1380
|
# Includes join table if modifying joins is allowed.
|
|
971
1381
|
def update_table_sql(sql)
|
|
972
|
-
sql <<
|
|
1382
|
+
sql << SPACE
|
|
1383
|
+
source_list_append(sql, @opts[:from])
|
|
973
1384
|
select_join_sql(sql) if supports_modifying_joins?
|
|
974
1385
|
end
|
|
975
1386
|
|
|
976
1387
|
# The SQL fragment specifying the columns and values to SET.
|
|
977
1388
|
def update_set_sql(sql)
|
|
978
1389
|
values = opts[:values]
|
|
979
|
-
|
|
1390
|
+
sql << SET
|
|
1391
|
+
if values.is_a?(Hash)
|
|
980
1392
|
values = opts[:defaults].merge(values) if opts[:defaults]
|
|
981
1393
|
values = values.merge(opts[:overrides]) if opts[:overrides]
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1394
|
+
c = false
|
|
1395
|
+
eq = EQUAL
|
|
1396
|
+
values.each do |k, v|
|
|
1397
|
+
sql << COMMA if c
|
|
1398
|
+
if k.is_a?(String) && !k.is_a?(LiteralString)
|
|
1399
|
+
quote_identifier_append(sql, k)
|
|
1400
|
+
else
|
|
1401
|
+
literal_append(sql, k)
|
|
1402
|
+
end
|
|
1403
|
+
sql << eq
|
|
1404
|
+
literal_append(sql, v)
|
|
1405
|
+
c ||= true
|
|
1406
|
+
end
|
|
986
1407
|
else
|
|
987
|
-
|
|
988
|
-
values
|
|
1408
|
+
sql << values
|
|
989
1409
|
end
|
|
990
|
-
|
|
1410
|
+
end
|
|
1411
|
+
|
|
1412
|
+
def update_update_sql(sql)
|
|
1413
|
+
sql << UPDATE
|
|
991
1414
|
end
|
|
992
1415
|
end
|
|
993
1416
|
end
|