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/doc/sharding.rdoc
CHANGED
|
@@ -8,9 +8,25 @@ that ship with Sequel.
|
|
|
8
8
|
|
|
9
9
|
== The :servers Database option
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
Sharding and read_only support are both enabled via the :servers database
|
|
12
|
+
option. Using the :servers database option makes Sequel use a connection pool
|
|
13
|
+
class that supports sharding, and the minimum required to enable sharding
|
|
14
|
+
support is to use the empty hash:
|
|
15
|
+
|
|
16
|
+
DB=Sequel.connect('postgres://master_server/database', :servers=>{})
|
|
17
|
+
|
|
18
|
+
In most cases, you are probably not going to want to use an empty hash,
|
|
19
|
+
so you'll want to have entries in the hash. Keys in the server hash are
|
|
20
|
+
not restricted to type, but the general recommendation is to use a symbol
|
|
21
|
+
unless you have special requirements. Values in the server hash should be
|
|
22
|
+
either hashes or procs that return hashes. These hashes are merged into
|
|
23
|
+
the Database object's default options hash to get the connection options
|
|
24
|
+
for the shard, so you don't need to override all options, just the ones
|
|
25
|
+
that need to be modified. For example, if you are using the same user,
|
|
26
|
+
password, and database name and just the host is changing, you only need
|
|
27
|
+
a :host entry in each shard's hash.
|
|
28
|
+
|
|
29
|
+
Note that all servers should have the same schema for all
|
|
14
30
|
tables you are accessing, unless you really know what you are doing.
|
|
15
31
|
|
|
16
32
|
== Master and Slave Database Configurations
|
|
@@ -93,7 +109,7 @@ schemas, so you should always have a default server that works.
|
|
|
93
109
|
|
|
94
110
|
To set the shard for a given query, you use the Dataset#server method:
|
|
95
111
|
|
|
96
|
-
DB[:hashes].server(:a).
|
|
112
|
+
DB[:hashes].server(:a).where(:hash=>/31337/)
|
|
97
113
|
|
|
98
114
|
That will return all matching rows on the hash_host_a shard that have a hash
|
|
99
115
|
column that contains 31337.
|
|
@@ -103,10 +119,11 @@ work, you might want to add a method to the dataset that automatically sets
|
|
|
103
119
|
the shard to use. This is fairly easy using a Sequel::Model:
|
|
104
120
|
|
|
105
121
|
class Rainbow < Sequel::Model(:hashes)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
dataset_module do
|
|
123
|
+
def plaintext_for_hash(hash)
|
|
124
|
+
raise(ArgumentError, 'Invalid SHA-1 Hash') unless /\A[0-9a-f]{40}\z/.match(hash)
|
|
125
|
+
server(hash[0...1].to_sym).where(:hash=>hash).get(:plaintext)
|
|
126
|
+
end
|
|
110
127
|
end
|
|
111
128
|
end
|
|
112
129
|
|
|
@@ -153,3 +170,77 @@ work well with shards. You just need to remember to set to model to use the plu
|
|
|
153
170
|
If all of your models are sharded, you can set all models to use the plugin via:
|
|
154
171
|
|
|
155
172
|
Sequel::Model.plugin :sharding
|
|
173
|
+
|
|
174
|
+
=== server_block Extension
|
|
175
|
+
|
|
176
|
+
By default, you must specify the server/shard you want to use for every dataset/action,
|
|
177
|
+
or Sequel will use the default shard. If you have a group of queries that should use the
|
|
178
|
+
same shard, it can get a bit redundent to specify the same shard for all of them.
|
|
179
|
+
|
|
180
|
+
The server_block extension adds a Database#with_server method that scopes all database
|
|
181
|
+
access inside the block to the given shard by default:
|
|
182
|
+
|
|
183
|
+
DB.extension :server_block
|
|
184
|
+
DB.with_server(:a) do
|
|
185
|
+
# this SELECT query uses the "a" shard
|
|
186
|
+
if r = Rainbow.first(:hash=>/31337/)
|
|
187
|
+
r.count += 1
|
|
188
|
+
# this UPDATE query also uses the "a" shard
|
|
189
|
+
r.save
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
The server_block extension doesn't currently integrate with the sharding plugin, as it
|
|
194
|
+
ties into the Dataset#server method. This shouldn't present a problem in practice as
|
|
195
|
+
long as you just access the models inside the with_server block, since they will use
|
|
196
|
+
the shard set by with_server by default. However, you will probably have issues if
|
|
197
|
+
you retrieve the models inside the block and save them outside of the block. If you
|
|
198
|
+
need to do that, call the server method explicitly on the dataset used to retrieve the
|
|
199
|
+
model objects.
|
|
200
|
+
|
|
201
|
+
=== arbitrary_servers Extension
|
|
202
|
+
|
|
203
|
+
By default, Sequel's sharding support is designed to work with predefined shards. It ships
|
|
204
|
+
with Database#add_servers and Database#remove_servers methods to modify these predefined
|
|
205
|
+
shards on the fly, but it is a bit cumbersome to work with truly arbitrary servers
|
|
206
|
+
(requiring you to call add_servers before use, then remove_servers after use).
|
|
207
|
+
|
|
208
|
+
The arbitrary_servers extension allows you to pass a server/shard options hash as the
|
|
209
|
+
server to use, and those options will be merged directly into the database's default options:
|
|
210
|
+
|
|
211
|
+
DB.extension :arbitrary_servers
|
|
212
|
+
DB[:rainbows].server(:host=>'hash_host_a').all
|
|
213
|
+
# or
|
|
214
|
+
DB[:rainbows].server(:host=>'hash_host_b', :database=>'backup').all
|
|
215
|
+
|
|
216
|
+
arbitrary_servers is designed to work well in conjunction with the server_block extension:
|
|
217
|
+
|
|
218
|
+
DB.with_server(:host=>'hash_host_b', :database=>'backup') do
|
|
219
|
+
DB.synchronize do
|
|
220
|
+
# All queries here default to the backup database on hash_host_b
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
If you are using arbitrary_servers with server_block, you may want to
|
|
225
|
+
define the following method (or something similar) so that you don't
|
|
226
|
+
need to call synchronize separately:
|
|
227
|
+
|
|
228
|
+
def DB.with_server(*)
|
|
229
|
+
super{synchronize{yield}}
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
The reason for the synchronize method is that it checks out a connection
|
|
233
|
+
and makes the same connection available for the duration of the block.
|
|
234
|
+
If you don't do that, Sequel will probably disconnect from the database
|
|
235
|
+
and reconnect to the database on each request, since connections to
|
|
236
|
+
arbitrary servers are not cached.
|
|
237
|
+
|
|
238
|
+
Note that this extension only works with the sharded threaded connection
|
|
239
|
+
pool. If you are using the sharded single connection pool, you need
|
|
240
|
+
to switch to the sharded threaded connection pool before using this
|
|
241
|
+
extension. If you are passing the :single_threaded option to
|
|
242
|
+
the Database, just remove that option. If you are setting:
|
|
243
|
+
|
|
244
|
+
Sequel.single_threaded = true
|
|
245
|
+
|
|
246
|
+
just remove or comment out that code.
|
data/doc/sql.rdoc
CHANGED
|
@@ -73,10 +73,14 @@ You can also use <tt>Database#<<</tt>:
|
|
|
73
73
|
|
|
74
74
|
=== Other Places
|
|
75
75
|
|
|
76
|
-
Almost everywhere in Sequel, you can drop down to literal SQL by providing a literal string, which you can create with <tt>
|
|
76
|
+
Almost everywhere in Sequel, you can drop down to literal SQL by providing a literal string, which you can create with <tt>Sequel.lit</tt>:
|
|
77
77
|
|
|
78
78
|
DB[:albums].select('name') # SELECT 'name' FROM albums
|
|
79
|
-
DB[:albums].select('name'
|
|
79
|
+
DB[:albums].select(Sequel.lit('name')) # SELECT name FROM albums
|
|
80
|
+
|
|
81
|
+
For a simpler way of creating literal strings, you can also use the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html], which adds the <tt>String#lit</tt> method, and other methods that integrate Sequel's DSL with the ruby language:
|
|
82
|
+
|
|
83
|
+
DB[:albums].select('name'.lit)
|
|
80
84
|
|
|
81
85
|
So you can use Sequel's DSL everywhere you find it helpful, and fallback to literal SQL if the DSL can't do what you want or you just find literal SQL easier.
|
|
82
86
|
|
|
@@ -129,9 +133,9 @@ Also note that specifying the period inside the symbol doesn't work if you are q
|
|
|
129
133
|
|
|
130
134
|
:"table.column" # "table.column"
|
|
131
135
|
|
|
132
|
-
The other way to qualify an identifier is to use the
|
|
136
|
+
The other way to qualify an identifier is to use the <tt>Sequel.qualify</tt> with the table and column symbols:
|
|
133
137
|
|
|
134
|
-
|
|
138
|
+
Sequel.qualify(:table, :column) # "table"."column"
|
|
135
139
|
|
|
136
140
|
Another way to generate identifiers is to use Sequel's {virtual row support}[link:files/doc/virtual_rows_rdoc.html]:
|
|
137
141
|
|
|
@@ -169,37 +173,37 @@ You can combine this with implicit qualification:
|
|
|
169
173
|
|
|
170
174
|
:table__column___alias # "table"."column" AS "alias"
|
|
171
175
|
|
|
172
|
-
You can also use the +as+ method on
|
|
176
|
+
You can also use the <tt>Sequel.as</tt> method to create an alias, and the +as+ method on most Sequel-specific expression objects:
|
|
173
177
|
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
Sequel.as(:column, :alias) # "column" AS "alias"
|
|
179
|
+
Sequel.qualify(:table, :column).as(:alias) # "table"."column" AS "alias"
|
|
176
180
|
|
|
177
181
|
=== Functions
|
|
178
182
|
|
|
179
183
|
The easiest way to use SQL functions is via a virtual row:
|
|
180
184
|
|
|
181
|
-
DB[:albums].select{
|
|
182
|
-
DB[:albums].select{
|
|
185
|
+
DB[:albums].select{func{}} # SELECT func() FROM "albums"
|
|
186
|
+
DB[:albums].select{func(col1, col2)} # SELECT func("col1", "col2") FROM "albums"
|
|
183
187
|
|
|
184
|
-
You can also use the
|
|
188
|
+
You can also use the <tt>Sequel.function</tt> method on the symbol that contains the function name:
|
|
185
189
|
|
|
186
|
-
:
|
|
187
|
-
|
|
190
|
+
Sequel.function(:func) # func()
|
|
191
|
+
Sequel.function(:func, :col1, :col2) # func("col1", "col2")
|
|
188
192
|
|
|
189
193
|
=== Aggregate Functions
|
|
190
194
|
|
|
191
195
|
Aggregate functions work the same way as normal functions, since they share the same syntax:
|
|
192
196
|
|
|
193
|
-
|
|
197
|
+
Sequel.function(:sum, :column) # sum(column)
|
|
194
198
|
|
|
195
199
|
However, if you want to use the DISTINCT modifier to an aggregate function, you either have to use literal SQL or a virtual row block:
|
|
196
200
|
|
|
197
|
-
:sum.
|
|
201
|
+
Sequel.function(:sum, Sequel.lit('DISTINCT column')) # sum(DISTINCT column)
|
|
198
202
|
DB[:albums].select{sum(:distinct, :column){}} # SELECT sum(DISTINCT column) FROM albums
|
|
199
203
|
|
|
200
204
|
If you want to use the wildcard as the sole argument of the aggregate function, you again have to use literal SQL or a virtual row block:
|
|
201
205
|
|
|
202
|
-
:count.
|
|
206
|
+
Sequel.function(:count, Sequel.lit('*')) # count(*)
|
|
203
207
|
DB[:albums].select{count(:*){}} # SELECT count(*) FROM albums
|
|
204
208
|
|
|
205
209
|
Note that Sequel provides helper methods for aggregate functions such as +count+, +sum+, +min+, +max+, +avg+, and +group_and_count+, which handle common uses of aggregate functions.
|
|
@@ -232,28 +236,35 @@ You can also specify this as an array of two element arrays:
|
|
|
232
236
|
|
|
233
237
|
=== Not Equal Operator (!=)
|
|
234
238
|
|
|
235
|
-
You can specify a not equals condition by inverting the hash or array of two element arrays using
|
|
239
|
+
You can specify a not equals condition by inverting the hash or array of two element arrays using <tt>Sequel.negate</tt> or <tt>Sequel.~</tt>:
|
|
240
|
+
|
|
241
|
+
Sequel.negate(:column => 1) # ("column" != 1)
|
|
242
|
+
Sequel.negate([[:column, 1]]) # ("column" != 1)
|
|
243
|
+
Sequel.~(:column => 1) # ("column" != 1)
|
|
244
|
+
Sequel.~([[:column, 1]]) # ("column" != 1)
|
|
236
245
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
246
|
+
The difference between the two is that negate only works on hashes and arrays of element arrays, and it negates all entries in the, while ~ does a general inversion. This is best shown by an example with multiple entries:
|
|
247
|
+
|
|
248
|
+
Sequel.negate(:column => 1, :foo => 2) # (("column" != 1) AND (foo != 2))
|
|
249
|
+
Sequel.~(:column => 1, :foo => 2) # (("column" != 1) OR (foo != 2))
|
|
241
250
|
|
|
242
251
|
The most common need for not equals is in filters, in which case you can use the +exclude+ method:
|
|
243
252
|
|
|
244
253
|
DB[:albums].exclude(:column=>1) # SELECT * FROM "albums" WHERE ("column" != 1)
|
|
245
254
|
|
|
255
|
+
Note that +exclude+ does a generalized inversion, similar to <tt>Sequel.~</tt>.
|
|
256
|
+
|
|
246
257
|
=== Inclusion and Exclusion Operators (IN, NOT IN)
|
|
247
258
|
|
|
248
259
|
Sequel also uses hashes to specify inclusion, and inversions of those hashes to specify exclusion:
|
|
249
260
|
|
|
250
261
|
{:column=>[1, 2, 3]} # ("column" IN (1, 2, 3))
|
|
251
|
-
|
|
262
|
+
Sequel.~(:column=>[1, 2, 3]) # ("column" NOT IN (1, 2, 3))
|
|
252
263
|
|
|
253
264
|
As you may have guessed, Sequel switches from an = to an IN when the hash value is an array. It also does this for datasets, which easily allows you to test for inclusion and exclusion in a subselect:
|
|
254
265
|
|
|
255
266
|
{:column=>DB[:albums].select(:id)} # ("column" IN (SELECT "id" FROM "albums"))
|
|
256
|
-
|
|
267
|
+
Sequel.~(:column=>DB[:albums].select(:id)) # ("column" NOT IN (SELECT "id" FROM "albums"))
|
|
257
268
|
|
|
258
269
|
Sequel also supports the SQL EXISTS operator using <tt>Dataset#exists</tt>:
|
|
259
270
|
|
|
@@ -269,19 +280,19 @@ Hashes in Sequel use IS if the value is true, false, or nil:
|
|
|
269
280
|
|
|
270
281
|
Negation works the same way as it does for equality and inclusion:
|
|
271
282
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
283
|
+
Sequel.~(:column=>nil) # ("column" IS NOT NULL)
|
|
284
|
+
Sequel.~(:column=>true) # ("column" IS NOT TRUE)
|
|
285
|
+
Sequel.~(:column=>false) # ("column" IS NOT FALSE)
|
|
275
286
|
|
|
276
287
|
=== Inversion Operator (NOT)
|
|
277
288
|
|
|
278
289
|
Sequel's general inversion operator is ~, which works on symbols and most Sequel-specific expression objects:
|
|
279
290
|
|
|
280
|
-
|
|
291
|
+
Sequel.~(:column) # NOT "column"
|
|
281
292
|
|
|
282
293
|
Note that ~ will actually apply the inversion operation to the underlying object, which is why
|
|
283
294
|
|
|
284
|
-
|
|
295
|
+
Sequel.~(:column=>1)
|
|
285
296
|
|
|
286
297
|
produces <tt>(column != 1)</tt> instead of <tt>NOT (column = 1)</tt>.
|
|
287
298
|
|
|
@@ -289,198 +300,229 @@ produces <tt>(column != 1)</tt> instead of <tt>NOT (column = 1)</tt>.
|
|
|
289
300
|
|
|
290
301
|
Sequel defines the inequality operators directly on most Sequel-specific expression objects:
|
|
291
302
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
:
|
|
295
|
-
|
|
303
|
+
Sequel.qualify(:table, :column) > 1 # ("table"."column" > 1)
|
|
304
|
+
Sequel.qualify(:table, :column) < 1 # ("table"."column" < 1)
|
|
305
|
+
Sequel.function(:func) >= 1 # (func() >= 1)
|
|
306
|
+
Sequel.function(:func, :column) <= 1 # (func("column") <= 1)
|
|
296
307
|
|
|
297
|
-
If you want to use them on a symbol, you should call
|
|
308
|
+
If you want to use them on a symbol, you should call <tt>Sequel.expr</tt> with the symbol:
|
|
298
309
|
|
|
299
|
-
:column
|
|
310
|
+
Sequel.expr(:column) > 1 # ("column" > 1)
|
|
300
311
|
|
|
301
312
|
A common use of virtual rows is to handle inequality operators:
|
|
302
313
|
|
|
303
|
-
DB[:albums].
|
|
314
|
+
DB[:albums].where{col1 > col2} # SELECT * FROM "albums" WHERE ("col1" > "col2")
|
|
304
315
|
|
|
305
316
|
=== Standard Mathematical Operators (+ - * /)
|
|
306
317
|
|
|
307
|
-
The standard mathematical operates are defined on
|
|
318
|
+
The standard mathematical operates are defined on most Sequel-specific expression objects:
|
|
319
|
+
|
|
320
|
+
Sequel.expr(:column) + 1 # "column" + 1
|
|
321
|
+
Sequel.expr(:table__column) - 1 # "table"."column" - 1
|
|
322
|
+
Sequel.qualify(:table, :column) * 1 # "table"."column" * 1
|
|
323
|
+
Sequel.expr(:column) / 1 # "column" / 1
|
|
308
324
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
:column
|
|
312
|
-
:
|
|
325
|
+
You can also call the operator methods directly on the Sequel module:
|
|
326
|
+
|
|
327
|
+
Sequel.+(:column, 1) # "column" + 1
|
|
328
|
+
Sequel.-(:table__column, 1) # "table"."column" - 1
|
|
329
|
+
Sequel.*(Sequel.qualify(:table, :column), 1) # "table"."column" * 1
|
|
330
|
+
Sequel./(:column, 1) # "column" / 1
|
|
313
331
|
|
|
314
332
|
Note that the following does not work:
|
|
315
333
|
|
|
316
|
-
1 + :column # raises TypeError
|
|
334
|
+
1 + Sequel.expr(:column) # raises TypeError
|
|
317
335
|
|
|
318
|
-
For commutative operates such as + and *, this isn't a problem as you can just reorder, but non-commutative operators such as - and / cannot be expressed directly.
|
|
336
|
+
For commutative operates such as + and *, this isn't a problem as you can just reorder, but non-commutative operators such as - and / cannot be expressed directly. The solution is to use one of the methods on the Sequel module:
|
|
319
337
|
|
|
320
|
-
Sequel.
|
|
321
|
-
1
|
|
338
|
+
Sequel.expr(1) / :column # (1 / "column")
|
|
339
|
+
Sequel./(1, :column) # (1 / "column")
|
|
322
340
|
|
|
323
341
|
=== Boolean Operators (AND OR)
|
|
324
342
|
|
|
325
|
-
Sequel defines the & and | methods on
|
|
343
|
+
Sequel defines the & and | methods on most Sequel-specific expression objects to handle AND and OR:
|
|
326
344
|
|
|
327
|
-
:column1 & :column2 # ("column1" AND "column2")
|
|
328
|
-
|
|
329
|
-
(:
|
|
345
|
+
Sequel.expr(:column1) & :column2 # ("column1" AND "column2")
|
|
346
|
+
Sequel.expr(:column1=>1) | {:column2=>2} # (("column1" = 1) OR ("column2" = 2))
|
|
347
|
+
(Sequel.function(:func) > 1) & :column3 # ((func() > 1) AND "column3")
|
|
330
348
|
|
|
331
349
|
Note the use of parentheses in the last statement. If you omit them, you won't get what you expect:
|
|
332
350
|
|
|
333
|
-
:
|
|
351
|
+
Sequel.function(:func) > 1 & :column3 # (func() > 1)
|
|
334
352
|
|
|
335
353
|
This is because & has higher precedence than >, so it is parsed as:
|
|
336
354
|
|
|
337
|
-
:
|
|
355
|
+
Sequel.function(:func) > (1 & :column3)
|
|
338
356
|
|
|
339
357
|
In this case, <tt>:column3.to_int</tt> returns an odd integer, so:
|
|
340
358
|
|
|
341
359
|
1 & :column3 # => 1
|
|
342
360
|
|
|
361
|
+
You and also use the <tt>Sequel.&</tt> and <tt>Sequel.|</tt> methods:
|
|
362
|
+
|
|
363
|
+
Sequel.&(:column1, :column2) # ("column1" AND "column2")
|
|
364
|
+
Sequel.|({:column1=>1}, {:column2=>2}) # (("column1" = 1) OR ("column2" = 2))
|
|
365
|
+
|
|
343
366
|
You can use hashes and arrays of two element arrays to specify AND and OR with equality conditions:
|
|
344
367
|
|
|
345
368
|
{:column1=>1, :column2=>2} # (("column1" = 1) AND ("column2" = 2))
|
|
346
369
|
[[:column1, 1], [:column2, 2]] # (("column1" = 1) AND ("column2" = 2))
|
|
347
370
|
|
|
348
|
-
As you can see, these literalize with ANDs by default. You can use the
|
|
371
|
+
As you can see, these literalize with ANDs by default. You can use the <tt>Sequel.or</tt> method to use OR instead:
|
|
349
372
|
|
|
350
|
-
|
|
373
|
+
Sequel.or(:column1=>1, :column2=>2) # (("column1" = 1) OR ("column2" = 2))
|
|
351
374
|
|
|
352
|
-
You've already seen the
|
|
375
|
+
You've already seen the <tt>Sequel.negate</tt> method, which will use ANDs if multiple entries are used:
|
|
353
376
|
|
|
354
|
-
|
|
377
|
+
Sequel.negate(:column1=>1, :column2=>2) # (("column1" != 1) AND ("column2" != 2))
|
|
355
378
|
|
|
356
|
-
To negate while using ORs, the
|
|
379
|
+
To negate while using ORs, the <tt>Sequel.~</tt> operator can be used:
|
|
357
380
|
|
|
358
|
-
|
|
381
|
+
Sequel.~(:column1=>1, :column2=>2) # (("column1" != 1) OR ("column2" != 2))
|
|
359
382
|
|
|
360
|
-
Note that <tt>Dataset#exclude</tt> uses ~, not +
|
|
383
|
+
Note again that <tt>Dataset#exclude</tt> uses ~, not +negate+:
|
|
361
384
|
|
|
362
385
|
DB[:albums].exclude(:column1=>1, :column2=>2) # SELECT * FROM "albums" WHERE (("column" != 1) OR ("column2" != 2))
|
|
363
386
|
|
|
364
387
|
=== Casts
|
|
365
388
|
|
|
366
|
-
Casting in Sequel is done with the +cast+ method, which is available on
|
|
389
|
+
Casting in Sequel is done with the +cast+ method, which is available on most of the Sequel-specific expression objects:
|
|
367
390
|
|
|
368
|
-
:name.cast(:text) # CAST("name" AS text)
|
|
369
|
-
'1'.cast(:integer) # CAST('1' AS integer)
|
|
370
|
-
|
|
391
|
+
Sequel.expr(:name).cast(:text) # CAST("name" AS text)
|
|
392
|
+
Sequel.expr('1').cast(:integer) # CAST('1' AS integer)
|
|
393
|
+
Sequel.qualify(:table, :column).cast(:date) # CAST("table"."column" AS date)
|
|
371
394
|
|
|
372
|
-
|
|
395
|
+
You can also use the <tt>Sequel.cast</tt> method:
|
|
373
396
|
|
|
374
|
-
Sequel
|
|
397
|
+
Sequel.cast(:name, :text) # CAST("name" AS text)
|
|
375
398
|
|
|
376
|
-
|
|
377
|
-
(:number + 1) & 5 # (("number" + 1) & 5)
|
|
399
|
+
=== Bitwise Mathematical Operators (& | ^ << >> ~)
|
|
378
400
|
|
|
379
|
-
|
|
401
|
+
Sequel allows the use of bitwise mathematical operators on Sequel::SQL::NumericExpression objects:
|
|
380
402
|
|
|
381
|
-
:number
|
|
403
|
+
Sequel.expr(:number) + 1 # => #<Sequel::SQL::NumericExpression ...>
|
|
404
|
+
(Sequel.expr(:number) + 1) & 5 # (("number" + 1) & 5)
|
|
382
405
|
|
|
383
|
-
|
|
406
|
+
As you can see, when you use the + operator on a symbol, you get a NumericExpression. You can turn an expression a NumericExpression using +sql_number+:
|
|
384
407
|
|
|
385
|
-
:
|
|
386
|
-
|
|
408
|
+
Sequel.expr(:number).sql_number | 5 # ("number" | 5)
|
|
409
|
+
Sequel.function(:func).sql_number << 7 # (func() << 7)
|
|
410
|
+
Sequel.cast(:name, :integer).sql_number >> 8 # (CAST("name" AS integer) >> 8)
|
|
387
411
|
|
|
388
412
|
Sequel allows you to do the cast and conversion at the same time via +cast_numeric+:
|
|
389
413
|
|
|
390
|
-
:name.cast_numeric ^ 9 # (CAST("name" AS integer) ^ 9)
|
|
414
|
+
Sequel.expr(:name).cast_numeric ^ 9 # (CAST("name" AS integer) ^ 9)
|
|
391
415
|
|
|
392
|
-
Note that &, |, and ~ are already defined to do AND, OR, and NOT on most
|
|
416
|
+
Note that &, |, and ~ are already defined to do AND, OR, and NOT on most expressions, so if you want to use the bitwise operators, you need to make sure that they are converted first:
|
|
393
417
|
|
|
394
|
-
|
|
395
|
-
|
|
418
|
+
~Sequel.expr(:name) # NOT "name"
|
|
419
|
+
~Sequel.expr(:name).sql_number # ~"name"
|
|
396
420
|
|
|
397
421
|
=== String Operators (||, LIKE, Regexp)
|
|
398
422
|
|
|
399
|
-
Sequel allows the use of the string concatenation operator on Sequel::SQL::StringExpression objects, which can be created using the +sql_string+ method:
|
|
423
|
+
Sequel allows the use of the string concatenation operator on Sequel::SQL::StringExpression objects, which can be created using the +sql_string+ method on an expression:
|
|
400
424
|
|
|
401
|
-
:name.sql_string + ' - Name' # ("name" || ' - Name')
|
|
425
|
+
Sequel.expr(:name).sql_string + ' - Name' # ("name" || ' - Name')
|
|
402
426
|
|
|
403
427
|
Just like for the bitwise operators, Sequel allows you do do the cast and conversion at the same time via +cast_string+:
|
|
404
428
|
|
|
405
|
-
:number.cast_string + ' - Number' # (CAST(number AS varchar(255)) || ' - Number')
|
|
429
|
+
Sequel.expr(:number).cast_string + ' - Number' # (CAST(number AS varchar(255)) || ' - Number')
|
|
406
430
|
|
|
407
431
|
Note that similar to the mathematical operators, you cannot switch the order the expression and have it work:
|
|
408
432
|
|
|
409
|
-
'Name - ' + :name.sql_string # raises TypeError
|
|
433
|
+
'Name - ' + Sequel.expr(:name).sql_string # raises TypeError
|
|
410
434
|
|
|
411
|
-
Just like for the mathematical operators, you can use
|
|
435
|
+
Just like for the mathematical operators, you can use <tt>Sequel.expr</tt> to wrap the object:
|
|
412
436
|
|
|
413
|
-
Sequel.
|
|
414
|
-
'Name - '.sql_expr + :name # ('Name - ' || "name")
|
|
437
|
+
Sequel.expr('Name - ') + :name # ('Name - ' || "name")
|
|
415
438
|
|
|
416
|
-
|
|
439
|
+
The <tt>Sequel.join</tt> method concatenates all of the elements in the array:
|
|
417
440
|
|
|
418
|
-
['Name', :name]
|
|
441
|
+
Sequel.join(['Name', :name]) # ('Name' || "name")
|
|
419
442
|
|
|
420
443
|
Just like ruby's <tt>String#join</tt>, you can provide an argument for a string used to join each element:
|
|
421
444
|
|
|
422
|
-
['Name', :name]
|
|
445
|
+
Sequel.join(['Name', :name], ' - ') # ('Name' || ' - ' || "name")
|
|
446
|
+
|
|
447
|
+
For the LIKE operator, Sequel defines the +like+ and +ilike+ methods on most Sequel-specific expression objects:
|
|
423
448
|
|
|
424
|
-
|
|
449
|
+
Sequel.expr(:name).like('A%') # ("name" LIKE 'A%')
|
|
450
|
+
Sequel.expr(:name).ilike('A%') # ("name" ILIKE 'A%')
|
|
425
451
|
|
|
426
|
-
|
|
427
|
-
:name.qualify.ilike('A%') # ("name" ILIKE 'A%')
|
|
452
|
+
You can also use the <tt>Sequel.like</tt> and <tt>Sequel.ilike</tt> methods:
|
|
428
453
|
|
|
429
|
-
|
|
454
|
+
Sequel.like(:name, 'A%') # ("name" LIKE 'A%')
|
|
455
|
+
Sequel.ilike(:name, 'A%') # ("name" ILIKE 'A%')
|
|
456
|
+
|
|
457
|
+
Note the above syntax for ilike, while Sequel's default, is specific to PostgreSQL. However, most other adapters override the behavior. For example, on MySQL, Sequel uses LIKE BINARY for +like+, and LIKE for +ilike+. If the database supports both case sensitive and case insensitive LIKE, then +like+ will use a case sensitive LIKE, and +ilike+ will use a case insensitive LIKE.
|
|
430
458
|
|
|
431
459
|
Inverting the LIKE operator works like other inversions:
|
|
432
460
|
|
|
433
|
-
|
|
461
|
+
~Sequel.like(:name, 'A%') # ("name" NOT LIKE 'A%')
|
|
434
462
|
|
|
435
|
-
Sequel also supports SQL regular expressions on MySQL and PostgreSQL. You can use these by passing a ruby regular expression to
|
|
463
|
+
Sequel also supports SQL regular expressions on MySQL and PostgreSQL. You can use these by passing a ruby regular expression to +like+ or +ilike+, or by making the regular expression a hash value:
|
|
436
464
|
|
|
437
|
-
|
|
438
|
-
|
|
465
|
+
Sequel.like(:name, /^A/) # ("name" ~ '^A')
|
|
466
|
+
~Sequel.ilike(:name, /^A/) # ("name" !~* '^A')
|
|
439
467
|
{:name=>/^A/i} # ("name" ~* '^A')
|
|
440
|
-
|
|
468
|
+
Sequel.~(:name=>/^A/) # ("name" !~ '^A')
|
|
441
469
|
|
|
442
470
|
Note that using +ilike+ with a regular expression will always make the regexp case insensitive. If you use +like+ or the hash with regexp value, it will only be case insensitive if the Regexp itself is case insensitive.
|
|
443
471
|
|
|
444
472
|
=== Order Specifications (ASC, DESC)
|
|
445
473
|
|
|
446
|
-
Sequel supports specifying ascending or descending order using the
|
|
474
|
+
Sequel supports specifying ascending or descending order using the asc+ and +desc+ method on most Sequel-specific expression objects:
|
|
475
|
+
|
|
476
|
+
Sequel.expr(:column).asc # "column" ASC
|
|
477
|
+
Sequel.expr(:column).qualify(:table).desc # "table"."column" DESC
|
|
447
478
|
|
|
448
|
-
|
|
449
|
-
|
|
479
|
+
You can also use the <tt>Sequel.asc</tt> and <tt>Sequel.desc</tt> methods:
|
|
480
|
+
|
|
481
|
+
Sequel.asc(:column) # "column" ASC
|
|
482
|
+
Sequel.desc(Sequel.expr(:column).qualify(:table)) # "table"."column" DESC
|
|
483
|
+
|
|
484
|
+
On some databases, you can specify null ordering:
|
|
485
|
+
|
|
486
|
+
Sequel.asc(:column, :nulls=>:first) # "column" ASC NULLS FIRST
|
|
487
|
+
Sequel.desc(Sequel.expr(:column).qualify(:table), :nulls=>:last) # "table"."column" DESC NULLS LAST
|
|
450
488
|
|
|
451
489
|
=== All Columns (.*)
|
|
452
490
|
|
|
453
|
-
To select all columns in a table, Sequel supports the * method on
|
|
491
|
+
To select all columns in a table, Sequel supports the * method on identifiers without an argument:
|
|
454
492
|
|
|
455
|
-
:table.* # "table".*
|
|
493
|
+
Sequel.expr(:table).* # "table".*
|
|
456
494
|
|
|
457
495
|
=== CASE statements
|
|
458
496
|
|
|
459
|
-
Sequel allows the easy production of SQL CASE statements using the
|
|
497
|
+
Sequel allows the easy production of SQL CASE statements using the <tt>Sequel.case</tt> method. The first argument is a hash or array of two element arrays representing the conditions, the second argument is the default value (ELSE). The keys of the hash (or first element in each array) is the WHEN condition, and the values of the hash (or second element in each array) is the THEN result. Here are some examples:
|
|
460
498
|
|
|
461
|
-
{:column=>1
|
|
462
|
-
[[column, 1]]
|
|
463
|
-
{{:column=>nil}=>1}
|
|
499
|
+
Sequel.case({:column=>1, 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
|
|
500
|
+
Sequel.case([[column, 1]], 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
|
|
501
|
+
Sequel.case({{:column=>nil}=>1}, 0) # (CASE WHEN (column IS NULL) THEN 1 ELSE 0 END)
|
|
464
502
|
|
|
465
503
|
If the hash or array has multiple arguments, multiple WHEN clauses are used:
|
|
466
504
|
|
|
467
|
-
{:c=>1, :d=>2}
|
|
468
|
-
[[:c, 1], [:d, 2]]
|
|
505
|
+
Sequel.case({:c=>1, :d=>2}, 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
|
|
506
|
+
Sequel.case([[:c, 1], [:d, 2]], 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
|
|
469
507
|
|
|
470
508
|
If you provide a 2nd argument to CASE, it goes between CASE and WHEN:
|
|
471
509
|
|
|
472
|
-
{2=>1, 3=>5}
|
|
510
|
+
Sequel.case({2=>1, 3=>5}, 0, :column) # (CASE column WHEN 2 THEN 1 WHEN 3 THEN 5 ELSE 0 END)
|
|
473
511
|
|
|
474
512
|
=== Subscripts/Array Access ([])
|
|
475
513
|
|
|
476
|
-
Sequel supports SQL subscripts using the +sql_subscript+ method on
|
|
514
|
+
Sequel supports SQL subscripts using the +sql_subscript+ method on most Sequel-specific expression objects:
|
|
515
|
+
|
|
516
|
+
Sequel.expr(:column).sql_subscript(3) # column[3]
|
|
517
|
+
Sequel.expr(:column).qualify(:table).sql_subscript(3) # table.column[3]
|
|
518
|
+
|
|
519
|
+
You can also use the <tt>Sequel.subscript</tt> method:
|
|
477
520
|
|
|
478
|
-
:column
|
|
479
|
-
:column.qualify(:table).sql_subscript(3) # table.column[3]
|
|
521
|
+
Sequel.subscript(:column, 3) # column[3]
|
|
480
522
|
|
|
481
523
|
Just like in SQL, you can use any expression as a subscript:
|
|
482
524
|
|
|
483
|
-
:column.
|
|
525
|
+
Sequel.subscript(:column, Sequel.function(:func)) # column[func()]
|
|
484
526
|
|
|
485
527
|
== Building Queries in Sequel
|
|
486
528
|
|
|
@@ -504,12 +546,12 @@ If you don't want to select from any FROM tables, use no arguments:
|
|
|
504
546
|
|
|
505
547
|
Once you have your dataset object, you build queries by chaining methods, usually with one method per clause in the query:
|
|
506
548
|
|
|
507
|
-
DB[:albums].select(:id, :name).where(
|
|
549
|
+
DB[:albums].select(:id, :name).where(Sequel.like(:name, 'A%')).order(:name)
|
|
508
550
|
# SELECT id, name FROM albums WHERE (name LIKE 'A%') ORDER BY name
|
|
509
551
|
|
|
510
552
|
Note that the order of your method chain is not usually important unless you have multiple methods that affect the same clause:
|
|
511
553
|
|
|
512
|
-
DB[:albums].order(:name).where(
|
|
554
|
+
DB[:albums].order(:name).where(Sequel.like(:name, 'A%')).select(:id, :name)
|
|
513
555
|
# SELECT id, name FROM albums WHERE (name LIKE 'A%') ORDER BY name
|
|
514
556
|
|
|
515
557
|
=== Using the Same Dataset for SELECT, INSERT, UPDATE, and DELETE
|
|
@@ -524,13 +566,13 @@ Also note that while the SELECT clause is displayed when you look at a dataset,
|
|
|
524
566
|
|
|
525
567
|
In general, the +insert+, +update+, and +delete+ methods use the appropriate clauses you defined on the dataset:
|
|
526
568
|
|
|
527
|
-
ds = DB[:albums].
|
|
569
|
+
ds = DB[:albums].where(:id=>1)
|
|
528
570
|
ds.all # SELECT * FROM albums WHERE (id = 1)
|
|
529
571
|
ds.insert(:name=>'RF') # INSERT INTO albums (name) VALUES ('RF')
|
|
530
572
|
ds.update(:name=>'RF') # UPDATE albums SET name = 'RF' WHERE (id = 1)
|
|
531
573
|
ds.delete # DELETE FROM albums WHERE (id = 1)
|
|
532
574
|
|
|
533
|
-
Note how +update+ and +delete+ used the +
|
|
575
|
+
Note how +update+ and +delete+ used the +where+ argument, but that +insert+ did not, because INSERT doesn't use a WHERE clause.
|
|
534
576
|
|
|
535
577
|
=== Methods Used for Each SQL Clause
|
|
536
578
|
|