sequel 3.21.0 → 3.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +1061 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +103 -63
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +67 -51
- data/doc/advanced_associations.rdoc +189 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +547 -0
- data/doc/opening_databases.rdoc +114 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +18 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +453 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +56 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +73 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +279 -97
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +125 -222
- data/lib/sequel/adapters/mysql2.rb +65 -56
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +349 -53
- data/lib/sequel/adapters/postgres.rb +368 -138
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +343 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +401 -116
- data/lib/sequel/adapters/shared/mysql.rb +424 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +257 -45
- data/lib/sequel/adapters/shared/postgres.rb +675 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +285 -96
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +28 -19
- data/lib/sequel/adapters/tinytds.rb +174 -22
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +11 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +43 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +38 -28
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +190 -46
- data/lib/sequel/database/query.rb +272 -110
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +300 -67
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +305 -54
- data/lib/sequel/dataset/sql.rb +720 -292
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +537 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +313 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +208 -0
- data/lib/sequel/extensions/pg_range.rb +512 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +58 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +167 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +55 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +649 -122
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +194 -66
- data/spec/adapters/mysql_spec.rb +475 -306
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +1982 -325
- data/spec/adapters/spec_helper.rb +9 -6
- data/spec/adapters/sqlite_spec.rb +203 -75
- data/spec/core/connection_pool_spec.rb +218 -93
- data/spec/core/database_spec.rb +956 -522
- data/spec/core/dataset_spec.rb +1631 -1242
- data/spec/core/expression_filters_spec.rb +690 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +320 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +194 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +23 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +8 -11
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +58 -67
- data/spec/extensions/validation_helpers_spec.rb +31 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +11 -5
- data/spec/integration/dataset_test.rb +717 -129
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +604 -147
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +367 -57
- data/spec/integration/spec_helper.rb +42 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +31 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +209 -80
- data/spec/core/core_sql_spec.rb +0 -451
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Postgres::HStoreOp" do
|
|
4
|
+
before do
|
|
5
|
+
@ds = Sequel.connect('mock://postgres', :quote_identifiers=>false).dataset
|
|
6
|
+
@h = Sequel.hstore_op(:h)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "#- should use the - operator" do
|
|
10
|
+
@ds.literal(@h - 'a').should == "(h - 'a')"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "#- should return an HStoreOp" do
|
|
14
|
+
@ds.literal((@h - 'a')['a']).should == "((h - 'a') -> 'a')"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "#[] should use the -> operator" do
|
|
18
|
+
@ds.literal(@h['a']).should == "(h -> 'a')"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "#[] should return a string expression" do
|
|
22
|
+
@ds.literal(@h['a'] + 'b').should == "((h -> 'a') || 'b')"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "#concat and #merge should use the || operator" do
|
|
26
|
+
@ds.literal(@h.concat(:h1)).should == "(h || h1)"
|
|
27
|
+
@ds.literal(@h.merge(:h1)).should == "(h || h1)"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "#concat should return an HStoreOp" do
|
|
31
|
+
@ds.literal(@h.concat(:h1)['a']).should == "((h || h1) -> 'a')"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "#contain_all should use the ?& operator" do
|
|
35
|
+
@ds.literal(@h.contain_all(:h1)).should == "(h ?& h1)"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "#contain_any should use the ?| operator" do
|
|
39
|
+
@ds.literal(@h.contain_any(:h1)).should == "(h ?| h1)"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "#contains should use the @> operator" do
|
|
43
|
+
@ds.literal(@h.contains(:h1)).should == "(h @> h1)"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "#contained_by should use the <@ operator" do
|
|
47
|
+
@ds.literal(@h.contained_by(:h1)).should == "(h <@ h1)"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "#defined should use the defined function" do
|
|
51
|
+
@ds.literal(@h.defined('a')).should == "defined(h, 'a')"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "#delete should use the delete function" do
|
|
55
|
+
@ds.literal(@h.delete('a')).should == "delete(h, 'a')"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "#delete should return an HStoreOp" do
|
|
59
|
+
@ds.literal(@h.delete('a')['a']).should == "(delete(h, 'a') -> 'a')"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "#each should use the each function" do
|
|
63
|
+
@ds.literal(@h.each).should == "each(h)"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "#has_key? and aliases should use the ? operator" do
|
|
67
|
+
@ds.literal(@h.has_key?('a')).should == "(h ? 'a')"
|
|
68
|
+
@ds.literal(@h.key?('a')).should == "(h ? 'a')"
|
|
69
|
+
@ds.literal(@h.member?('a')).should == "(h ? 'a')"
|
|
70
|
+
@ds.literal(@h.include?('a')).should == "(h ? 'a')"
|
|
71
|
+
@ds.literal(@h.exist?('a')).should == "(h ? 'a')"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "#hstore should return the receiver" do
|
|
75
|
+
@h.hstore.should equal(@h)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "#keys and #akeys should use the akeys function" do
|
|
79
|
+
@ds.literal(@h.keys).should == "akeys(h)"
|
|
80
|
+
@ds.literal(@h.akeys).should == "akeys(h)"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "#populate should use the populate_record function" do
|
|
84
|
+
@ds.literal(@h.populate(:a)).should == "populate_record(a, h)"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "#record_set should use the #= operator" do
|
|
88
|
+
@ds.literal(@h.record_set(:a)).should == "(a #= h)"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "#skeys should use the skeys function" do
|
|
92
|
+
@ds.literal(@h.skeys).should == "skeys(h)"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "#slice should should use the slice function" do
|
|
96
|
+
@ds.literal(@h.slice(:a)).should == "slice(h, a)"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "#slice should return an HStoreOp" do
|
|
100
|
+
@ds.literal(@h.slice(:a)['a']).should == "(slice(h, a) -> 'a')"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "#svals should use the svals function" do
|
|
104
|
+
@ds.literal(@h.svals).should == "svals(h)"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "#to_array should use the hstore_to_array function" do
|
|
108
|
+
@ds.literal(@h.to_array).should == "hstore_to_array(h)"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "#to_matrix should use the hstore_to_matrix function" do
|
|
112
|
+
@ds.literal(@h.to_matrix).should == "hstore_to_matrix(h)"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "#values and #avals should use the avals function" do
|
|
116
|
+
@ds.literal(@h.values).should == "avals(h)"
|
|
117
|
+
@ds.literal(@h.avals).should == "avals(h)"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "should have Sequel.hstore_op return HStoreOp instances as-is" do
|
|
121
|
+
Sequel.hstore_op(@h).should equal(@h)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should have Sequel.hstore return HStoreOp instances" do
|
|
125
|
+
Sequel.hstore(:h).should == @h
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should be able to turn expressions into hstore ops using hstore" do
|
|
129
|
+
@ds.literal(Sequel.qualify(:b, :a).hstore['a']).should == "(b.a -> 'a')"
|
|
130
|
+
@ds.literal(Sequel.function(:a, :b).hstore['a']).should == "(a(b) -> 'a')"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "should be able to turn literal strings into hstore ops using hstore" do
|
|
134
|
+
@ds.literal(Sequel.lit('a').hstore['a']).should == "(a -> 'a')"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "should allow transforming HStore instances into HStoreOp instances" do
|
|
138
|
+
@ds.literal(Sequel.hstore('a'=>'b').op['a']).should == "('\"a\"=>\"b\"'::hstore -> 'a')"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "pg_hstore extension" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
|
|
6
|
+
@m = Sequel::Postgres
|
|
7
|
+
@c = @m::HStore
|
|
8
|
+
@db.extension :pg_hstore
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should parse hstore strings correctly" do
|
|
12
|
+
@c.parse('').to_hash.should == {}
|
|
13
|
+
@c.parse('"a"=>"b"').to_hash.should == {'a'=>'b'}
|
|
14
|
+
@c.parse('"a"=>"b", "c"=>NULL').to_hash.should == {'a'=>'b', 'c'=>nil}
|
|
15
|
+
@c.parse('"a"=>"b", "c"=>"NULL"').to_hash.should == {'a'=>'b', 'c'=>'NULL'}
|
|
16
|
+
@c.parse('"a"=>"b", "c"=>"\\\\ \\"\'=>"').to_hash.should == {'a'=>'b', 'c'=>'\ "\'=>'}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should cache parse results" do
|
|
20
|
+
r = @c::Parser.new('')
|
|
21
|
+
o = r.parse
|
|
22
|
+
o.should == {}
|
|
23
|
+
r.parse.should equal(o)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should literalize HStores to strings correctly" do
|
|
27
|
+
@db.literal(Sequel.hstore({})).should == '\'\'::hstore'
|
|
28
|
+
@db.literal(Sequel.hstore("a"=>"b")).should == '\'"a"=>"b"\'::hstore'
|
|
29
|
+
@db.literal(Sequel.hstore("c"=>nil)).should == '\'"c"=>NULL\'::hstore'
|
|
30
|
+
@db.literal(Sequel.hstore("c"=>'NULL')).should == '\'"c"=>"NULL"\'::hstore'
|
|
31
|
+
@db.literal(Sequel.hstore('c'=>'\ "\'=>')).should == '\'"c"=>"\\\\ \\"\'\'=>"\'::hstore'
|
|
32
|
+
['\'"a"=>"b","c"=>"d"\'::hstore', '\'"c"=>"d","a"=>"b"\'::hstore'].should include(@db.literal(Sequel.hstore("a"=>"b","c"=>"d")))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should have Sequel.hstore method for creating HStore instances" do
|
|
36
|
+
Sequel.hstore({}).should be_a_kind_of(@c)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should have Sequel.hstore return HStores as-is" do
|
|
40
|
+
a = Sequel.hstore({})
|
|
41
|
+
Sequel.hstore(a).should equal(a)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should HStore#to_hash method for getting underlying hash" do
|
|
45
|
+
Sequel.hstore({}).to_hash.should be_a_kind_of(Hash)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should convert keys and values to strings on creation" do
|
|
49
|
+
Sequel.hstore(1=>2).to_hash.should == {"1"=>"2"}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should convert keys and values to strings on assignment" do
|
|
53
|
+
v = Sequel.hstore({})
|
|
54
|
+
v[1] = 2
|
|
55
|
+
v.to_hash.should == {"1"=>"2"}
|
|
56
|
+
v.store(:'1', 3)
|
|
57
|
+
v.to_hash.should == {"1"=>"3"}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should not convert nil values to strings on creation" do
|
|
61
|
+
Sequel.hstore(:foo=>nil).to_hash.should == {"foo"=>nil}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should not convert nil values to strings on assignment" do
|
|
65
|
+
v = Sequel.hstore({})
|
|
66
|
+
v[:foo] = nil
|
|
67
|
+
v.to_hash.should == {"foo"=>nil}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should convert lookups by key to string" do
|
|
71
|
+
Sequel.hstore('foo'=>'bar')[:foo].should == 'bar'
|
|
72
|
+
Sequel.hstore('1'=>'bar')[1].should == 'bar'
|
|
73
|
+
|
|
74
|
+
Sequel.hstore('foo'=>'bar').fetch(:foo).should == 'bar'
|
|
75
|
+
Sequel.hstore('foo'=>'bar').fetch(:foo2, 2).should == 2
|
|
76
|
+
k = nil
|
|
77
|
+
Sequel.hstore('foo2'=>'bar').fetch(:foo){|key| k = key }.should == 'foo'
|
|
78
|
+
k.should == 'foo'
|
|
79
|
+
|
|
80
|
+
Sequel.hstore('foo'=>'bar').has_key?(:foo).should be_true
|
|
81
|
+
Sequel.hstore('foo'=>'bar').has_key?(:bar).should be_false
|
|
82
|
+
Sequel.hstore('foo'=>'bar').key?(:foo).should be_true
|
|
83
|
+
Sequel.hstore('foo'=>'bar').key?(:bar).should be_false
|
|
84
|
+
Sequel.hstore('foo'=>'bar').member?(:foo).should be_true
|
|
85
|
+
Sequel.hstore('foo'=>'bar').member?(:bar).should be_false
|
|
86
|
+
Sequel.hstore('foo'=>'bar').include?(:foo).should be_true
|
|
87
|
+
Sequel.hstore('foo'=>'bar').include?(:bar).should be_false
|
|
88
|
+
|
|
89
|
+
Sequel.hstore('foo'=>'bar', '1'=>'2').values_at(:foo3, :foo, :foo2, 1).should == [nil, 'bar', nil, '2']
|
|
90
|
+
|
|
91
|
+
if RUBY_VERSION >= '1.9.0'
|
|
92
|
+
Sequel.hstore('foo'=>'bar').assoc(:foo).should == ['foo', 'bar']
|
|
93
|
+
Sequel.hstore('foo'=>'bar').assoc(:foo2).should == nil
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "should convert has_value?/value? lookups to string" do
|
|
98
|
+
Sequel.hstore('foo'=>'bar').has_value?(:bar).should be_true
|
|
99
|
+
Sequel.hstore('foo'=>'bar').has_value?(:foo).should be_false
|
|
100
|
+
Sequel.hstore('foo'=>'bar').value?(:bar).should be_true
|
|
101
|
+
Sequel.hstore('foo'=>'bar').value?(:foo).should be_false
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should handle nil values in has_value?/value? lookups" do
|
|
105
|
+
Sequel.hstore('foo'=>'').has_value?('').should be_true
|
|
106
|
+
Sequel.hstore('foo'=>'').has_value?(nil).should be_false
|
|
107
|
+
Sequel.hstore('foo'=>nil).has_value?(nil).should be_true
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should have underlying hash convert lookups by key to string" do
|
|
111
|
+
Sequel.hstore('foo'=>'bar').to_hash[:foo].should == 'bar'
|
|
112
|
+
Sequel.hstore('1'=>'bar').to_hash[1].should == 'bar'
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
if RUBY_VERSION >= '1.9.0'
|
|
116
|
+
it "should convert key lookups to string" do
|
|
117
|
+
Sequel.hstore('foo'=>'bar').key(:bar).should == 'foo'
|
|
118
|
+
Sequel.hstore('foo'=>'bar').key(:bar2).should be_nil
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "should handle nil values in key lookups" do
|
|
122
|
+
Sequel.hstore('foo'=>'').key('').should == 'foo'
|
|
123
|
+
Sequel.hstore('foo'=>'').key(nil).should == nil
|
|
124
|
+
Sequel.hstore('foo'=>nil).key(nil).should == 'foo'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "should convert rassoc lookups to string" do
|
|
128
|
+
Sequel.hstore('foo'=>'bar').rassoc(:bar).should == ['foo', 'bar']
|
|
129
|
+
Sequel.hstore('foo'=>'bar').rassoc(:bar2).should be_nil
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "should handle nil values in rassoc lookups" do
|
|
133
|
+
Sequel.hstore('foo'=>'').rassoc('').should == ['foo', '']
|
|
134
|
+
Sequel.hstore('foo'=>'').rassoc(nil).should == nil
|
|
135
|
+
Sequel.hstore('foo'=>nil).rassoc(nil).should == ['foo', nil]
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "should have delete convert key to string" do
|
|
140
|
+
v = Sequel.hstore('foo'=>'bar')
|
|
141
|
+
v.delete(:foo).should == 'bar'
|
|
142
|
+
v.to_hash.should == {}
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should handle #replace with hashes that do not use strings" do
|
|
146
|
+
v = Sequel.hstore('foo'=>'bar')
|
|
147
|
+
v.replace(:bar=>1)
|
|
148
|
+
v.should be_a_kind_of(@c)
|
|
149
|
+
v.should == {'bar'=>'1'}
|
|
150
|
+
v.to_hash[:bar].should == '1'
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should handle #merge with hashes that do not use strings" do
|
|
154
|
+
v = Sequel.hstore('foo'=>'bar').merge(:bar=>1)
|
|
155
|
+
v.should be_a_kind_of(@c)
|
|
156
|
+
v.should == {'foo'=>'bar', 'bar'=>'1'}
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "should handle #merge/#update with hashes that do not use strings" do
|
|
160
|
+
v = Sequel.hstore('foo'=>'bar')
|
|
161
|
+
v.merge!(:bar=>1)
|
|
162
|
+
v.should be_a_kind_of(@c)
|
|
163
|
+
v.should == {'foo'=>'bar', 'bar'=>'1'}
|
|
164
|
+
|
|
165
|
+
v = Sequel.hstore('foo'=>'bar')
|
|
166
|
+
v.update(:bar=>1)
|
|
167
|
+
v.should be_a_kind_of(@c)
|
|
168
|
+
v.should == {'foo'=>'bar', 'bar'=>'1'}
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "should support using hstores as bound variables" do
|
|
172
|
+
@db.bound_variable_arg(1, nil).should == 1
|
|
173
|
+
@db.bound_variable_arg({'1'=>'2'}, nil).should == '"1"=>"2"'
|
|
174
|
+
@db.bound_variable_arg(Sequel.hstore('1'=>'2'), nil).should == '"1"=>"2"'
|
|
175
|
+
@db.bound_variable_arg(Sequel.hstore('1'=>nil), nil).should == '"1"=>NULL'
|
|
176
|
+
@db.bound_variable_arg(Sequel.hstore('1'=>"NULL"), nil).should == '"1"=>"NULL"'
|
|
177
|
+
@db.bound_variable_arg(Sequel.hstore('1'=>"'\\ \"=>"), nil).should == '"1"=>"\'\\\\ \\"=>"'
|
|
178
|
+
['"a"=>"b","c"=>"d"', '"c"=>"d","a"=>"b"'].should include(@db.bound_variable_arg(Sequel.hstore("a"=>"b","c"=>"d"), nil))
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "should parse hstore type from the schema correctly" do
|
|
182
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer'}, {:name=>'i', :db_type=>'hstore'}]
|
|
183
|
+
@db.schema(:items).map{|e| e[1][:type]}.should == [:integer, :hstore]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "should support typecasting for the hstore type" do
|
|
187
|
+
h = Sequel.hstore(1=>2)
|
|
188
|
+
@db.typecast_value(:hstore, h).should equal(h)
|
|
189
|
+
@db.typecast_value(:hstore, {}).should be_a_kind_of(@c)
|
|
190
|
+
@db.typecast_value(:hstore, {}).should == Sequel.hstore({})
|
|
191
|
+
@db.typecast_value(:hstore, {'a'=>'b'}).should == Sequel.hstore("a"=>"b")
|
|
192
|
+
proc{@db.typecast_value(:hstore, [])}.should raise_error(Sequel::InvalidValue)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "pg_inet extension" do
|
|
4
|
+
ipv6_broken = (IPAddr.new('::1'); false) rescue true
|
|
5
|
+
before do
|
|
6
|
+
@db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
|
|
7
|
+
@db.extension(:pg_array, :pg_inet)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should literalize IPAddr v4 instances to strings correctly" do
|
|
11
|
+
@db.literal(IPAddr.new('127.0.0.1')).should == "'127.0.0.1/32'"
|
|
12
|
+
@db.literal(IPAddr.new('127.0.0.0/8')).should == "'127.0.0.0/8'"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should literalize IPAddr v6 instances to strings correctly" do
|
|
16
|
+
@db.literal(IPAddr.new('2001:4f8:3:ba::/64')).should == "'2001:4f8:3:ba::/64'"
|
|
17
|
+
@db.literal(IPAddr.new('2001:4f8:3:ba:2e0:81ff:fe22:d1f1')).should == "'2001:4f8:3:ba:2e0:81ff:fe22:d1f1/128'"
|
|
18
|
+
end unless ipv6_broken
|
|
19
|
+
|
|
20
|
+
it "should not affect literalization of custom objects" do
|
|
21
|
+
o = Object.new
|
|
22
|
+
def o.sql_literal(ds) 'v' end
|
|
23
|
+
@db.literal(o).should == 'v'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should support using IPAddr as bound variables" do
|
|
27
|
+
@db.bound_variable_arg(1, nil).should == 1
|
|
28
|
+
@db.bound_variable_arg(IPAddr.new('127.0.0.1'), nil).should == '127.0.0.1/32'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should support using IPAddr instances in array types in bound variables" do
|
|
32
|
+
@db.bound_variable_arg(Sequel.pg_array([IPAddr.new('127.0.0.1')]), nil).should == '{"127.0.0.1/32"}'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should parse inet/cidr type from the schema correctly" do
|
|
36
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer'}, {:name=>'i', :db_type=>'inet'}, {:name=>'c', :db_type=>'cidr'}]
|
|
37
|
+
@db.schema(:items).map{|e| e[1][:type]}.should == [:integer, :ipaddr, :ipaddr]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should support typecasting for the ipaddr type" do
|
|
41
|
+
ip = IPAddr.new('127.0.0.1')
|
|
42
|
+
@db.typecast_value(:ipaddr, ip).should equal(ip)
|
|
43
|
+
@db.typecast_value(:ipaddr, ip.to_s).should == ip
|
|
44
|
+
proc{@db.typecast_value(:ipaddr, '')}.should raise_error(Sequel::InvalidValue)
|
|
45
|
+
proc{@db.typecast_value(:ipaddr, 1)}.should raise_error(Sequel::InvalidValue)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'active_support/duration'
|
|
5
|
+
rescue LoadError => e
|
|
6
|
+
skip_warn "pg_interval plugin: can't load active_support/duration (#{e.class}: #{e})"
|
|
7
|
+
else
|
|
8
|
+
describe "pg_interval extension" do
|
|
9
|
+
before do
|
|
10
|
+
@db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
|
|
11
|
+
@db.extension(:pg_array, :pg_interval)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should literalize ActiveSupport::Duration instances to strings correctly" do
|
|
15
|
+
@db.literal(ActiveSupport::Duration.new(0, [])).should == "'0'::interval"
|
|
16
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 0]])).should == "'0'::interval"
|
|
17
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 10], [:minutes, 20], [:days, 3], [:months, 4], [:years, 6]])).should == "'6 years 4 months 3 days 20 minutes 10 seconds '::interval"
|
|
18
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, -10.000001], [:minutes, -20], [:days, -3], [:months, -4], [:years, -6]])).should == "'-6 years -4 months -3 days -20 minutes -10.000001 seconds '::interval"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should literalize ActiveSupport::Duration instances with repeated parts correctly" do
|
|
22
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1]])).should == "'3 seconds '::interval"
|
|
23
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1], [:days, 1], [:days, 4]])).should == "'5 days 3 seconds '::interval"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should not affect literalization of custom objects" do
|
|
27
|
+
o = Object.new
|
|
28
|
+
def o.sql_literal(ds) 'v' end
|
|
29
|
+
@db.literal(o).should == 'v'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should support using ActiveSupport::Duration instances as bound variables" do
|
|
33
|
+
@db.bound_variable_arg(1, nil).should == 1
|
|
34
|
+
@db.bound_variable_arg(ActiveSupport::Duration.new(0, [[:seconds, 0]]), nil).should == '0'
|
|
35
|
+
@db.bound_variable_arg(ActiveSupport::Duration.new(0, [[:seconds, -10.000001], [:minutes, -20], [:days, -3], [:months, -4], [:years, -6]]), nil).should == '-6 years -4 months -3 days -20 minutes -10.000001 seconds '
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should support using ActiveSupport::Duration instances in array types in bound variables" do
|
|
39
|
+
@db.bound_variable_arg(Sequel.pg_array([ActiveSupport::Duration.new(0, [[:seconds, 0]])]), nil).should == '{"0"}'
|
|
40
|
+
@db.bound_variable_arg(Sequel.pg_array([ActiveSupport::Duration.new(0, [[:seconds, -10.000001], [:minutes, -20], [:days, -3], [:months, -4], [:years, -6]])]), nil).should == '{"-6 years -4 months -3 days -20 minutes -10.000001 seconds "}'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should parse interval type from the schema correctly" do
|
|
44
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer'}, {:name=>'i', :db_type=>'interval'}]
|
|
45
|
+
@db.schema(:items).map{|e| e[1][:type]}.should == [:integer, :interval]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should support typecasting for the interval type" do
|
|
49
|
+
ip = IPAddr.new('127.0.0.1')
|
|
50
|
+
d = ActiveSupport::Duration.new(31557600 + 2*86400*30 + 3*86400*7 + 4*86400 + 5*3600 + 6*60 + 7, [[:years, 1], [:months, 2], [:days, 25], [:seconds, 18367]])
|
|
51
|
+
@db.typecast_value(:interval, d).object_id.should == d.object_id
|
|
52
|
+
|
|
53
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07").is_a?(ActiveSupport::Duration).should be_true
|
|
54
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07").should == d
|
|
55
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07").parts.sort_by{|k,v| k.to_s}.should == d.parts.sort_by{|k,v| k.to_s}
|
|
56
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07.0").parts.sort_by{|k,v| k.to_s}.should == d.parts.sort_by{|k,v| k.to_s}
|
|
57
|
+
|
|
58
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7 secs").is_a?(ActiveSupport::Duration).should be_true
|
|
59
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7 secs").should == d
|
|
60
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7 secs").parts.sort_by{|k,v| k.to_s}.should == d.parts.sort_by{|k,v| k.to_s}
|
|
61
|
+
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7.0 secs").parts.sort_by{|k,v| k.to_s}.should == d.parts.sort_by{|k,v| k.to_s}
|
|
62
|
+
|
|
63
|
+
d2 = ActiveSupport::Duration.new(1, [[:seconds, 1]])
|
|
64
|
+
@db.typecast_value(:interval, 1).is_a?(ActiveSupport::Duration).should be_true
|
|
65
|
+
@db.typecast_value(:interval, 1).should == d2
|
|
66
|
+
@db.typecast_value(:interval, 1).parts.sort_by{|k,v| k.to_s}.should == d2.parts.sort_by{|k,v| k.to_s}
|
|
67
|
+
|
|
68
|
+
proc{@db.typecast_value(:interval, 'foo')}.should raise_error(Sequel::InvalidValue)
|
|
69
|
+
proc{@db.typecast_value(:interval, Object.new)}.should raise_error(Sequel::InvalidValue)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "pg_json extension" do
|
|
4
|
+
before(:all) do
|
|
5
|
+
m = Sequel::Postgres
|
|
6
|
+
@m = m::JSONDatabaseMethods
|
|
7
|
+
@hc = m::JSONHash
|
|
8
|
+
@ac = m::JSONArray
|
|
9
|
+
|
|
10
|
+
# Create subclass in correct namespace for easily overriding methods
|
|
11
|
+
j = m::JSON = JSON.dup
|
|
12
|
+
j.instance_eval do
|
|
13
|
+
Parser = JSON::Parser
|
|
14
|
+
alias old_parse parse
|
|
15
|
+
def parse(s)
|
|
16
|
+
return 1 if s == '1'
|
|
17
|
+
old_parse(s)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
before do
|
|
22
|
+
@db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
|
|
23
|
+
@db.extension(:pg_array, :pg_json)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should parse json strings correctly" do
|
|
27
|
+
@m.parse_json('[]').should be_a_kind_of(@ac)
|
|
28
|
+
@m.parse_json('[]').to_a.should == []
|
|
29
|
+
@m.parse_json('[1]').to_a.should == [1]
|
|
30
|
+
@m.parse_json('[1, 2]').to_a.should == [1, 2]
|
|
31
|
+
@m.parse_json('[1, [2], {"a": "b"}]').to_a.should == [1, [2], {'a'=>'b'}]
|
|
32
|
+
@m.parse_json('{}').should be_a_kind_of(@hc)
|
|
33
|
+
@m.parse_json('{}').to_hash.should == {}
|
|
34
|
+
@m.parse_json('{"a": "b"}').to_hash.should == {'a'=>'b'}
|
|
35
|
+
@m.parse_json('{"a": "b", "c": [1, 2, 3]}').to_hash.should == {'a'=>'b', 'c'=>[1, 2, 3]}
|
|
36
|
+
@m.parse_json('{"a": "b", "c": {"d": "e"}}').to_hash.should == {'a'=>'b', 'c'=>{'d'=>'e'}}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should raise an error when attempting to parse invalid json" do
|
|
40
|
+
proc{@m.parse_json('')}.should raise_error(Sequel::InvalidValue)
|
|
41
|
+
proc{@m.parse_json('1')}.should raise_error(Sequel::InvalidValue)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should literalize HStores to strings correctly" do
|
|
45
|
+
@db.literal(Sequel.pg_json([])).should == "'[]'::json"
|
|
46
|
+
@db.literal(Sequel.pg_json([1, [2], {'a'=>'b'}])).should == "'[1,[2],{\"a\":\"b\"}]'::json"
|
|
47
|
+
@db.literal(Sequel.pg_json({})).should == "'{}'::json"
|
|
48
|
+
@db.literal(Sequel.pg_json('a'=>'b')).should == "'{\"a\":\"b\"}'::json"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should have Sequel.pg_json return JSONHash and JSONArray as is" do
|
|
52
|
+
a = Sequel.pg_json({})
|
|
53
|
+
Sequel.pg_json(a).should equal(a)
|
|
54
|
+
a = Sequel.pg_json([])
|
|
55
|
+
Sequel.pg_json(a).should equal(a)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should have Sequel.pg_json raise an Error if called with a non-hash or array" do
|
|
59
|
+
proc{Sequel.pg_json(:a)}.should raise_error(Sequel::Error)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should have JSONHash#to_hash method for getting underlying hash" do
|
|
63
|
+
Sequel.pg_json({}).to_hash.should be_a_kind_of(Hash)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should have JSONArray#to_a method for getting underlying array" do
|
|
67
|
+
Sequel.pg_json([]).to_a.should be_a_kind_of(Array)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should support using JSONHash and JSONArray as bound variables" do
|
|
71
|
+
@db.bound_variable_arg(1, nil).should == 1
|
|
72
|
+
@db.bound_variable_arg(Sequel.pg_json([1]), nil).should == '[1]'
|
|
73
|
+
@db.bound_variable_arg(Sequel.pg_json('a'=>'b'), nil).should == '{"a":"b"}'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should support using json[] types in bound variables" do
|
|
77
|
+
@db.bound_variable_arg(Sequel.pg_array([Sequel.pg_json([{"a"=>1}]), Sequel.pg_json("b"=>[1, 2])]), nil).should == '{"[{\\"a\\":1}]","{\\"b\\":[1,2]}"}'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should parse json type from the schema correctly" do
|
|
81
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer'}, {:name=>'i', :db_type=>'json'}]
|
|
82
|
+
@db.schema(:items).map{|e| e[1][:type]}.should == [:integer, :json]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should support typecasting for the json type" do
|
|
86
|
+
h = Sequel.pg_json(1=>2)
|
|
87
|
+
a = Sequel.pg_json([1])
|
|
88
|
+
@db.typecast_value(:json, h).should equal(h)
|
|
89
|
+
@db.typecast_value(:json, h.to_hash).should == h
|
|
90
|
+
@db.typecast_value(:json, h.to_hash).should be_a_kind_of(@hc)
|
|
91
|
+
@db.typecast_value(:json, a).should equal(a)
|
|
92
|
+
@db.typecast_value(:json, a.to_a).should == a
|
|
93
|
+
@db.typecast_value(:json, a.to_a).should be_a_kind_of(@ac)
|
|
94
|
+
@db.typecast_value(:json, '[]').should == Sequel.pg_json([])
|
|
95
|
+
@db.typecast_value(:json, '{"a": "b"}').should == Sequel.pg_json("a"=>"b")
|
|
96
|
+
proc{@db.typecast_value(:json, '')}.should raise_error(Sequel::InvalidValue)
|
|
97
|
+
proc{@db.typecast_value(:json, 1)}.should raise_error(Sequel::InvalidValue)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Postgres::RangeOp" do
|
|
4
|
+
before do
|
|
5
|
+
@ds = Sequel.connect('mock://postgres', :quote_identifiers=>false).dataset
|
|
6
|
+
@h = Sequel.pg_range_op(:h)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "#pg_range should return self" do
|
|
10
|
+
@h.pg_range.should equal(@h)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "Sequel.pg_range_op should return argument if already a RangeOp" do
|
|
14
|
+
Sequel.pg_range_op(@h).should equal(@h)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "Sequel.pg_range should return a new RangeOp if not given a range" do
|
|
18
|
+
@ds.literal(Sequel.pg_range(:h).lower).should == "lower(h)"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "#pg_range should return a RangeOp for literal strings, and expressions" do
|
|
22
|
+
@ds.literal(Sequel.function(:b, :h).pg_range.lower).should == "lower(b(h))"
|
|
23
|
+
@ds.literal(Sequel.lit('h').pg_range.lower).should == "lower(h)"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "PGRange#op should return a RangeOp" do
|
|
27
|
+
@ds.literal(Sequel.pg_range(1..2, :numrange).op.lower).should == "lower('[1,2]'::numrange)"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should define methods for all of the the PostgreSQL range operators" do
|
|
31
|
+
@ds.literal(@h.contains(@h)).should == "(h @> h)"
|
|
32
|
+
@ds.literal(@h.contained_by(@h)).should == "(h <@ h)"
|
|
33
|
+
@ds.literal(@h.overlaps(@h)).should == "(h && h)"
|
|
34
|
+
@ds.literal(@h.left_of(@h)).should == "(h << h)"
|
|
35
|
+
@ds.literal(@h.right_of(@h)).should == "(h >> h)"
|
|
36
|
+
@ds.literal(@h.starts_before(@h)).should == "(h &< h)"
|
|
37
|
+
@ds.literal(@h.ends_after(@h)).should == "(h &> h)"
|
|
38
|
+
@ds.literal(@h.adjacent_to(@h)).should == "(h -|- h)"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should define methods for all of the the PostgreSQL range functions" do
|
|
42
|
+
@ds.literal(@h.lower).should == "lower(h)"
|
|
43
|
+
@ds.literal(@h.upper).should == "upper(h)"
|
|
44
|
+
@ds.literal(@h.isempty).should == "isempty(h)"
|
|
45
|
+
@ds.literal(@h.lower_inc).should == "lower_inc(h)"
|
|
46
|
+
@ds.literal(@h.upper_inc).should == "upper_inc(h)"
|
|
47
|
+
@ds.literal(@h.lower_inf).should == "lower_inf(h)"
|
|
48
|
+
@ds.literal(@h.upper_inf).should == "upper_inf(h)"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "+ - * operators should be defined and return a RangeOp" do
|
|
52
|
+
@ds.literal((@h + @h).lower).should == "lower((h + h))"
|
|
53
|
+
@ds.literal((@h * @h).lower).should == "lower((h * h))"
|
|
54
|
+
@ds.literal((@h - @h).lower).should == "lower((h - h))"
|
|
55
|
+
end
|
|
56
|
+
end
|