sequel 4.26.0 → 5.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|
@@ -7,14 +7,14 @@ the following adapters:
|
|
|
7
7
|
|
|
8
8
|
* ibmdb (prepared statements only)
|
|
9
9
|
* jdbc
|
|
10
|
-
* mysql (prepared statements
|
|
11
|
-
* mysql2 (prepared statements
|
|
10
|
+
* mysql (server prepared statements using literalized connection variables)
|
|
11
|
+
* mysql2 (full support on 0.4+, otherwise server prepared statements using literalized connection variables)
|
|
12
12
|
* oracle (requires type specifiers for nil/NULL values)
|
|
13
13
|
* postgres (when using the pg driver)
|
|
14
14
|
* sqlite
|
|
15
15
|
* tinytds
|
|
16
16
|
|
|
17
|
-
Support on other adapters is emulated
|
|
17
|
+
Support on other adapters is emulated.
|
|
18
18
|
|
|
19
19
|
You can use the prepared_statements model plugin to automatically use prepared
|
|
20
20
|
statements for some common model actions such as saving or deleting a model
|
|
@@ -29,7 +29,7 @@ significantly for placeholders (e.g. :name, $1, ?). Sequel abstracts all of
|
|
|
29
29
|
that and allows you to specify placeholders by using the :$name format for
|
|
30
30
|
placeholders, e.g.:
|
|
31
31
|
|
|
32
|
-
ds = DB[:items].where(:
|
|
32
|
+
ds = DB[:items].where(name: :$n)
|
|
33
33
|
|
|
34
34
|
You can use these placeholders in most places where you can use the value
|
|
35
35
|
directly. For example, if you want to use placeholders while also using
|
|
@@ -41,45 +41,49 @@ raw SQL, you can do:
|
|
|
41
41
|
|
|
42
42
|
Using bound variables for this query is simple:
|
|
43
43
|
|
|
44
|
-
ds.call(:select, :
|
|
44
|
+
ds.call(:select, n: 'Jim')
|
|
45
45
|
|
|
46
46
|
This will do the equivalent of selecting records that have the name 'Jim'. It
|
|
47
47
|
returns all records, and can take a block that is passed to <tt>Dataset#all</tt>.
|
|
48
48
|
|
|
49
49
|
Deleting or returning the first record works similarly:
|
|
50
50
|
|
|
51
|
-
ds.call(:first, :
|
|
52
|
-
ds.call(:delete, :
|
|
51
|
+
ds.call(:first, n: 'Jim') # First record with name 'Jim'
|
|
52
|
+
ds.call(:delete, n: 'Jim') # Delete records with name 'Jim'
|
|
53
53
|
|
|
54
54
|
For inserting/updating records, you should also specify a value hash, which
|
|
55
55
|
may itself contain placeholders:
|
|
56
56
|
|
|
57
57
|
# Insert record with 'Jim', note that the previous filter is ignored
|
|
58
|
-
ds.call(:insert, {:
|
|
58
|
+
ds.call(:insert, {n: 'Jim'}, name: :$n)
|
|
59
59
|
# Change name to 'Bob' for all records with name of 'Jim'
|
|
60
|
-
ds.call(:update, {:
|
|
60
|
+
ds.call(:update, {n: 'Jim', new_n: 'Bob'}, name: :$new_n)
|
|
61
61
|
|
|
62
62
|
== Prepared Statements
|
|
63
63
|
|
|
64
64
|
Prepared statement support is similar to bound variable support, but you
|
|
65
65
|
use <tt>Dataset#prepare</tt> with a name, and <tt>Dataset#call</tt> or <tt>Database#call</tt> later with the values:
|
|
66
66
|
|
|
67
|
-
ds = DB[:items].
|
|
67
|
+
ds = DB[:items].where(name: :$n)
|
|
68
68
|
ps = ds.prepare(:select, :select_by_name)
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
|
|
70
|
+
ps.call(n: 'Jim')
|
|
71
|
+
DB.call(:select_by_name, n: 'Jim') # same
|
|
71
72
|
|
|
72
73
|
The <tt>Dataset#prepare</tt> method returns a prepared statement, and also stores a
|
|
73
74
|
copy of the prepared statement in the database for later use. For insert
|
|
74
75
|
and update queries, the hash to insert/update is passed to +prepare+:
|
|
75
76
|
|
|
76
|
-
ps1 = DB[:items].prepare(:insert, :insert_with_name, :
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
ps1 = DB[:items].prepare(:insert, :insert_with_name, name: :$n)
|
|
78
|
+
|
|
79
|
+
ps1.call(n: 'Jim')
|
|
80
|
+
DB.call(:insert_with_name, n: 'Jim') # same
|
|
81
|
+
|
|
82
|
+
ds = DB[:items].where(name: :$n)
|
|
83
|
+
ps2 = ds.prepare(:update, :update_name, name: :$new_n)
|
|
84
|
+
|
|
85
|
+
ps2.call(n: 'Jim', new_n: 'Bob')
|
|
86
|
+
DB.call(:update_name, n: 'Jim', new_n: 'Bob') # same
|
|
83
87
|
|
|
84
88
|
== Implementation Issues
|
|
85
89
|
|
|
@@ -92,7 +96,7 @@ to create prepared statements dynamically at runtime.
|
|
|
92
96
|
|
|
93
97
|
=== PostgreSQL
|
|
94
98
|
|
|
95
|
-
If you are using the
|
|
99
|
+
If you are using the postgres-pr driver, PostgreSQL uses the
|
|
96
100
|
default emulated support. If you are using ruby-pg, there is native support
|
|
97
101
|
for both prepared statements and bound variables. Prepared statements are
|
|
98
102
|
always server side.
|
|
@@ -103,9 +107,10 @@ SQLite supports both prepared statements and bound variables.
|
|
|
103
107
|
|
|
104
108
|
=== MySQL/Mysql2
|
|
105
109
|
|
|
106
|
-
The MySQL
|
|
107
|
-
variable methods
|
|
108
|
-
|
|
110
|
+
The MySQL and Mysql2 <0.4 ruby drivers do not support bound variables, so the bound
|
|
111
|
+
variable methods are emulated. It uses server side prepared statements.
|
|
112
|
+
|
|
113
|
+
Mysql2 0.4+ supports both prepared statements and bound variables.
|
|
109
114
|
|
|
110
115
|
=== JDBC
|
|
111
116
|
|
|
@@ -136,4 +141,4 @@ not currently supported.
|
|
|
136
141
|
|
|
137
142
|
=== All Others
|
|
138
143
|
|
|
139
|
-
Support is emulated
|
|
144
|
+
Support is emulated.
|
data/doc/querying.rdoc
CHANGED
|
@@ -4,15 +4,15 @@ This guide is based on http://guides.rubyonrails.org/active_record_querying.html
|
|
|
4
4
|
|
|
5
5
|
== Purpose of this Guide
|
|
6
6
|
|
|
7
|
-
Sequel is a
|
|
7
|
+
Sequel is a flexible and powerful database library
|
|
8
8
|
that supports a wide variety of different querying methods. This guide
|
|
9
|
-
aims to be a
|
|
9
|
+
aims to be a introduction to Sequel's querying support.
|
|
10
10
|
|
|
11
|
-
While you can
|
|
11
|
+
While you can use raw SQL with Sequel, a large part of the
|
|
12
12
|
advantage you get from using Sequel is Sequel's ability to abstract
|
|
13
|
-
SQL from you and give you a
|
|
13
|
+
SQL from you and give you a pure-ruby interface. Sequel also ships with
|
|
14
14
|
a {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
|
15
|
-
which
|
|
15
|
+
which adds methods to core ruby types to work with Sequel.
|
|
16
16
|
|
|
17
17
|
== Retrieving Objects
|
|
18
18
|
|
|
@@ -39,7 +39,7 @@ by its primary key value:
|
|
|
39
39
|
|
|
40
40
|
# Find artist with primary key (id) 1
|
|
41
41
|
artist = Artist[1]
|
|
42
|
-
# SELECT * FROM artists WHERE id = 1
|
|
42
|
+
# SELECT * FROM artists WHERE (id = 1)
|
|
43
43
|
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
44
44
|
|
|
45
45
|
If there is no record with the given primary key, nil will be returned. If you want
|
|
@@ -49,7 +49,7 @@ to raise an exception if no record is found, you can use <tt>Sequel::Model.with_
|
|
|
49
49
|
|
|
50
50
|
==== Using +first+
|
|
51
51
|
|
|
52
|
-
If you
|
|
52
|
+
If you want the first record in the dataset,
|
|
53
53
|
<tt>Sequel::Dataset#first</tt> is probably the most obvious method to use:
|
|
54
54
|
|
|
55
55
|
artist = Artist.first
|
|
@@ -58,7 +58,7 @@ If you just want the first record in the dataset,
|
|
|
58
58
|
|
|
59
59
|
Any options you pass to +first+ will be used as a filter:
|
|
60
60
|
|
|
61
|
-
artist = Artist.first(:
|
|
61
|
+
artist = Artist.first(name: 'YJM')
|
|
62
62
|
# SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
|
|
63
63
|
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
64
64
|
|
|
@@ -72,7 +72,7 @@ raise an exception instead, use <tt>first!</tt>.
|
|
|
72
72
|
<tt>Sequel::Dataset#[]</tt> is basically an alias for +first+, except it
|
|
73
73
|
requires an argument:
|
|
74
74
|
|
|
75
|
-
DB[:artists][:
|
|
75
|
+
DB[:artists][{name: 'YJM'}]
|
|
76
76
|
# SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
|
|
77
77
|
# => {:name=>"YJM", :id=>1}
|
|
78
78
|
|
|
@@ -82,22 +82,19 @@ Dataset#[] does not (unless it is a model dataset).
|
|
|
82
82
|
==== Using +last+
|
|
83
83
|
|
|
84
84
|
If you want the last record in the dataset,
|
|
85
|
-
<tt>Sequel::Dataset#last</tt> is an obvious method to use.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
reverse order by the primary key field:
|
|
85
|
+
<tt>Sequel::Dataset#last</tt> is an obvious method to use. +last+ requires the
|
|
86
|
+
dataset be ordered, unless the dataset is a model dataset in which case +last+
|
|
87
|
+
will do a reverse order by the primary key field:
|
|
89
88
|
|
|
90
89
|
artist = Artist.last
|
|
91
90
|
# SELECT * FROM artists ORDER BY id DESC LIMIT 1
|
|
92
91
|
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
93
92
|
|
|
94
|
-
Note
|
|
95
|
-
call +first+. This is why +last+ raises a Sequel::Error if there is no
|
|
96
|
-
order on a plain dataset, because otherwise it would provide the same record
|
|
97
|
-
as +first+, and most users would find that confusing.
|
|
93
|
+
Note:
|
|
98
94
|
|
|
99
|
-
|
|
100
|
-
in the dataset unless you give the dataset an unambiguous order.
|
|
95
|
+
1. +last+ is equivalent to running a +reverse.first+ query, in other words it reverses the order of the dataset and then calls +first+. This is why +last+ raises a Sequel::Error when there is no order on a plain dataset - because it will provide the same record as +first+, and most users will find that confusing.
|
|
96
|
+
2. +last+ is not necessarily going to give you the last record in the dataset unless you give the dataset an unambiguous order.
|
|
97
|
+
3. +last+ will ignore +limit+ if chained together in a query because it sets a limit of 1 if no arguments are given.
|
|
101
98
|
|
|
102
99
|
==== Retrieving a Single Column Value
|
|
103
100
|
|
|
@@ -109,6 +106,15 @@ you want:
|
|
|
109
106
|
# SELECT name FROM artists LIMIT 1
|
|
110
107
|
# => "YJM"
|
|
111
108
|
|
|
109
|
+
==== Retrieving a Multiple Column Values
|
|
110
|
+
|
|
111
|
+
If you want the value for multiple columns, you can pass an array to
|
|
112
|
+
<tt>Sequel::Dataset#get</tt>:
|
|
113
|
+
|
|
114
|
+
artist_id, artist_name = Artist.get([:id, :name])
|
|
115
|
+
# SELECT id, name FROM artists LIMIT 1
|
|
116
|
+
# => [1, "YJM"]
|
|
117
|
+
|
|
112
118
|
=== Retrieving Multiple Objects
|
|
113
119
|
|
|
114
120
|
==== As an Array of Hashes or Model Objects
|
|
@@ -181,21 +187,21 @@ an array of arrays of values will be returned:
|
|
|
181
187
|
==== As a Hash
|
|
182
188
|
|
|
183
189
|
Sequel makes it easy to take an SQL query and return it as a ruby hash,
|
|
184
|
-
using the +
|
|
190
|
+
using the +as_hash+ method:
|
|
185
191
|
|
|
186
|
-
artist_names = Artist.
|
|
192
|
+
artist_names = Artist.as_hash(:id, :name)
|
|
187
193
|
# SELECT * FROM artists
|
|
188
194
|
# => {1=>"YJM", 2=>"AS"}
|
|
189
195
|
|
|
190
|
-
As you can see, the +
|
|
196
|
+
As you can see, the +as_hash+ method uses the first symbol as the key
|
|
191
197
|
and the second symbol as the value. So if you swap the two arguments the hash
|
|
192
198
|
will have its keys and values transposed:
|
|
193
199
|
|
|
194
|
-
artist_names = Artist.
|
|
200
|
+
artist_names = Artist.as_hash(:name, :id)
|
|
195
201
|
# SELECT * FROM artists
|
|
196
202
|
# => {"YJM"=>1, "AS"=>2}
|
|
197
203
|
|
|
198
|
-
Now what if you have multiple values for the same key? By default, +
|
|
204
|
+
Now what if you have multiple values for the same key? By default, +as_hash+
|
|
199
205
|
will just have the last matching value. If you care about all matching values,
|
|
200
206
|
use +to_hash_groups+, which makes the values of the array an array of matching
|
|
201
207
|
values, in the order they were received:
|
|
@@ -204,10 +210,10 @@ values, in the order they were received:
|
|
|
204
210
|
# SELECT * FROM artists
|
|
205
211
|
# => {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
|
|
206
212
|
|
|
207
|
-
If you only provide one argument to +
|
|
213
|
+
If you only provide one argument to +as_hash+, it uses the entire hash
|
|
208
214
|
or model object as the value:
|
|
209
215
|
|
|
210
|
-
artist_names = DB[:artists].
|
|
216
|
+
artist_names = DB[:artists].as_hash(:name)
|
|
211
217
|
# SELECT * FROM artists
|
|
212
218
|
# => {"YJM"=>{:id=>1, :name=>"YJM"}, "AS"=>{:id=>2, :name=>"AS"}}
|
|
213
219
|
|
|
@@ -217,12 +223,12 @@ and +to_hash_groups+ works similarly:
|
|
|
217
223
|
# SELECT * FROM artists
|
|
218
224
|
# => {"YJM"=>[{:id=>1, :name=>"YJM"}, {:id=>10, :name=>"YJM"}], ...}
|
|
219
225
|
|
|
220
|
-
Model datasets have a +
|
|
226
|
+
Model datasets have a +as_hash+ method that can be called without any
|
|
221
227
|
arguments, in which case it will use the primary key as the key and
|
|
222
228
|
the model object as the value. This can be used to easily create an
|
|
223
229
|
identity map:
|
|
224
230
|
|
|
225
|
-
artist_names = Artist.
|
|
231
|
+
artist_names = Artist.as_hash
|
|
226
232
|
# SELECT * FROM artists
|
|
227
233
|
# => {1=>#<Artist @values={:id=>1, :name=>"YGM"}>,
|
|
228
234
|
# 2=>#<Artist @values={:id=>2, :name=>"AS"}>}
|
|
@@ -230,7 +236,7 @@ identity map:
|
|
|
230
236
|
There is no equivalent handling to +to_hash_groups+, since there would
|
|
231
237
|
only be one matching record, as the primary key must be unique.
|
|
232
238
|
|
|
233
|
-
Note that +
|
|
239
|
+
Note that +as_hash+ never modifies the columns selected. However, just
|
|
234
240
|
like Sequel has a +select_map+ method to modify the columns selected and
|
|
235
241
|
return an array, Sequel also has a +select_hash+ method to modify the
|
|
236
242
|
columns selected and return a hash:
|
|
@@ -260,8 +266,8 @@ be using:
|
|
|
260
266
|
1. Methods that return row(s), discussed above
|
|
261
267
|
2. Methods that return modified datasets, discussed below
|
|
262
268
|
|
|
263
|
-
Sequel
|
|
264
|
-
|
|
269
|
+
Sequel datasets are frozen and use a method chaining, functional style API
|
|
270
|
+
that returns modified datasets. Let's start with a simple example.
|
|
265
271
|
|
|
266
272
|
This is a basic dataset that includes all records in the
|
|
267
273
|
table +artists+:
|
|
@@ -273,7 +279,7 @@ Let's say we are only interested in the artists whose names
|
|
|
273
279
|
start with "A":
|
|
274
280
|
|
|
275
281
|
ds2 = ds1.where(Sequel.like(:name, 'A%'))
|
|
276
|
-
# SELECT * FROM artists WHERE name LIKE 'A%' ESCAPE '\'
|
|
282
|
+
# SELECT * FROM artists WHERE (name LIKE 'A%' ESCAPE '\')
|
|
277
283
|
|
|
278
284
|
Here we see that +where+ returns a dataset that adds a +WHERE+
|
|
279
285
|
clause to the query. It's important to note that +where+ does
|
|
@@ -282,10 +288,9 @@ not modify the receiver:
|
|
|
282
288
|
ds1
|
|
283
289
|
# SELECT * FROM artists
|
|
284
290
|
ds2
|
|
285
|
-
# SELECT * FROM artists WHERE name LIKE 'A%' ESCAPE '\'
|
|
291
|
+
# SELECT * FROM artists WHERE (name LIKE 'A%' ESCAPE '\')
|
|
286
292
|
|
|
287
|
-
In Sequel,
|
|
288
|
-
not modify the dataset itself, so you can freely use the dataset in multiple
|
|
293
|
+
In Sequel, dataset methods do not modify the dataset itself, so you can freely use the dataset in multiple
|
|
289
294
|
places without worrying that its usage in one place will affect its usage
|
|
290
295
|
in another place. This is what is meant by a functional style API.
|
|
291
296
|
|
|
@@ -293,7 +298,7 @@ Let's say we only want to select the id and name columns, and that
|
|
|
293
298
|
we want to order by name:
|
|
294
299
|
|
|
295
300
|
ds3 = ds2.order(:name).select(:id, :name)
|
|
296
|
-
# SELECT id, name FROM artists WHERE name LIKE 'A%' ESCAPE '\' ORDER BY name
|
|
301
|
+
# SELECT id, name FROM artists WHERE (name LIKE 'A%' ESCAPE '\') ORDER BY name
|
|
297
302
|
|
|
298
303
|
Note how you don't need to assign the returned value of order to a variable,
|
|
299
304
|
and then call select on that. Because order just returns a dataset, you can
|
|
@@ -315,54 +320,57 @@ below.
|
|
|
315
320
|
=== Hashes
|
|
316
321
|
|
|
317
322
|
The most common format for providing filters is via a hash. In general, Sequel
|
|
318
|
-
treats conditions specified with a hash as equality or
|
|
323
|
+
treats conditions specified with a hash as equality, inclusion, or identity. What type
|
|
319
324
|
of condition is used depends on the values in the hash.
|
|
320
325
|
|
|
321
326
|
Unless Sequel has special support for the value's class, it uses a simple
|
|
322
327
|
equality statement:
|
|
323
328
|
|
|
324
|
-
Artist.where(:
|
|
325
|
-
# SELECT * FROM artists WHERE id = 1
|
|
329
|
+
Artist.where(id: 1)
|
|
330
|
+
# SELECT * FROM artists WHERE (id = 1)
|
|
326
331
|
|
|
327
|
-
Artist.where(:
|
|
328
|
-
# SELECT * FROM artists WHERE name = 'YJM'
|
|
332
|
+
Artist.where(name: 'YJM')
|
|
333
|
+
# SELECT * FROM artists WHERE (name = 'YJM')
|
|
329
334
|
|
|
330
|
-
For arrays, Sequel uses the IN operator
|
|
335
|
+
For arrays, Sequel uses the IN operator with a value list:
|
|
331
336
|
|
|
332
|
-
Artist.where(:
|
|
333
|
-
# SELECT * FROM artists WHERE id IN (1, 2)
|
|
337
|
+
Artist.where(id: [1, 2])
|
|
338
|
+
# SELECT * FROM artists WHERE (id IN (1, 2))
|
|
334
339
|
|
|
335
340
|
For datasets, Sequel uses the IN operator with a subselect:
|
|
336
341
|
|
|
337
|
-
Artist.where(:
|
|
338
|
-
# SELECT * FROM artists WHERE id IN (
|
|
339
|
-
# SELECT artist_id FROM albums)
|
|
342
|
+
Artist.where(id: Album.select(:artist_id))
|
|
343
|
+
# SELECT * FROM artists WHERE (id IN (
|
|
344
|
+
# SELECT artist_id FROM albums))
|
|
340
345
|
|
|
341
346
|
For boolean values such as nil, true, and false, Sequel uses the IS operator:
|
|
342
347
|
|
|
343
|
-
Artist.where(:
|
|
344
|
-
# SELECT * FROM artists WHERE id IS NULL
|
|
348
|
+
Artist.where(id: nil)
|
|
349
|
+
# SELECT * FROM artists WHERE (id IS NULL)
|
|
345
350
|
|
|
346
351
|
For ranges, Sequel uses a pair of inequality statements:
|
|
347
352
|
|
|
348
|
-
Artist.where(:
|
|
349
|
-
# SELECT * FROM artists WHERE id >= 1 AND id <= 5
|
|
353
|
+
Artist.where(id: 1..5)
|
|
354
|
+
# SELECT * FROM artists WHERE ((id >= 1) AND (id <= 5))
|
|
355
|
+
|
|
356
|
+
Artist.where(id: 1...5)
|
|
357
|
+
# SELECT * FROM artists WHERE ((id >= 1) AND (id < 5))
|
|
350
358
|
|
|
351
359
|
Finally, for regexps, Sequel uses an SQL regular expression. Note that this
|
|
352
360
|
is probably only supported on PostgreSQL and MySQL.
|
|
353
361
|
|
|
354
|
-
Artist.where(:
|
|
355
|
-
# SELECT * FROM artists WHERE name ~ 'JM$'
|
|
362
|
+
Artist.where(name: /JM$/)
|
|
363
|
+
# SELECT * FROM artists WHERE (name ~ 'JM$')
|
|
356
364
|
|
|
357
365
|
If there are multiple arguments in the hash, the filters are ANDed together:
|
|
358
366
|
|
|
359
|
-
Artist.where(:
|
|
360
|
-
# SELECT * FROM artists WHERE id = 1 AND name ~ 'JM$'
|
|
367
|
+
Artist.where(id: 1, name: /JM$/)
|
|
368
|
+
# SELECT * FROM artists WHERE ((id = 1) AND (name ~ 'JM$'))
|
|
361
369
|
|
|
362
370
|
This works the same as if you used two separate +where+ calls:
|
|
363
371
|
|
|
364
|
-
Artist.where(:
|
|
365
|
-
# SELECT * FROM artists WHERE id = 1 AND name ~ 'JM$'
|
|
372
|
+
Artist.where(id: 1).where(name: /JM$/)
|
|
373
|
+
# SELECT * FROM artists WHERE ((id = 1) AND (name ~ 'JM$'))
|
|
366
374
|
|
|
367
375
|
=== Array of Two Element Arrays
|
|
368
376
|
|
|
@@ -371,28 +379,28 @@ advantage to using an array of two element arrays is that it allows you to
|
|
|
371
379
|
duplicate keys, so you can do:
|
|
372
380
|
|
|
373
381
|
Artist.where([[:name, /JM$/], [:name, /^YJ/]])
|
|
374
|
-
# SELECT * FROM artists WHERE name ~ 'JM$' AND name ~ '^YJ'
|
|
382
|
+
# SELECT * FROM artists WHERE ((name ~ 'JM$')) AND ((name ~ '^YJ'))
|
|
375
383
|
|
|
376
384
|
=== Virtual Row Blocks
|
|
377
385
|
|
|
378
386
|
If a block is passed to a filter, it is treated as a virtual row block:
|
|
379
387
|
|
|
380
388
|
Artist.where{id > 5}
|
|
381
|
-
# SELECT * FROM artists WHERE id > 5
|
|
389
|
+
# SELECT * FROM artists WHERE (id > 5)
|
|
382
390
|
|
|
383
391
|
You can learn more about virtual row blocks in the {"Virtual Rows" guide}[rdoc-ref:doc/virtual_rows.rdoc].
|
|
384
392
|
|
|
385
393
|
You can provide both regular arguments and a block, in which case the results
|
|
386
394
|
will be ANDed together:
|
|
387
395
|
|
|
388
|
-
Artist.where(:
|
|
389
|
-
# SELECT * FROM artists WHERE name >= 'A' AND name < 'M' AND id > 5
|
|
396
|
+
Artist.where(name: 'A'...'M'){id > 5}
|
|
397
|
+
# SELECT * FROM artists WHERE ((name >= 'A') AND (name < 'M') AND (id > 5))
|
|
390
398
|
|
|
391
399
|
Using virtual row blocks, what you can do with single entry hash or an array with
|
|
392
400
|
a single two element array can also be done using the =~ method:
|
|
393
401
|
|
|
394
402
|
Artist.where{id =~ 5}
|
|
395
|
-
# SELECT * FROM artists WHERE id = 5
|
|
403
|
+
# SELECT * FROM artists WHERE (id = 5)
|
|
396
404
|
|
|
397
405
|
=== Symbols
|
|
398
406
|
|
|
@@ -416,47 +424,48 @@ which is used directly in the filter.
|
|
|
416
424
|
|
|
417
425
|
You can use the DSL to create arbitrarily complex expressions. SQL::Expression
|
|
418
426
|
objects can be created via singleton methods on the Sequel module. The most common
|
|
419
|
-
method is Sequel.
|
|
427
|
+
method is Sequel.[], which takes any object and wraps it in a SQL::Expression
|
|
420
428
|
object. In most cases, the SQL::Expression returned supports the & operator for
|
|
421
429
|
+AND+, the | operator for +OR+, and the ~ operator for inversion:
|
|
422
430
|
|
|
423
|
-
Artist.where(Sequel.like(:name, 'Y%') & (Sequel
|
|
424
|
-
# SELECT * FROM artists WHERE name LIKE 'Y%' ESCAPE '\' AND (b = 1 OR c != 3)
|
|
431
|
+
Artist.where(Sequel.like(:name, 'Y%') & (Sequel[{b: 1}] | Sequel.~(c: 3)))
|
|
432
|
+
# SELECT * FROM artists WHERE ((name LIKE 'Y%' ESCAPE '\') AND ((b = 1) OR (c != 3)))
|
|
425
433
|
|
|
426
434
|
You can combine these expression operators with the virtual row support:
|
|
427
435
|
|
|
428
436
|
Artist.where{(a > 1) & ~((b(c) < 1) | d)}
|
|
429
|
-
# SELECT * FROM artists WHERE a > 1 AND b(c) >= 1 AND NOT d
|
|
437
|
+
# SELECT * FROM artists WHERE ((a > 1) AND (b(c) >= 1) AND NOT d)
|
|
430
438
|
|
|
431
439
|
Note the use of parentheses when using the & and | operators, as they have lower
|
|
432
440
|
precedence than other operators. The following will not work:
|
|
433
441
|
|
|
434
442
|
Artist.where{a > 1 & ~(b(c) < 1 | d)}
|
|
435
|
-
# Raises a TypeError
|
|
443
|
+
# Raises a TypeError
|
|
436
444
|
|
|
437
445
|
=== Strings with Placeholders
|
|
438
446
|
|
|
439
|
-
Assuming you want to get your hands dirty and
|
|
440
|
-
to
|
|
447
|
+
Assuming you want to get your hands dirty and use SQL fragments in filters, Sequel allows you
|
|
448
|
+
to do so if you explicitly mark the strings as literal strings using +Sequel.lit+. You can
|
|
449
|
+
use placeholders in the string and pass arguments for the placeholders:
|
|
441
450
|
|
|
442
|
-
Artist.where("name LIKE ?", 'Y%')
|
|
443
|
-
# SELECT * FROM artists WHERE name LIKE 'Y%'
|
|
451
|
+
Artist.where(Sequel.lit("name LIKE ?", 'Y%'))
|
|
452
|
+
# SELECT * FROM artists WHERE (name LIKE 'Y%')
|
|
444
453
|
|
|
445
454
|
This is the most common type of placeholder, where each question mark is substituted
|
|
446
455
|
with the next argument:
|
|
447
456
|
|
|
448
|
-
Artist.where("name LIKE ? AND id = ?", 'Y%', 5)
|
|
449
|
-
# SELECT * FROM artists WHERE name LIKE 'Y%' AND id = 5
|
|
457
|
+
Artist.where(Sequel.lit("name LIKE ? AND id = ?", 'Y%', 5))
|
|
458
|
+
# SELECT * FROM artists WHERE (name LIKE 'Y%' AND id = 5)
|
|
450
459
|
|
|
451
460
|
You can also use named placeholders with a hash, where the named placeholders use
|
|
452
461
|
colons before the placeholder names:
|
|
453
462
|
|
|
454
|
-
Artist.where("name LIKE :name AND id = :id", :
|
|
455
|
-
# SELECT * FROM artists WHERE name LIKE 'Y%' AND id = 5
|
|
463
|
+
Artist.where(Sequel.lit("name LIKE :name AND id = :id", name: 'Y%', id: 5))
|
|
464
|
+
# SELECT * FROM artists WHERE (name LIKE 'Y%' AND id = 5)
|
|
456
465
|
|
|
457
466
|
You don't have to provide any placeholders if you don't want to:
|
|
458
467
|
|
|
459
|
-
Artist.where("id = 2")
|
|
468
|
+
Artist.where(Sequel.lit("id = 2"))
|
|
460
469
|
# SELECT * FROM artists WHERE id = 2
|
|
461
470
|
|
|
462
471
|
However, if you are using any untrusted input, you should definitely be using placeholders.
|
|
@@ -464,9 +473,9 @@ In general, unless you are hardcoding values in the strings, you should use plac
|
|
|
464
473
|
You should never pass a string that has been built using interpolation, unless you are
|
|
465
474
|
sure of what you are doing.
|
|
466
475
|
|
|
467
|
-
Artist.where("id = #{params[:id]}") # Don't do this!
|
|
468
|
-
Artist.where("id = ?", params[:id]) # Do this instead
|
|
469
|
-
Artist.where(:
|
|
476
|
+
Artist.where(Sequel.lit("id = #{params[:id]}")) # Don't do this!
|
|
477
|
+
Artist.where(Sequel.lit("id = ?", params[:id])) # Do this instead
|
|
478
|
+
Artist.where(id: params[:id].to_i) # Even better
|
|
470
479
|
|
|
471
480
|
=== Inverting
|
|
472
481
|
|
|
@@ -474,53 +483,53 @@ You may be wondering how to specify a not equals condition in Sequel, or the NOT
|
|
|
474
483
|
operator. Sequel has generic support for inverting conditions, so to write a not
|
|
475
484
|
equals condition, you write an equals condition, and invert it:
|
|
476
485
|
|
|
477
|
-
Artist.where(:
|
|
478
|
-
# SELECT * FROM artists WHERE id != 5
|
|
486
|
+
Artist.where(id: 5).invert
|
|
487
|
+
# SELECT * FROM artists WHERE (id != 5)
|
|
479
488
|
|
|
480
489
|
Note that +invert+ inverts the entire filter:
|
|
481
490
|
|
|
482
|
-
Artist.where(:
|
|
483
|
-
# SELECT * FROM artists WHERE id != 5 OR name <= 'A'
|
|
491
|
+
Artist.where(id: 5).where{name > 'A'}.invert
|
|
492
|
+
# SELECT * FROM artists WHERE ((id != 5) OR (name <= 'A'))
|
|
484
493
|
|
|
485
494
|
In general, +invert+ is used rarely, since +exclude+ allows you to invert only specific
|
|
486
495
|
filters:
|
|
487
496
|
|
|
488
|
-
Artist.exclude(:
|
|
489
|
-
# SELECT * FROM artists WHERE id != 5
|
|
497
|
+
Artist.exclude(id: 5)
|
|
498
|
+
# SELECT * FROM artists WHERE (id != 5)
|
|
490
499
|
|
|
491
|
-
Artist.where(:
|
|
492
|
-
# SELECT * FROM artists WHERE id = 5 OR name <= 'A'
|
|
500
|
+
Artist.where(id: 5).exclude{name > 'A'}
|
|
501
|
+
# SELECT * FROM artists WHERE ((id = 5) OR (name <= 'A')
|
|
493
502
|
|
|
494
503
|
So to do a NOT IN with an array:
|
|
495
504
|
|
|
496
|
-
Artist.exclude(:
|
|
497
|
-
# SELECT * FROM artists WHERE id NOT IN (1, 2)
|
|
505
|
+
Artist.exclude(id: [1, 2])
|
|
506
|
+
# SELECT * FROM artists WHERE (id NOT IN (1, 2))
|
|
498
507
|
|
|
499
508
|
Or to use the NOT LIKE operator:
|
|
500
509
|
|
|
501
510
|
Artist.exclude(Sequel.like(:name, '%J%'))
|
|
502
|
-
# SELECT * FROM artists WHERE name NOT LIKE '%J%' ESCAPE '\'
|
|
511
|
+
# SELECT * FROM artists WHERE (name NOT LIKE '%J%' ESCAPE '\')
|
|
503
512
|
|
|
504
513
|
You can use Sequel.~ to negate expressions:
|
|
505
514
|
|
|
506
|
-
Artist.where(Sequel.~(:
|
|
515
|
+
Artist.where(Sequel.~(id: 5))
|
|
507
516
|
# SELECT * FROM artists WHERE id != 5
|
|
508
517
|
|
|
509
518
|
On Sequel expression objects, you can use ~ to negate them:
|
|
510
519
|
|
|
511
520
|
Artist.where(~Sequel.like(:name, '%J%'))
|
|
512
|
-
# SELECT * FROM artists WHERE name NOT LIKE '%J%' ESCAPE '\'
|
|
521
|
+
# SELECT * FROM artists WHERE (name NOT LIKE '%J%' ESCAPE '\')
|
|
513
522
|
|
|
514
|
-
|
|
523
|
+
You can use !~ on Sequel expressions to create negated expressions:
|
|
515
524
|
|
|
516
|
-
Artist.where{
|
|
517
|
-
# SELECT * FROM artists WHERE id != 5
|
|
525
|
+
Artist.where{id !~ 5}
|
|
526
|
+
# SELECT * FROM artists WHERE (id != 5)
|
|
518
527
|
|
|
519
528
|
=== Removing
|
|
520
529
|
|
|
521
530
|
To remove all existing filters, use +unfiltered+:
|
|
522
531
|
|
|
523
|
-
Artist.where(:
|
|
532
|
+
Artist.where(id: 1).unfiltered
|
|
524
533
|
# SELECT * FROM artists
|
|
525
534
|
|
|
526
535
|
== Ordering
|
|
@@ -555,14 +564,17 @@ If you want to add a column to the beginning of the existing order:
|
|
|
555
564
|
=== Reversing
|
|
556
565
|
|
|
557
566
|
Just like you can invert an existing filter, you can reverse an existing
|
|
558
|
-
order, using +reverse
|
|
567
|
+
order, using +reverse+ without an order:
|
|
559
568
|
|
|
560
569
|
Artist.order(:id).reverse
|
|
561
570
|
# SELECT FROM artists ORDER BY id DESC
|
|
562
571
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
572
|
+
Alternatively, you can provide reverse with the order:
|
|
573
|
+
|
|
574
|
+
Artist.reverse(:id)
|
|
575
|
+
# SELECT FROM artists ORDER BY id DESC
|
|
576
|
+
|
|
577
|
+
To specify a single entry be reversed, <tt>Sequel.desc</tt> can be used:
|
|
566
578
|
|
|
567
579
|
Artist.order(Sequel.desc(:id))
|
|
568
580
|
# SELECT FROM artists ORDER BY id DESC
|
|
@@ -658,7 +670,7 @@ You can also call the +offset+ method separately:
|
|
|
658
670
|
Either of these would return the 11th through 15th records in the original
|
|
659
671
|
dataset.
|
|
660
672
|
|
|
661
|
-
To remove a limit from a dataset, use +unlimited+:
|
|
673
|
+
To remove a limit and offset from a dataset, use +unlimited+:
|
|
662
674
|
|
|
663
675
|
Artist.limit(5, 10).unlimited
|
|
664
676
|
# SELECT * FROM artists
|
|
@@ -709,50 +721,46 @@ filters the results after the grouping has been applied, instead of
|
|
|
709
721
|
before. One possible use is if you only wanted to return artists
|
|
710
722
|
who had at least 10 albums:
|
|
711
723
|
|
|
712
|
-
Album.group_and_count(:artist_id).having{count
|
|
724
|
+
Album.group_and_count(:artist_id).having{count.function.* >= 10}
|
|
713
725
|
# SELECT artist_id, count(*) AS count FROM albums
|
|
714
|
-
# GROUP BY artist_id HAVING count(*) >= 10
|
|
726
|
+
# GROUP BY artist_id HAVING (count(*) >= 10)
|
|
715
727
|
|
|
716
728
|
Both the WHERE clause and the HAVING clause are removed by +unfiltered+:
|
|
717
729
|
|
|
718
|
-
Album.group_and_count(:artist_id).having{count
|
|
730
|
+
Album.group_and_count(:artist_id).having{count.function.* >= 10}.
|
|
719
731
|
where(:name.like('A%')).unfiltered
|
|
720
732
|
# SELECT artist_id, count(*) AS count FROM albums GROUP BY artist_id
|
|
721
733
|
|
|
722
734
|
== Joins
|
|
723
735
|
|
|
724
|
-
Sequel
|
|
736
|
+
Sequel has support for many different SQL join types.
|
|
725
737
|
The underlying method used is +join_table+:
|
|
726
738
|
|
|
727
|
-
Album.join_table(:inner, :artists, :
|
|
739
|
+
Album.join_table(:inner, :artists, id: :artist_id)
|
|
728
740
|
# SELECT * FROM albums
|
|
729
|
-
# INNER JOIN artists ON artists.id = albums.artist_id
|
|
741
|
+
# INNER JOIN artists ON (artists.id = albums.artist_id)
|
|
730
742
|
|
|
731
743
|
In most cases, you won't call +join_table+ directly, as Sequel provides
|
|
732
744
|
shortcuts for all common (and most uncommon) join types. For example
|
|
733
745
|
+join+ does an inner join:
|
|
734
746
|
|
|
735
|
-
Album.join(:artists, :
|
|
747
|
+
Album.join(:artists, id: :artist_id)
|
|
736
748
|
# SELECT * FROM albums
|
|
737
|
-
# INNER JOIN artists ON artists.id = albums.artist_id
|
|
749
|
+
# INNER JOIN artists ON (artists.id = albums.artist_id))))
|
|
738
750
|
|
|
739
751
|
And +left_join+ does a LEFT JOIN:
|
|
740
752
|
|
|
741
|
-
Album.left_join(:artists, :
|
|
753
|
+
Album.left_join(:artists, id: :artist_id)
|
|
742
754
|
# SELECT * FROM albums
|
|
743
|
-
# LEFT JOIN artists ON artists.id = albums.artist_id
|
|
755
|
+
# LEFT JOIN artists ON (artists.id = albums.artist_id)
|
|
744
756
|
|
|
745
757
|
=== Table/Dataset to Join
|
|
746
758
|
|
|
747
759
|
For all of these specialized join methods, the first argument is
|
|
748
760
|
generally the name of the table to which you are joining. However, you
|
|
749
|
-
can also provide a
|
|
761
|
+
can also provide a dataset, in which case a subselect is used:
|
|
750
762
|
|
|
751
|
-
Album.join(Artist, :
|
|
752
|
-
|
|
753
|
-
Or a dataset, in which case a subselect is used:
|
|
754
|
-
|
|
755
|
-
Album.join(Artist.where{name < 'A'}, :id=>:artist_id)
|
|
763
|
+
Album.join(Artist.where{name < 'A'}, id: :artist_id)
|
|
756
764
|
# SELECT * FROM albums
|
|
757
765
|
# INNER JOIN (SELECT * FROM artists WHERE (name < 'A')) AS t1
|
|
758
766
|
# ON (t1.id = albums.artist_id)
|
|
@@ -768,80 +776,78 @@ a few minor exceptions.
|
|
|
768
776
|
A hash used as the join conditions operates similarly to a filter,
|
|
769
777
|
except that unqualified symbol keys are automatically qualified
|
|
770
778
|
with the table from the first argument, and unqualified symbol values
|
|
771
|
-
are automatically qualified with the
|
|
772
|
-
|
|
773
|
-
in Sequel are easy to specify:
|
|
779
|
+
are automatically qualified with the last table joined (or the first
|
|
780
|
+
table in the dataset if there hasn't been a previous join):
|
|
774
781
|
|
|
775
|
-
Album.join(:artists, :
|
|
782
|
+
Album.join(:artists, id: :artist_id)
|
|
776
783
|
# SELECT * FROM albums
|
|
777
|
-
# INNER JOIN artists ON artists.id = albums.artist_id
|
|
784
|
+
# INNER JOIN artists ON (artists.id = albums.artist_id)
|
|
778
785
|
|
|
779
|
-
Note how the
|
|
786
|
+
Note how the +id+ symbol is automatically qualified with +artists+,
|
|
780
787
|
while the +artist_id+ symbol is automatically qualified with +albums+.
|
|
781
788
|
|
|
782
789
|
Because Sequel uses the last joined table for implicit qualifications
|
|
783
790
|
of values, you can do things like:
|
|
784
791
|
|
|
785
|
-
Album.join(:artists, :
|
|
786
|
-
join(:members, :
|
|
792
|
+
Album.join(:artists, id: :artist_id).
|
|
793
|
+
join(:members, artist_id: :id)
|
|
787
794
|
# SELECT * FROM albums
|
|
788
|
-
# INNER JOIN artists ON artists.id = albums.artist_id
|
|
789
|
-
# INNER JOIN members ON members.artist_id = artists.id
|
|
795
|
+
# INNER JOIN artists ON (artists.id = albums.artist_id)
|
|
796
|
+
# INNER JOIN members ON (members.artist_id = artists.id)
|
|
790
797
|
|
|
791
798
|
Note that when joining to the +members+ table, +artist_id+ is qualified
|
|
792
799
|
with +members+ and +id+ is qualified with +artists+.
|
|
793
800
|
|
|
794
801
|
While a good default, implicit qualification is not always correct:
|
|
795
802
|
|
|
796
|
-
Album.join(:artists, :
|
|
797
|
-
join(:tracks, :
|
|
803
|
+
Album.join(:artists, id: :artist_id).
|
|
804
|
+
join(:tracks, album_id: :id)
|
|
798
805
|
# SELECT * FROM albums
|
|
799
|
-
# INNER JOIN artists ON artists.id = albums.artist_id
|
|
800
|
-
# INNER JOIN tracks ON tracks.album_id = artists.id
|
|
806
|
+
# INNER JOIN artists ON (artists.id = albums.artist_id)
|
|
807
|
+
# INNER JOIN tracks ON (tracks.album_id = artists.id)
|
|
801
808
|
|
|
802
809
|
Note here how +id+ is qualified with +artists+ instead of +albums+. This
|
|
803
810
|
is wrong as the foreign key <tt>tracks.album_id</tt> refers to <tt>albums.id</tt>, not
|
|
804
811
|
<tt>artists.id</tt>. To fix this, you need to explicitly qualify when joining:
|
|
805
812
|
|
|
806
|
-
Album.join(:artists, :
|
|
807
|
-
join(:tracks, :
|
|
813
|
+
Album.join(:artists, id: :artist_id).
|
|
814
|
+
join(:tracks, album_id: Sequel[:albums][:id])
|
|
808
815
|
# SELECT * FROM albums
|
|
809
|
-
# INNER JOIN artists ON artists.id = albums.artist_id
|
|
810
|
-
# INNER JOIN tracks ON tracks.album_id = albums.id
|
|
816
|
+
# INNER JOIN artists ON (artists.id = albums.artist_id)
|
|
817
|
+
# INNER JOIN tracks ON (tracks.album_id = albums.id)
|
|
811
818
|
|
|
812
819
|
Just like in filters, an array of two element arrays is treated the same
|
|
813
820
|
as a hash, but allows for duplicate keys:
|
|
814
821
|
|
|
815
822
|
Album.join(:artists, [[:id, :artist_id], [:id, 1..5]])
|
|
816
823
|
# SELECT * FROM albums INNER JOIN artists
|
|
817
|
-
# ON artists.id = albums.artist_id
|
|
818
|
-
# AND artists.id >= 1 AND artists.id <= 5
|
|
824
|
+
# ON ((artists.id = albums.artist_id)
|
|
825
|
+
# AND (artists.id >= 1) AND (artists.id <= 5))
|
|
819
826
|
|
|
820
827
|
And just like in the hash case, unqualified symbol elements in the
|
|
821
828
|
array are implicitly qualified.
|
|
822
829
|
|
|
823
830
|
By default, Sequel only qualifies unqualified symbols in the conditions. However,
|
|
824
|
-
You can provide an options hash with a <tt
|
|
831
|
+
You can provide an options hash with a <tt>qualify: :deep</tt> option to do a deep
|
|
825
832
|
qualification, which can qualify subexpressions. For example, let's say you are doing
|
|
826
833
|
a JOIN using case insensitive string comparison:
|
|
827
834
|
|
|
828
835
|
Album.join(:artists, {Sequel.function(:lower, :name) =>
|
|
829
836
|
Sequel.function(:lower, :artist_name)},
|
|
830
|
-
:
|
|
837
|
+
qualify: :deep)
|
|
831
838
|
# SELECT * FROM albums INNER JOIN artists
|
|
832
839
|
# ON (lower(artists.name) = lower(albums.artist_name))
|
|
833
840
|
|
|
834
|
-
Note how the arguments to lower were qualified correctly in both cases.
|
|
835
|
-
the <tt>:qualify=>:deep</tt> option is going to become the default.
|
|
841
|
+
Note how the arguments to lower were qualified correctly in both cases.
|
|
836
842
|
|
|
837
843
|
==== USING Joins
|
|
838
844
|
|
|
839
845
|
The most common type of join conditions is a JOIN ON, as displayed
|
|
840
846
|
above. However, the SQL standard allows for join conditions to be
|
|
841
|
-
specified with JOIN USING,
|
|
847
|
+
specified with JOIN USING, assuming the column name is the same in
|
|
848
|
+
both tables.
|
|
842
849
|
|
|
843
|
-
|
|
844
|
-
names in both tables. For example, if instead of having a primary
|
|
850
|
+
For example, if instead of having a primary
|
|
845
851
|
column named +id+ in all of your tables, you use +artist_id+ in your
|
|
846
852
|
+artists+ table and +album_id+ in your +albums+ table, you could do:
|
|
847
853
|
|
|
@@ -852,7 +858,7 @@ See here how you specify the USING columns as an array of symbols.
|
|
|
852
858
|
|
|
853
859
|
==== NATURAL Joins
|
|
854
860
|
|
|
855
|
-
NATURAL
|
|
861
|
+
NATURAL joins take it one step further than USING joins, by assuming
|
|
856
862
|
that all columns with the same names in both tables should be
|
|
857
863
|
used for joining:
|
|
858
864
|
|
|
@@ -875,12 +881,12 @@ being used. For example, lets say you wanted to join the albums
|
|
|
875
881
|
and artists tables, but only want albums where the artist's name
|
|
876
882
|
comes before the album's name.
|
|
877
883
|
|
|
878
|
-
Album.join(:artists, :
|
|
879
|
-
Sequel
|
|
884
|
+
Album.join(:artists, id: :artist_id) do |j, lj, js|
|
|
885
|
+
Sequel[j][:name] < Sequel[lj][:name]
|
|
880
886
|
end
|
|
881
887
|
# SELECT * FROM albums INNER JOIN artists
|
|
882
|
-
# ON artists.id = albums.artist_id
|
|
883
|
-
# AND artists.name < albums.name
|
|
888
|
+
# ON ((artists.id = albums.artist_id)
|
|
889
|
+
# AND (artists.name < albums.name))
|
|
884
890
|
|
|
885
891
|
Because greater than can't be expressed with a hash in Sequel, you
|
|
886
892
|
need to use a block and qualify the tables manually.
|
|
@@ -904,8 +910,8 @@ number of old albums.
|
|
|
904
910
|
Using multiple FROM tables and setting conditions in the WHERE clause is
|
|
905
911
|
an old-school way of joining tables:
|
|
906
912
|
|
|
907
|
-
DB.from(:albums, :artists).where
|
|
908
|
-
# SELECT * FROM albums, artists WHERE artists.id = albums.artist_id
|
|
913
|
+
DB.from(:albums, :artists).where{{artists[:id]=>albums[:artist_id]}}
|
|
914
|
+
# SELECT * FROM albums, artists WHERE (artists.id = albums.artist_id)
|
|
909
915
|
|
|
910
916
|
=== Using the current dataset in a subselect
|
|
911
917
|
|
|
@@ -916,7 +922,7 @@ Here's an example using +from_self+:
|
|
|
916
922
|
# SELECT * FROM (SELECT * FROM albums ORDER BY artist_id LIMIT 100)
|
|
917
923
|
# AS t1 GROUP BY artist_id
|
|
918
924
|
|
|
919
|
-
This is
|
|
925
|
+
This is different than without +from_self+:
|
|
920
926
|
|
|
921
927
|
Album.order(:artist_id).limit(100).group(:artist_id)
|
|
922
928
|
# SELECT * FROM albums GROUP BY artist_id ORDER BY name LIMIT 100
|
|
@@ -937,8 +943,8 @@ current transaction commits. You just use the +for_update+ dataset
|
|
|
937
943
|
method when returning the rows:
|
|
938
944
|
|
|
939
945
|
DB.transaction do
|
|
940
|
-
album = Album.for_update.first(:
|
|
941
|
-
# SELECT * FROM albums WHERE id = 1 FOR UPDATE
|
|
946
|
+
album = Album.for_update.first(id: 1)
|
|
947
|
+
# SELECT * FROM albums WHERE (id = 1) FOR UPDATE
|
|
942
948
|
album.num_tracks += 1
|
|
943
949
|
album.save
|
|
944
950
|
end
|
|
@@ -956,7 +962,7 @@ stateless nature.
|
|
|
956
962
|
|
|
957
963
|
== Custom SQL
|
|
958
964
|
|
|
959
|
-
Sequel makes it easy to use custom SQL by providing it to the <tt>Database#[]</tt>
|
|
965
|
+
Sequel makes it easy to use custom SQL for the query by providing it to the <tt>Database#[]</tt>
|
|
960
966
|
method as a string:
|
|
961
967
|
|
|
962
968
|
DB["SELECT * FROM artists"]
|
|
@@ -973,7 +979,7 @@ With either of these methods, you can use placeholders:
|
|
|
973
979
|
DB["SELECT * FROM artists WHERE id = ?", 5]
|
|
974
980
|
# SELECT * FROM artists WHERE id = 5
|
|
975
981
|
|
|
976
|
-
DB[:albums].with_sql("SELECT * FROM artists WHERE id = :id", :
|
|
982
|
+
DB[:albums].with_sql("SELECT * FROM artists WHERE id = :id", id: 5)
|
|
977
983
|
# SELECT * FROM artists WHERE id = 5
|
|
978
984
|
|
|
979
985
|
Note that if you specify the dataset using custom SQL, you can still call the dataset
|
|
@@ -982,6 +988,13 @@ modification methods, but in many cases they will appear to have no affect:
|
|
|
982
988
|
DB["SELECT * FROM artists"].select(:name).order(:id)
|
|
983
989
|
# SELECT * FROM artists
|
|
984
990
|
|
|
991
|
+
You can use the implicit_subquery extension to automatically wrap queries that use
|
|
992
|
+
custom SQL in subqueries if a method is called that would modify the SQL:
|
|
993
|
+
|
|
994
|
+
DB.extension :implicit_subquery
|
|
995
|
+
DB["SELECT * FROM artists"].select(:name).order(:id)
|
|
996
|
+
# SELECT name FROM (SELECT * FROM artists) AS t1 ORDER BY id"
|
|
997
|
+
|
|
985
998
|
If you must drop down to using custom SQL, it's recommended that you only do so for
|
|
986
999
|
specific parts of a query. For example, if the reason you are using custom SQL is
|
|
987
1000
|
to use a custom operator in the database in the SELECT clause:
|
|
@@ -1003,12 +1016,12 @@ If you just want to know whether the current dataset would return any rows, use
|
|
|
1003
1016
|
# SELECT 1 FROM albums LIMIT 1
|
|
1004
1017
|
# => false
|
|
1005
1018
|
|
|
1006
|
-
Album.where(:
|
|
1007
|
-
# SELECT 1 FROM albums WHERE id = 0 LIMIT 1
|
|
1019
|
+
Album.where(id: 0).empty?
|
|
1020
|
+
# SELECT 1 FROM albums WHERE (id = 0) LIMIT 1
|
|
1008
1021
|
# => true
|
|
1009
1022
|
|
|
1010
1023
|
Album.where(Sequel.like(:name, 'R%')).empty?
|
|
1011
|
-
# SELECT 1 FROM albums WHERE name LIKE 'R%' ESCAPE '\' LIMIT 1
|
|
1024
|
+
# SELECT 1 FROM albums WHERE (name LIKE 'R%' ESCAPE '\') LIMIT 1
|
|
1012
1025
|
# => false
|
|
1013
1026
|
|
|
1014
1027
|
== Aggregate Calculations
|
|
@@ -1022,22 +1035,29 @@ for each of these aggregate functions.
|
|
|
1022
1035
|
Album.count
|
|
1023
1036
|
# SELECT count(*) AS count FROM albums LIMIT 1
|
|
1024
1037
|
# => 2
|
|
1025
|
-
|
|
1038
|
+
|
|
1039
|
+
If you pass an expression to count, it will return the number of records where
|
|
1040
|
+
that expression in not NULL:
|
|
1041
|
+
|
|
1042
|
+
Album.count(:artist_id)
|
|
1043
|
+
# SELECT count(artist_id) AS count FROM albums LIMIT 1
|
|
1044
|
+
# => 1
|
|
1045
|
+
|
|
1026
1046
|
The other methods take a column argument and call the aggregate function with
|
|
1027
1047
|
the argument:
|
|
1028
1048
|
|
|
1029
1049
|
Album.sum(:id)
|
|
1030
|
-
# SELECT sum(id) FROM albums LIMIT 1
|
|
1050
|
+
# SELECT sum(id) AS sum FROM albums LIMIT 1
|
|
1031
1051
|
# => 3
|
|
1032
1052
|
|
|
1033
1053
|
Album.avg(:id)
|
|
1034
|
-
# SELECT avg(id) FROM albums LIMIT 1
|
|
1054
|
+
# SELECT avg(id) AS avg FROM albums LIMIT 1
|
|
1035
1055
|
# => 1.5
|
|
1036
1056
|
|
|
1037
1057
|
Album.min(:id)
|
|
1038
|
-
# SELECT min(id) FROM albums LIMIT 1
|
|
1058
|
+
# SELECT min(id) AS min FROM albums LIMIT 1
|
|
1039
1059
|
# => 1
|
|
1040
1060
|
|
|
1041
1061
|
Album.max(:id)
|
|
1042
|
-
# SELECT max(id) FROM albums LIMIT 1
|
|
1062
|
+
# SELECT max(id) AS max FROM albums LIMIT 1
|
|
1043
1063
|
# => 2
|