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,161 @@
|
|
1
|
+
module Sequel
|
2
|
+
# The offset of the current time zone from UTC, in seconds.
|
3
|
+
LOCAL_DATETIME_OFFSET_SECS = Time.now.utc_offset
|
4
|
+
|
5
|
+
# The offset of the current time zone from UTC, as a fraction of a day.
|
6
|
+
LOCAL_DATETIME_OFFSET = respond_to?(:Rational, true) ? Rational(LOCAL_DATETIME_OFFSET_SECS, 60*60*24) : LOCAL_DATETIME_OFFSET_SECS/60/60/24.0
|
7
|
+
|
8
|
+
@application_timezone = nil
|
9
|
+
@database_timezone = nil
|
10
|
+
@typecast_timezone = nil
|
11
|
+
|
12
|
+
module Timezones
|
13
|
+
attr_reader :application_timezone, :database_timezone, :typecast_timezone
|
14
|
+
|
15
|
+
%w'application database typecast'.each do |t|
|
16
|
+
class_eval("def #{t}_timezone=(tz); @#{t}_timezone = convert_timezone_setter_arg(tz) end", __FILE__, __LINE__)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convert the given Time/DateTime object into the database timezone, used when
|
20
|
+
# literalizing objects in an SQL string.
|
21
|
+
def application_to_database_timestamp(v)
|
22
|
+
convert_output_timestamp(v, Sequel.database_timezone)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Convert the given object into an object of Sequel.datetime_class in the
|
26
|
+
# application_timezone. Used when coverting datetime/timestamp columns
|
27
|
+
# returned by the database.
|
28
|
+
def database_to_application_timestamp(v)
|
29
|
+
convert_timestamp(v, Sequel.database_timezone)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sets the database, application, and typecasting timezones to the given timezone.
|
33
|
+
def default_timezone=(tz)
|
34
|
+
self.database_timezone = tz
|
35
|
+
self.application_timezone = tz
|
36
|
+
self.typecast_timezone = tz
|
37
|
+
end
|
38
|
+
|
39
|
+
# Convert the given object into an object of Sequel.datetime_class in the
|
40
|
+
# application_timezone. Used when typecasting values when assigning them
|
41
|
+
# to model datetime attributes.
|
42
|
+
def typecast_to_application_timestamp(v)
|
43
|
+
convert_timestamp(v, Sequel.typecast_timezone)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Convert the given DateTime to the given input_timezone, keeping the
|
49
|
+
# same time and just modifying the timezone.
|
50
|
+
def convert_input_datetime_no_offset(v, input_timezone)
|
51
|
+
case input_timezone
|
52
|
+
when :utc, nil
|
53
|
+
v # DateTime assumes UTC if no offset is given
|
54
|
+
when :local
|
55
|
+
v.new_offset(LOCAL_DATETIME_OFFSET) - LOCAL_DATETIME_OFFSET
|
56
|
+
else
|
57
|
+
convert_input_datetime_other(v, input_timezone)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Convert the given DateTime to the given input_timezone that is not supported
|
62
|
+
# by default (such as nil, :local, or :utc). Raises an error by default.
|
63
|
+
# Can be overridden in extensions.
|
64
|
+
def convert_input_datetime_other(v, input_timezone)
|
65
|
+
raise InvalidValue, "Invalid input_timezone: #{input_timezone.inspect}"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Converts the object from a String, Array, Date, DateTime, or Time into an
|
69
|
+
# instance of Sequel.datetime_class. If given an array or a string that doesn't
|
70
|
+
# contain an offset, assume that the array/string is already in the given input_timezone.
|
71
|
+
def convert_input_timestamp(v, input_timezone)
|
72
|
+
case v
|
73
|
+
when String
|
74
|
+
v2 = Sequel.string_to_datetime(v)
|
75
|
+
if !input_timezone || Date._parse(v).has_key?(:offset)
|
76
|
+
v2
|
77
|
+
else
|
78
|
+
# Correct for potentially wrong offset if string doesn't include offset
|
79
|
+
if v2.is_a?(DateTime)
|
80
|
+
v2 = convert_input_datetime_no_offset(v2, input_timezone)
|
81
|
+
else
|
82
|
+
# Time assumes local time if no offset is given
|
83
|
+
v2 = v2.getutc + LOCAL_DATETIME_OFFSET_SECS if input_timezone == :utc
|
84
|
+
end
|
85
|
+
v2
|
86
|
+
end
|
87
|
+
when Array
|
88
|
+
y, mo, d, h, mi, s = v
|
89
|
+
if datetime_class == DateTime
|
90
|
+
convert_input_datetime_no_offset(DateTime.civil(y, mo, d, h, mi, s, 0), input_timezone)
|
91
|
+
else
|
92
|
+
Time.send(input_timezone == :utc ? :utc : :local, y, mo, d, h, mi, s)
|
93
|
+
end
|
94
|
+
when Time
|
95
|
+
if datetime_class == DateTime
|
96
|
+
v.respond_to?(:to_datetime) ? v.to_datetime : string_to_datetime(v.iso8601)
|
97
|
+
else
|
98
|
+
v
|
99
|
+
end
|
100
|
+
when DateTime
|
101
|
+
if datetime_class == DateTime
|
102
|
+
v
|
103
|
+
else
|
104
|
+
v.respond_to?(:to_time) ? v.to_time : string_to_datetime(v.to_s)
|
105
|
+
end
|
106
|
+
when Date
|
107
|
+
convert_input_timestamp(v.to_s, input_timezone)
|
108
|
+
else
|
109
|
+
raise InvalidValue, "Invalid convert_input_timestamp type: #{v.inspect}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Convert the given DateTime to the given output_timezone that is not supported
|
114
|
+
# by default (such as nil, :local, or :utc). Raises an error by default.
|
115
|
+
# Can be overridden in extensions.
|
116
|
+
def convert_output_datetime_other(v, output_timezone)
|
117
|
+
raise InvalidValue, "Invalid output_timezone: #{output_timezone.inspect}"
|
118
|
+
end
|
119
|
+
|
120
|
+
# Converts the object to the given output_timezone.
|
121
|
+
def convert_output_timestamp(v, output_timezone)
|
122
|
+
if output_timezone
|
123
|
+
if v.is_a?(DateTime)
|
124
|
+
case output_timezone
|
125
|
+
when :utc
|
126
|
+
v.new_offset(0)
|
127
|
+
when :local
|
128
|
+
v.new_offset(LOCAL_DATETIME_OFFSET)
|
129
|
+
else
|
130
|
+
convert_output_datetime_other(v, output_timezone)
|
131
|
+
end
|
132
|
+
else
|
133
|
+
v.send(output_timezone == :utc ? :getutc : :getlocal)
|
134
|
+
end
|
135
|
+
else
|
136
|
+
v
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Converts the given object from the given input timezone to the
|
141
|
+
# application timezone using convert_input_timestamp and
|
142
|
+
# convert_output_timestamp.
|
143
|
+
def convert_timestamp(v, input_timezone)
|
144
|
+
begin
|
145
|
+
convert_output_timestamp(convert_input_timestamp(v, input_timezone), Sequel.application_timezone)
|
146
|
+
rescue InvalidValue
|
147
|
+
raise
|
148
|
+
rescue => e
|
149
|
+
raise convert_exception_class(e, InvalidValue)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Convert the timezone setter argument. Returns argument given by default,
|
154
|
+
# exists for easier overriding in extensions.
|
155
|
+
def convert_timezone_setter_arg(tz)
|
156
|
+
tz
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
extend Timezones
|
161
|
+
end
|
data/lib/sequel_core.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sequel/core'
|
data/lib/sequel_model.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sequel/model'
|
@@ -0,0 +1,407 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
2
|
+
|
3
|
+
unless defined?(FIREBIRD_DB)
|
4
|
+
FIREBIRD_URL = 'firebird://sysdba:masterkey@localhost/reality_spec' unless defined? FIREBIRD_URL
|
5
|
+
FIREBIRD_DB = Sequel.connect(ENV['SEQUEL_FB_SPEC_DB']||FIREBIRD_URL)
|
6
|
+
end
|
7
|
+
INTEGRATION_DB = FIREBIRD_DB unless defined?(INTEGRATION_DB)
|
8
|
+
|
9
|
+
def FIREBIRD_DB.sqls
|
10
|
+
(@sqls ||= [])
|
11
|
+
end
|
12
|
+
logger = Object.new
|
13
|
+
def logger.method_missing(m, msg)
|
14
|
+
FIREBIRD_DB.sqls.push(msg)
|
15
|
+
end
|
16
|
+
FIREBIRD_DB.logger = logger
|
17
|
+
|
18
|
+
FIREBIRD_DB.create_table! :test do
|
19
|
+
varchar :name, :size => 50
|
20
|
+
integer :val, :index => true
|
21
|
+
end
|
22
|
+
|
23
|
+
FIREBIRD_DB.create_table! :test2 do
|
24
|
+
integer :val
|
25
|
+
timestamp :time_stamp
|
26
|
+
end
|
27
|
+
|
28
|
+
FIREBIRD_DB.create_table! :test3 do
|
29
|
+
integer :val
|
30
|
+
timestamp :time_stamp
|
31
|
+
end
|
32
|
+
|
33
|
+
FIREBIRD_DB.create_table! :test5 do
|
34
|
+
primary_key :xid
|
35
|
+
integer :val
|
36
|
+
end
|
37
|
+
|
38
|
+
FIREBIRD_DB.create_table! :test6 do
|
39
|
+
primary_key :xid
|
40
|
+
blob :val
|
41
|
+
String :val2
|
42
|
+
varchar :val3, :size=>200
|
43
|
+
String :val4, :text=>true
|
44
|
+
end
|
45
|
+
|
46
|
+
context "A Firebird database" do
|
47
|
+
before do
|
48
|
+
@db = FIREBIRD_DB
|
49
|
+
end
|
50
|
+
|
51
|
+
specify "should provide disconnect functionality" do
|
52
|
+
@db.tables
|
53
|
+
@db.pool.size.should == 1
|
54
|
+
@db.disconnect
|
55
|
+
@db.pool.size.should == 0
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "should raise Sequel::Error on error" do
|
59
|
+
proc{@db << "SELECT 1 + 'a'"}.should raise_error(Sequel::Error)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "A Firebird dataset" do
|
64
|
+
before do
|
65
|
+
@d = FIREBIRD_DB[:test]
|
66
|
+
@d.delete # remove all records
|
67
|
+
@d.quote_identifiers = true
|
68
|
+
end
|
69
|
+
|
70
|
+
specify "should return the correct record count" do
|
71
|
+
@d.count.should == 0
|
72
|
+
@d << {:name => 'abc', :val => 123}
|
73
|
+
@d << {:name => 'abc', :val => 456}
|
74
|
+
@d << {:name => 'def', :val => 789}
|
75
|
+
@d.count.should == 3
|
76
|
+
end
|
77
|
+
|
78
|
+
specify "should return the correct records" do
|
79
|
+
@d.to_a.should == []
|
80
|
+
@d << {:name => 'abc', :val => 123}
|
81
|
+
@d << {:name => 'abc', :val => 456}
|
82
|
+
@d << {:name => 'def', :val => 789}
|
83
|
+
|
84
|
+
@d.order(:val).to_a.should == [
|
85
|
+
{:name => 'abc', :val => 123},
|
86
|
+
{:name => 'abc', :val => 456},
|
87
|
+
{:name => 'def', :val => 789}
|
88
|
+
]
|
89
|
+
end
|
90
|
+
|
91
|
+
specify "should update records correctly" do
|
92
|
+
@d << {:name => 'abc', :val => 123}
|
93
|
+
@d << {:name => 'abc', :val => 456}
|
94
|
+
@d << {:name => 'def', :val => 789}
|
95
|
+
@d.filter(:name => 'abc').update(:val => 530)
|
96
|
+
|
97
|
+
# the third record should stay the same
|
98
|
+
# floating-point precision bullshit
|
99
|
+
@d[:name => 'def'][:val].should == 789
|
100
|
+
@d.filter(:val => 530).count.should == 2
|
101
|
+
end
|
102
|
+
|
103
|
+
specify "should delete records correctly" do
|
104
|
+
@d << {:name => 'abc', :val => 123}
|
105
|
+
@d << {:name => 'abc', :val => 456}
|
106
|
+
@d << {:name => 'def', :val => 789}
|
107
|
+
@d.filter(:name => 'abc').delete
|
108
|
+
|
109
|
+
@d.count.should == 1
|
110
|
+
@d.first[:name].should == 'def'
|
111
|
+
end
|
112
|
+
|
113
|
+
specify "should be able to literalize booleans" do
|
114
|
+
proc {@d.literal(true)}.should_not raise_error
|
115
|
+
proc {@d.literal(false)}.should_not raise_error
|
116
|
+
end
|
117
|
+
|
118
|
+
specify "should quote columns and tables using double quotes if quoting identifiers" do
|
119
|
+
@d.quote_identifiers = true
|
120
|
+
@d.select(:name).sql.should == \
|
121
|
+
'SELECT "NAME" FROM "TEST"'
|
122
|
+
|
123
|
+
@d.select('COUNT(*)'.lit).sql.should == \
|
124
|
+
'SELECT COUNT(*) FROM "TEST"'
|
125
|
+
|
126
|
+
@d.select(:max[:val]).sql.should == \
|
127
|
+
'SELECT max("VAL") FROM "TEST"'
|
128
|
+
|
129
|
+
@d.select(:now[]).sql.should == \
|
130
|
+
'SELECT now() FROM "TEST"'
|
131
|
+
|
132
|
+
@d.select(:max[:items__val]).sql.should == \
|
133
|
+
'SELECT max("ITEMS"."VAL") FROM "TEST"'
|
134
|
+
|
135
|
+
@d.order(:name.desc).sql.should == \
|
136
|
+
'SELECT * FROM "TEST" ORDER BY "NAME" DESC'
|
137
|
+
|
138
|
+
@d.select('TEST.NAME AS item_:name'.lit).sql.should == \
|
139
|
+
'SELECT TEST.NAME AS item_:name FROM "TEST"'
|
140
|
+
|
141
|
+
@d.select('"NAME"'.lit).sql.should == \
|
142
|
+
'SELECT "NAME" FROM "TEST"'
|
143
|
+
|
144
|
+
@d.select('max(TEST."NAME") AS "max_:name"'.lit).sql.should == \
|
145
|
+
'SELECT max(TEST."NAME") AS "max_:name" FROM "TEST"'
|
146
|
+
|
147
|
+
@d.select(:test[:ABC, 'hello']).sql.should == \
|
148
|
+
"SELECT test(\"ABC\", 'hello') FROM \"TEST\""
|
149
|
+
|
150
|
+
@d.select(:test[:ABC__DEF, 'hello']).sql.should == \
|
151
|
+
"SELECT test(\"ABC\".\"DEF\", 'hello') FROM \"TEST\""
|
152
|
+
|
153
|
+
@d.select(:test[:ABC__DEF, 'hello'].as(:X2)).sql.should == \
|
154
|
+
"SELECT test(\"ABC\".\"DEF\", 'hello') AS \"X2\" FROM \"TEST\""
|
155
|
+
|
156
|
+
@d.insert_sql(:val => 333).should =~ \
|
157
|
+
/\AINSERT INTO "TEST" \("VAL"\) VALUES \(333\)( RETURNING NULL)?\z/
|
158
|
+
|
159
|
+
@d.insert_sql(:X => :Y).should =~ \
|
160
|
+
/\AINSERT INTO "TEST" \("X"\) VALUES \("Y"\)( RETURNING NULL)?\z/
|
161
|
+
end
|
162
|
+
|
163
|
+
specify "should quote fields correctly when reversing the order if quoting identifiers" do
|
164
|
+
@d.quote_identifiers = true
|
165
|
+
@d.reverse_order(:name).sql.should == \
|
166
|
+
'SELECT * FROM "TEST" ORDER BY "NAME" DESC'
|
167
|
+
|
168
|
+
@d.reverse_order(:name.desc).sql.should == \
|
169
|
+
'SELECT * FROM "TEST" ORDER BY "NAME" ASC'
|
170
|
+
|
171
|
+
@d.reverse_order(:name, :test.desc).sql.should == \
|
172
|
+
'SELECT * FROM "TEST" ORDER BY "NAME" DESC, "TEST" ASC'
|
173
|
+
|
174
|
+
@d.reverse_order(:name.desc, :test).sql.should == \
|
175
|
+
'SELECT * FROM "TEST" ORDER BY "NAME" ASC, "TEST" DESC'
|
176
|
+
end
|
177
|
+
|
178
|
+
specify "should support transactions" do
|
179
|
+
FIREBIRD_DB.transaction do
|
180
|
+
@d << {:name => 'abc', :val => 1}
|
181
|
+
end
|
182
|
+
|
183
|
+
@d.count.should == 1
|
184
|
+
end
|
185
|
+
|
186
|
+
specify "should have #transaction yield the connection" do
|
187
|
+
FIREBIRD_DB.transaction do |conn|
|
188
|
+
conn.should_not == nil
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
specify "should correctly rollback transactions" do
|
193
|
+
proc do
|
194
|
+
FIREBIRD_DB.transaction do
|
195
|
+
@d << {:name => 'abc', :val => 1}
|
196
|
+
raise RuntimeError, 'asdf'
|
197
|
+
end
|
198
|
+
end.should raise_error(RuntimeError)
|
199
|
+
|
200
|
+
@d.count.should == 0
|
201
|
+
end
|
202
|
+
|
203
|
+
specify "should handle returning inside of the block by committing" do
|
204
|
+
def FIREBIRD_DB.ret_commit
|
205
|
+
transaction do
|
206
|
+
self[:test] << {:name => 'abc'}
|
207
|
+
return
|
208
|
+
self[:test] << {:name => 'd'}
|
209
|
+
end
|
210
|
+
end
|
211
|
+
@d.count.should == 0
|
212
|
+
FIREBIRD_DB.ret_commit
|
213
|
+
@d.count.should == 1
|
214
|
+
FIREBIRD_DB.ret_commit
|
215
|
+
@d.count.should == 2
|
216
|
+
proc do
|
217
|
+
FIREBIRD_DB.transaction do
|
218
|
+
raise RuntimeError, 'asdf'
|
219
|
+
end
|
220
|
+
end.should raise_error(RuntimeError)
|
221
|
+
|
222
|
+
@d.count.should == 2
|
223
|
+
end
|
224
|
+
|
225
|
+
specify "should quote and upcase reserved keywords" do
|
226
|
+
@d = FIREBIRD_DB[:testing]
|
227
|
+
@d.quote_identifiers = true
|
228
|
+
@d.select(:select).sql.should == \
|
229
|
+
'SELECT "SELECT" FROM "TESTING"'
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
context "A Firebird dataset with a timestamp field" do
|
234
|
+
before do
|
235
|
+
@d = FIREBIRD_DB[:test3]
|
236
|
+
@d.delete
|
237
|
+
end
|
238
|
+
|
239
|
+
specify "should store milliseconds in time fields" do
|
240
|
+
t = Time.now
|
241
|
+
@d << {:val=>1, :time_stamp=>t}
|
242
|
+
@d.literal(@d[:val =>'1'][:time_stamp]).should == @d.literal(t)
|
243
|
+
@d[:val=>'1'][:time_stamp].usec.should == t.usec - t.usec % 100
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context "A Firebird database" do
|
248
|
+
before do
|
249
|
+
@db = FIREBIRD_DB
|
250
|
+
@db.drop_table(:posts) rescue nil
|
251
|
+
@db.sqls.clear
|
252
|
+
end
|
253
|
+
|
254
|
+
specify "should allow us to name the sequences" do
|
255
|
+
@db.create_table(:posts){primary_key :id, :sequence_name => "seq_test"}
|
256
|
+
@db.sqls.should == [
|
257
|
+
"DROP SEQUENCE SEQ_TEST",
|
258
|
+
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
259
|
+
"CREATE SEQUENCE SEQ_TEST",
|
260
|
+
" CREATE TRIGGER BI_POSTS_ID for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_test;\n end\n end\n\n"
|
261
|
+
]
|
262
|
+
end
|
263
|
+
|
264
|
+
specify "should allow us to set the starting position for the sequences" do
|
265
|
+
@db.create_table(:posts){primary_key :id, :sequence_start_position => 999}
|
266
|
+
@db.sqls.should == [
|
267
|
+
"DROP SEQUENCE SEQ_POSTS_ID",
|
268
|
+
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
269
|
+
"CREATE SEQUENCE SEQ_POSTS_ID",
|
270
|
+
"ALTER SEQUENCE SEQ_POSTS_ID RESTART WITH 999",
|
271
|
+
" CREATE TRIGGER BI_POSTS_ID for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_posts_id;\n end\n end\n\n"
|
272
|
+
]
|
273
|
+
end
|
274
|
+
|
275
|
+
specify "should allow us to name and set the starting position for the sequences" do
|
276
|
+
@db.create_table(:posts){primary_key :id, :sequence_name => "seq_test", :sequence_start_position => 999}
|
277
|
+
@db.sqls.should == [
|
278
|
+
"DROP SEQUENCE SEQ_TEST",
|
279
|
+
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
280
|
+
"CREATE SEQUENCE SEQ_TEST",
|
281
|
+
"ALTER SEQUENCE SEQ_TEST RESTART WITH 999",
|
282
|
+
" CREATE TRIGGER BI_POSTS_ID for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_test;\n end\n end\n\n"
|
283
|
+
]
|
284
|
+
end
|
285
|
+
|
286
|
+
specify "should allow us to name the triggers" do
|
287
|
+
@db.create_table(:posts){primary_key :id, :trigger_name => "trig_test"}
|
288
|
+
@db.sqls.should == [
|
289
|
+
"DROP SEQUENCE SEQ_POSTS_ID",
|
290
|
+
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
291
|
+
"CREATE SEQUENCE SEQ_POSTS_ID",
|
292
|
+
" CREATE TRIGGER TRIG_TEST for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_posts_id;\n end\n end\n\n"
|
293
|
+
]
|
294
|
+
end
|
295
|
+
|
296
|
+
specify "should allow us to not create the sequence" do
|
297
|
+
@db.create_table(:posts){primary_key :id, :create_sequence => false}
|
298
|
+
@db.sqls.should == [
|
299
|
+
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
300
|
+
" CREATE TRIGGER BI_POSTS_ID for POSTS\n ACTIVE BEFORE INSERT position 0\n as begin\n if ((new.ID is null) or (new.ID = 0)) then\n begin\n new.ID = next value for seq_posts_id;\n end\n end\n\n"
|
301
|
+
]
|
302
|
+
end
|
303
|
+
|
304
|
+
specify "should allow us to not create the trigger" do
|
305
|
+
@db.create_table(:posts){primary_key :id, :create_trigger => false}
|
306
|
+
@db.sqls.should == [
|
307
|
+
"DROP SEQUENCE SEQ_POSTS_ID",
|
308
|
+
"CREATE TABLE POSTS (ID integer PRIMARY KEY )",
|
309
|
+
"CREATE SEQUENCE SEQ_POSTS_ID",
|
310
|
+
]
|
311
|
+
end
|
312
|
+
|
313
|
+
specify "should allow us to not create either the sequence nor the trigger" do
|
314
|
+
@db.create_table(:posts){primary_key :id, :create_sequence => false, :create_trigger => false}
|
315
|
+
@db.sqls.should == [
|
316
|
+
"CREATE TABLE POSTS (ID integer PRIMARY KEY )"
|
317
|
+
]
|
318
|
+
end
|
319
|
+
|
320
|
+
specify "should support column operations" do
|
321
|
+
@db.create_table!(:test2){varchar :name, :size => 50; integer :val}
|
322
|
+
@db[:test2] << {}
|
323
|
+
@db[:test2].columns.should == [:name, :val]
|
324
|
+
|
325
|
+
@db.add_column :test2, :xyz, :varchar, :size => 50
|
326
|
+
@db[:test2].columns.should == [:name, :val, :xyz]
|
327
|
+
|
328
|
+
@db[:test2].columns.should == [:name, :val, :xyz]
|
329
|
+
@db.drop_column :test2, :xyz
|
330
|
+
|
331
|
+
@db[:test2].columns.should == [:name, :val]
|
332
|
+
|
333
|
+
@db[:test2].delete
|
334
|
+
@db.add_column :test2, :xyz, :varchar, :default => '000', :size => 50#, :create_domain => 'xyz_varchar'
|
335
|
+
@db[:test2] << {:name => 'mmm', :val => 111, :xyz => 'qqqq'}
|
336
|
+
|
337
|
+
@db[:test2].columns.should == [:name, :val, :xyz]
|
338
|
+
@db.rename_column :test2, :xyz, :zyx
|
339
|
+
@db[:test2].columns.should == [:name, :val, :zyx]
|
340
|
+
@db[:test2].first[:zyx].should == 'qqqq'
|
341
|
+
|
342
|
+
@db.add_column :test2, :xyz, :decimal, :elements => [12, 2]
|
343
|
+
@db[:test2].delete
|
344
|
+
@db[:test2] << {:name => 'mmm', :val => 111, :xyz => 56.4}
|
345
|
+
@db.set_column_type :test2, :xyz, :varchar, :size => 50
|
346
|
+
|
347
|
+
@db[:test2].first[:xyz].should == "56.40"
|
348
|
+
end
|
349
|
+
|
350
|
+
specify "should allow us to retrieve the primary key for a table" do
|
351
|
+
@db.create_table!(:test2){primary_key :id}
|
352
|
+
@db.primary_key(:test2).should == ["id"]
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
context "Postgres::Dataset#insert" do
|
357
|
+
before do
|
358
|
+
@ds = FIREBIRD_DB[:test5]
|
359
|
+
@ds.delete
|
360
|
+
end
|
361
|
+
|
362
|
+
specify "should using call insert_returning_sql" do
|
363
|
+
# @ds.should_receive(:single_value).once.with(:sql=>'INSERT INTO TEST5 (VAL) VALUES (10) RETURNING XID', :server=> :default)
|
364
|
+
@ds.should_receive(:single_value).once
|
365
|
+
@ds.insert(:val=>10)
|
366
|
+
end
|
367
|
+
|
368
|
+
specify "should have insert_returning_sql use the RETURNING keyword" do
|
369
|
+
@ds.insert_returning_sql(:XID, :val=>10).should == "INSERT INTO TEST5 (VAL) VALUES (10) RETURNING XID"
|
370
|
+
@ds.insert_returning_sql('*'.lit, :val=>10).should == "INSERT INTO TEST5 (VAL) VALUES (10) RETURNING *"
|
371
|
+
@ds.insert_returning_sql('NULL'.lit, :val=>10).should == "INSERT INTO TEST5 (VAL) VALUES (10) RETURNING NULL"
|
372
|
+
end
|
373
|
+
|
374
|
+
specify "should correctly return the inserted record's primary key value" do
|
375
|
+
value1 = 10
|
376
|
+
id1 = @ds.insert(:val=>value1)
|
377
|
+
@ds.first(:XID=>id1)[:val].should == value1
|
378
|
+
value2 = 20
|
379
|
+
id2 = @ds.insert(:val=>value2)
|
380
|
+
@ds.first(:XID=>id2)[:val].should == value2
|
381
|
+
end
|
382
|
+
|
383
|
+
specify "should return nil if the table has no primary key" do
|
384
|
+
ds = FIREBIRD_DB[:test]
|
385
|
+
ds.delete
|
386
|
+
ds.insert(:name=>'a').should == nil
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
context "Postgres::Dataset#insert" do
|
391
|
+
before do
|
392
|
+
@ds = FIREBIRD_DB[:test6]
|
393
|
+
@ds.delete
|
394
|
+
end
|
395
|
+
|
396
|
+
specify "should insert and retrieve a blob successfully" do
|
397
|
+
value1 = "\1\2\2\2\2222\2\2\2"
|
398
|
+
value2 = "abcd"
|
399
|
+
value3 = "efgh"
|
400
|
+
value4 = "ijkl"
|
401
|
+
id1 = @ds.insert(:val=>value1, :val2=>value2, :val3=>value3, :val4=>value4)
|
402
|
+
@ds.first(:XID=>id1)[:val].should == value1
|
403
|
+
@ds.first(:XID=>id1)[:val2].should == value2
|
404
|
+
@ds.first(:XID=>id1)[:val3].should == value3
|
405
|
+
@ds.first(:XID=>id1)[:val4].should == value4
|
406
|
+
end
|
407
|
+
end
|