viking-sequel 3.10.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 +3134 -0
- data/COPYING +19 -0
- data/README.rdoc +723 -0
- data/Rakefile +193 -0
- data/bin/sequel +196 -0
- data/doc/advanced_associations.rdoc +644 -0
- data/doc/cheat_sheet.rdoc +218 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/opening_databases.rdoc +296 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/reflection.rdoc +84 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/doc/release_notes/3.10.0.txt +286 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/release_notes/3.5.0.txt +510 -0
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/release_notes/3.7.0.txt +179 -0
- data/doc/release_notes/3.8.0.txt +151 -0
- data/doc/release_notes/3.9.0.txt +233 -0
- data/doc/schema.rdoc +36 -0
- data/doc/sharding.rdoc +113 -0
- data/doc/virtual_rows.rdoc +205 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +90 -0
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/amalgalite.rb +176 -0
- data/lib/sequel/adapters/db2.rb +139 -0
- data/lib/sequel/adapters/dbi.rb +113 -0
- data/lib/sequel/adapters/do.rb +188 -0
- data/lib/sequel/adapters/do/mysql.rb +49 -0
- data/lib/sequel/adapters/do/postgres.rb +91 -0
- data/lib/sequel/adapters/do/sqlite.rb +40 -0
- data/lib/sequel/adapters/firebird.rb +283 -0
- data/lib/sequel/adapters/informix.rb +77 -0
- data/lib/sequel/adapters/jdbc.rb +587 -0
- data/lib/sequel/adapters/jdbc/as400.rb +58 -0
- data/lib/sequel/adapters/jdbc/h2.rb +133 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
- data/lib/sequel/adapters/mysql.rb +421 -0
- data/lib/sequel/adapters/odbc.rb +143 -0
- data/lib/sequel/adapters/odbc/mssql.rb +42 -0
- data/lib/sequel/adapters/openbase.rb +64 -0
- data/lib/sequel/adapters/oracle.rb +131 -0
- data/lib/sequel/adapters/postgres.rb +504 -0
- data/lib/sequel/adapters/shared/mssql.rb +490 -0
- data/lib/sequel/adapters/shared/mysql.rb +498 -0
- data/lib/sequel/adapters/shared/oracle.rb +195 -0
- data/lib/sequel/adapters/shared/postgres.rb +830 -0
- data/lib/sequel/adapters/shared/progress.rb +44 -0
- data/lib/sequel/adapters/shared/sqlite.rb +389 -0
- data/lib/sequel/adapters/sqlite.rb +224 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
- data/lib/sequel/connection_pool.rb +99 -0
- data/lib/sequel/connection_pool/sharded_single.rb +84 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
- data/lib/sequel/connection_pool/single.rb +29 -0
- data/lib/sequel/connection_pool/threaded.rb +150 -0
- data/lib/sequel/core.rb +293 -0
- data/lib/sequel/core_sql.rb +241 -0
- data/lib/sequel/database.rb +1079 -0
- data/lib/sequel/database/schema_generator.rb +327 -0
- data/lib/sequel/database/schema_methods.rb +203 -0
- data/lib/sequel/database/schema_sql.rb +320 -0
- data/lib/sequel/dataset.rb +32 -0
- data/lib/sequel/dataset/actions.rb +441 -0
- data/lib/sequel/dataset/features.rb +86 -0
- data/lib/sequel/dataset/graph.rb +254 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +227 -0
- data/lib/sequel/dataset/query.rb +709 -0
- data/lib/sequel/dataset/sql.rb +996 -0
- data/lib/sequel/exceptions.rb +51 -0
- data/lib/sequel/extensions/blank.rb +43 -0
- data/lib/sequel/extensions/inflector.rb +242 -0
- data/lib/sequel/extensions/looser_typecasting.rb +21 -0
- data/lib/sequel/extensions/migration.rb +239 -0
- data/lib/sequel/extensions/named_timezones.rb +61 -0
- data/lib/sequel/extensions/pagination.rb +100 -0
- data/lib/sequel/extensions/pretty_table.rb +82 -0
- data/lib/sequel/extensions/query.rb +52 -0
- data/lib/sequel/extensions/schema_dumper.rb +271 -0
- data/lib/sequel/extensions/sql_expr.rb +122 -0
- data/lib/sequel/extensions/string_date_time.rb +46 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
- data/lib/sequel/metaprogramming.rb +9 -0
- data/lib/sequel/model.rb +120 -0
- data/lib/sequel/model/associations.rb +1514 -0
- data/lib/sequel/model/base.rb +1069 -0
- data/lib/sequel/model/default_inflections.rb +45 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/sequel/model/exceptions.rb +21 -0
- data/lib/sequel/model/inflections.rb +162 -0
- data/lib/sequel/model/plugins.rb +70 -0
- data/lib/sequel/plugins/active_model.rb +59 -0
- data/lib/sequel/plugins/association_dependencies.rb +103 -0
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/boolean_readers.rb +53 -0
- data/lib/sequel/plugins/caching.rb +141 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
- data/lib/sequel/plugins/composition.rb +138 -0
- data/lib/sequel/plugins/force_encoding.rb +72 -0
- data/lib/sequel/plugins/hook_class_methods.rb +126 -0
- data/lib/sequel/plugins/identity_map.rb +116 -0
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +77 -0
- data/lib/sequel/plugins/many_through_many.rb +208 -0
- data/lib/sequel/plugins/nested_attributes.rb +206 -0
- data/lib/sequel/plugins/optimistic_locking.rb +81 -0
- data/lib/sequel/plugins/rcte_tree.rb +281 -0
- data/lib/sequel/plugins/schema.rb +66 -0
- data/lib/sequel/plugins/serialization.rb +166 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
- data/lib/sequel/plugins/subclasses.rb +45 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/touch.rb +118 -0
- data/lib/sequel/plugins/typecast_on_load.rb +72 -0
- data/lib/sequel/plugins/validation_class_methods.rb +405 -0
- data/lib/sequel/plugins/validation_helpers.rb +223 -0
- data/lib/sequel/sql.rb +1020 -0
- data/lib/sequel/timezones.rb +161 -0
- data/lib/sequel/version.rb +12 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/firebird_spec.rb +407 -0
- data/spec/adapters/informix_spec.rb +97 -0
- data/spec/adapters/mssql_spec.rb +403 -0
- data/spec/adapters/mysql_spec.rb +1019 -0
- data/spec/adapters/oracle_spec.rb +286 -0
- data/spec/adapters/postgres_spec.rb +969 -0
- data/spec/adapters/spec_helper.rb +51 -0
- data/spec/adapters/sqlite_spec.rb +432 -0
- data/spec/core/connection_pool_spec.rb +808 -0
- data/spec/core/core_sql_spec.rb +417 -0
- data/spec/core/database_spec.rb +1662 -0
- data/spec/core/dataset_spec.rb +3827 -0
- data/spec/core/expression_filters_spec.rb +595 -0
- data/spec/core/object_graph_spec.rb +296 -0
- data/spec/core/schema_generator_spec.rb +159 -0
- data/spec/core/schema_spec.rb +830 -0
- data/spec/core/spec_helper.rb +56 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/active_model_spec.rb +76 -0
- data/spec/extensions/association_dependencies_spec.rb +127 -0
- data/spec/extensions/association_proxies_spec.rb +50 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/boolean_readers_spec.rb +92 -0
- data/spec/extensions/caching_spec.rb +250 -0
- data/spec/extensions/class_table_inheritance_spec.rb +252 -0
- data/spec/extensions/composition_spec.rb +194 -0
- data/spec/extensions/force_encoding_spec.rb +117 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/identity_map_spec.rb +202 -0
- data/spec/extensions/inflector_spec.rb +181 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +153 -0
- data/spec/extensions/looser_typecasting_spec.rb +39 -0
- data/spec/extensions/many_through_many_spec.rb +884 -0
- data/spec/extensions/migration_spec.rb +332 -0
- data/spec/extensions/named_timezones_spec.rb +72 -0
- data/spec/extensions/nested_attributes_spec.rb +396 -0
- data/spec/extensions/optimistic_locking_spec.rb +100 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/rcte_tree_spec.rb +205 -0
- data/spec/extensions/schema_dumper_spec.rb +357 -0
- data/spec/extensions/schema_spec.rb +127 -0
- data/spec/extensions/serialization_spec.rb +209 -0
- data/spec/extensions/single_table_inheritance_spec.rb +96 -0
- data/spec/extensions/spec_helper.rb +91 -0
- data/spec/extensions/sql_expr_spec.rb +89 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/subclasses_spec.rb +52 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/thread_local_timezones_spec.rb +45 -0
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/touch_spec.rb +155 -0
- data/spec/extensions/typecast_on_load_spec.rb +69 -0
- data/spec/extensions/validation_class_methods_spec.rb +984 -0
- data/spec/extensions/validation_helpers_spec.rb +438 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/database_test.rb +26 -0
- data/spec/integration/dataset_test.rb +963 -0
- data/spec/integration/eager_loader_test.rb +734 -0
- data/spec/integration/model_test.rb +130 -0
- data/spec/integration/plugin_test.rb +814 -0
- data/spec/integration/prepared_statement_test.rb +213 -0
- data/spec/integration/schema_test.rb +361 -0
- data/spec/integration/spec_helper.rb +73 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/integration/transaction_test.rb +122 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +175 -0
- data/spec/model/associations_spec.rb +2633 -0
- data/spec/model/base_spec.rb +418 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1391 -0
- data/spec/model/hooks_spec.rb +240 -0
- data/spec/model/inflector_spec.rb +26 -0
- data/spec/model/model_spec.rb +593 -0
- data/spec/model/plugins_spec.rb +236 -0
- data/spec/model/record_spec.rb +1500 -0
- data/spec/model/spec_helper.rb +97 -0
- data/spec/model/validations_spec.rb +153 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +346 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'logger'
|
3
|
+
unless Object.const_defined?('Sequel')
|
4
|
+
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
5
|
+
require 'sequel'
|
6
|
+
Sequel.quote_identifiers = false
|
7
|
+
end
|
8
|
+
begin
|
9
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'spec_config.rb')
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
|
13
|
+
class Sequel::Database
|
14
|
+
def log_duration(duration, message)
|
15
|
+
log_info(message)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Spec::Example::ExampleGroup
|
20
|
+
def log
|
21
|
+
begin
|
22
|
+
INTEGRATION_DB.loggers << Logger.new(STDOUT)
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
INTEGRATION_DB.loggers.pop
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.log_specify(message, &block)
|
30
|
+
specify(message){log{instance_eval(&block)}}
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.cspecify(message, *checked, &block)
|
34
|
+
pending = false
|
35
|
+
checked.each do |c|
|
36
|
+
case c
|
37
|
+
when INTEGRATION_DB.class.adapter_scheme
|
38
|
+
pending = c
|
39
|
+
when Proc
|
40
|
+
pending = c if c.first.call(INTEGRATION_DB)
|
41
|
+
when Array
|
42
|
+
pending = c if c.first == INTEGRATION_DB.class.adapter_scheme && c.last == INTEGRATION_DB.call(INTEGRATION_DB)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
if pending
|
46
|
+
specify(message){pending("Not yet working on #{Array(pending).join(', ')}", &block)}
|
47
|
+
else
|
48
|
+
specify(message, &block)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,432 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
|
+
|
3
|
+
unless defined?(SQLITE_DB)
|
4
|
+
SQLITE_URL = 'sqlite:/' unless defined? SQLITE_URL
|
5
|
+
SQLITE_DB = Sequel.connect(ENV['SEQUEL_SQLITE_SPEC_DB']||SQLITE_URL)
|
6
|
+
end
|
7
|
+
INTEGRATION_DB = SQLITE_DB unless defined?(INTEGRATION_DB)
|
8
|
+
|
9
|
+
context "An SQLite database" do
|
10
|
+
before do
|
11
|
+
@db = SQLITE_DB
|
12
|
+
end
|
13
|
+
after do
|
14
|
+
Sequel.datetime_class = Time
|
15
|
+
end
|
16
|
+
|
17
|
+
if SQLITE_DB.auto_vacuum == :none
|
18
|
+
specify "should support getting pragma values" do
|
19
|
+
@db.pragma_get(:auto_vacuum).to_s.should == '0'
|
20
|
+
end
|
21
|
+
|
22
|
+
specify "should support setting pragma values" do
|
23
|
+
@db.pragma_set(:auto_vacuum, '1')
|
24
|
+
@db.pragma_get(:auto_vacuum).to_s.should == '1'
|
25
|
+
@db.pragma_set(:auto_vacuum, '2')
|
26
|
+
@db.pragma_get(:auto_vacuum).to_s.should == '2'
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "should support getting and setting the auto_vacuum pragma" do
|
30
|
+
@db.auto_vacuum = :full
|
31
|
+
@db.auto_vacuum.should == :full
|
32
|
+
@db.auto_vacuum = :incremental
|
33
|
+
@db.auto_vacuum.should == :incremental
|
34
|
+
|
35
|
+
proc {@db.auto_vacuum = :invalid}.should raise_error(Sequel::Error)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
specify "should provide the SQLite version as an integer" do
|
40
|
+
@db.sqlite_version.should be_a_kind_of(Integer)
|
41
|
+
end
|
42
|
+
|
43
|
+
specify "should support setting and getting the foreign_keys pragma" do
|
44
|
+
(@db.sqlite_version >= 30619 ? [true, false] : [nil]).should include(@db.foreign_keys)
|
45
|
+
@db.foreign_keys = true
|
46
|
+
@db.foreign_keys = false
|
47
|
+
end
|
48
|
+
|
49
|
+
if SQLITE_DB.sqlite_version >= 30619
|
50
|
+
specify "should enforce foreign key integrity if foreign_keys pragma is set" do
|
51
|
+
@db.foreign_keys = true
|
52
|
+
@db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
|
53
|
+
@db[:fk].insert(1, nil)
|
54
|
+
@db[:fk].insert(2, 1)
|
55
|
+
@db[:fk].insert(3, 3)
|
56
|
+
proc{@db[:fk].insert(4, 5)}.should raise_error(Sequel::Error)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "should not enforce foreign key integrity if foreign_keys pragma is unset" do
|
61
|
+
@db.foreign_keys = false
|
62
|
+
@db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
|
63
|
+
@db[:fk].insert(1, 2)
|
64
|
+
@db[:fk].all.should == [{:id=>1, :parent_id=>2}]
|
65
|
+
end
|
66
|
+
|
67
|
+
specify "should provide a list of existing tables" do
|
68
|
+
@db.drop_table(:testing) rescue nil
|
69
|
+
@db.tables.should be_a_kind_of(Array)
|
70
|
+
@db.tables.should_not include(:testing)
|
71
|
+
@db.create_table! :testing do
|
72
|
+
text :name
|
73
|
+
end
|
74
|
+
@db.tables.should include(:testing)
|
75
|
+
end
|
76
|
+
|
77
|
+
specify "should support getting and setting the synchronous pragma" do
|
78
|
+
@db.synchronous = :off
|
79
|
+
@db.synchronous.should == :off
|
80
|
+
@db.synchronous = :normal
|
81
|
+
@db.synchronous.should == :normal
|
82
|
+
@db.synchronous = :full
|
83
|
+
@db.synchronous.should == :full
|
84
|
+
|
85
|
+
proc {@db.synchronous = :invalid}.should raise_error(Sequel::Error)
|
86
|
+
end
|
87
|
+
|
88
|
+
specify "should support getting and setting the temp_store pragma" do
|
89
|
+
@db.temp_store = :default
|
90
|
+
@db.temp_store.should == :default
|
91
|
+
@db.temp_store = :file
|
92
|
+
@db.temp_store.should == :file
|
93
|
+
@db.temp_store = :memory
|
94
|
+
@db.temp_store.should == :memory
|
95
|
+
|
96
|
+
proc {@db.temp_store = :invalid}.should raise_error(Sequel::Error)
|
97
|
+
end
|
98
|
+
|
99
|
+
cspecify "should support timestamps and datetimes and respect datetime_class", :do, :jdbc, :amalgalite do
|
100
|
+
@db.create_table!(:time){timestamp :t; datetime :d}
|
101
|
+
t1 = Time.at(1)
|
102
|
+
@db[:time] << {:t => t1, :d => t1.to_i}
|
103
|
+
@db[:time] << {:t => t1.to_i, :d => t1}
|
104
|
+
@db[:time].map(:t).should == [t1, t1]
|
105
|
+
@db[:time].map(:d).should == [t1, t1]
|
106
|
+
Sequel.datetime_class = DateTime
|
107
|
+
t2 = Sequel.string_to_datetime(t1.iso8601)
|
108
|
+
@db[:time].map(:t).should == [t2, t2]
|
109
|
+
@db[:time].map(:d).should == [t2, t2]
|
110
|
+
end
|
111
|
+
|
112
|
+
specify "should support sequential primary keys" do
|
113
|
+
@db.create_table!(:with_pk) {primary_key :id; text :name}
|
114
|
+
@db[:with_pk] << {:name => 'abc'}
|
115
|
+
@db[:with_pk] << {:name => 'def'}
|
116
|
+
@db[:with_pk] << {:name => 'ghi'}
|
117
|
+
@db[:with_pk].order(:name).all.should == [
|
118
|
+
{:id => 1, :name => 'abc'},
|
119
|
+
{:id => 2, :name => 'def'},
|
120
|
+
{:id => 3, :name => 'ghi'}
|
121
|
+
]
|
122
|
+
end
|
123
|
+
|
124
|
+
specify "should correctly parse the schema" do
|
125
|
+
@db.create_table!(:time2) {timestamp :t}
|
126
|
+
@db.schema(:time2, :reload=>true).should == [[:t, {:type=>:datetime, :allow_null=>true, :default=>nil, :ruby_default=>nil, :db_type=>"timestamp", :primary_key=>false}]]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "An SQLite dataset" do
|
131
|
+
before do
|
132
|
+
@d = SQLITE_DB[:items]
|
133
|
+
end
|
134
|
+
|
135
|
+
specify "should handle string pattern matches correctly" do
|
136
|
+
@d.literal(:x.like('a')).should == "(x LIKE 'a')"
|
137
|
+
@d.literal(~:x.like('a')).should == "NOT (x LIKE 'a')"
|
138
|
+
@d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
|
139
|
+
@d.literal(~:x.ilike('a')).should == "NOT (x LIKE 'a')"
|
140
|
+
end
|
141
|
+
|
142
|
+
specify "should raise errors if given a regexp pattern match" do
|
143
|
+
proc{@d.literal(:x.like(/a/))}.should raise_error(Sequel::Error)
|
144
|
+
proc{@d.literal(~:x.like(/a/))}.should raise_error(Sequel::Error)
|
145
|
+
proc{@d.literal(:x.like(/a/i))}.should raise_error(Sequel::Error)
|
146
|
+
proc{@d.literal(~:x.like(/a/i))}.should raise_error(Sequel::Error)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "An SQLite numeric column" do
|
151
|
+
specify "should handle and return BigDecimal values" do
|
152
|
+
SQLITE_DB.create_table!(:d){numeric :d}
|
153
|
+
d = SQLITE_DB[:d]
|
154
|
+
d.insert(:d=>BigDecimal.new('80.0'))
|
155
|
+
d.insert(:d=>BigDecimal.new('NaN'))
|
156
|
+
d.insert(:d=>BigDecimal.new('Infinity'))
|
157
|
+
d.insert(:d=>BigDecimal.new('-Infinity'))
|
158
|
+
ds = d.all
|
159
|
+
ds.shift.should == {:d=>BigDecimal.new('80.0')}
|
160
|
+
ds.map{|x| x[:d].to_s}.should == %w'NaN Infinity -Infinity'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "An SQLite dataset AS clause" do
|
165
|
+
specify "should use a string literal for :col___alias" do
|
166
|
+
SQLITE_DB.literal(:c___a).should == "c AS 'a'"
|
167
|
+
end
|
168
|
+
|
169
|
+
specify "should use a string literal for :table__col___alias" do
|
170
|
+
SQLITE_DB.literal(:t__c___a).should == "t.c AS 'a'"
|
171
|
+
end
|
172
|
+
|
173
|
+
specify "should use a string literal for :column.as(:alias)" do
|
174
|
+
SQLITE_DB.literal(:c.as(:a)).should == "c AS 'a'"
|
175
|
+
end
|
176
|
+
|
177
|
+
specify "should use a string literal in the SELECT clause" do
|
178
|
+
SQLITE_DB[:t].select(:c___a).sql.should == "SELECT c AS 'a' FROM t"
|
179
|
+
end
|
180
|
+
|
181
|
+
specify "should use a string literal in the FROM clause" do
|
182
|
+
SQLITE_DB[:t___a].sql.should == "SELECT * FROM t AS 'a'"
|
183
|
+
end
|
184
|
+
|
185
|
+
specify "should use a string literal in the JOIN clause" do
|
186
|
+
SQLITE_DB[:t].join_table(:natural, :j, nil, :a).sql.should == "SELECT * FROM t NATURAL JOIN j AS 'a'"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
context "SQLite::Dataset#delete" do
|
191
|
+
before do
|
192
|
+
SQLITE_DB.create_table! :items do
|
193
|
+
primary_key :id
|
194
|
+
String :name
|
195
|
+
Float :value
|
196
|
+
end
|
197
|
+
@d = SQLITE_DB[:items]
|
198
|
+
@d.delete # remove all records
|
199
|
+
@d << {:name => 'abc', :value => 1.23}
|
200
|
+
@d << {:name => 'def', :value => 4.56}
|
201
|
+
@d << {:name => 'ghi', :value => 7.89}
|
202
|
+
end
|
203
|
+
|
204
|
+
specify "should return the number of records affected when filtered" do
|
205
|
+
@d.count.should == 3
|
206
|
+
@d.filter(:value.sql_number < 3).delete.should == 1
|
207
|
+
@d.count.should == 2
|
208
|
+
|
209
|
+
@d.filter(:value.sql_number < 3).delete.should == 0
|
210
|
+
@d.count.should == 2
|
211
|
+
end
|
212
|
+
|
213
|
+
specify "should return the number of records affected when unfiltered" do
|
214
|
+
@d.count.should == 3
|
215
|
+
@d.delete.should == 3
|
216
|
+
@d.count.should == 0
|
217
|
+
|
218
|
+
@d.delete.should == 0
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context "SQLite::Dataset#update" do
|
223
|
+
before do
|
224
|
+
SQLITE_DB.create_table! :items do
|
225
|
+
primary_key :id
|
226
|
+
String :name
|
227
|
+
Float :value
|
228
|
+
end
|
229
|
+
@d = SQLITE_DB[:items]
|
230
|
+
@d.delete # remove all records
|
231
|
+
@d << {:name => 'abc', :value => 1.23}
|
232
|
+
@d << {:name => 'def', :value => 4.56}
|
233
|
+
@d << {:name => 'ghi', :value => 7.89}
|
234
|
+
end
|
235
|
+
|
236
|
+
specify "should return the number of records affected" do
|
237
|
+
@d.filter(:name => 'abc').update(:value => 2).should == 1
|
238
|
+
|
239
|
+
@d.update(:value => 10).should == 3
|
240
|
+
|
241
|
+
@d.filter(:name => 'xxx').update(:value => 23).should == 0
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
context "SQLite dataset" do
|
246
|
+
before do
|
247
|
+
SQLITE_DB.create_table! :test do
|
248
|
+
primary_key :id
|
249
|
+
String :name
|
250
|
+
Float :value
|
251
|
+
end
|
252
|
+
SQLITE_DB.create_table! :items do
|
253
|
+
primary_key :id
|
254
|
+
String :name
|
255
|
+
Float :value
|
256
|
+
end
|
257
|
+
@d = SQLITE_DB[:items]
|
258
|
+
@d << {:name => 'abc', :value => 1.23}
|
259
|
+
@d << {:name => 'def', :value => 4.56}
|
260
|
+
@d << {:name => 'ghi', :value => 7.89}
|
261
|
+
end
|
262
|
+
after do
|
263
|
+
SQLITE_DB.drop_table(:test, :items)
|
264
|
+
end
|
265
|
+
|
266
|
+
specify "should be able to insert from a subquery" do
|
267
|
+
SQLITE_DB[:test] << @d
|
268
|
+
SQLITE_DB[:test].count.should == 3
|
269
|
+
SQLITE_DB[:test].select(:name, :value).order(:value).to_a.should == \
|
270
|
+
@d.select(:name, :value).order(:value).to_a
|
271
|
+
end
|
272
|
+
|
273
|
+
specify "should support #explain" do
|
274
|
+
SQLITE_DB[:test].explain.should be_a_kind_of(Array)
|
275
|
+
end
|
276
|
+
|
277
|
+
specify "should have #explain work when identifier_output_method is modified" do
|
278
|
+
ds = SQLITE_DB[:test]
|
279
|
+
ds.identifier_output_method = :upcase
|
280
|
+
ds.explain.should be_a_kind_of(Array)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
context "A SQLite database" do
|
285
|
+
before do
|
286
|
+
@db = SQLITE_DB
|
287
|
+
@db.create_table! :test2 do
|
288
|
+
text :name
|
289
|
+
integer :value
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
specify "should support add_column operations" do
|
294
|
+
@db.add_column :test2, :xyz, :text
|
295
|
+
|
296
|
+
@db[:test2].columns.should == [:name, :value, :xyz]
|
297
|
+
@db[:test2] << {:name => 'mmm', :value => 111, :xyz=>'000'}
|
298
|
+
@db[:test2].first.should == {:name => 'mmm', :value => 111, :xyz=>'000'}
|
299
|
+
end
|
300
|
+
|
301
|
+
specify "should support drop_column operations" do
|
302
|
+
@db.drop_column :test2, :value
|
303
|
+
@db[:test2].columns.should == [:name]
|
304
|
+
@db[:test2] << {:name => 'mmm'}
|
305
|
+
@db[:test2].first.should == {:name => 'mmm'}
|
306
|
+
end
|
307
|
+
|
308
|
+
specify "should support drop_column operations in a transaction" do
|
309
|
+
@db.transaction{@db.drop_column :test2, :value}
|
310
|
+
@db[:test2].columns.should == [:name]
|
311
|
+
@db[:test2] << {:name => 'mmm'}
|
312
|
+
@db[:test2].first.should == {:name => 'mmm'}
|
313
|
+
end
|
314
|
+
|
315
|
+
specify "should keep column attributes when dropping a column" do
|
316
|
+
@db.create_table! :test3 do
|
317
|
+
primary_key :id
|
318
|
+
text :name
|
319
|
+
integer :value
|
320
|
+
end
|
321
|
+
|
322
|
+
# This lame set of additions and deletions are to test that the primary keys
|
323
|
+
# don't get messed up when we recreate the database.
|
324
|
+
@db[:test3] << { :name => "foo", :value => 1}
|
325
|
+
@db[:test3] << { :name => "foo", :value => 2}
|
326
|
+
@db[:test3] << { :name => "foo", :value => 3}
|
327
|
+
@db[:test3].filter(:id => 2).delete
|
328
|
+
|
329
|
+
@db.drop_column :test3, :value
|
330
|
+
|
331
|
+
@db['PRAGMA table_info(?)', :test3][:id][:pk].to_i.should == 1
|
332
|
+
@db[:test3].select(:id).all.should == [{:id => 1}, {:id => 3}]
|
333
|
+
end
|
334
|
+
|
335
|
+
specify "should support rename_column operations" do
|
336
|
+
@db[:test2].delete
|
337
|
+
@db.add_column :test2, :xyz, :text
|
338
|
+
@db[:test2] << {:name => 'mmm', :value => 111, :xyz => 'qqqq'}
|
339
|
+
|
340
|
+
@db[:test2].columns.should == [:name, :value, :xyz]
|
341
|
+
@db.rename_column :test2, :xyz, :zyx, :type => :text
|
342
|
+
@db[:test2].columns.should == [:name, :value, :zyx]
|
343
|
+
@db[:test2].first[:zyx].should == 'qqqq'
|
344
|
+
@db[:test2].count.should eql(1)
|
345
|
+
end
|
346
|
+
|
347
|
+
specify "should preserve defaults when dropping or renaming columns" do
|
348
|
+
@db.create_table! :test3 do
|
349
|
+
String :s, :default=>'a'
|
350
|
+
Integer :i
|
351
|
+
end
|
352
|
+
|
353
|
+
@db[:test3].insert
|
354
|
+
@db[:test3].first[:s].should == 'a'
|
355
|
+
@db[:test3].delete
|
356
|
+
@db.drop_column :test3, :i
|
357
|
+
@db[:test3].insert
|
358
|
+
@db[:test3].first[:s].should == 'a'
|
359
|
+
@db[:test3].delete
|
360
|
+
@db.rename_column :test3, :s, :t
|
361
|
+
@db[:test3].insert
|
362
|
+
@db[:test3].first[:t].should == 'a'
|
363
|
+
@db[:test3].delete
|
364
|
+
end
|
365
|
+
|
366
|
+
specify "should handle quoted tables when dropping or renaming columns" do
|
367
|
+
@db.quote_identifiers = true
|
368
|
+
table_name = "T T"
|
369
|
+
@db.drop_table(table_name) rescue nil
|
370
|
+
@db.create_table! table_name do
|
371
|
+
Integer :"s s"
|
372
|
+
Integer :"i i"
|
373
|
+
end
|
374
|
+
|
375
|
+
@db.from(table_name).insert(:"s s"=>1, :"i i"=>2)
|
376
|
+
@db.from(table_name).all.should == [{:"s s"=>1, :"i i"=>2}]
|
377
|
+
@db.drop_column table_name, :"i i"
|
378
|
+
@db.from(table_name).all.should == [{:"s s"=>1}]
|
379
|
+
@db.rename_column table_name, :"s s", :"t t"
|
380
|
+
@db.from(table_name).all.should == [{:"t t"=>1}]
|
381
|
+
end
|
382
|
+
|
383
|
+
specify "should choose a temporary table name that isn't already used when dropping or renaming columns" do
|
384
|
+
sqls = []
|
385
|
+
@db.loggers << (l=Class.new{define_method(:info){|sql| sqls << sql}}.new)
|
386
|
+
@db.create_table! :test3 do
|
387
|
+
Integer :h
|
388
|
+
Integer :i
|
389
|
+
end
|
390
|
+
@db.create_table! :test3_backup0 do
|
391
|
+
Integer :j
|
392
|
+
end
|
393
|
+
@db.create_table! :test3_backup1 do
|
394
|
+
Integer :k
|
395
|
+
end
|
396
|
+
|
397
|
+
@db[:test3].columns.should == [:h, :i]
|
398
|
+
@db[:test3_backup0].columns.should == [:j]
|
399
|
+
@db[:test3_backup1].columns.should == [:k]
|
400
|
+
sqls.clear
|
401
|
+
@db.drop_column(:test3, :i)
|
402
|
+
sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup2/}.should == true
|
403
|
+
sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup[01]/}.should == false
|
404
|
+
@db[:test3].columns.should == [:h]
|
405
|
+
@db[:test3_backup0].columns.should == [:j]
|
406
|
+
@db[:test3_backup1].columns.should == [:k]
|
407
|
+
|
408
|
+
@db.create_table! :test3_backup2 do
|
409
|
+
Integer :l
|
410
|
+
end
|
411
|
+
|
412
|
+
sqls.clear
|
413
|
+
@db.rename_column(:test3, :h, :i)
|
414
|
+
sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup3/}.should == true
|
415
|
+
sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup[012]/}.should == false
|
416
|
+
@db[:test3].columns.should == [:i]
|
417
|
+
@db[:test3_backup0].columns.should == [:j]
|
418
|
+
@db[:test3_backup1].columns.should == [:k]
|
419
|
+
@db[:test3_backup2].columns.should == [:l]
|
420
|
+
@db.loggers.delete(l)
|
421
|
+
end
|
422
|
+
|
423
|
+
specify "should support add_index" do
|
424
|
+
@db.add_index :test2, :value, :unique => true
|
425
|
+
@db.add_index :test2, [:name, :value]
|
426
|
+
end
|
427
|
+
|
428
|
+
specify "should support drop_index" do
|
429
|
+
@db.add_index :test2, :value, :unique => true
|
430
|
+
@db.drop_index :test2, :value
|
431
|
+
end
|
432
|
+
end
|