sequel 3.21.0 → 3.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +576 -0
- data/doc/opening_databases.rdoc +121 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +539 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +334 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +137 -16
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +77 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +168 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +227 -33
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/connection_validator_spec.rb +118 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +324 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +200 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +340 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +65 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +8 -11
- data/spec/extensions/touch_spec.rb +53 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +223 -81
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# The pg_array_ops extension adds support to Sequel's DSL to make
|
|
2
|
+
# it easier to call PostgreSQL array functions and operators.
|
|
3
|
+
#
|
|
4
|
+
# To load the extension:
|
|
5
|
+
#
|
|
6
|
+
# Sequel.extension :pg_array_ops
|
|
7
|
+
#
|
|
8
|
+
# The most common usage is passing an expression to Sequel.pg_array_op:
|
|
9
|
+
#
|
|
10
|
+
# ia = Sequel.pg_array_op(:int_array_column)
|
|
11
|
+
#
|
|
12
|
+
# If you have also loaded the pg_array extension, you can use
|
|
13
|
+
# Sequel.pg_array as well:
|
|
14
|
+
#
|
|
15
|
+
# ia = Sequel.pg_array(:int_array_column)
|
|
16
|
+
#
|
|
17
|
+
# Also, on most Sequel expression objects, you can call the pg_array
|
|
18
|
+
# method:
|
|
19
|
+
#
|
|
20
|
+
# ia = Sequel.expr(:int_array_column).pg_array
|
|
21
|
+
#
|
|
22
|
+
# If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
|
|
23
|
+
# you can also call Symbol#pg_array:
|
|
24
|
+
#
|
|
25
|
+
# ia = :int_array_column.pg_array
|
|
26
|
+
#
|
|
27
|
+
# This creates a Sequel::Postgres::ArrayOp object that can be used
|
|
28
|
+
# for easier querying:
|
|
29
|
+
#
|
|
30
|
+
# ia[1] # int_array_column[1]
|
|
31
|
+
# ia[1][2] # int_array_column[1][2]
|
|
32
|
+
#
|
|
33
|
+
# ia.contains(:other_int_array_column) # @>
|
|
34
|
+
# ia.contained_by(:other_int_array_column) # <@
|
|
35
|
+
# ia.overlaps(:other_int_array_column) # &&
|
|
36
|
+
# ia.concat(:other_int_array_column) # ||
|
|
37
|
+
#
|
|
38
|
+
# ia.push(1) # int_array_column || 1
|
|
39
|
+
# ia.unshift(1) # 1 || int_array_column
|
|
40
|
+
#
|
|
41
|
+
# ia.any # ANY(int_array_column)
|
|
42
|
+
# ia.all # ALL(int_array_column)
|
|
43
|
+
# ia.dims # array_dims(int_array_column)
|
|
44
|
+
# ia.length # array_length(int_array_column, 1)
|
|
45
|
+
# ia.length(2) # array_length(int_array_column, 2)
|
|
46
|
+
# ia.lower # array_lower(int_array_column, 1)
|
|
47
|
+
# ia.lower(2) # array_lower(int_array_column, 2)
|
|
48
|
+
# ia.join # array_to_string(int_array_column, '', NULL)
|
|
49
|
+
# ia.join(':') # array_to_string(int_array_column, ':', NULL)
|
|
50
|
+
# ia.join(':', ' ') # array_to_string(int_array_column, ':', ' ')
|
|
51
|
+
# ia.unnest # unnest(int_array_column)
|
|
52
|
+
#
|
|
53
|
+
# See the PostgreSQL array function and operator documentation for more
|
|
54
|
+
# details on what these functions and operators do.
|
|
55
|
+
#
|
|
56
|
+
# If you are also using the pg_array extension, you should load it before
|
|
57
|
+
# loading this extension. Doing so will allow you to use PGArray#op to get
|
|
58
|
+
# an ArrayOp, allowing you to perform array operations on array literals.
|
|
59
|
+
module Sequel
|
|
60
|
+
module Postgres
|
|
61
|
+
# The ArrayOp class is a simple container for a single object that
|
|
62
|
+
# defines methods that yield Sequel expression objects representing
|
|
63
|
+
# PostgreSQL array operators and functions.
|
|
64
|
+
#
|
|
65
|
+
# In the method documentation examples, assume that:
|
|
66
|
+
#
|
|
67
|
+
# array_op = :array.pg_array
|
|
68
|
+
class ArrayOp < Sequel::SQL::Wrapper
|
|
69
|
+
CONCAT = ["(".freeze, " || ".freeze, ")".freeze].freeze
|
|
70
|
+
CONTAINS = ["(".freeze, " @> ".freeze, ")".freeze].freeze
|
|
71
|
+
CONTAINED_BY = ["(".freeze, " <@ ".freeze, ")".freeze].freeze
|
|
72
|
+
OVERLAPS = ["(".freeze, " && ".freeze, ")".freeze].freeze
|
|
73
|
+
|
|
74
|
+
# Access a member of the array, returns an SQL::Subscript instance:
|
|
75
|
+
#
|
|
76
|
+
# array_op[1] # array[1]
|
|
77
|
+
def [](key)
|
|
78
|
+
Sequel::SQL::Subscript.new(self, [key])
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Call the ALL function:
|
|
82
|
+
#
|
|
83
|
+
# array_op.all # ALL(array)
|
|
84
|
+
#
|
|
85
|
+
# Usually used like:
|
|
86
|
+
#
|
|
87
|
+
# dataset.where(1=>array_op.all)
|
|
88
|
+
# # WHERE (1 = ALL(array))
|
|
89
|
+
def all
|
|
90
|
+
function(:ALL)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Call the ANY function:
|
|
94
|
+
#
|
|
95
|
+
# array_op.all # ANY(array)
|
|
96
|
+
#
|
|
97
|
+
# Usually used like:
|
|
98
|
+
#
|
|
99
|
+
# dataset.where(1=>array_op.any)
|
|
100
|
+
# # WHERE (1 = ANY(array))
|
|
101
|
+
def any
|
|
102
|
+
function(:ANY)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Use the contains (@>) operator:
|
|
106
|
+
#
|
|
107
|
+
# array_op.contains(:a) # (array @> a)
|
|
108
|
+
def contains(other)
|
|
109
|
+
bool_op(CONTAINS, wrap_array(other))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Use the contained by (<@) operator:
|
|
113
|
+
#
|
|
114
|
+
# array_op.contained_by(:a) # (array <@ a)
|
|
115
|
+
def contained_by(other)
|
|
116
|
+
bool_op(CONTAINED_BY, wrap_array(other))
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Call the array_dims method:
|
|
120
|
+
#
|
|
121
|
+
# array_op.dims # array_dims(array)
|
|
122
|
+
def dims
|
|
123
|
+
function(:array_dims)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Call the array_length method:
|
|
127
|
+
#
|
|
128
|
+
# array_op.length # array_length(array, 1)
|
|
129
|
+
# array_op.length(2) # array_length(array, 2)
|
|
130
|
+
def length(dimension = 1)
|
|
131
|
+
function(:array_length, dimension)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Call the array_lower method:
|
|
135
|
+
#
|
|
136
|
+
# array_op.lower # array_lower(array, 1)
|
|
137
|
+
# array_op.lower(2) # array_lower(array, 2)
|
|
138
|
+
def lower(dimension = 1)
|
|
139
|
+
function(:array_lower, dimension)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Use the overlaps (&&) operator:
|
|
143
|
+
#
|
|
144
|
+
# array_op.overlaps(:a) # (array && a)
|
|
145
|
+
def overlaps(other)
|
|
146
|
+
bool_op(OVERLAPS, wrap_array(other))
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Use the concatentation (||) operator:
|
|
150
|
+
#
|
|
151
|
+
# array_op.push(:a) # (array || a)
|
|
152
|
+
# array_op.concat(:a) # (array || a)
|
|
153
|
+
def push(other)
|
|
154
|
+
array_op(CONCAT, [self, wrap_array(other)])
|
|
155
|
+
end
|
|
156
|
+
alias concat push
|
|
157
|
+
|
|
158
|
+
# Return the receiver.
|
|
159
|
+
def pg_array
|
|
160
|
+
self
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Call the array_to_string method:
|
|
164
|
+
#
|
|
165
|
+
# array_op.join # array_to_string(array, '', NULL)
|
|
166
|
+
# array_op.to_string # array_to_string(array, '', NULL)
|
|
167
|
+
# array_op.join(":") # array_to_string(array, ':', NULL)
|
|
168
|
+
# array_op.join(":", "*") # array_to_string(array, ':', '*')
|
|
169
|
+
def to_string(joiner="", null=nil)
|
|
170
|
+
function(:array_to_string, joiner, null)
|
|
171
|
+
end
|
|
172
|
+
alias join to_string
|
|
173
|
+
|
|
174
|
+
# Call the unnest method:
|
|
175
|
+
#
|
|
176
|
+
# array_op.unnest # unnest(array)
|
|
177
|
+
def unnest
|
|
178
|
+
function(:unnest)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Use the concatentation (||) operator, reversing the order:
|
|
182
|
+
#
|
|
183
|
+
# array_op.unshift(:a) # (a || array)
|
|
184
|
+
def unshift(other)
|
|
185
|
+
array_op(CONCAT, [wrap_array(other), self])
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
private
|
|
189
|
+
|
|
190
|
+
# Return a placeholder literal with the given str and args, wrapped
|
|
191
|
+
# in an ArrayOp, used by operators that return arrays.
|
|
192
|
+
def array_op(str, args)
|
|
193
|
+
ArrayOp.new(Sequel::SQL::PlaceholderLiteralString.new(str, args))
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Return a placeholder literal with the given str and args, wrapped
|
|
197
|
+
# in a boolean expression, used by operators that return booleans.
|
|
198
|
+
def bool_op(str, other)
|
|
199
|
+
Sequel::SQL::BooleanExpression.new(:NOOP, Sequel::SQL::PlaceholderLiteralString.new(str, [value, other]))
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Return a function with the given name, and the receiver as the first
|
|
203
|
+
# argument, with any additional arguments given.
|
|
204
|
+
def function(name, *args)
|
|
205
|
+
SQL::Function.new(name, self, *args)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Automatically wrap argument in a PGArray if it is a plain Array.
|
|
209
|
+
# Requires that the pg_array extension has been loaded to work.
|
|
210
|
+
def wrap_array(arg)
|
|
211
|
+
if arg.instance_of?(Array)
|
|
212
|
+
Sequel.pg_array(arg)
|
|
213
|
+
else
|
|
214
|
+
arg
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
module ArrayOpMethods
|
|
220
|
+
# Wrap the receiver in an ArrayOp so you can easily use the PostgreSQL
|
|
221
|
+
# array functions and operators with it.
|
|
222
|
+
def pg_array
|
|
223
|
+
ArrayOp.new(self)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
if defined?(PGArray)
|
|
228
|
+
class PGArray
|
|
229
|
+
# Wrap the PGArray instance in an ArrayOp, allowing you to easily use
|
|
230
|
+
# the PostgreSQL array functions and operators with literal arrays.
|
|
231
|
+
def op
|
|
232
|
+
ArrayOp.new(self)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
module SQL::Builders
|
|
239
|
+
# Return the object wrapped in an Postgres::ArrayOp.
|
|
240
|
+
def pg_array_op(v)
|
|
241
|
+
case v
|
|
242
|
+
when Postgres::ArrayOp
|
|
243
|
+
v
|
|
244
|
+
else
|
|
245
|
+
Postgres::ArrayOp.new(v)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
class SQL::GenericExpression
|
|
251
|
+
include Sequel::Postgres::ArrayOpMethods
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
class LiteralString
|
|
255
|
+
include Sequel::Postgres::ArrayOpMethods
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
if Sequel.core_extensions?
|
|
260
|
+
class Symbol
|
|
261
|
+
include Sequel::Postgres::ArrayOpMethods
|
|
262
|
+
end
|
|
263
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# This extension allows Sequel's postgres adapter to automatically
|
|
2
|
+
# parameterize all common queries. Sequel's default behavior has always
|
|
3
|
+
# been to literalize all arguments unless specifically using
|
|
4
|
+
# parameters (via :$arg placeholders and the prepare/call methods).
|
|
5
|
+
# This extension makes Sequel take all string, numeric, date, and
|
|
6
|
+
# time types and automatically turn them into parameters. Example:
|
|
7
|
+
#
|
|
8
|
+
# # Default
|
|
9
|
+
# DB[:test].where(:a=>1)
|
|
10
|
+
# # SQL: SELECT * FROM test WHERE a = 1
|
|
11
|
+
#
|
|
12
|
+
# DB.extension :pg_auto_parameterize
|
|
13
|
+
# DB[:test].where(:a=>1)
|
|
14
|
+
# # SQL: SELECT * FROM test WHERE a = $1 (args: [1])
|
|
15
|
+
#
|
|
16
|
+
# This extension is not necessarily faster or more safe than the
|
|
17
|
+
# default behavior. In some cases it is faster, such as when using
|
|
18
|
+
# large strings. However, there are also some known issues with
|
|
19
|
+
# this approach:
|
|
20
|
+
#
|
|
21
|
+
# 1. Because of the way it operates, it has no context to make a
|
|
22
|
+
# determination about whether to literalize an object or not.
|
|
23
|
+
# For example, if it comes across an integer, it will turn it
|
|
24
|
+
# into a parameter. That breaks code such as:
|
|
25
|
+
#
|
|
26
|
+
# DB[:table].select(:a, :b).order(2, 1)
|
|
27
|
+
#
|
|
28
|
+
# Since it will use the following SQL (which isn't valid):
|
|
29
|
+
#
|
|
30
|
+
# SELECT a, b FROM table ORDER BY $1, $2
|
|
31
|
+
#
|
|
32
|
+
# To work around this, you can either specify the columns
|
|
33
|
+
# manually or use a literal string:
|
|
34
|
+
#
|
|
35
|
+
# DB[:table].select(:a, :b).order(:b, :a)
|
|
36
|
+
# DB[:table].select(:a, :b).order(Sequel.lit('2, 1'))
|
|
37
|
+
#
|
|
38
|
+
# 2. In order to avoid many type errors, it attempts to guess the
|
|
39
|
+
# appropriate type and automatically casts all placeholders.
|
|
40
|
+
# Unfortunately, if the type guess is incorrect, the query will
|
|
41
|
+
# be rejected. For example, the following works without
|
|
42
|
+
# automatic parameterization, but fails with it:
|
|
43
|
+
#
|
|
44
|
+
# DB[:table].insert(:interval=>'1 day')
|
|
45
|
+
#
|
|
46
|
+
# To work around this, you can just add the necessary casts
|
|
47
|
+
# manually:
|
|
48
|
+
#
|
|
49
|
+
# DB[:table].insert(:interval=>'1 day'.cast(:interval))
|
|
50
|
+
#
|
|
51
|
+
# You can also work around any issues that come up by disabling automatic
|
|
52
|
+
# parameterization by calling the no_auto_parameterize method on the
|
|
53
|
+
# dataset (which returns a clone of the dataset).
|
|
54
|
+
#
|
|
55
|
+
# It is likely there are other corner cases I am not yet aware of
|
|
56
|
+
# when using this extension, so use this extension with caution.
|
|
57
|
+
#
|
|
58
|
+
# This extension is only compatible when using the pg driver, not
|
|
59
|
+
# when using the old postgres driver or the postgres-pr driver.
|
|
60
|
+
|
|
61
|
+
module Sequel
|
|
62
|
+
module Postgres
|
|
63
|
+
# Enable automatically parameterizing queries by hijacking the
|
|
64
|
+
# SQL query string that Sequel builds to also hold the array
|
|
65
|
+
# of parameters.
|
|
66
|
+
module AutoParameterize
|
|
67
|
+
# String that holds an array of parameters
|
|
68
|
+
class StringWithArray < ::String
|
|
69
|
+
PLACEHOLDER = '$'.freeze
|
|
70
|
+
CAST = '::'.freeze
|
|
71
|
+
|
|
72
|
+
# The array of parameters used by this query.
|
|
73
|
+
attr_reader :args
|
|
74
|
+
|
|
75
|
+
# Add a new parameter to this query, which adds
|
|
76
|
+
# the parameter to the array of parameters, and an
|
|
77
|
+
# SQL placeholder to the query itself.
|
|
78
|
+
def add_arg(s, type=nil)
|
|
79
|
+
@args ||= []
|
|
80
|
+
@args << s
|
|
81
|
+
self << PLACEHOLDER << @args.length.to_s
|
|
82
|
+
self << CAST << type.to_s if type
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Show args when the string is inspected
|
|
86
|
+
def inspect
|
|
87
|
+
@args ? "#{self}; #{@args.inspect}".inspect : super
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
module DatabaseMethods
|
|
92
|
+
# Extend the database's datasets with the necessary code.
|
|
93
|
+
def self.extended(db)
|
|
94
|
+
db.extend_datasets(DatasetMethods)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# If the sql string has an embedded parameter array,
|
|
98
|
+
# extract the arguments from that.
|
|
99
|
+
def execute(sql, opts={})
|
|
100
|
+
if sql.is_a?(StringWithArray) && (args = sql.args)
|
|
101
|
+
opts = opts.merge(:arguments=>args)
|
|
102
|
+
end
|
|
103
|
+
super
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
module DatasetMethods
|
|
108
|
+
# Return a clone of the dataset that will not do
|
|
109
|
+
# automatic parameterization.
|
|
110
|
+
def no_auto_parameterize
|
|
111
|
+
clone(:no_auto_parameterize=>true)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# For strings, numeric arguments, and date/time arguments, add
|
|
115
|
+
# them as parameters to the query instead of literalizing them
|
|
116
|
+
# into the SQL.
|
|
117
|
+
def literal_append(sql, v)
|
|
118
|
+
if sql.is_a?(StringWithArray)
|
|
119
|
+
case v
|
|
120
|
+
when String
|
|
121
|
+
case v
|
|
122
|
+
when LiteralString
|
|
123
|
+
super
|
|
124
|
+
when Sequel::SQL::Blob
|
|
125
|
+
sql.add_arg(v, :bytea)
|
|
126
|
+
else
|
|
127
|
+
sql.add_arg(v)
|
|
128
|
+
end
|
|
129
|
+
when Bignum
|
|
130
|
+
sql.add_arg(v, :int8)
|
|
131
|
+
when Fixnum
|
|
132
|
+
sql.add_arg(v, :int4)
|
|
133
|
+
when Float
|
|
134
|
+
sql.add_arg(v, :"double precision")
|
|
135
|
+
when BigDecimal
|
|
136
|
+
sql.add_arg(v, :numeric)
|
|
137
|
+
when Sequel::SQLTime
|
|
138
|
+
sql.add_arg(v, :time)
|
|
139
|
+
when Time, DateTime
|
|
140
|
+
sql.add_arg(v, :timestamp)
|
|
141
|
+
when Date
|
|
142
|
+
sql.add_arg(v, :date)
|
|
143
|
+
else
|
|
144
|
+
super
|
|
145
|
+
end
|
|
146
|
+
else
|
|
147
|
+
super
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def use_cursor(*)
|
|
152
|
+
super.no_auto_parameterize
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
protected
|
|
156
|
+
|
|
157
|
+
# Disable automatic parameterization for prepared statements,
|
|
158
|
+
# since they will use manual parameterization.
|
|
159
|
+
def to_prepared_statement(*a)
|
|
160
|
+
opts[:no_auto_parameterize] ? super : no_auto_parameterize.to_prepared_statement(*a)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
private
|
|
164
|
+
|
|
165
|
+
# Unless auto parameterization is turned off, use a string that
|
|
166
|
+
# can store the parameterized arguments.
|
|
167
|
+
def sql_string_origin
|
|
168
|
+
opts[:no_auto_parameterize] ? super : StringWithArray.new
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
Database.register_extension(:pg_auto_parameterize, Postgres::AutoParameterize::DatabaseMethods)
|
|
175
|
+
end
|