sequel 3.21.0 → 3.36.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 +855 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -7
- data/Rakefile +42 -24
- data/bin/sequel +26 -8
- data/doc/active_record.rdoc +1 -0
- data/doc/advanced_associations.rdoc +171 -11
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +85 -552
- data/doc/model_hooks.rdoc +78 -27
- data/doc/object_model.rdoc +541 -0
- data/doc/opening_databases.rdoc +97 -50
- data/doc/prepared_statements.rdoc +40 -14
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +30 -4
- 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/schema_modification.rdoc +572 -0
- data/doc/sharding.rdoc +95 -3
- data/doc/testing.rdoc +129 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +51 -2
- 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 +1 -57
- 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 +47 -0
- data/lib/sequel/adapters/jdbc/derby.rb +287 -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 +29 -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 +58 -48
- 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 +265 -94
- data/lib/sequel/adapters/mock.rb +361 -0
- data/lib/sequel/adapters/mysql.rb +118 -222
- data/lib/sequel/adapters/mysql2.rb +58 -57
- data/lib/sequel/adapters/odbc/mssql.rb +15 -7
- 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 +356 -107
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +342 -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 +335 -118
- data/lib/sequel/adapters/shared/mysql.rb +340 -76
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
- data/lib/sequel/adapters/shared/oracle.rb +243 -45
- data/lib/sequel/adapters/shared/postgres.rb +524 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +265 -89
- data/lib/sequel/adapters/sqlite.rb +101 -39
- data/lib/sequel/adapters/swift/mysql.rb +9 -12
- data/lib/sequel/adapters/swift/postgres.rb +9 -74
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +8 -7
- data/lib/sequel/adapters/tinytds.rb +161 -21
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -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 +28 -2
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +38 -14
- data/lib/sequel/connection_pool.rb +10 -2
- data/lib/sequel/core.rb +118 -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 +150 -46
- data/lib/sequel/database/query.rb +215 -65
- data/lib/sequel/database/schema_generator.rb +64 -20
- data/lib/sequel/database/schema_methods.rb +212 -54
- data/lib/sequel/dataset/actions.rb +322 -85
- data/lib/sequel/dataset/features.rb +96 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +237 -44
- data/lib/sequel/dataset/sql.rb +698 -278
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
- data/lib/sequel/extensions/migration.rb +97 -11
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_inet.rb +89 -0
- data/lib/sequel/extensions/pg_json.rb +178 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query.rb +1 -1
- 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 +251 -37
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/server_block.rb +139 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1187 -393
- data/lib/sequel/model/base.rb +578 -170
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- 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/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -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 +123 -8
- 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 +12 -2
- data/lib/sequel/plugins/many_through_many.rb +79 -28
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +139 -63
- data/lib/sequel/plugins/optimistic_locking.rb +8 -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 +29 -15
- data/lib/sequel/plugins/schema.rb +7 -2
- 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 +10 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- 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/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +526 -59
- data/lib/sequel/timezones.rb +57 -38
- 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 +142 -40
- data/spec/adapters/mysql_spec.rb +380 -234
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +1050 -212
- data/spec/adapters/spec_helper.rb +8 -5
- data/spec/adapters/sqlite_spec.rb +139 -27
- data/spec/core/connection_pool_spec.rb +196 -93
- data/spec/core/database_spec.rb +879 -510
- data/spec/core/dataset_spec.rb +1415 -1086
- data/spec/core/expression_filters_spec.rb +554 -109
- data/spec/core/mock_adapter_spec.rb +449 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +482 -38
- data/spec/core/spec_helper.rb +6 -48
- 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/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/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +69 -92
- data/spec/extensions/identity_map_spec.rb +131 -22
- 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 -6
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +48 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- 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 +251 -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 +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_inet_spec.rb +44 -0
- data/spec/extensions/pg_json_spec.rb +101 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -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 +168 -0
- data/spec/extensions/query_spec.rb +6 -0
- 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 +429 -22
- data/spec/extensions/schema_spec.rb +25 -21
- 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 +85 -43
- 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 +22 -61
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -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 +4 -7
- 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 +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- 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 +9 -3
- data/spec/integration/dataset_test.rb +605 -91
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +454 -143
- data/spec/integration/prepared_statement_test.rb +263 -128
- data/spec/integration/schema_test.rb +309 -43
- data/spec/integration/spec_helper.rb +40 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +18 -4
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +1067 -661
- data/spec/model/base_spec.rb +329 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +240 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +490 -232
- data/spec/model/spec_helper.rb +14 -71
- data/spec/model/validations_spec.rb +11 -0
- data/spec/rcov.opts +2 -0
- metadata +178 -80
data/doc/testing.rdoc
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
= Testing with Sequel
|
|
2
|
+
|
|
3
|
+
Whether or not you use Sequel in your application, you are usually going to want to have tests that ensure that your code works. When you are using Sequel, it's helpful to integrate it into your testing framework, and it's generally best to run each test in its own transaction if possible. That keeps all tests isolated from each other, and it's simple as it handles all of the cleanup for you. Sequel doesn't ship with helpers for common libraries, as the exact code you need is often application-specific, but this page offers some examples that you can either use directly or build on.
|
|
4
|
+
|
|
5
|
+
== Transactional tests
|
|
6
|
+
|
|
7
|
+
These run each test in its own transaction, the recommended way to test.
|
|
8
|
+
|
|
9
|
+
Make sure you are using Sequel 3.29.0 or above when using these examples, as older versions don't support the <tt>:rollback=>:always</tt> option.
|
|
10
|
+
|
|
11
|
+
=== RSpec 1
|
|
12
|
+
|
|
13
|
+
class Spec::Example::ExampleGroup
|
|
14
|
+
def execute(*args, &block)
|
|
15
|
+
x = nil
|
|
16
|
+
Sequel::Model.db.transaction(:rollback=>:always){x = super(*args, &block)}
|
|
17
|
+
x
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
=== RSpec 2
|
|
22
|
+
|
|
23
|
+
class RSpec::Core::ExampleGroup
|
|
24
|
+
# Setting an around filter globally doesn't appear to work in 2.7 (and maybe other versions),
|
|
25
|
+
# so set one up for each subclass.
|
|
26
|
+
def self.inherited(subclass)
|
|
27
|
+
super
|
|
28
|
+
subclass.around do |example|
|
|
29
|
+
Sequel::Model.db.transaction(:rollback=>:always){example.call}
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
=== Test::Unit
|
|
35
|
+
|
|
36
|
+
# Must use this class as the base class for your tests
|
|
37
|
+
class SequelTestCase < Test::Unit::TestCase
|
|
38
|
+
def run(*args, &block)
|
|
39
|
+
Sequel::Model.db.transaction(:rollback=>:always){super}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
=== MiniTest::Unit
|
|
44
|
+
|
|
45
|
+
# Must use this class as the base class for your tests
|
|
46
|
+
class SequelTestCase < MiniTest::Unit::TestCase
|
|
47
|
+
def run(*args, &block)
|
|
48
|
+
Sequel::Model.db.transaction(:rollback=>:always){super}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
== Transactional testing with multiple databases
|
|
53
|
+
|
|
54
|
+
You can use the Sequel.transaction method to run a transaction on multiple databases, rolling all of them back. Instead of:
|
|
55
|
+
|
|
56
|
+
Sequel::Model.db.transaction(:rollback=>:always)
|
|
57
|
+
|
|
58
|
+
Use Sequel.transaction with an array of databases:
|
|
59
|
+
|
|
60
|
+
Sequel.transaction([DB1, DB2, DB3], :rollback=>:always)
|
|
61
|
+
|
|
62
|
+
== Nontransactional tests
|
|
63
|
+
|
|
64
|
+
In some cases, it is not possible to use transactions. For example, if you are testing a web application that is running in a separate process, you don't have access to that process's database connections, so you can't run your examples in transactions. In that case, the best way to handle things is to cleanup after each test by deleting or truncating the database tables used in the test.
|
|
65
|
+
|
|
66
|
+
The order in which you delete/truncate the tables is important if you are using referential integrity in your database (which you probably should be doing). If you are using referential integrity, you need to make sure to delete in tables referencing other tables before the tables that are being referenced. For example, if you have an +albums+ table with an +artist_id+ field referencing the +artists+ table, you want to delete/truncate the +albums+ table before the +artists+ table. Note that if you have cyclic references in your database, you will probably need to write your own custom cleaning code.
|
|
67
|
+
|
|
68
|
+
=== RSpec
|
|
69
|
+
|
|
70
|
+
class Spec::Example::ExampleGroup
|
|
71
|
+
after do
|
|
72
|
+
[:table1, :table2].each{|x| Sequel::Model.db.from(x).truncate}
|
|
73
|
+
# or
|
|
74
|
+
[:table1, :table2].each{|x| Sequel::Model.db.from(x).delete}
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
=== Test::Unit
|
|
79
|
+
|
|
80
|
+
# Must use this class as the base class for your tests
|
|
81
|
+
class SequelTestCase < Test::Unit::TestCase
|
|
82
|
+
def teardown
|
|
83
|
+
[:table1, :table2].each{|x| Sequel::Model.db.from(x).truncate}
|
|
84
|
+
# or
|
|
85
|
+
[:table1, :table2].each{|x| Sequel::Model.db.from(x).delete}
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
= Testing Sequel Itself
|
|
90
|
+
|
|
91
|
+
Sequel has multiple separate test suites. All test suites run under either RSpec 1 or RSpec 2.
|
|
92
|
+
|
|
93
|
+
== rake spec
|
|
94
|
+
|
|
95
|
+
The +spec+ rake task (which is also the default rake task) runs Sequel's core and model specs. These specs use a mocked database connection, and test for specific SQL used and for generally correct behavior.
|
|
96
|
+
|
|
97
|
+
== rake spec_plugin
|
|
98
|
+
|
|
99
|
+
The +spec_plugin+ rake task runs the specs for the plugins and extensions that ship with Sequel. These also use a mocked database connection, and operate very similarly to the general Sequel core and model specs.
|
|
100
|
+
|
|
101
|
+
== rake spec_<i>adapter</i> (e.g. rake spec_postgres)
|
|
102
|
+
|
|
103
|
+
The <tt>spec_<i>adapter</i></tt> specs run against a real database connection with nothing mocked, and test for correct results. They are slower than the standard specs, but they will catch errors that are mocked out by the default specs, as well as show issues that only occur on a certain database, adapter, or a combination of the two.
|
|
104
|
+
|
|
105
|
+
These specs are broken down into two parts. For each database, there are specific specs that only apply to that database, and these are called the adapter specs. There are also shared specs that apply to all (or almost all) databases, these are called the integration specs.
|
|
106
|
+
|
|
107
|
+
== Environment variables
|
|
108
|
+
|
|
109
|
+
Sequel often uses environment variables when testing to specify either the database to be tested or specify how testing should be done. You can also specify the databases to test by copying spec/spec_config.rb.example to spec/spec_config.rb and modifying it. See that file for details. It may be necessary to use spec_config.rb as opposed to an environment variable if your database connection cannot be specified by a connection string.
|
|
110
|
+
|
|
111
|
+
=== Connection Strings
|
|
112
|
+
|
|
113
|
+
The following environment variables specify Database connection URL strings:
|
|
114
|
+
|
|
115
|
+
* SEQUEL_INTEGRATION_URL: integration specs
|
|
116
|
+
* SEQUEL_FB_SPEC_DB: firebird adapter specs
|
|
117
|
+
* SEQUEL_MSSQL_SPEC_DB: mssql adapter specs
|
|
118
|
+
* SEQUEL_PG_SPEC_DB: postgres adapter specs
|
|
119
|
+
* SEQUEL_SQLITE_SPEC_DB: sqlite adapter specs
|
|
120
|
+
* SEQUEL_MY_SPEC_DB: mysql adapter specs
|
|
121
|
+
* SEQUEL_DB2_SPEC_DB: db2 adapter specs
|
|
122
|
+
|
|
123
|
+
=== Other
|
|
124
|
+
|
|
125
|
+
* SEQUEL_MSSQL_SPEC_REQUIRE: Separate file to require when running mssql adapter specs
|
|
126
|
+
* SEQUEL_DB2_SPEC_REQUIRE: Separate file to require when running db2 adapter specs
|
|
127
|
+
* SEQUEL_COLUMNS_INTROSPECTION: Whether to run the specs with the columns_introspection extension loaded by default
|
|
128
|
+
* SEQUEL_NO_PENDING: Don't mark any specs as pending, try running all specs
|
|
129
|
+
* SKIPPED_TEST_WARN: Warn when skipping any tests because libraries aren't available
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
= Thread Safety
|
|
2
|
+
|
|
3
|
+
Most Sequel usage (and all common Sequel usage) is thread safe by default. Specifically, multiple threads can operate on Database instances, Dataset instances, and Model classes concurrently without problems. In general, Database instance and Model classes are not modified after application startup, and modifying Dataset instances returns modified copies of the dataset instead of mutating it.
|
|
4
|
+
|
|
5
|
+
== Connection Pool
|
|
6
|
+
|
|
7
|
+
In order to allow multiple threads to operate on the same database at the same time, Sequel uses a connection pool. The connection pool is designed so that a thread uses a connection for the minimum amount of time, returning the connection to the pool as soon as it is done using the connection. If a thread requests a connection and the pool is empty, the thread will block (actually busy-wait) until a connection is available or the the connection pool timeout has elapsed (in which case a PoolTimeout error will be raised).
|
|
8
|
+
|
|
9
|
+
== Exceptions
|
|
10
|
+
|
|
11
|
+
This is a small list of things that are specifically non thread-safe. This is not an exhaustive list, there may be cases not mentioned here.
|
|
12
|
+
|
|
13
|
+
1) Model instances: Model instances are not thread-safe unless they are frozen first. Multiple threads should not operate on an unfrozen model instance concurrently.
|
|
14
|
+
|
|
15
|
+
2) Model class modifications: Model class modifications, such as adding associations and loading plugins, are not designed to be thread safe. You should not modify a class in one thread if any other thread can concurrently access it. Model subclassing is designed to be thread-safe, so you create a model subclass in a thread and modify it safely.
|
|
16
|
+
|
|
17
|
+
3) Dataset mutation methods: Dataset mutation methods are not thread safe, you should not call them on datasets that could be accessed by other threads. It is safe to clone the dataset first inside a thread and call mutation methods on the cloned dataset.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
= Database Transactions
|
|
2
|
+
|
|
3
|
+
Sequel uses autocommit mode by default for all of its database adapters, so in general in Sequel if you want to use database transactions, you need to be explicit about it. There are a few cases where transactions are used implicitly by default:
|
|
4
|
+
|
|
5
|
+
* Dataset#import to insert many records at once
|
|
6
|
+
* Model#save
|
|
7
|
+
* Model#destroy
|
|
8
|
+
* Migrations
|
|
9
|
+
* A few model plugins
|
|
10
|
+
|
|
11
|
+
Everywhere else, it is up to use to use a database transaction if you want to.
|
|
12
|
+
|
|
13
|
+
== Basic Transaction Usage
|
|
14
|
+
|
|
15
|
+
In Sequel, the <tt>Database#transaction</tt> method should be called if you want to use a database transaction. This method must be called with a block. If the block does not raise an exception, the transaction is committed:
|
|
16
|
+
|
|
17
|
+
DB.transaction do # BEGIN
|
|
18
|
+
DB[:foo].insert(1) # INSERT
|
|
19
|
+
end # COMMIT
|
|
20
|
+
|
|
21
|
+
If the block raises a Sequel::Rollback exception, the transaction is rolled back, but no exception is raised outside the block:
|
|
22
|
+
|
|
23
|
+
DB.transaction do # BEGIN
|
|
24
|
+
raise Sequel::Rollback
|
|
25
|
+
end # ROLLBACK
|
|
26
|
+
# no exception raised
|
|
27
|
+
|
|
28
|
+
If any other exception is raised, the transaction is rolled back, and the exception is raised outside the block:
|
|
29
|
+
|
|
30
|
+
# ArgumentError raised
|
|
31
|
+
DB.transaction do # BEGIN
|
|
32
|
+
raise ArgumentError
|
|
33
|
+
end # ROLLBACK
|
|
34
|
+
# ArgumentError raised
|
|
35
|
+
|
|
36
|
+
If you want Sequel::Rollback exceptions to be reraised, use the <tt>:rollback => :reraise</tt> option:
|
|
37
|
+
|
|
38
|
+
DB.transaction(:rollback => :reraise) do # BEGIN
|
|
39
|
+
raise Sequel::Rollback
|
|
40
|
+
end # ROLLBACK
|
|
41
|
+
# Sequel::Rollback raised
|
|
42
|
+
|
|
43
|
+
If you always want to rollback (useful for testing), use the <tt>:rollback => :always</tt> option:
|
|
44
|
+
|
|
45
|
+
DB.transaction(:rollback => :always) do # BEGIN
|
|
46
|
+
DB[:foo].insert(1) # INSERT
|
|
47
|
+
end # ROLLBACK
|
|
48
|
+
|
|
49
|
+
If you want to check whether you are currently in a transaction, use the Database#in_transaction? method:
|
|
50
|
+
|
|
51
|
+
DB.in_transaction? # false
|
|
52
|
+
DB.transaction do
|
|
53
|
+
DB.in_transaction? # true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
== Transaction Hooks
|
|
57
|
+
|
|
58
|
+
You can add hooks to an in progress transaction that are called after the transaction commits or rolls back:
|
|
59
|
+
|
|
60
|
+
x = nil
|
|
61
|
+
DB.transaction do
|
|
62
|
+
DB.after_commit{x = 1}
|
|
63
|
+
DB.after_rollback{x = 2}
|
|
64
|
+
x # nil
|
|
65
|
+
end
|
|
66
|
+
x # 1
|
|
67
|
+
|
|
68
|
+
x = nil
|
|
69
|
+
DB.transaction do
|
|
70
|
+
DB.after_commit{x = 1}
|
|
71
|
+
DB.after_rollback{x = 2}
|
|
72
|
+
raise Sequel::Rollback
|
|
73
|
+
end
|
|
74
|
+
x # 2
|
|
75
|
+
|
|
76
|
+
== Nested Transaction Calls / Savepoints
|
|
77
|
+
|
|
78
|
+
You can nest calls to transaction, which by default just reuses the existing transaction:
|
|
79
|
+
|
|
80
|
+
DB.transaction do # BEGIN
|
|
81
|
+
DB.transaction do
|
|
82
|
+
DB[:foo].insert(1) # INSERT
|
|
83
|
+
end
|
|
84
|
+
end # COMMIT
|
|
85
|
+
|
|
86
|
+
You can use the <tt>:savepoint => true</tt> option in the inner transaction to explicitly use a savepoint (if the database supports it):
|
|
87
|
+
|
|
88
|
+
DB.transaction do # BEGIN
|
|
89
|
+
DB.transaction(:savepoint => true) do # SAVEPOINT
|
|
90
|
+
DB[:foo].insert(1) # INSERT
|
|
91
|
+
end # RELEASE SAVEPOINT
|
|
92
|
+
end # COMMIT
|
|
93
|
+
|
|
94
|
+
If a Sequel::Rollback exception is raised inside the savepoint block, it will only rollback to the savepoint:
|
|
95
|
+
|
|
96
|
+
DB.transaction do # BEGIN
|
|
97
|
+
DB.transaction(:savepoint => true) do # SAVEPOINT
|
|
98
|
+
raise Sequel::Rollback
|
|
99
|
+
end # ROLLBACK TO SAVEPOINT
|
|
100
|
+
# no exception raised
|
|
101
|
+
end # COMMIT
|
|
102
|
+
|
|
103
|
+
Other exceptions, unless rescued inside the outer transaction block, will rollback the savepoint and the outer transactions, since they are reraised by the transaction code:
|
|
104
|
+
|
|
105
|
+
DB.transaction do # BEGIN
|
|
106
|
+
DB.transaction(:savepoint => true) do # SAVEPOINT
|
|
107
|
+
raise ArgumentError
|
|
108
|
+
end # ROLLBACK TO SAVEPOINT
|
|
109
|
+
end # ROLLBACK
|
|
110
|
+
# ArgumentError raised
|
|
111
|
+
|
|
112
|
+
== Prepared Transactions / Two-Phase Commit
|
|
113
|
+
|
|
114
|
+
Sequel supports database prepared transactions on PostgreSQL, MySQL, and H2. With prepared transactions, at the end of the transaction, the transaction is not immediately committed (it acts like a rollback). Later, you can call +commit_prepared_transaction+ to commit the transaction or +rollback_prepared_transaction+ to roll the transaction back. Prepared transactions are usually used with distributed databases to make sure all databases commit the same transaction or none of them do.
|
|
115
|
+
|
|
116
|
+
To use prepared transactions in Sequel, you provide a string as the value of the :prepare option:
|
|
117
|
+
|
|
118
|
+
DB.transaction(:prepare => 'foo') do # BEGIN
|
|
119
|
+
DB[:foo].insert(1) # INSERT
|
|
120
|
+
end # PREPARE TRANSACTION 'foo'
|
|
121
|
+
|
|
122
|
+
Later, you can commit the prepared transaction:
|
|
123
|
+
|
|
124
|
+
DB.commit_prepared_transaction('foo')
|
|
125
|
+
|
|
126
|
+
or roll the prepared transaction back:
|
|
127
|
+
|
|
128
|
+
DB.rollback_prepared_transaction('foo')
|
|
129
|
+
|
|
130
|
+
== Transaction Isolation Levels
|
|
131
|
+
|
|
132
|
+
The SQL standard supports 4 isolation levels: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, and SERIALIZABLE. Not all databases implement the levels as specified in the standard (or implement the levels at all), but on PostgreSQL, MySQL, and Microsoft SQL Server, you can specify which transaction isolation level you want to use via the :isolation option to <tt>Database#transaction</tt>. The isolation level is specified as one of the following symbols: :uncommitted, :committed, :repeatable, and :serializable. Using this option make Sequel use the correct transaction isolation syntax for your database:
|
|
133
|
+
|
|
134
|
+
DB.transaction(:isolation => :serializable) do # BEGIN
|
|
135
|
+
# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
|
|
136
|
+
DB[:foo].insert(1) # INSERT
|
|
137
|
+
end # COMMIT
|
data/doc/virtual_rows.rdoc
CHANGED
|
@@ -40,7 +40,7 @@ available. For example, you are no longer able to do:
|
|
|
40
40
|
# WHERE a AND (b OR NOT c)
|
|
41
41
|
|
|
42
42
|
Because Symbol#&, Symbol#| and Symbol#~ are not defined when the core
|
|
43
|
-
extensions are turned off. However,
|
|
43
|
+
extensions are turned off. However, virtual rows allow almost the same
|
|
44
44
|
syntax even without the core extensions:
|
|
45
45
|
|
|
46
46
|
dataset.filter{a & (b | ~c)}
|
|
@@ -87,7 +87,7 @@ and second is the difference between the the use of "a". In the regular proc,
|
|
|
87
87
|
you couldn't call c without an explicit receiver in the proc, unless the self of the
|
|
88
88
|
surrounding scope responded to it. For a, note how ruby calls the method on
|
|
89
89
|
the receiver of the surrounding scope in the regular proc, which returns an integer,
|
|
90
|
-
and does the
|
|
90
|
+
and does the substitution before Sequel gets access to it. In the instance evaled
|
|
91
91
|
proc, calling a without a receiver calls the a method on the VirtualRow instance.
|
|
92
92
|
For b, note that it operates the same in both cases, as it is a local variable.
|
|
93
93
|
|
|
@@ -205,6 +205,55 @@ call, with an optional hash as the second argument: Here are some examples of us
|
|
|
205
205
|
ds.select{sum(:over, :args=>col1, :partition=>col2, :order=>col3){}}
|
|
206
206
|
# SELECT sum(col1) OVER (PARTITION BY col2 ORDER BY col3)
|
|
207
207
|
|
|
208
|
+
== Operators
|
|
209
|
+
|
|
210
|
+
VirtualRows use method_missing to handle almost all method calls. However, they
|
|
211
|
+
have special handling of some operator methods to make certain things easier. The
|
|
212
|
+
operators all use a prefix form.
|
|
213
|
+
|
|
214
|
+
=== Math Operators
|
|
215
|
+
|
|
216
|
+
The standard +, -, *, and / mathematical operators are defined:
|
|
217
|
+
|
|
218
|
+
ds.select{|o| o.-(1, o.a).as(b)}
|
|
219
|
+
ds.select{self.-(1, a).as(b)}
|
|
220
|
+
# SELECT (1 - a) AS b
|
|
221
|
+
|
|
222
|
+
=== Boolean Operators
|
|
223
|
+
|
|
224
|
+
The & and | methods are defined to use AND and OR:
|
|
225
|
+
|
|
226
|
+
ds.where{|o| o.&({:a=>:b}, :c)}
|
|
227
|
+
ds.where{self.&({:a=>:b}, :c)}
|
|
228
|
+
# WHERE ((a = b) AND c)
|
|
229
|
+
|
|
230
|
+
The ~ method is defined to do inversion:
|
|
231
|
+
|
|
232
|
+
ds.where{|o| o.~({:a=>1, :b=>2})}
|
|
233
|
+
ds.where{self.~({:a=>1, :b=>2})}
|
|
234
|
+
# WHERE ((a != 1) OR (b != 2))
|
|
235
|
+
|
|
236
|
+
=== Inequality Operators
|
|
237
|
+
|
|
238
|
+
The standard >, <, >=, and <= inequality operators are defined:
|
|
239
|
+
|
|
240
|
+
ds.where{|o| o.>(1, :c)}
|
|
241
|
+
ds.where{self.>(1, :c)}
|
|
242
|
+
# WHERE (1 > c)
|
|
243
|
+
|
|
244
|
+
== Literal Strings
|
|
245
|
+
|
|
246
|
+
The backtick operator can be used inside an instance-evaled
|
|
247
|
+
virtual row block to create a literal string:
|
|
248
|
+
|
|
249
|
+
ds.where{a > `some SQL`}
|
|
250
|
+
# WHERE (a > some SQL)
|
|
251
|
+
|
|
252
|
+
You can use this on a regular virtual row block too, but it
|
|
253
|
+
doesn't look as nice:
|
|
254
|
+
|
|
255
|
+
ds.where{|o| o.>(:a, o.`('some SQL')}
|
|
256
|
+
|
|
208
257
|
== Returning multiple values
|
|
209
258
|
|
|
210
259
|
It's common when using select and order virtual row blocks to want to
|
|
@@ -11,11 +11,6 @@ module Sequel
|
|
|
11
11
|
# delete query.
|
|
12
12
|
ROWS_AFFECTED = "SELECT @@ROWCOUNT AS AffectedRows"
|
|
13
13
|
|
|
14
|
-
# Return instance of Sequel::ADO::MSSQL::Dataset with the given opts.
|
|
15
|
-
def dataset(opts=nil)
|
|
16
|
-
Sequel::ADO::MSSQL::Dataset.new(self, opts)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
14
|
# Just execute so it doesn't attempt to return the number of rows modified.
|
|
20
15
|
def execute_ddl(sql, opts={})
|
|
21
16
|
execute(sql, opts)
|
|
@@ -37,11 +32,28 @@ module Sequel
|
|
|
37
32
|
end
|
|
38
33
|
end
|
|
39
34
|
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# The ADO adapter's default provider doesn't support transactions, since it
|
|
39
|
+
# creates a new native connection for each query. So Sequel only attempts
|
|
40
|
+
# to use transactions if an explicit :provider is given.
|
|
41
|
+
def begin_transaction(conn, opts={})
|
|
42
|
+
super if @opts[:provider]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def commit_transaction(conn, opts={})
|
|
46
|
+
super if @opts[:provider]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def rollback_transaction(conn, opts={})
|
|
50
|
+
super if @opts[:provider]
|
|
51
|
+
end
|
|
40
52
|
end
|
|
41
53
|
|
|
42
54
|
class Dataset < ADO::Dataset
|
|
43
55
|
include Sequel::MSSQL::DatasetMethods
|
|
44
|
-
|
|
56
|
+
|
|
45
57
|
# Use a nasty hack of multiple SQL statements in the same call and
|
|
46
58
|
# having the last one return the most recently inserted id. This
|
|
47
59
|
# is necessary as ADO's default :provider uses a separate native
|
data/lib/sequel/adapters/ado.rb
CHANGED
|
@@ -4,6 +4,8 @@ module Sequel
|
|
|
4
4
|
# The ADO adapter provides connectivity to ADO databases in Windows.
|
|
5
5
|
module ADO
|
|
6
6
|
class Database < Sequel::Database
|
|
7
|
+
DISCONNECT_ERROR_RE = /Communication link failure/
|
|
8
|
+
|
|
7
9
|
set_adapter_scheme :ado
|
|
8
10
|
|
|
9
11
|
def initialize(opts)
|
|
@@ -12,12 +14,15 @@ module Sequel
|
|
|
12
14
|
when /Microsoft\.(Jet|ACE)\.OLEDB/io
|
|
13
15
|
Sequel.ts_require 'adapters/shared/access'
|
|
14
16
|
extend Sequel::Access::DatabaseMethods
|
|
15
|
-
|
|
17
|
+
extend_datasets(Sequel::Access::DatasetMethods)
|
|
18
|
+
else
|
|
16
19
|
@opts[:driver] ||= 'SQL Server'
|
|
17
20
|
case @opts[:driver]
|
|
18
21
|
when 'SQL Server'
|
|
19
22
|
Sequel.ts_require 'adapters/ado/mssql'
|
|
20
23
|
extend Sequel::ADO::MSSQL::DatabaseMethods
|
|
24
|
+
@dataset_class = ADO::MSSQL::Dataset
|
|
25
|
+
set_mssql_unicode_strings
|
|
21
26
|
end
|
|
22
27
|
end
|
|
23
28
|
end
|
|
@@ -52,10 +57,6 @@ module Sequel
|
|
|
52
57
|
handle
|
|
53
58
|
end
|
|
54
59
|
|
|
55
|
-
def dataset(opts = nil)
|
|
56
|
-
ADO::Dataset.new(self, opts)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
60
|
def execute(sql, opts={})
|
|
60
61
|
synchronize(opts[:server]) do |conn|
|
|
61
62
|
begin
|
|
@@ -74,28 +75,49 @@ module Sequel
|
|
|
74
75
|
# The ADO adapter's default provider doesn't support transactions, since it
|
|
75
76
|
# creates a new native connection for each query. So Sequel only attempts
|
|
76
77
|
# to use transactions if an explicit :provider is given.
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
th = Thread.current
|
|
80
|
-
begin
|
|
81
|
-
@transactions << th
|
|
82
|
-
yield conn
|
|
83
|
-
rescue Sequel::Rollback
|
|
84
|
-
ensure
|
|
85
|
-
@transactions.delete(th)
|
|
86
|
-
end
|
|
78
|
+
def begin_transaction(conn, opts={})
|
|
79
|
+
super if @opts[:provider]
|
|
87
80
|
end
|
|
88
|
-
|
|
81
|
+
|
|
82
|
+
def commit_transaction(conn, opts={})
|
|
83
|
+
super if @opts[:provider]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def database_error_classes
|
|
87
|
+
[::WIN32OLERuntimeError]
|
|
88
|
+
end
|
|
89
|
+
|
|
89
90
|
def disconnect_connection(conn)
|
|
90
91
|
conn.Close
|
|
91
92
|
end
|
|
93
|
+
|
|
94
|
+
def disconnect_error?(e, opts)
|
|
95
|
+
super || (e.is_a?(::WIN32OLERuntimeError) && e.message =~ DISCONNECT_ERROR_RE)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def rollback_transaction(conn, opts={})
|
|
99
|
+
super if @opts[:provider]
|
|
100
|
+
end
|
|
92
101
|
end
|
|
93
102
|
|
|
94
103
|
class Dataset < Sequel::Dataset
|
|
104
|
+
Database::DatasetClass = self
|
|
105
|
+
|
|
95
106
|
def fetch_rows(sql)
|
|
96
107
|
execute(sql) do |s|
|
|
97
|
-
|
|
98
|
-
|
|
108
|
+
columns = cols = s.Fields.extend(Enumerable).map{|column| output_identifier(column.Name)}
|
|
109
|
+
if opts[:offset] && offset_returns_row_number_column?
|
|
110
|
+
rn = row_number_column
|
|
111
|
+
columns = columns.dup
|
|
112
|
+
columns.delete(rn)
|
|
113
|
+
end
|
|
114
|
+
@columns = columns
|
|
115
|
+
s.getRows.transpose.each do |r|
|
|
116
|
+
row = {}
|
|
117
|
+
cols.each{|c| row[c] = r.shift}
|
|
118
|
+
row.delete(rn) if rn
|
|
119
|
+
yield row
|
|
120
|
+
end unless s.eof
|
|
99
121
|
end
|
|
100
122
|
end
|
|
101
123
|
|
|
@@ -14,6 +14,12 @@ module Sequel
|
|
|
14
14
|
'float' => ['float', 'double', 'real', 'double precision'],
|
|
15
15
|
'decimal' => %w'numeric decimal money'
|
|
16
16
|
)
|
|
17
|
+
|
|
18
|
+
# Store the related database object, in order to be able to correctly
|
|
19
|
+
# handle the database timezone.
|
|
20
|
+
def initialize(db)
|
|
21
|
+
@db = db
|
|
22
|
+
end
|
|
17
23
|
|
|
18
24
|
# Return blobs as instances of Sequel::SQL::Blob instead of
|
|
19
25
|
# Amalgamite::Blob
|
|
@@ -29,7 +35,11 @@ module Sequel
|
|
|
29
35
|
|
|
30
36
|
# Return datetime types as instances of Sequel.datetime_class
|
|
31
37
|
def datetime(s)
|
|
32
|
-
|
|
38
|
+
@db.to_application_timestamp(s)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def time(s)
|
|
42
|
+
Sequel.string_to_time(s)
|
|
33
43
|
end
|
|
34
44
|
|
|
35
45
|
# Don't raise an error if the value is a string and the declared
|
|
@@ -68,7 +78,8 @@ module Sequel
|
|
|
68
78
|
opts[:database] = ':memory:' if blank_object?(opts[:database])
|
|
69
79
|
db = ::Amalgalite::Database.new(opts[:database])
|
|
70
80
|
db.busy_handler(::Amalgalite::BusyTimeout.new(opts.fetch(:timeout, 5000)/50, 50))
|
|
71
|
-
db.type_map = SequelTypeMap.new
|
|
81
|
+
db.type_map = SequelTypeMap.new(self)
|
|
82
|
+
connection_pragmas.each{|s| log_yield(s){db.execute_batch(s)}}
|
|
72
83
|
db
|
|
73
84
|
end
|
|
74
85
|
|
|
@@ -77,11 +88,6 @@ module Sequel
|
|
|
77
88
|
:sqlite
|
|
78
89
|
end
|
|
79
90
|
|
|
80
|
-
# Return instance of Sequel::Amalgalite::Dataset with the given options.
|
|
81
|
-
def dataset(opts = nil)
|
|
82
|
-
Amalgalite::Dataset.new(self, opts)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
91
|
# Run the given SQL with the given arguments. Returns nil.
|
|
86
92
|
def execute_ddl(sql, opts={})
|
|
87
93
|
_execute(sql, opts){|conn| log_yield(sql){conn.execute_batch(sql)}}
|
|
@@ -151,6 +157,8 @@ module Sequel
|
|
|
151
157
|
# Dataset class for SQLite datasets that use the amalgalite driver.
|
|
152
158
|
class Dataset < Sequel::Dataset
|
|
153
159
|
include ::Sequel::SQLite::DatasetMethods
|
|
160
|
+
|
|
161
|
+
Database::DatasetClass = self
|
|
154
162
|
|
|
155
163
|
# Yield a hash for each row in the dataset.
|
|
156
164
|
def fetch_rows(sql)
|
|
@@ -168,8 +176,8 @@ module Sequel
|
|
|
168
176
|
private
|
|
169
177
|
|
|
170
178
|
# Quote the string using the adapter instance method.
|
|
171
|
-
def
|
|
172
|
-
db.synchronize{|c| c.quote(v)}
|
|
179
|
+
def literal_string_append(sql, v)
|
|
180
|
+
db.synchronize{|c| sql << c.quote(v)}
|
|
173
181
|
end
|
|
174
182
|
end
|
|
175
183
|
end
|