sequel 4.26.0 → 5.37.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG +405 -5656
- data/MIT-LICENSE +1 -1
- data/README.rdoc +232 -157
- data/bin/sequel +32 -9
- data/doc/advanced_associations.rdoc +252 -188
- data/doc/association_basics.rdoc +231 -273
- data/doc/bin_sequel.rdoc +5 -3
- data/doc/cheat_sheet.rdoc +75 -48
- data/doc/code_order.rdoc +28 -10
- data/doc/core_extensions.rdoc +104 -63
- data/doc/dataset_basics.rdoc +12 -21
- data/doc/dataset_filtering.rdoc +99 -86
- data/doc/extensions.rdoc +3 -10
- data/doc/mass_assignment.rdoc +74 -31
- data/doc/migration.rdoc +72 -46
- data/doc/model_dataset_method_design.rdoc +129 -0
- data/doc/model_hooks.rdoc +15 -25
- data/doc/model_plugins.rdoc +12 -12
- data/doc/mssql_stored_procedures.rdoc +3 -3
- data/doc/object_model.rdoc +59 -69
- data/doc/opening_databases.rdoc +84 -94
- data/doc/postgresql.rdoc +268 -38
- data/doc/prepared_statements.rdoc +29 -24
- data/doc/querying.rdoc +184 -164
- data/doc/reflection.rdoc +5 -6
- data/doc/release_notes/5.0.0.txt +159 -0
- data/doc/release_notes/5.1.0.txt +31 -0
- data/doc/release_notes/5.10.0.txt +84 -0
- data/doc/release_notes/5.11.0.txt +83 -0
- data/doc/release_notes/5.12.0.txt +141 -0
- data/doc/release_notes/5.13.0.txt +27 -0
- data/doc/release_notes/5.14.0.txt +63 -0
- data/doc/release_notes/5.15.0.txt +39 -0
- data/doc/release_notes/5.16.0.txt +110 -0
- data/doc/release_notes/5.17.0.txt +31 -0
- data/doc/release_notes/5.18.0.txt +69 -0
- data/doc/release_notes/5.19.0.txt +28 -0
- data/doc/release_notes/5.2.0.txt +33 -0
- data/doc/release_notes/5.20.0.txt +89 -0
- data/doc/release_notes/5.21.0.txt +87 -0
- data/doc/release_notes/5.22.0.txt +48 -0
- data/doc/release_notes/5.23.0.txt +56 -0
- data/doc/release_notes/5.24.0.txt +56 -0
- data/doc/release_notes/5.25.0.txt +32 -0
- data/doc/release_notes/5.26.0.txt +35 -0
- data/doc/release_notes/5.27.0.txt +21 -0
- data/doc/release_notes/5.28.0.txt +16 -0
- data/doc/release_notes/5.29.0.txt +22 -0
- data/doc/release_notes/5.3.0.txt +121 -0
- data/doc/release_notes/5.30.0.txt +20 -0
- data/doc/release_notes/5.31.0.txt +148 -0
- data/doc/release_notes/5.32.0.txt +46 -0
- data/doc/release_notes/5.33.0.txt +24 -0
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.4.0.txt +80 -0
- data/doc/release_notes/5.5.0.txt +61 -0
- data/doc/release_notes/5.6.0.txt +31 -0
- data/doc/release_notes/5.7.0.txt +108 -0
- data/doc/release_notes/5.8.0.txt +170 -0
- data/doc/release_notes/5.9.0.txt +99 -0
- data/doc/schema_modification.rdoc +102 -77
- data/doc/security.rdoc +160 -87
- data/doc/sharding.rdoc +74 -47
- data/doc/sql.rdoc +135 -122
- data/doc/testing.rdoc +34 -18
- data/doc/thread_safety.rdoc +2 -4
- data/doc/transactions.rdoc +101 -19
- data/doc/validations.rdoc +64 -51
- data/doc/virtual_rows.rdoc +90 -109
- data/lib/sequel.rb +3 -1
- data/lib/sequel/adapters/ado.rb +154 -22
- data/lib/sequel/adapters/ado/access.rb +21 -21
- data/lib/sequel/adapters/ado/mssql.rb +8 -15
- data/lib/sequel/adapters/amalgalite.rb +17 -25
- data/lib/sequel/adapters/ibmdb.rb +52 -58
- data/lib/sequel/adapters/jdbc.rb +149 -127
- data/lib/sequel/adapters/jdbc/db2.rb +32 -40
- data/lib/sequel/adapters/jdbc/derby.rb +56 -58
- data/lib/sequel/adapters/jdbc/h2.rb +40 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +22 -33
- data/lib/sequel/adapters/jdbc/jtds.rb +4 -10
- data/lib/sequel/adapters/jdbc/mssql.rb +6 -12
- data/lib/sequel/adapters/jdbc/mysql.rb +17 -18
- data/lib/sequel/adapters/jdbc/oracle.rb +25 -19
- data/lib/sequel/adapters/jdbc/postgresql.rb +90 -69
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +14 -24
- data/lib/sequel/adapters/jdbc/sqlite.rb +50 -12
- data/lib/sequel/adapters/jdbc/sqlserver.rb +36 -9
- data/lib/sequel/adapters/jdbc/transactions.rb +25 -39
- data/lib/sequel/adapters/mock.rb +104 -113
- data/lib/sequel/adapters/mysql.rb +42 -61
- data/lib/sequel/adapters/mysql2.rb +126 -35
- data/lib/sequel/adapters/odbc.rb +21 -28
- data/lib/sequel/adapters/odbc/db2.rb +3 -1
- data/lib/sequel/adapters/odbc/mssql.rb +11 -15
- data/lib/sequel/adapters/odbc/oracle.rb +11 -0
- data/lib/sequel/adapters/oracle.rb +62 -68
- data/lib/sequel/adapters/postgres.rb +257 -311
- data/lib/sequel/adapters/postgresql.rb +3 -1
- data/lib/sequel/adapters/shared/access.rb +75 -79
- data/lib/sequel/adapters/shared/db2.rb +96 -74
- data/lib/sequel/adapters/shared/mssql.rb +258 -213
- data/lib/sequel/adapters/shared/mysql.rb +284 -216
- data/lib/sequel/adapters/shared/oracle.rb +175 -60
- data/lib/sequel/adapters/shared/postgres.rb +829 -383
- data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -127
- data/lib/sequel/adapters/shared/sqlite.rb +382 -159
- data/lib/sequel/adapters/sqlanywhere.rb +53 -38
- data/lib/sequel/adapters/sqlite.rb +111 -105
- data/lib/sequel/adapters/tinytds.rb +38 -46
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -9
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
- data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
- data/lib/sequel/adapters/utils/replace.rb +3 -4
- data/lib/sequel/adapters/utils/split_alter_table.rb +2 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
- data/lib/sequel/ast_transformer.rb +13 -89
- data/lib/sequel/connection_pool.rb +54 -26
- data/lib/sequel/connection_pool/sharded_single.rb +19 -12
- data/lib/sequel/connection_pool/sharded_threaded.rb +160 -111
- data/lib/sequel/connection_pool/single.rb +21 -12
- data/lib/sequel/connection_pool/threaded.rb +137 -119
- data/lib/sequel/core.rb +352 -320
- data/lib/sequel/database.rb +19 -2
- data/lib/sequel/database/connecting.rb +70 -55
- data/lib/sequel/database/dataset.rb +15 -5
- data/lib/sequel/database/dataset_defaults.rb +20 -102
- data/lib/sequel/database/features.rb +20 -4
- data/lib/sequel/database/logging.rb +25 -7
- data/lib/sequel/database/misc.rb +132 -118
- data/lib/sequel/database/query.rb +51 -28
- data/lib/sequel/database/schema_generator.rb +188 -75
- data/lib/sequel/database/schema_methods.rb +161 -92
- data/lib/sequel/database/transactions.rb +260 -58
- data/lib/sequel/dataset.rb +28 -12
- data/lib/sequel/dataset/actions.rb +354 -170
- data/lib/sequel/dataset/dataset_module.rb +46 -0
- data/lib/sequel/dataset/features.rb +81 -34
- data/lib/sequel/dataset/graph.rb +82 -58
- data/lib/sequel/dataset/misc.rb +139 -47
- data/lib/sequel/dataset/placeholder_literalizer.rb +66 -26
- data/lib/sequel/dataset/prepared_statements.rb +188 -85
- data/lib/sequel/dataset/query.rb +428 -214
- data/lib/sequel/dataset/sql.rb +446 -339
- data/lib/sequel/deprecated.rb +14 -2
- data/lib/sequel/exceptions.rb +48 -16
- data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
- data/lib/sequel/extensions/_model_pg_row.rb +43 -0
- data/lib/sequel/extensions/_pretty_table.rb +10 -9
- data/lib/sequel/extensions/any_not_empty.rb +45 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +15 -11
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/blank.rb +2 -0
- data/lib/sequel/extensions/caller_logging.rb +79 -0
- data/lib/sequel/extensions/columns_introspection.rb +9 -4
- data/lib/sequel/extensions/connection_expiration.rb +99 -0
- data/lib/sequel/extensions/connection_validator.rb +26 -13
- data/lib/sequel/extensions/constant_sql_override.rb +65 -0
- data/lib/sequel/extensions/constraint_validations.rb +93 -38
- data/lib/sequel/extensions/core_extensions.rb +45 -53
- data/lib/sequel/extensions/core_refinements.rb +44 -46
- data/lib/sequel/extensions/current_datetime_timestamp.rb +5 -4
- data/lib/sequel/extensions/dataset_source_alias.rb +4 -0
- data/lib/sequel/extensions/date_arithmetic.rb +42 -16
- data/lib/sequel/extensions/datetime_parse_to_time.rb +37 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +94 -0
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -3
- data/lib/sequel/extensions/error_sql.rb +7 -3
- data/lib/sequel/extensions/escaped_like.rb +100 -0
- data/lib/sequel/extensions/eval_inspect.rb +14 -15
- data/lib/sequel/extensions/exclude_or_null.rb +68 -0
- data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
- data/lib/sequel/extensions/freeze_datasets.rb +3 -0
- data/lib/sequel/extensions/from_block.rb +2 -31
- data/lib/sequel/extensions/graph_each.rb +19 -6
- data/lib/sequel/extensions/identifier_mangling.rb +180 -0
- data/lib/sequel/extensions/implicit_subquery.rb +48 -0
- data/lib/sequel/extensions/index_caching.rb +109 -0
- data/lib/sequel/extensions/inflector.rb +8 -4
- data/lib/sequel/extensions/integer64.rb +32 -0
- data/lib/sequel/extensions/looser_typecasting.rb +19 -9
- data/lib/sequel/extensions/migration.rb +132 -80
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +4 -0
- data/lib/sequel/extensions/named_timezones.rb +88 -23
- data/lib/sequel/extensions/no_auto_literal_strings.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +12 -8
- data/lib/sequel/extensions/pagination.rb +35 -28
- data/lib/sequel/extensions/pg_array.rb +227 -316
- data/lib/sequel/extensions/pg_array_ops.rb +19 -7
- data/lib/sequel/extensions/pg_enum.rb +69 -24
- data/lib/sequel/extensions/pg_extended_date_support.rb +250 -0
- data/lib/sequel/extensions/pg_hstore.rb +50 -59
- data/lib/sequel/extensions/pg_hstore_ops.rb +9 -3
- data/lib/sequel/extensions/pg_inet.rb +34 -15
- data/lib/sequel/extensions/pg_inet_ops.rb +5 -1
- data/lib/sequel/extensions/pg_interval.rb +26 -26
- data/lib/sequel/extensions/pg_json.rb +422 -141
- data/lib/sequel/extensions/pg_json_ops.rb +248 -9
- data/lib/sequel/extensions/pg_loose_count.rb +5 -1
- data/lib/sequel/extensions/pg_range.rb +162 -146
- data/lib/sequel/extensions/pg_range_ops.rb +10 -5
- data/lib/sequel/extensions/pg_row.rb +53 -87
- data/lib/sequel/extensions/pg_row_ops.rb +36 -13
- data/lib/sequel/extensions/pg_static_cache_updater.rb +6 -2
- data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
- data/lib/sequel/extensions/pretty_table.rb +4 -0
- data/lib/sequel/extensions/query.rb +12 -7
- data/lib/sequel/extensions/round_timestamps.rb +6 -9
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +59 -0
- data/lib/sequel/extensions/schema_caching.rb +14 -1
- data/lib/sequel/extensions/schema_dumper.rb +83 -55
- data/lib/sequel/extensions/select_remove.rb +8 -4
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
- data/lib/sequel/extensions/server_block.rb +50 -17
- data/lib/sequel/extensions/server_logging.rb +61 -0
- data/lib/sequel/extensions/split_array_nil.rb +8 -4
- data/lib/sequel/extensions/sql_comments.rb +96 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -1
- data/lib/sequel/extensions/string_agg.rb +181 -0
- data/lib/sequel/extensions/string_date_time.rb +2 -0
- data/lib/sequel/extensions/symbol_aref.rb +53 -0
- data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
- data/lib/sequel/extensions/symbol_as.rb +23 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
- data/lib/sequel/extensions/synchronize_sql.rb +45 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +4 -0
- data/lib/sequel/extensions/to_dot.rb +15 -5
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model.rb +36 -126
- data/lib/sequel/model/associations.rb +850 -257
- data/lib/sequel/model/base.rb +652 -764
- data/lib/sequel/model/dataset_module.rb +13 -10
- data/lib/sequel/model/default_inflections.rb +3 -1
- data/lib/sequel/model/errors.rb +3 -3
- data/lib/sequel/model/exceptions.rb +12 -12
- data/lib/sequel/model/inflections.rb +8 -19
- data/lib/sequel/model/plugins.rb +111 -0
- data/lib/sequel/plugins/accessed_columns.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +32 -7
- data/lib/sequel/plugins/after_initialize.rb +3 -1
- data/lib/sequel/plugins/association_dependencies.rb +27 -18
- data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
- data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
- data/lib/sequel/plugins/association_pks.rb +181 -83
- data/lib/sequel/plugins/association_proxies.rb +33 -9
- data/lib/sequel/plugins/auto_validations.rb +58 -23
- data/lib/sequel/plugins/before_after_save.rb +8 -0
- data/lib/sequel/plugins/blacklist_security.rb +23 -12
- data/lib/sequel/plugins/boolean_readers.rb +9 -6
- data/lib/sequel/plugins/boolean_subsets.rb +64 -0
- data/lib/sequel/plugins/caching.rb +27 -16
- data/lib/sequel/plugins/class_table_inheritance.rb +192 -94
- data/lib/sequel/plugins/column_conflicts.rb +18 -3
- data/lib/sequel/plugins/column_select.rb +9 -5
- data/lib/sequel/plugins/columns_updated.rb +42 -0
- data/lib/sequel/plugins/composition.rb +36 -24
- data/lib/sequel/plugins/constraint_validations.rb +37 -16
- data/lib/sequel/plugins/csv_serializer.rb +58 -35
- data/lib/sequel/plugins/dataset_associations.rb +60 -18
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/defaults_setter.rb +74 -13
- data/lib/sequel/plugins/delay_add_association.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +65 -24
- data/lib/sequel/plugins/eager_each.rb +27 -3
- data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
- data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
- data/lib/sequel/plugins/error_splitter.rb +19 -12
- data/lib/sequel/plugins/finder.rb +246 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
- data/lib/sequel/plugins/force_encoding.rb +9 -12
- data/lib/sequel/plugins/hook_class_methods.rb +39 -54
- data/lib/sequel/plugins/input_transformer.rb +20 -10
- data/lib/sequel/plugins/insert_conflict.rb +72 -0
- data/lib/sequel/plugins/insert_returning_select.rb +4 -2
- data/lib/sequel/plugins/instance_filters.rb +12 -8
- data/lib/sequel/plugins/instance_hooks.rb +36 -17
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/inverted_subsets.rb +24 -13
- data/lib/sequel/plugins/json_serializer.rb +123 -47
- data/lib/sequel/plugins/lazy_attributes.rb +20 -14
- data/lib/sequel/plugins/list.rb +40 -26
- data/lib/sequel/plugins/many_through_many.rb +28 -12
- data/lib/sequel/plugins/modification_detection.rb +17 -5
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -5
- data/lib/sequel/plugins/nested_attributes.rb +55 -28
- data/lib/sequel/plugins/optimistic_locking.rb +5 -3
- data/lib/sequel/plugins/pg_array_associations.rb +52 -18
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +348 -0
- data/lib/sequel/plugins/pg_row.rb +7 -51
- data/lib/sequel/plugins/prepared_statements.rb +53 -72
- data/lib/sequel/plugins/prepared_statements_safe.rb +13 -5
- data/lib/sequel/plugins/rcte_tree.rb +43 -63
- data/lib/sequel/plugins/serialization.rb +37 -44
- data/lib/sequel/plugins/serialization_modification_detection.rb +3 -1
- data/lib/sequel/plugins/sharding.rb +17 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +62 -28
- data/lib/sequel/plugins/singular_table_names.rb +2 -0
- data/lib/sequel/plugins/skip_create_refresh.rb +5 -3
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/split_values.rb +13 -6
- data/lib/sequel/plugins/static_cache.rb +79 -53
- data/lib/sequel/plugins/static_cache_cache.rb +53 -0
- data/lib/sequel/plugins/string_stripper.rb +5 -3
- data/lib/sequel/plugins/subclasses.rb +20 -2
- data/lib/sequel/plugins/subset_conditions.rb +48 -0
- data/lib/sequel/plugins/table_select.rb +4 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +120 -6
- data/lib/sequel/plugins/throw_failures.rb +110 -0
- data/lib/sequel/plugins/timestamps.rb +22 -8
- data/lib/sequel/plugins/touch.rb +21 -8
- data/lib/sequel/plugins/tree.rb +57 -30
- data/lib/sequel/plugins/typecast_on_load.rb +14 -4
- data/lib/sequel/plugins/unlimited_update.rb +3 -7
- data/lib/sequel/plugins/update_or_create.rb +6 -4
- data/lib/sequel/plugins/update_primary_key.rb +3 -1
- data/lib/sequel/plugins/update_refresh.rb +28 -15
- data/lib/sequel/plugins/uuid.rb +70 -0
- data/lib/sequel/plugins/validate_associated.rb +20 -0
- data/lib/sequel/plugins/validation_class_methods.rb +40 -19
- data/lib/sequel/plugins/validation_contexts.rb +49 -0
- data/lib/sequel/plugins/validation_helpers.rb +49 -31
- data/lib/sequel/plugins/whitelist_security.rb +122 -0
- data/lib/sequel/plugins/xml_serializer.rb +31 -30
- data/lib/sequel/sql.rb +479 -329
- data/lib/sequel/timezones.rb +62 -32
- data/lib/sequel/version.rb +10 -3
- metadata +177 -477
- data/Rakefile +0 -165
- data/doc/active_record.rdoc +0 -912
- data/doc/release_notes/1.0.txt +0 -38
- data/doc/release_notes/1.1.txt +0 -143
- data/doc/release_notes/1.3.txt +0 -101
- data/doc/release_notes/1.4.0.txt +0 -53
- data/doc/release_notes/1.5.0.txt +0 -155
- data/doc/release_notes/2.0.0.txt +0 -298
- data/doc/release_notes/2.1.0.txt +0 -271
- data/doc/release_notes/2.10.0.txt +0 -328
- data/doc/release_notes/2.11.0.txt +0 -215
- data/doc/release_notes/2.12.0.txt +0 -534
- data/doc/release_notes/2.2.0.txt +0 -253
- data/doc/release_notes/2.3.0.txt +0 -88
- data/doc/release_notes/2.4.0.txt +0 -106
- data/doc/release_notes/2.5.0.txt +0 -137
- data/doc/release_notes/2.6.0.txt +0 -157
- data/doc/release_notes/2.7.0.txt +0 -166
- data/doc/release_notes/2.8.0.txt +0 -171
- data/doc/release_notes/2.9.0.txt +0 -97
- data/doc/release_notes/3.0.0.txt +0 -221
- data/doc/release_notes/3.1.0.txt +0 -406
- data/doc/release_notes/3.10.0.txt +0 -286
- data/doc/release_notes/3.11.0.txt +0 -254
- data/doc/release_notes/3.12.0.txt +0 -304
- data/doc/release_notes/3.13.0.txt +0 -210
- data/doc/release_notes/3.14.0.txt +0 -118
- data/doc/release_notes/3.15.0.txt +0 -78
- data/doc/release_notes/3.16.0.txt +0 -45
- data/doc/release_notes/3.17.0.txt +0 -58
- data/doc/release_notes/3.18.0.txt +0 -120
- data/doc/release_notes/3.19.0.txt +0 -67
- data/doc/release_notes/3.2.0.txt +0 -268
- data/doc/release_notes/3.20.0.txt +0 -41
- data/doc/release_notes/3.21.0.txt +0 -87
- data/doc/release_notes/3.22.0.txt +0 -39
- data/doc/release_notes/3.23.0.txt +0 -172
- data/doc/release_notes/3.24.0.txt +0 -420
- data/doc/release_notes/3.25.0.txt +0 -88
- data/doc/release_notes/3.26.0.txt +0 -88
- data/doc/release_notes/3.27.0.txt +0 -82
- data/doc/release_notes/3.28.0.txt +0 -304
- data/doc/release_notes/3.29.0.txt +0 -459
- data/doc/release_notes/3.3.0.txt +0 -192
- data/doc/release_notes/3.30.0.txt +0 -135
- data/doc/release_notes/3.31.0.txt +0 -146
- data/doc/release_notes/3.32.0.txt +0 -202
- data/doc/release_notes/3.33.0.txt +0 -157
- data/doc/release_notes/3.34.0.txt +0 -671
- data/doc/release_notes/3.35.0.txt +0 -144
- data/doc/release_notes/3.36.0.txt +0 -245
- data/doc/release_notes/3.37.0.txt +0 -338
- data/doc/release_notes/3.38.0.txt +0 -234
- data/doc/release_notes/3.39.0.txt +0 -237
- data/doc/release_notes/3.4.0.txt +0 -325
- data/doc/release_notes/3.40.0.txt +0 -73
- data/doc/release_notes/3.41.0.txt +0 -155
- data/doc/release_notes/3.42.0.txt +0 -74
- data/doc/release_notes/3.43.0.txt +0 -105
- data/doc/release_notes/3.44.0.txt +0 -152
- data/doc/release_notes/3.45.0.txt +0 -179
- data/doc/release_notes/3.46.0.txt +0 -122
- data/doc/release_notes/3.47.0.txt +0 -270
- data/doc/release_notes/3.48.0.txt +0 -477
- data/doc/release_notes/3.5.0.txt +0 -510
- data/doc/release_notes/3.6.0.txt +0 -366
- data/doc/release_notes/3.7.0.txt +0 -179
- data/doc/release_notes/3.8.0.txt +0 -151
- data/doc/release_notes/3.9.0.txt +0 -233
- data/doc/release_notes/4.0.0.txt +0 -262
- data/doc/release_notes/4.1.0.txt +0 -85
- data/doc/release_notes/4.10.0.txt +0 -226
- data/doc/release_notes/4.11.0.txt +0 -147
- data/doc/release_notes/4.12.0.txt +0 -105
- data/doc/release_notes/4.13.0.txt +0 -169
- data/doc/release_notes/4.14.0.txt +0 -68
- data/doc/release_notes/4.15.0.txt +0 -56
- data/doc/release_notes/4.16.0.txt +0 -36
- data/doc/release_notes/4.17.0.txt +0 -38
- data/doc/release_notes/4.18.0.txt +0 -36
- data/doc/release_notes/4.19.0.txt +0 -45
- data/doc/release_notes/4.2.0.txt +0 -129
- data/doc/release_notes/4.20.0.txt +0 -79
- data/doc/release_notes/4.21.0.txt +0 -94
- data/doc/release_notes/4.22.0.txt +0 -72
- data/doc/release_notes/4.23.0.txt +0 -65
- data/doc/release_notes/4.24.0.txt +0 -99
- data/doc/release_notes/4.25.0.txt +0 -181
- data/doc/release_notes/4.26.0.txt +0 -44
- data/doc/release_notes/4.3.0.txt +0 -40
- data/doc/release_notes/4.4.0.txt +0 -92
- data/doc/release_notes/4.5.0.txt +0 -34
- data/doc/release_notes/4.6.0.txt +0 -30
- data/doc/release_notes/4.7.0.txt +0 -103
- data/doc/release_notes/4.8.0.txt +0 -175
- data/doc/release_notes/4.9.0.txt +0 -190
- data/lib/sequel/adapters/cubrid.rb +0 -142
- data/lib/sequel/adapters/do.rb +0 -156
- data/lib/sequel/adapters/do/mysql.rb +0 -64
- data/lib/sequel/adapters/do/postgres.rb +0 -42
- data/lib/sequel/adapters/do/sqlite3.rb +0 -40
- data/lib/sequel/adapters/jdbc/as400.rb +0 -82
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -62
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -34
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -31
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -31
- data/lib/sequel/adapters/odbc/progress.rb +0 -8
- data/lib/sequel/adapters/shared/cubrid.rb +0 -243
- data/lib/sequel/adapters/shared/firebird.rb +0 -245
- data/lib/sequel/adapters/shared/informix.rb +0 -52
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -150
- data/lib/sequel/adapters/shared/progress.rb +0 -38
- data/lib/sequel/adapters/swift.rb +0 -158
- data/lib/sequel/adapters/swift/mysql.rb +0 -47
- data/lib/sequel/adapters/swift/postgres.rb +0 -45
- data/lib/sequel/adapters/swift/sqlite.rb +0 -47
- data/lib/sequel/adapters/utils/pg_types.rb +0 -68
- data/lib/sequel/dataset/mutation.rb +0 -109
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -3
- data/lib/sequel/extensions/filter_having.rb +0 -59
- data/lib/sequel/extensions/hash_aliases.rb +0 -45
- data/lib/sequel/extensions/meta_def.rb +0 -31
- data/lib/sequel/extensions/query_literals.rb +0 -80
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -22
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -118
- data/lib/sequel/extensions/set_overrides.rb +0 -72
- data/lib/sequel/no_core_ext.rb +0 -1
- data/lib/sequel/plugins/association_autoreloading.rb +0 -7
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -7
- data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -78
- data/lib/sequel/plugins/prepared_statements_associations.rb +0 -117
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -59
- data/lib/sequel/plugins/schema.rb +0 -80
- data/lib/sequel/plugins/scissors.rb +0 -33
- data/spec/adapters/db2_spec.rb +0 -160
- data/spec/adapters/firebird_spec.rb +0 -411
- data/spec/adapters/informix_spec.rb +0 -100
- data/spec/adapters/mssql_spec.rb +0 -706
- data/spec/adapters/mysql_spec.rb +0 -1287
- data/spec/adapters/oracle_spec.rb +0 -313
- data/spec/adapters/postgres_spec.rb +0 -3725
- data/spec/adapters/spec_helper.rb +0 -43
- data/spec/adapters/sqlanywhere_spec.rb +0 -170
- data/spec/adapters/sqlite_spec.rb +0 -653
- data/spec/bin_spec.rb +0 -254
- data/spec/core/connection_pool_spec.rb +0 -1016
- data/spec/core/database_spec.rb +0 -2531
- data/spec/core/dataset_spec.rb +0 -5098
- data/spec/core/deprecated_spec.rb +0 -70
- data/spec/core/expression_filters_spec.rb +0 -1243
- data/spec/core/mock_adapter_spec.rb +0 -462
- data/spec/core/object_graph_spec.rb +0 -303
- data/spec/core/placeholder_literalizer_spec.rb +0 -163
- data/spec/core/schema_generator_spec.rb +0 -179
- data/spec/core/schema_spec.rb +0 -1659
- data/spec/core/spec_helper.rb +0 -34
- data/spec/core/version_spec.rb +0 -7
- data/spec/core_extensions_spec.rb +0 -699
- data/spec/extensions/accessed_columns_spec.rb +0 -51
- data/spec/extensions/active_model_spec.rb +0 -123
- data/spec/extensions/after_initialize_spec.rb +0 -24
- data/spec/extensions/arbitrary_servers_spec.rb +0 -109
- data/spec/extensions/association_dependencies_spec.rb +0 -117
- data/spec/extensions/association_pks_spec.rb +0 -365
- data/spec/extensions/association_proxies_spec.rb +0 -86
- data/spec/extensions/auto_validations_spec.rb +0 -192
- data/spec/extensions/blacklist_security_spec.rb +0 -88
- data/spec/extensions/blank_spec.rb +0 -69
- data/spec/extensions/boolean_readers_spec.rb +0 -93
- data/spec/extensions/caching_spec.rb +0 -270
- data/spec/extensions/class_table_inheritance_spec.rb +0 -420
- data/spec/extensions/column_conflicts_spec.rb +0 -60
- data/spec/extensions/column_select_spec.rb +0 -108
- data/spec/extensions/columns_introspection_spec.rb +0 -91
- data/spec/extensions/composition_spec.rb +0 -242
- data/spec/extensions/connection_validator_spec.rb +0 -120
- data/spec/extensions/constraint_validations_plugin_spec.rb +0 -274
- data/spec/extensions/constraint_validations_spec.rb +0 -325
- data/spec/extensions/core_refinements_spec.rb +0 -519
- data/spec/extensions/csv_serializer_spec.rb +0 -173
- data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
- data/spec/extensions/dataset_associations_spec.rb +0 -311
- data/spec/extensions/dataset_source_alias_spec.rb +0 -51
- data/spec/extensions/date_arithmetic_spec.rb +0 -150
- data/spec/extensions/defaults_setter_spec.rb +0 -101
- data/spec/extensions/delay_add_association_spec.rb +0 -52
- data/spec/extensions/dirty_spec.rb +0 -180
- data/spec/extensions/eager_each_spec.rb +0 -42
- data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
- data/spec/extensions/error_splitter_spec.rb +0 -18
- data/spec/extensions/error_sql_spec.rb +0 -20
- data/spec/extensions/eval_inspect_spec.rb +0 -73
- data/spec/extensions/filter_having_spec.rb +0 -40
- data/spec/extensions/force_encoding_spec.rb +0 -114
- data/spec/extensions/from_block_spec.rb +0 -21
- data/spec/extensions/graph_each_spec.rb +0 -109
- data/spec/extensions/hash_aliases_spec.rb +0 -24
- data/spec/extensions/hook_class_methods_spec.rb +0 -429
- data/spec/extensions/inflector_spec.rb +0 -183
- data/spec/extensions/input_transformer_spec.rb +0 -54
- data/spec/extensions/insert_returning_select_spec.rb +0 -46
- data/spec/extensions/instance_filters_spec.rb +0 -79
- data/spec/extensions/instance_hooks_spec.rb +0 -276
- data/spec/extensions/inverted_subsets_spec.rb +0 -33
- data/spec/extensions/json_serializer_spec.rb +0 -291
- data/spec/extensions/lazy_attributes_spec.rb +0 -170
- data/spec/extensions/list_spec.rb +0 -267
- data/spec/extensions/looser_typecasting_spec.rb +0 -43
- data/spec/extensions/many_through_many_spec.rb +0 -2172
- data/spec/extensions/meta_def_spec.rb +0 -21
- data/spec/extensions/migration_spec.rb +0 -712
- data/spec/extensions/modification_detection_spec.rb +0 -80
- data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
- data/spec/extensions/named_timezones_spec.rb +0 -108
- data/spec/extensions/nested_attributes_spec.rb +0 -697
- data/spec/extensions/null_dataset_spec.rb +0 -85
- data/spec/extensions/optimistic_locking_spec.rb +0 -128
- data/spec/extensions/pagination_spec.rb +0 -118
- data/spec/extensions/pg_array_associations_spec.rb +0 -736
- data/spec/extensions/pg_array_ops_spec.rb +0 -143
- data/spec/extensions/pg_array_spec.rb +0 -395
- data/spec/extensions/pg_enum_spec.rb +0 -92
- data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
- data/spec/extensions/pg_hstore_spec.rb +0 -206
- data/spec/extensions/pg_inet_ops_spec.rb +0 -101
- data/spec/extensions/pg_inet_spec.rb +0 -52
- data/spec/extensions/pg_interval_spec.rb +0 -76
- data/spec/extensions/pg_json_ops_spec.rb +0 -229
- data/spec/extensions/pg_json_spec.rb +0 -218
- data/spec/extensions/pg_loose_count_spec.rb +0 -17
- data/spec/extensions/pg_range_ops_spec.rb +0 -58
- data/spec/extensions/pg_range_spec.rb +0 -404
- data/spec/extensions/pg_row_ops_spec.rb +0 -60
- data/spec/extensions/pg_row_plugin_spec.rb +0 -62
- data/spec/extensions/pg_row_spec.rb +0 -360
- data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
- data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
- data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
- data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
- data/spec/extensions/prepared_statements_spec.rb +0 -103
- data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
- data/spec/extensions/pretty_table_spec.rb +0 -92
- data/spec/extensions/query_literals_spec.rb +0 -183
- data/spec/extensions/query_spec.rb +0 -102
- data/spec/extensions/rcte_tree_spec.rb +0 -392
- data/spec/extensions/round_timestamps_spec.rb +0 -43
- data/spec/extensions/schema_caching_spec.rb +0 -41
- data/spec/extensions/schema_dumper_spec.rb +0 -789
- data/spec/extensions/schema_spec.rb +0 -117
- data/spec/extensions/scissors_spec.rb +0 -26
- data/spec/extensions/select_remove_spec.rb +0 -38
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
- data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
- data/spec/extensions/serialization_spec.rb +0 -362
- data/spec/extensions/server_block_spec.rb +0 -90
- data/spec/extensions/set_overrides_spec.rb +0 -61
- data/spec/extensions/sharding_spec.rb +0 -198
- data/spec/extensions/shared_caching_spec.rb +0 -175
- data/spec/extensions/single_table_inheritance_spec.rb +0 -297
- data/spec/extensions/singular_table_names_spec.rb +0 -22
- data/spec/extensions/skip_create_refresh_spec.rb +0 -17
- data/spec/extensions/spec_helper.rb +0 -71
- data/spec/extensions/split_array_nil_spec.rb +0 -24
- data/spec/extensions/split_values_spec.rb +0 -22
- data/spec/extensions/sql_expr_spec.rb +0 -60
- data/spec/extensions/static_cache_spec.rb +0 -361
- data/spec/extensions/string_date_time_spec.rb +0 -95
- data/spec/extensions/string_stripper_spec.rb +0 -68
- data/spec/extensions/subclasses_spec.rb +0 -66
- data/spec/extensions/table_select_spec.rb +0 -71
- data/spec/extensions/tactical_eager_loading_spec.rb +0 -82
- data/spec/extensions/thread_local_timezones_spec.rb +0 -67
- data/spec/extensions/timestamps_spec.rb +0 -175
- data/spec/extensions/to_dot_spec.rb +0 -154
- data/spec/extensions/touch_spec.rb +0 -203
- data/spec/extensions/tree_spec.rb +0 -274
- data/spec/extensions/typecast_on_load_spec.rb +0 -80
- data/spec/extensions/unlimited_update_spec.rb +0 -20
- data/spec/extensions/update_or_create_spec.rb +0 -87
- data/spec/extensions/update_primary_key_spec.rb +0 -100
- data/spec/extensions/update_refresh_spec.rb +0 -53
- data/spec/extensions/validate_associated_spec.rb +0 -52
- data/spec/extensions/validation_class_methods_spec.rb +0 -1027
- data/spec/extensions/validation_helpers_spec.rb +0 -541
- data/spec/extensions/xml_serializer_spec.rb +0 -207
- data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
- data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
- data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
- data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
- data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
- data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
- data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
- data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
- data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
- data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
- data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
- data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
- data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/reversible_migrations/001_reversible.rb +0 -5
- data/spec/files/reversible_migrations/002_reversible.rb +0 -5
- data/spec/files/reversible_migrations/003_reversible.rb +0 -5
- data/spec/files/reversible_migrations/004_reversible.rb +0 -5
- data/spec/files/reversible_migrations/005_reversible.rb +0 -10
- data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
- data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
- data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
- data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
- data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
- data/spec/guards_helper.rb +0 -55
- data/spec/integration/associations_test.rb +0 -2454
- data/spec/integration/database_test.rb +0 -113
- data/spec/integration/dataset_test.rb +0 -1808
- data/spec/integration/eager_loader_test.rb +0 -687
- data/spec/integration/migrator_test.rb +0 -240
- data/spec/integration/model_test.rb +0 -226
- data/spec/integration/plugin_test.rb +0 -2240
- data/spec/integration/prepared_statement_test.rb +0 -467
- data/spec/integration/schema_test.rb +0 -817
- data/spec/integration/spec_helper.rb +0 -48
- data/spec/integration/timezone_test.rb +0 -86
- data/spec/integration/transaction_test.rb +0 -374
- data/spec/integration/type_test.rb +0 -133
- data/spec/model/association_reflection_spec.rb +0 -525
- data/spec/model/associations_spec.rb +0 -4426
- data/spec/model/base_spec.rb +0 -759
- data/spec/model/class_dataset_methods_spec.rb +0 -146
- data/spec/model/dataset_methods_spec.rb +0 -149
- data/spec/model/eager_loading_spec.rb +0 -2137
- data/spec/model/hooks_spec.rb +0 -604
- data/spec/model/inflector_spec.rb +0 -26
- data/spec/model/model_spec.rb +0 -982
- data/spec/model/plugins_spec.rb +0 -299
- data/spec/model/record_spec.rb +0 -2147
- data/spec/model/spec_helper.rb +0 -46
- data/spec/model/validations_spec.rb +0 -193
- data/spec/sequel_coverage.rb +0 -15
- data/spec/spec_config.rb +0 -10
data/doc/sharding.rdoc
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
=
|
1
|
+
= Primary/Replica Configurations and Database Sharding
|
2
2
|
|
3
|
-
Sequel has support for
|
4
|
-
with
|
3
|
+
Sequel has support for primary/replica configurations (writable primary
|
4
|
+
database with read only replicas databases), as well as database sharding (where you can
|
5
5
|
pick a server to use for a given dataset). Support for both
|
6
6
|
features is database independent, and should work for all database adapters
|
7
7
|
that ship with Sequel.
|
@@ -13,7 +13,7 @@ option. Using the :servers database option makes Sequel use a connection pool
|
|
13
13
|
class that supports sharding, and the minimum required to enable sharding
|
14
14
|
support is to use the empty hash:
|
15
15
|
|
16
|
-
DB=Sequel.connect('postgres://
|
16
|
+
DB=Sequel.connect('postgres://primary_server/database', servers: {})
|
17
17
|
|
18
18
|
In most cases, you are probably not going to want to use an empty hash. Keys in the server hash are
|
19
19
|
not restricted to type, but the general recommendation is to use a symbol
|
@@ -28,69 +28,69 @@ a :host entry in each shard's hash.
|
|
28
28
|
Note that all servers should have the same schema for all
|
29
29
|
tables you are accessing, unless you really know what you are doing.
|
30
30
|
|
31
|
-
==
|
31
|
+
== Primary and Replica Database Configurations
|
32
32
|
|
33
|
-
=== Single
|
33
|
+
=== Single Primary, Single Replica
|
34
34
|
|
35
|
-
To use a single, read-only
|
35
|
+
To use a single, read-only replica that handles SELECT queries, the following
|
36
36
|
is the simplest configuration:
|
37
37
|
|
38
|
-
DB=Sequel.connect('postgres://
|
39
|
-
:
|
38
|
+
DB=Sequel.connect('postgres://primary_server/database',
|
39
|
+
servers: {read_only: {host: 'replica_server'}})
|
40
40
|
|
41
|
-
This will use the
|
41
|
+
This will use the replica_server for SELECT queries and primary_server for
|
42
42
|
other queries.
|
43
43
|
|
44
44
|
If you want to ensure your queries are going to a specific database, you
|
45
45
|
can force this for a given query by using the .server method and passing
|
46
46
|
the symbol name defined in the connect options. For example:
|
47
47
|
|
48
|
-
# Force the SELECT to run on the
|
48
|
+
# Force the SELECT to run on the primary server
|
49
49
|
DB[:users].server(:default).all
|
50
50
|
|
51
|
-
# Force the
|
52
|
-
DB[:users].server(:read_only).
|
51
|
+
# Force the DELETE to run on the read-only replica
|
52
|
+
DB[:users].server(:read_only).delete
|
53
53
|
|
54
|
-
===
|
54
|
+
=== Single Primary, Multiple Replicas
|
55
55
|
|
56
|
-
Let's say you have 4
|
57
|
-
|
56
|
+
Let's say you have 4 replica servers with names replica_server0,
|
57
|
+
replica_server1, replica_server2, and replica_server3.
|
58
58
|
|
59
59
|
num_read_only = 4
|
60
60
|
read_only_host = rand(num_read_only)
|
61
61
|
read_only_proc = proc do |db|
|
62
|
-
{:
|
62
|
+
{host: "replica_server#{(read_only_host+=1) % num_read_only}"}
|
63
63
|
end
|
64
|
-
DB=Sequel.connect('postgres://
|
65
|
-
:
|
64
|
+
DB=Sequel.connect('postgres://primary_server/database',
|
65
|
+
servers: {read_only: read_only_proc})
|
66
66
|
|
67
|
-
This will use one of the
|
68
|
-
|
67
|
+
This will use one of the replica servers for SELECT queries and use the
|
68
|
+
primary server for other queries. It's also possible to pick a random host
|
69
69
|
instead of using the round robin approach presented above, but that can result
|
70
70
|
in less optimal resource usage.
|
71
71
|
|
72
|
-
=== Multiple
|
72
|
+
=== Multiple Primary, Multiple Replicas
|
73
73
|
|
74
|
-
This involves the same basic idea as the multiple
|
75
|
-
it shows that the
|
76
|
-
4
|
74
|
+
This involves the same basic idea as the multiple replicas, single primary, but
|
75
|
+
it shows that the primary database is named :default. So for 4 primary servers and
|
76
|
+
4 replica servers:
|
77
77
|
|
78
78
|
num_read_only = 4
|
79
79
|
read_only_host = rand(num_read_only)
|
80
80
|
read_only_proc = proc do |db|
|
81
|
-
{:
|
81
|
+
{host: "replica_server#{(read_only_host+=1) % num_read_only}"}
|
82
82
|
end
|
83
83
|
num_default = 4
|
84
84
|
default_host = rand(num_default)
|
85
85
|
default_proc = proc do |db|
|
86
|
-
{:
|
86
|
+
{host: "primary_server#{(default_host+=1) % num_default}"}
|
87
87
|
end
|
88
|
-
DB=Sequel.connect('postgres://
|
89
|
-
:
|
88
|
+
DB=Sequel.connect('postgres://primary_server/database',
|
89
|
+
servers: {default: default_proc, read_only: read_only_proc})
|
90
90
|
|
91
91
|
== Sharding
|
92
92
|
|
93
|
-
There is specific support in Sequel for handling
|
93
|
+
There is specific support in Sequel for handling primary/replica database
|
94
94
|
combinations, with the only necessary setup being the database configuration.
|
95
95
|
However, since sharding is always going to be implementation dependent, Sequel
|
96
96
|
supplies the basic infrastructure, but you have to tell it which server to use
|
@@ -100,16 +100,16 @@ of 16 shards). First, you need to configure the database:
|
|
100
100
|
|
101
101
|
servers = {}
|
102
102
|
(('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
|
103
|
-
servers[hex.to_sym] = {:
|
103
|
+
servers[hex.to_sym] = {host: "hash_host_#{hex}"}
|
104
104
|
end
|
105
|
-
DB=Sequel.connect('postgres://hash_host/hashes', :servers
|
105
|
+
DB=Sequel.connect('postgres://hash_host/hashes', servers: servers)
|
106
106
|
|
107
107
|
This configures 17 servers, the 16 shard servers (/hash_host_[0-9a-f]/), and 1
|
108
108
|
default server which will be used if no shard is specified ("hash_host"). If
|
109
109
|
you want the default server to be one of the shard servers (e.g. hash_host_a),
|
110
110
|
it's easiest to do:
|
111
111
|
|
112
|
-
DB=Sequel.connect('postgres://hash_host_a/hashes', :servers
|
112
|
+
DB=Sequel.connect('postgres://hash_host_a/hashes', servers: servers)
|
113
113
|
|
114
114
|
That will still set up a second pool of connections for the default server,
|
115
115
|
since it considers the default server and shard servers independent. Note that
|
@@ -120,7 +120,7 @@ schemas, so you should always have a default server that works.
|
|
120
120
|
|
121
121
|
To set the shard for a given query, you use the Dataset#server method:
|
122
122
|
|
123
|
-
DB[:hashes].server(:a).where(:
|
123
|
+
DB[:hashes].server(:a).where(hash: /31337/)
|
124
124
|
|
125
125
|
That will return all matching rows on the hash_host_a shard that have a hash
|
126
126
|
column that contains 31337.
|
@@ -133,37 +133,39 @@ the shard to use. This is fairly easy using a Sequel::Model:
|
|
133
133
|
dataset_module do
|
134
134
|
def plaintext_for_hash(hash)
|
135
135
|
raise(ArgumentError, 'Invalid SHA-1 Hash') unless /\A[0-9a-f]{40}\z/.match(hash)
|
136
|
-
server(hash[0...1].to_sym).where(:hash
|
136
|
+
server(hash[0...1].to_sym).where(hash: hash).get(:plaintext)
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
141
|
Rainbow.plaintext_for_hash("e580726d31f6e1ad216ffd87279e536d1f74e606")
|
142
142
|
|
143
|
+
=== :servers_hash Option
|
144
|
+
|
143
145
|
The connection pool can be further controlled to change how it handles attempts
|
144
146
|
to access shards that haven't been configured. The default is
|
145
147
|
to assume the :default shard. However, you can specify a
|
146
148
|
different shard using the :servers_hash option when connecting
|
147
149
|
to the database:
|
148
150
|
|
149
|
-
DB = Sequel.connect('postgres://...', :
|
151
|
+
DB = Sequel.connect('postgres://...', servers_hash: Hash.new(:some_shard))
|
150
152
|
|
151
153
|
You can also use this feature to raise an exception if an
|
152
154
|
unconfigured shard is used:
|
153
155
|
|
154
|
-
DB = Sequel.connect('postgres://...', :
|
156
|
+
DB = Sequel.connect('postgres://...', servers_hash: Hash.new{raise 'foo'})
|
155
157
|
|
156
158
|
If you specify a :servers_hash option to raise an exception for non configured
|
157
159
|
shards you should also explicitly specify a :read_only entry in your :servers option
|
158
160
|
for the case where a shard is not specified. In most cases it is sufficient
|
159
161
|
to make the :read_only entry the same as the :default shard:
|
160
162
|
|
161
|
-
servers = {:
|
163
|
+
servers = {read_only: {}}
|
162
164
|
(('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
|
163
|
-
servers[hex.to_sym] = {:
|
165
|
+
servers[hex.to_sym] = {host: "hash_host_#{hex}"}
|
164
166
|
end
|
165
|
-
DB=Sequel.connect('postgres://hash_host/hashes', :servers
|
166
|
-
:
|
167
|
+
DB=Sequel.connect('postgres://hash_host/hashes', servers: servers,
|
168
|
+
servers_hash: Hash.new{raise "Invalid Server"})
|
167
169
|
|
168
170
|
=== Sharding Plugin
|
169
171
|
|
@@ -176,7 +178,7 @@ work well with shards. You just need to remember to set to model to use the plu
|
|
176
178
|
plugin :sharding
|
177
179
|
end
|
178
180
|
|
179
|
-
Rainbow.server(:a).first(:
|
181
|
+
Rainbow.server(:a).first(id: 1).update(plaintext: 'VGM')
|
180
182
|
|
181
183
|
If all of your models are sharded, you can set all models to use the plugin via:
|
182
184
|
|
@@ -186,7 +188,7 @@ If all of your models are sharded, you can set all models to use the plugin via:
|
|
186
188
|
|
187
189
|
By default, you must specify the server/shard you want to use for every dataset/action,
|
188
190
|
or Sequel will use the default shard. If you have a group of queries that should use the
|
189
|
-
same shard, it can get a bit
|
191
|
+
same shard, it can get a bit redundant to specify the same shard for all of them.
|
190
192
|
|
191
193
|
The server_block extension adds a Database#with_server method that scopes all database
|
192
194
|
access inside the block to the given shard by default:
|
@@ -194,7 +196,7 @@ access inside the block to the given shard by default:
|
|
194
196
|
DB.extension :server_block
|
195
197
|
DB.with_server(:a) do
|
196
198
|
# this SELECT query uses the "a" shard
|
197
|
-
if r = Rainbow.first(:
|
199
|
+
if r = Rainbow.first(hash: /31337/)
|
198
200
|
r.count += 1
|
199
201
|
# this UPDATE query also uses the "a" shard
|
200
202
|
r.save
|
@@ -209,6 +211,19 @@ you retrieve the models inside the block and save them outside of the block. If
|
|
209
211
|
need to do that, call the server method explicitly on the dataset used to retrieve the
|
210
212
|
model objects.
|
211
213
|
|
214
|
+
The with_server method also supports a second argument for the default read_only server
|
215
|
+
to use, which can be useful if you are mixing sharding and primary/replica servers:
|
216
|
+
|
217
|
+
DB.extension :server_block
|
218
|
+
DB.with_server(:a, :a_read_only) do
|
219
|
+
# this SELECT query uses the "a_read_only" shard
|
220
|
+
if r = Rainbow.first(hash: /31337/)
|
221
|
+
r.count += 1
|
222
|
+
# this UPDATE query also uses the "a" shard
|
223
|
+
r.save
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
212
227
|
=== arbitrary_servers Extension
|
213
228
|
|
214
229
|
By default, Sequel's sharding support is designed to work with predefined shards. It ships
|
@@ -220,13 +235,13 @@ The arbitrary_servers extension allows you to pass a server/shard options hash a
|
|
220
235
|
server to use, and those options will be merged directly into the database's default options:
|
221
236
|
|
222
237
|
DB.extension :arbitrary_servers
|
223
|
-
DB[:rainbows].server(:
|
238
|
+
DB[:rainbows].server(host: 'hash_host_a').all
|
224
239
|
# or
|
225
|
-
DB[:rainbows].server(:
|
240
|
+
DB[:rainbows].server(host: 'hash_host_b', database: 'backup').all
|
226
241
|
|
227
242
|
arbitrary_servers is designed to work well in conjunction with the server_block extension:
|
228
243
|
|
229
|
-
DB.with_server(:
|
244
|
+
DB.with_server(host: 'hash_host_b', database: 'backup') do
|
230
245
|
DB.synchronize do
|
231
246
|
# All queries here default to the backup database on hash_host_b
|
232
247
|
end
|
@@ -255,3 +270,15 @@ the Database, just remove that option. If you are setting:
|
|
255
270
|
Sequel.single_threaded = true
|
256
271
|
|
257
272
|
just remove or comment out that code.
|
273
|
+
|
274
|
+
== JDBC
|
275
|
+
|
276
|
+
If you are using the jdbc adapter, note that it does not handle separate
|
277
|
+
options such as +:host+, +:user+, and +:port+. If you would like to use
|
278
|
+
the +:servers+ option when connecting to a JDBC database, each hash value in
|
279
|
+
the +servers+ option should contain a +:uri+ key with a JDBC connection string
|
280
|
+
for that shard as the value. Example:
|
281
|
+
|
282
|
+
DB=Sequel.connect('jdbc:postgresql://primary_server/database',
|
283
|
+
servers: {read_only: {uri: 'jdbc:postgresql://replica_server/database'}})
|
284
|
+
|
data/doc/sql.rdoc
CHANGED
@@ -14,7 +14,7 @@ For SELECT queries, you should probably use <tt>Database#fetch</tt> with a strin
|
|
14
14
|
puts row[:name]
|
15
15
|
end
|
16
16
|
|
17
|
-
<tt>Database#fetch</tt> will take the query you give it, execute it on the database, and yield a hash with column symbol keys for each row returned. If you want to use some placeholder variables, you can set the placeholders with ? and add the arguments to fetch
|
17
|
+
<tt>Database#fetch</tt> will take the query you give it, execute it on the database, and yield a hash with column symbol keys for each row returned. If you want to use some placeholder variables, you can set the placeholders with ? and add the corresponding arguments to +fetch+:
|
18
18
|
|
19
19
|
DB.fetch("SELECT * FROM albums WHERE name LIKE ?", 'A%') do |row|
|
20
20
|
puts row[:name]
|
@@ -22,13 +22,13 @@ For SELECT queries, you should probably use <tt>Database#fetch</tt> with a strin
|
|
22
22
|
|
23
23
|
You can also use named placeholders by starting the placeholder with a colon, and using a hash for the argument:
|
24
24
|
|
25
|
-
DB.fetch("SELECT * FROM albums WHERE name LIKE :pattern", :
|
25
|
+
DB.fetch("SELECT * FROM albums WHERE name LIKE :pattern", pattern: 'A%') do |row|
|
26
26
|
puts row[:name]
|
27
27
|
end
|
28
28
|
|
29
|
-
This can be helpful for long queries where it is difficult to match the
|
29
|
+
This can be helpful for long queries where it is difficult to match the question marks in the query with the arguments.
|
30
30
|
|
31
|
-
What Sequel actually does internally is two separate things. It first creates a dataset representing the query, and then it executes the dataset's SQL code to retrieve the objects. Often, you want to define a dataset at some point, but not execute it
|
31
|
+
What Sequel actually does internally is two separate things. It first creates a dataset representing the query, and then it executes the dataset's SQL code to retrieve the objects. Often, you want to define a dataset at some point, but not execute it until later. You can do this by leaving off the block, and storing the dataset in a variable:
|
32
32
|
|
33
33
|
ds = DB.fetch("SELECT * FROM albums")
|
34
34
|
|
@@ -41,7 +41,7 @@ You should note that <tt>Database#[]</tt> calls <tt>Database#fetch</tt> if a str
|
|
41
41
|
ds = DB["SELECT * FROM albums"]
|
42
42
|
ds.each{|r| puts r[:name]}
|
43
43
|
|
44
|
-
However, note that <tt>Database#[]</tt> cannot take a block directly, you have to call +each+ on the returned dataset. There are plenty of other methods besides +each
|
44
|
+
However, note that <tt>Database#[]</tt> cannot take a block directly, you have to call +each+ on the returned dataset. There are plenty of other methods besides +each+. For example, the +all+ method returns all records in the dataset as an array:
|
45
45
|
|
46
46
|
DB["SELECT * FROM albums"].all # [{:id=>1, :name=>'RF', ...}, ...]
|
47
47
|
|
@@ -78,7 +78,7 @@ Almost everywhere in Sequel, you can drop down to literal SQL by providing a lit
|
|
78
78
|
DB[:albums].select('name') # SELECT 'name' FROM albums
|
79
79
|
DB[:albums].select(Sequel.lit('name')) # SELECT name FROM albums
|
80
80
|
|
81
|
-
For a simpler way of creating literal strings, you can also use the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc], which adds the <tt>String#lit</tt> method, and other methods that integrate Sequel's DSL with the
|
81
|
+
For a simpler way of creating literal strings, you can also use the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc], which adds the <tt>String#lit</tt> method, and other methods that integrate Sequel's DSL with the Ruby language:
|
82
82
|
|
83
83
|
DB[:albums].select('name'.lit)
|
84
84
|
|
@@ -113,7 +113,7 @@ Now that you know how to see what SQL is being used, let's jump in and see how t
|
|
113
113
|
|
114
114
|
=== Identifiers
|
115
115
|
|
116
|
-
In Sequel, SQL identifiers are usually specified as
|
116
|
+
In Sequel, SQL identifiers are usually specified as Ruby symbols:
|
117
117
|
|
118
118
|
:column # "column"
|
119
119
|
|
@@ -121,30 +121,33 @@ As you can see, Sequel quotes identifiers by default. Depending on your databas
|
|
121
121
|
|
122
122
|
:column # "COLUMN" on some databases
|
123
123
|
|
124
|
-
A plain symbol is usually treated as an unqualified identifier. However, if you are using multiple tables in a query, and you want to reference a column in one of the tables that has the same name as a column in another one of the tables, you need to qualify that reference.
|
125
|
-
|
126
|
-
:table__column # "table"."column"
|
127
|
-
|
128
|
-
Note that you can't use a period to separate them:
|
124
|
+
A plain symbol is usually treated as an unqualified identifier. However, if you are using multiple tables in a query, and you want to reference a column in one of the tables that has the same name as a column in another one of the tables, you need to qualify that reference. Note that you can't use a period to separate them:
|
129
125
|
|
130
126
|
:table.column # calls the column method on the symbol
|
131
127
|
|
132
128
|
Also note that specifying the period inside the symbol doesn't work if you are quoting identifiers:
|
133
129
|
|
134
|
-
:"table.column" # "table.column"
|
130
|
+
:"table.column" # "table.column" instead of "table"."column"
|
135
131
|
|
136
|
-
The
|
132
|
+
There are a few different Sequel methods for creating qualified identifier objects. The recommended way is to explicitly create a qualified identifier by using <tt>Sequel.[]</tt> to create an identifier and call <tt>[]</tt> or +qualify+ on that, or by using the <tt>Sequel.qualify</tt> method with the table and column symbols:
|
137
133
|
|
134
|
+
Sequel[:table][:column] # "table"."column"
|
135
|
+
Sequel[:column].qualify(:table) # "table"."column"
|
138
136
|
Sequel.qualify(:table, :column) # "table"."column"
|
139
137
|
|
140
138
|
Another way to generate identifiers is to use Sequel's {virtual row support}[rdoc-ref:doc/virtual_rows.rdoc]:
|
141
139
|
|
142
140
|
DB[:albums].select{name} # SELECT "name" FROM "albums"
|
143
|
-
DB[:albums].select{
|
141
|
+
DB[:albums].select{albums[:name]} # SELECT "albums"."name" FROM "albums"
|
142
|
+
|
143
|
+
You can also use the symbol_aref extension for creating qualified identifiers:
|
144
|
+
|
145
|
+
Sequel.extension :symbol_aref
|
146
|
+
:table[:column] # "table"."column"
|
144
147
|
|
145
148
|
=== Numbers
|
146
149
|
|
147
|
-
In general,
|
150
|
+
In general, Ruby numbers map directly to SQL numbers:
|
148
151
|
|
149
152
|
# Integers
|
150
153
|
1 # 1
|
@@ -158,25 +161,24 @@ In general, ruby numbers map directly to SQL numbers:
|
|
158
161
|
|
159
162
|
=== Strings
|
160
163
|
|
161
|
-
In general,
|
164
|
+
In general, Ruby strings map directly to SQL strings:
|
162
165
|
|
163
166
|
'name' # 'name'
|
164
167
|
"name" # 'name'
|
165
168
|
|
166
169
|
=== Aliasing
|
167
170
|
|
168
|
-
|
169
|
-
|
170
|
-
:column___alias # "column" AS "alias"
|
171
|
-
|
172
|
-
You can combine this with implicit qualification:
|
171
|
+
You can use the <tt>Sequel.as</tt> method to create an alias, and the +as+ method on most Sequel-specific expression objects:
|
173
172
|
|
174
|
-
:
|
173
|
+
Sequel.as(:column, :alias) # "column" AS "alias"
|
174
|
+
Sequel[:column].as(:alias) # "column" AS "alias"
|
175
|
+
Sequel[:table][:column].as(:alias) # "table"."column" AS "alias"
|
176
|
+
(Sequel[:column] + 1).as(:alias) # ("column" + 1) AS "alias"
|
175
177
|
|
176
|
-
You can also use the
|
178
|
+
You can also use the symbol_as extension for creating aliased identifiers:
|
177
179
|
|
178
|
-
Sequel.
|
179
|
-
|
180
|
+
Sequel.extension :symbol_as
|
181
|
+
:column.as(:alias) # "column" AS "alias"
|
180
182
|
|
181
183
|
If you want to use a derived column list, you can provide an array of column aliases:
|
182
184
|
|
@@ -200,11 +202,11 @@ Aggregate functions work the same way as normal functions, since they share the
|
|
200
202
|
|
201
203
|
Sequel.function(:sum, :column) # sum(column)
|
202
204
|
|
203
|
-
To use the DISTINCT modifier to an aggregate function, call the distinct method on the function:
|
205
|
+
To use the DISTINCT modifier to an aggregate function, call the +distinct+ method on the function expression, which returns a new function expression:
|
204
206
|
|
205
207
|
DB[:albums].select{sum(:column).distinct} # SELECT sum(DISTINCT column) FROM albums
|
206
208
|
|
207
|
-
If you want to use the wildcard as the sole argument of the aggregate function, use the * method on the
|
209
|
+
If you want to use the wildcard as the sole argument of the aggregate function, use the * method on the function expression:
|
208
210
|
|
209
211
|
Sequel.function(:count).* # count(*)
|
210
212
|
DB[:albums].select{count.function.*} # SELECT count(*) FROM albums
|
@@ -213,10 +215,10 @@ Note that Sequel provides helper methods for aggregate functions such as +count+
|
|
213
215
|
|
214
216
|
=== Window Functions
|
215
217
|
|
216
|
-
If the database supports window functions, Sequel can handle them by calling the over method on a
|
218
|
+
If the database supports window functions, Sequel can handle them by calling the +over+ method on a function expression:
|
217
219
|
|
218
|
-
DB[:albums].select{
|
219
|
-
# SELECT
|
220
|
+
DB[:albums].select{row_number.function.over}
|
221
|
+
# SELECT row_number() OVER () FROM albums
|
220
222
|
|
221
223
|
DB[:albums].select{count.function.*.over}
|
222
224
|
# SELECT count(*) OVER () FROM albums
|
@@ -224,17 +226,29 @@ If the database supports window functions, Sequel can handle them by calling the
|
|
224
226
|
DB[:albums].select{function(:col1).over(:partition=>col2, :order=>col3)}
|
225
227
|
# SELECT function(col1) OVER (PARTITION BY col2 ORDER BY col3) FROM albums
|
226
228
|
|
227
|
-
DB[:albums].select{function(c1, c2).over(:partition=>[c3, c4], :order=>[c5, c6])}
|
228
|
-
# SELECT function(c1, c2) OVER (PARTITION BY c3, c4 ORDER BY c5, c6) FROM albums
|
229
|
+
DB[:albums].select{function(c1, c2).over(:partition=>[c3, c4], :order=>[c5, c6.desc])}
|
230
|
+
# SELECT function(c1, c2) OVER (PARTITION BY c3, c4 ORDER BY c5, c6 DESC) FROM albums
|
231
|
+
|
232
|
+
DB[:albums].select{function(c1).over(:partition=>c2, :order=>:c3, :frame=>:rows)}
|
233
|
+
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM albums
|
234
|
+
|
235
|
+
DB[:albums].select{function(c1).over(:partition=>c2, :order=>:c3, :frame=>{:type=>:range, :start=>1, :end=>1})}
|
236
|
+
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) FROM albums
|
237
|
+
|
238
|
+
DB[:albums].select{function(c1).over(:partition=>c2, :order=>:c3, :frame=>{:type=>:groups, :start=>[2, :preceding], :end=>[1, :preceding]})}
|
239
|
+
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) FROM albums
|
240
|
+
|
241
|
+
DB[:albums].select{function(c1).over(:partition=>c2, :order=>:c3, :frame=>{:type=>:range, :start=>:preceding, :exclude=>:current})}
|
242
|
+
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 RANGE UNBOUNDED PRECEDING EXCLUDE CURRENT ROW) FROM albums
|
229
243
|
|
230
244
|
=== Schema Qualified Functions
|
231
245
|
|
232
|
-
If the database supports schema qualified functions, Sequel can handle them by calling the function method on a
|
246
|
+
If the database supports schema qualified functions, Sequel can handle them by calling the +function+ method on a qualified identifier:
|
233
247
|
|
234
|
-
DB[:albums].select{
|
248
|
+
DB[:albums].select{schema[:function].function}
|
235
249
|
# SELECT schema.function() FROM albums
|
236
250
|
|
237
|
-
DB[:albums].select{
|
251
|
+
DB[:albums].select{schema[:function].function(:col, 2, "a")}
|
238
252
|
# SELECT schema.function(col, 2, 'a') FROM albums
|
239
253
|
|
240
254
|
=== Portable/Emulated Functions
|
@@ -250,7 +264,7 @@ Some examples are:
|
|
250
264
|
|
251
265
|
Sequel uses hashes to specify equality:
|
252
266
|
|
253
|
-
{:
|
267
|
+
{column: 1} # ("column" = 1)
|
254
268
|
|
255
269
|
You can also specify this as an array of two element arrays:
|
256
270
|
|
@@ -264,27 +278,27 @@ For expression objects, you can also use the =~ method:
|
|
264
278
|
|
265
279
|
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>:
|
266
280
|
|
267
|
-
Sequel.negate(:
|
281
|
+
Sequel.negate(column: 1) # ("column" != 1)
|
268
282
|
Sequel.negate([[:column, 1]]) # ("column" != 1)
|
269
|
-
Sequel.~(:
|
283
|
+
Sequel.~(column: 1) # ("column" != 1)
|
270
284
|
Sequel.~([[:column, 1]]) # ("column" != 1)
|
271
285
|
|
272
|
-
The difference between the two is that negate only works on hashes and arrays of element arrays, and it negates all entries in the hash or array, while ~ does a general inversion. This is best shown by an example with multiple entries:
|
286
|
+
The difference between the two is that +negate+ only works on hashes and arrays of element arrays, and it negates all entries in the hash or array, while ~ does a general inversion. This is best shown by an example with multiple entries:
|
273
287
|
|
274
|
-
Sequel.negate(:
|
275
|
-
Sequel.~(:
|
288
|
+
Sequel.negate(column: 1, foo: 2) # (("column" != 1) AND (foo != 2))
|
289
|
+
Sequel.~(column: 1, foo: 2) # (("column" != 1) OR (foo != 2))
|
276
290
|
|
277
291
|
You can also use the ~ method on an equality expression:
|
278
292
|
|
279
293
|
where{~(column =~ 1)} # ("column" != 1)
|
280
294
|
|
281
|
-
|
295
|
+
Or you can use the !~ method:
|
282
296
|
|
283
297
|
where{column !~ 1} # ("column" != 1)
|
284
298
|
|
285
299
|
The most common need for not equals is in filters, in which case you can use the +exclude+ method:
|
286
300
|
|
287
|
-
DB[:albums].exclude(:
|
301
|
+
DB[:albums].exclude(column: 1) # SELECT * FROM "albums" WHERE ("column" != 1)
|
288
302
|
|
289
303
|
Note that +exclude+ does a generalized inversion, similar to <tt>Sequel.~</tt>.
|
290
304
|
|
@@ -292,19 +306,19 @@ Note that +exclude+ does a generalized inversion, similar to <tt>Sequel.~</tt>.
|
|
292
306
|
|
293
307
|
Sequel also uses hashes to specify inclusion, and inversions of those hashes to specify exclusion:
|
294
308
|
|
295
|
-
{:
|
296
|
-
Sequel.~(:
|
309
|
+
{column: [1, 2, 3]} # ("column" IN (1, 2, 3))
|
310
|
+
Sequel.~(column: [1, 2, 3]) # ("column" NOT IN (1, 2, 3))
|
297
311
|
|
298
312
|
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:
|
299
313
|
|
300
|
-
{:
|
301
|
-
Sequel.~(:
|
314
|
+
{column: DB[:albums].select(:id)} # ("column" IN (SELECT "id" FROM "albums"))
|
315
|
+
Sequel.~(column: DB[:albums].select(:id)) # ("column" NOT IN (SELECT "id" FROM "albums"))
|
302
316
|
|
303
317
|
Similar to =, you can also use =~ with expressions for inclusion:
|
304
318
|
|
305
319
|
where{column =~ [1, 2, 3]} # ("column" IN (1, 2, 3))
|
306
320
|
|
307
|
-
and
|
321
|
+
and !~ for exclusion:
|
308
322
|
|
309
323
|
where{column !~ [1, 2, 3]} # ("column" NOT IN (1, 2, 3))
|
310
324
|
|
@@ -314,19 +328,19 @@ Sequel also supports the SQL EXISTS operator using <tt>Dataset#exists</tt>:
|
|
314
328
|
|
315
329
|
=== Identity Operators (IS, IS NOT)
|
316
330
|
|
317
|
-
Hashes in Sequel use IS if the value is true
|
331
|
+
Hashes in Sequel use IS if the value is +true+, +false+, or +nil+:
|
318
332
|
|
319
|
-
{:
|
320
|
-
{:
|
321
|
-
{:
|
333
|
+
{column: nil} # ("column" IS NULL)
|
334
|
+
{column: true} # ("column" IS TRUE)
|
335
|
+
{column: false} # ("column" IS FALSE)
|
322
336
|
|
323
337
|
Negation works the same way as it does for equality and inclusion:
|
324
338
|
|
325
|
-
Sequel.~(:
|
326
|
-
Sequel.~(:
|
327
|
-
Sequel.~(:
|
339
|
+
Sequel.~(column: nil) # ("column" IS NOT NULL)
|
340
|
+
Sequel.~(column: true) # ("column" IS NOT TRUE)
|
341
|
+
Sequel.~(column: false) # ("column" IS NOT FALSE)
|
328
342
|
|
329
|
-
Likewise, =~ works for identity
|
343
|
+
Likewise, =~ works for identity and !~ for negative identity on expressions:
|
330
344
|
|
331
345
|
where{column =~ nil} # ("column" IS NULL)
|
332
346
|
where{column !~ nil} # ("column" IS NOT NULL)
|
@@ -339,7 +353,7 @@ Sequel's general inversion operator is ~, which works on symbols and most Sequel
|
|
339
353
|
|
340
354
|
Note that ~ will actually apply the inversion operation to the underlying object, which is why
|
341
355
|
|
342
|
-
Sequel.~(:
|
356
|
+
Sequel.~(column: 1)
|
343
357
|
|
344
358
|
produces <tt>(column != 1)</tt> instead of <tt>NOT (column = 1)</tt>.
|
345
359
|
|
@@ -347,14 +361,14 @@ produces <tt>(column != 1)</tt> instead of <tt>NOT (column = 1)</tt>.
|
|
347
361
|
|
348
362
|
Sequel defines the inequality operators directly on most Sequel-specific expression objects:
|
349
363
|
|
350
|
-
Sequel
|
351
|
-
Sequel
|
364
|
+
Sequel[:table][:column] > 1 # ("table"."column" > 1)
|
365
|
+
Sequel[:table][:column] < 1 # ("table"."column" < 1)
|
352
366
|
Sequel.function(:func) >= 1 # (func() >= 1)
|
353
367
|
Sequel.function(:func, :column) <= 1 # (func("column") <= 1)
|
354
368
|
|
355
|
-
If you want to use them on a symbol, you should call <tt>Sequel.
|
369
|
+
If you want to use them on a symbol, you should call <tt>Sequel.[]</tt> with the symbol to get an expression object:
|
356
370
|
|
357
|
-
Sequel
|
371
|
+
Sequel[:column] > 1 # ("column" > 1)
|
358
372
|
|
359
373
|
A common use of virtual rows is to handle inequality operators:
|
360
374
|
|
@@ -364,33 +378,31 @@ A common use of virtual rows is to handle inequality operators:
|
|
364
378
|
|
365
379
|
The standard mathematical operates are defined on most Sequel-specific expression objects:
|
366
380
|
|
367
|
-
Sequel
|
368
|
-
Sequel
|
369
|
-
Sequel
|
370
|
-
Sequel
|
381
|
+
Sequel[:column] + 1 # "column" + 1
|
382
|
+
Sequel[:table][:column] - 1 # "table"."column" - 1
|
383
|
+
Sequel[:table][:column] * 1 # "table"."column" * 1
|
384
|
+
Sequel[:column] / 1 # "column" / 1
|
385
|
+
Sequel[:column] ** 1 # power("column", 1)
|
371
386
|
|
372
387
|
You can also call the operator methods directly on the Sequel module:
|
373
388
|
|
374
389
|
Sequel.+(:column, 1) # "column" + 1
|
375
|
-
Sequel.-(:
|
376
|
-
Sequel.*(Sequel
|
390
|
+
Sequel.-(Sequel[:table][:column], 1) # "table"."column" - 1
|
391
|
+
Sequel.*(Sequel[:table][:column], 1) # "table"."column" * 1
|
377
392
|
Sequel./(:column, 1) # "column" / 1
|
393
|
+
Sequel.**(:column, 1) # power("column", 1)
|
378
394
|
|
379
|
-
Note that the following
|
380
|
-
|
381
|
-
1 + Sequel.expr(:column) # raises TypeError
|
382
|
-
|
383
|
-
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:
|
395
|
+
Note that since Sequel implements support for Ruby's coercion protocol, the following also works:
|
384
396
|
|
385
|
-
|
386
|
-
|
397
|
+
1 + Sequel[:column]
|
398
|
+
1 - Sequel[:table][:column]
|
387
399
|
|
388
400
|
=== Boolean Operators (AND OR)
|
389
401
|
|
390
402
|
Sequel defines the & and | methods on most Sequel-specific expression objects to handle AND and OR:
|
391
403
|
|
392
|
-
Sequel
|
393
|
-
Sequel
|
404
|
+
Sequel[:column1] & :column2 # ("column1" AND "column2")
|
405
|
+
Sequel[{column1: 1}] | {column2: 2} # (("column1" = 1) OR ("column2" = 2))
|
394
406
|
(Sequel.function(:func) > 1) & :column3 # ((func() > 1) AND "column3")
|
395
407
|
|
396
408
|
Note the use of parentheses in the last statement. If you omit them, you won't get what you expect.
|
@@ -402,39 +414,39 @@ is parsed as:
|
|
402
414
|
|
403
415
|
Sequel.function(:func) > (1 & :column3)
|
404
416
|
|
405
|
-
You
|
417
|
+
You can also use the <tt>Sequel.&</tt> and <tt>Sequel.|</tt> methods:
|
406
418
|
|
407
419
|
Sequel.&(:column1, :column2) # ("column1" AND "column2")
|
408
|
-
Sequel.|({:
|
420
|
+
Sequel.|({column1: 1}, {column2: 2}) # (("column1" = 1) OR ("column2" = 2))
|
409
421
|
|
410
422
|
You can use hashes and arrays of two element arrays to specify AND and OR with equality conditions:
|
411
423
|
|
412
|
-
{:
|
424
|
+
{column1: 1, column2: 2} # (("column1" = 1) AND ("column2" = 2))
|
413
425
|
[[:column1, 1], [:column2, 2]] # (("column1" = 1) AND ("column2" = 2))
|
414
426
|
|
415
427
|
As you can see, these literalize with ANDs by default. You can use the <tt>Sequel.or</tt> method to use OR instead:
|
416
428
|
|
417
|
-
Sequel.or(:
|
429
|
+
Sequel.or(column1: 1, column2: 2) # (("column1" = 1) OR ("column2" = 2))
|
418
430
|
|
419
431
|
You've already seen the <tt>Sequel.negate</tt> method, which will use ANDs if multiple entries are used:
|
420
432
|
|
421
|
-
Sequel.negate(:
|
433
|
+
Sequel.negate(column1: 1, column2: 2) # (("column1" != 1) AND ("column2" != 2))
|
422
434
|
|
423
435
|
To negate while using ORs, the <tt>Sequel.~</tt> operator can be used:
|
424
436
|
|
425
|
-
Sequel.~(:
|
437
|
+
Sequel.~(column1: 1, column2: 2) # (("column1" != 1) OR ("column2" != 2))
|
426
438
|
|
427
439
|
Note again that <tt>Dataset#exclude</tt> uses ~, not +negate+:
|
428
440
|
|
429
|
-
DB[:albums].exclude(:
|
441
|
+
DB[:albums].exclude(column1: 1, column2: 2) # SELECT * FROM "albums" WHERE (("column" != 1) OR ("column2" != 2))
|
430
442
|
|
431
443
|
=== Casts
|
432
444
|
|
433
445
|
Casting in Sequel is done with the +cast+ method, which is available on most of the Sequel-specific expression objects:
|
434
446
|
|
435
|
-
Sequel
|
436
|
-
Sequel
|
437
|
-
Sequel
|
447
|
+
Sequel[:name].cast(:text) # CAST("name" AS text)
|
448
|
+
Sequel['1'].cast(:integer) # CAST('1' AS integer)
|
449
|
+
Sequel[:table][:column].cast(:date) # CAST("table"."column" AS date)
|
438
450
|
|
439
451
|
You can also use the <tt>Sequel.cast</tt> method:
|
440
452
|
|
@@ -444,72 +456,72 @@ You can also use the <tt>Sequel.cast</tt> method:
|
|
444
456
|
|
445
457
|
Sequel allows the use of bitwise mathematical operators on Sequel::SQL::NumericExpression objects:
|
446
458
|
|
447
|
-
Sequel
|
448
|
-
(Sequel
|
459
|
+
Sequel[:number] + 1 # => #<Sequel::SQL::NumericExpression ...>
|
460
|
+
(Sequel[:number] + 1) & 5 # (("number" + 1) & 5)
|
449
461
|
|
450
462
|
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+:
|
451
463
|
|
452
|
-
Sequel
|
464
|
+
Sequel[:number].sql_number | 5 # ("number" | 5)
|
453
465
|
Sequel.function(:func).sql_number << 7 # (func() << 7)
|
454
466
|
Sequel.cast(:name, :integer).sql_number >> 8 # (CAST("name" AS integer) >> 8)
|
455
467
|
|
456
468
|
Sequel allows you to do the cast and conversion at the same time via +cast_numeric+:
|
457
469
|
|
458
|
-
Sequel
|
470
|
+
Sequel[:name].cast_numeric ^ 9 # (CAST("name" AS integer) ^ 9)
|
459
471
|
|
460
472
|
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:
|
461
473
|
|
462
|
-
~Sequel
|
463
|
-
~Sequel
|
474
|
+
~Sequel[:name] # NOT "name"
|
475
|
+
~Sequel[:name].sql_number # ~"name"
|
464
476
|
|
465
477
|
=== String Operators (||, LIKE, Regexp)
|
466
478
|
|
467
479
|
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:
|
468
480
|
|
469
|
-
Sequel
|
481
|
+
Sequel[:name].sql_string + ' - Name' # ("name" || ' - Name')
|
470
482
|
|
471
|
-
Just like for the bitwise operators, Sequel allows you
|
483
|
+
Just like for the bitwise operators, Sequel allows you to do the cast and conversion at the same time via +cast_string+:
|
472
484
|
|
473
|
-
Sequel
|
485
|
+
Sequel[:number].cast_string + ' - Number' # (CAST(number AS varchar(255)) || ' - Number')
|
474
486
|
|
475
487
|
Note that similar to the mathematical operators, you cannot switch the order the expression and have it work:
|
476
488
|
|
477
|
-
'Name - ' + Sequel
|
489
|
+
'Name - ' + Sequel[:name].sql_string # raises TypeError
|
478
490
|
|
479
|
-
Just like for the mathematical operators, you can use <tt>Sequel.
|
491
|
+
Just like for the mathematical operators, you can use <tt>Sequel.[]</tt> to wrap the object:
|
480
492
|
|
481
|
-
Sequel
|
493
|
+
Sequel['Name - '] + :name # ('Name - ' || "name")
|
482
494
|
|
483
495
|
The <tt>Sequel.join</tt> method concatenates all of the elements in the array:
|
484
496
|
|
485
497
|
Sequel.join(['Name', :name]) # ('Name' || "name")
|
486
498
|
|
487
|
-
Just like
|
499
|
+
Just like Ruby's <tt>String#join</tt>, you can provide an argument for a string used to join each element:
|
488
500
|
|
489
501
|
Sequel.join(['Name', :name], ' - ') # ('Name' || ' - ' || "name")
|
490
502
|
|
491
503
|
For the LIKE operator, Sequel defines the +like+ and +ilike+ methods on most Sequel-specific expression objects:
|
492
504
|
|
493
|
-
Sequel
|
494
|
-
Sequel
|
505
|
+
Sequel[:name].like('A%') # ("name" LIKE 'A%' ESCAPE '\')
|
506
|
+
Sequel[:name].ilike('A%') # ("name" ILIKE 'A%' ESCAPE '\')
|
495
507
|
|
496
508
|
You can also use the <tt>Sequel.like</tt> and <tt>Sequel.ilike</tt> methods:
|
497
509
|
|
498
510
|
Sequel.like(:name, 'A%') # ("name" LIKE 'A%' ESCAPE '\')
|
499
511
|
Sequel.ilike(:name, 'A%') # ("name" ILIKE 'A%' ESCAPE '\')
|
500
512
|
|
501
|
-
Note the above syntax for ilike
|
513
|
+
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.
|
502
514
|
|
503
515
|
Inverting the LIKE operator works like other inversions:
|
504
516
|
|
505
517
|
~Sequel.like(:name, 'A%') # ("name" NOT LIKE 'A%' ESCAPE '\')
|
506
518
|
|
507
|
-
Sequel also supports SQL regular expressions on MySQL and PostgreSQL. You can use these by passing a
|
519
|
+
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:
|
508
520
|
|
509
521
|
Sequel.like(:name, /^A/) # ("name" ~ '^A')
|
510
522
|
~Sequel.ilike(:name, /^A/) # ("name" !~* '^A')
|
511
|
-
{:
|
512
|
-
Sequel.~(:
|
523
|
+
{name: /^A/i} # ("name" ~* '^A')
|
524
|
+
Sequel.~(name: /^A/) # ("name" !~ '^A')
|
513
525
|
|
514
526
|
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.
|
515
527
|
|
@@ -517,36 +529,37 @@ Note that using +ilike+ with a regular expression will always make the regexp ca
|
|
517
529
|
|
518
530
|
Sequel supports specifying ascending or descending order using the +asc+ and +desc+ method on most Sequel-specific expression objects:
|
519
531
|
|
520
|
-
Sequel
|
521
|
-
Sequel
|
532
|
+
Sequel[:column].asc # "column" ASC
|
533
|
+
Sequel[:table][:column].desc # "table"."column" DESC
|
522
534
|
|
523
535
|
You can also use the <tt>Sequel.asc</tt> and <tt>Sequel.desc</tt> methods:
|
524
536
|
|
525
537
|
Sequel.asc(:column) # "column" ASC
|
526
|
-
Sequel.desc(Sequel
|
538
|
+
Sequel.desc(Sequel[:table][:column]) # "table"."column" DESC
|
527
539
|
|
528
540
|
On some databases, you can specify null ordering:
|
529
541
|
|
530
542
|
Sequel.asc(:column, :nulls=>:first) # "column" ASC NULLS FIRST
|
531
|
-
Sequel.desc(Sequel
|
543
|
+
Sequel.desc(Sequel[:table][:column], :nulls=>:last) # "table"."column" DESC NULLS LAST
|
532
544
|
|
533
545
|
=== All Columns (.*)
|
534
546
|
|
535
|
-
To select all columns in a table, Sequel supports the * method on identifiers without an argument:
|
547
|
+
To select all columns in a table, Sequel supports the * method on identifiers and qualified without an argument:
|
536
548
|
|
537
|
-
Sequel
|
549
|
+
Sequel[:table].* # "table".*
|
550
|
+
Sequel[:schema][:table].* # "schema"."table".*
|
538
551
|
|
539
552
|
=== CASE statements
|
540
553
|
|
541
|
-
Sequel
|
554
|
+
Sequel supports 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:
|
542
555
|
|
543
|
-
Sequel.case({:
|
544
|
-
Sequel.case([[column, 1]], 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
|
545
|
-
Sequel.case({{:
|
556
|
+
Sequel.case({column: 1}, 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
|
557
|
+
Sequel.case([[:column, 1]], 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
|
558
|
+
Sequel.case({{column: nil}=>1}, 0) # (CASE WHEN (column IS NULL) THEN 1 ELSE 0 END)
|
546
559
|
|
547
560
|
If the hash or array has multiple arguments, multiple WHEN clauses are used:
|
548
561
|
|
549
|
-
Sequel.case({:
|
562
|
+
Sequel.case({c: 1, d: 2}, 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
|
550
563
|
Sequel.case([[:c, 1], [:d, 2]], 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
|
551
564
|
|
552
565
|
If you provide a 3rd argument to <tt>Sequel.case</tt>, it goes between CASE and WHEN:
|
@@ -557,8 +570,8 @@ If you provide a 3rd argument to <tt>Sequel.case</tt>, it goes between CASE and
|
|
557
570
|
|
558
571
|
Sequel supports SQL subscripts using the +sql_subscript+ method on most Sequel-specific expression objects:
|
559
572
|
|
560
|
-
Sequel
|
561
|
-
Sequel
|
573
|
+
Sequel[:column].sql_subscript(3) # column[3]
|
574
|
+
Sequel[:table][:column].sql_subscript(3) # table.column[3]
|
562
575
|
|
563
576
|
You can also use the <tt>Sequel.subscript</tt> method:
|
564
577
|
|
@@ -574,7 +587,7 @@ In Sequel, the SQL queries are build with method chaining.
|
|
574
587
|
|
575
588
|
=== Creating Datasets
|
576
589
|
|
577
|
-
You generally start
|
590
|
+
You generally start creating a dataset by calling <tt>Dataset#[]</tt> with a symbol specifying the table name:
|
578
591
|
|
579
592
|
DB[:albums] # SELECT * FROM albums
|
580
593
|
|
@@ -582,7 +595,7 @@ If you want to select from multiple FROM tables, use multiple arguments:
|
|
582
595
|
|
583
596
|
DB[:albums, :artists] # SELECT * FROM albums, artists
|
584
597
|
|
585
|
-
If you don't want to select from any FROM tables, just call dataset
|
598
|
+
If you don't want to select from any FROM tables, just call +dataset+:
|
586
599
|
|
587
600
|
DB.dataset # SELECT *
|
588
601
|
|
@@ -616,7 +629,7 @@ In general, the +insert+, +update+, and +delete+ methods use the appropriate cla
|
|
616
629
|
ds.update(:name=>'RF') # UPDATE albums SET name = 'RF' WHERE (id = 1)
|
617
630
|
ds.delete # DELETE FROM albums WHERE (id = 1)
|
618
631
|
|
619
|
-
Note how +update+ and +delete+ used the +where+ argument, but
|
632
|
+
Note how +update+ and +delete+ used the +where+ argument, but +insert+ did not, because INSERT doesn't use a WHERE clause.
|
620
633
|
|
621
634
|
=== Methods Used for Each SQL Clause
|
622
635
|
|