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,91 @@
|
|
1
|
+
Sequel.require 'adapters/shared/postgres'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
Postgres::CONVERTED_EXCEPTIONS << ::DataObjects::Error
|
5
|
+
|
6
|
+
module DataObjects
|
7
|
+
# Adapter, Database, and Dataset support for accessing a PostgreSQL
|
8
|
+
# database via DataObjects.
|
9
|
+
module Postgres
|
10
|
+
# Methods to add to the DataObjects adapter/connection to allow it to work
|
11
|
+
# with the shared PostgreSQL code.
|
12
|
+
module AdapterMethods
|
13
|
+
include Sequel::Postgres::AdapterMethods
|
14
|
+
|
15
|
+
# Give the DataObjects adapter a direct execute method, which creates
|
16
|
+
# a statement with the given sql and executes it.
|
17
|
+
def execute(sql, args=nil)
|
18
|
+
command = create_command(sql)
|
19
|
+
begin
|
20
|
+
if block_given?
|
21
|
+
begin
|
22
|
+
yield(reader = @db.log_yield(sql){command.execute_reader})
|
23
|
+
ensure
|
24
|
+
reader.close if reader
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@db.log_yield(sql){command.execute_non_query}
|
28
|
+
end
|
29
|
+
rescue ::DataObjects::Error => e
|
30
|
+
raise_error(e)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# DataObjects specific method of getting specific values from a result set.
|
37
|
+
def single_value(reader)
|
38
|
+
while(reader.next!) do
|
39
|
+
return reader.values.at(0)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Methods to add to Database instances that access PostgreSQL via
|
45
|
+
# DataObjects.
|
46
|
+
module DatabaseMethods
|
47
|
+
include Sequel::Postgres::DatabaseMethods
|
48
|
+
|
49
|
+
# Add the primary_keys and primary_key_sequences instance variables,
|
50
|
+
# so we can get the correct return values for inserted rows.
|
51
|
+
def self.extended(db)
|
52
|
+
db.instance_eval do
|
53
|
+
@primary_keys = {}
|
54
|
+
@primary_key_sequences = {}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return instance of Sequel::DataObjects::Postgres::Dataset with the given opts.
|
59
|
+
def dataset(opts=nil)
|
60
|
+
Sequel::DataObjects::Postgres::Dataset.new(self, opts)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Run the INSERT sql on the database and return the primary key
|
64
|
+
# for the record.
|
65
|
+
def execute_insert(sql, opts={})
|
66
|
+
synchronize(opts[:server]) do |conn|
|
67
|
+
com = conn.create_command(sql)
|
68
|
+
log_yield(sql){com.execute_non_query}
|
69
|
+
insert_result(conn, opts[:table], opts[:values])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Extend the adapter with the DataObjects PostgreSQL AdapterMethods
|
76
|
+
def setup_connection(conn)
|
77
|
+
conn = super(conn)
|
78
|
+
conn.extend(Sequel::DataObjects::Postgres::AdapterMethods)
|
79
|
+
conn.db = self
|
80
|
+
conn.apply_connection_settings
|
81
|
+
conn
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Dataset subclass used for datasets that connect to PostgreSQL via DataObjects.
|
86
|
+
class Dataset < DataObjects::Dataset
|
87
|
+
include Sequel::Postgres::DatasetMethods
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
Sequel.require 'adapters/shared/sqlite'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module DataObjects
|
5
|
+
# Database and Dataset support for SQLite databases accessed via DataObjects.
|
6
|
+
module SQLite
|
7
|
+
# Instance methods for SQLite Database objects accessed via DataObjects.
|
8
|
+
module DatabaseMethods
|
9
|
+
include Sequel::SQLite::DatabaseMethods
|
10
|
+
|
11
|
+
# Return Sequel::DataObjects::SQLite::Dataset object with the given opts.
|
12
|
+
def dataset(opts=nil)
|
13
|
+
Sequel::DataObjects::SQLite::Dataset.new(self, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Default to a single connection for a memory database.
|
19
|
+
def connection_pool_default_options
|
20
|
+
o = super
|
21
|
+
uri == 'sqlite3::memory:' ? o.merge(:max_connections=>1) : o
|
22
|
+
end
|
23
|
+
|
24
|
+
# Execute the connection pragmas on the connection
|
25
|
+
def setup_connection(conn)
|
26
|
+
connection_pragmas.each do |s|
|
27
|
+
com = conn.create_command(s)
|
28
|
+
log_yield(s){com.execute_non_query}
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Dataset class for SQLite datasets accessed via DataObjects.
|
35
|
+
class Dataset < DataObjects::Dataset
|
36
|
+
include Sequel::SQLite::DatasetMethods
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,283 @@
|
|
1
|
+
require 'fb'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
# The Sequel Firebird adapter requires the ruby fb driver located at
|
5
|
+
# http://github.com/wishdev/fb.
|
6
|
+
module Firebird
|
7
|
+
class Database < Sequel::Database
|
8
|
+
set_adapter_scheme :firebird
|
9
|
+
|
10
|
+
AUTO_INCREMENT = ''.freeze
|
11
|
+
TEMPORARY = 'GLOBAL TEMPORARY '.freeze
|
12
|
+
|
13
|
+
# Add the primary_keys and primary_key_sequences instance variables,
|
14
|
+
# so we can get the correct return values for inserted rows.
|
15
|
+
def initialize(*args)
|
16
|
+
super
|
17
|
+
@primary_keys = {}
|
18
|
+
@primary_key_sequences = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def connect(server)
|
22
|
+
opts = server_opts(server)
|
23
|
+
|
24
|
+
db = Fb::Database.new(
|
25
|
+
:database => "#{opts[:host]}:#{opts[:database]}",
|
26
|
+
:username => opts[:user],
|
27
|
+
:password => opts[:password])
|
28
|
+
conn = db.connect
|
29
|
+
conn.downcase_names = true
|
30
|
+
conn
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_trigger(*args)
|
34
|
+
self << create_trigger_sql(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def dataset(opts = nil)
|
38
|
+
Firebird::Dataset.new(self, opts)
|
39
|
+
end
|
40
|
+
|
41
|
+
def drop_sequence(name)
|
42
|
+
self << drop_sequence_sql(name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def execute(sql, opts={})
|
46
|
+
begin
|
47
|
+
synchronize(opts[:server]) do |conn|
|
48
|
+
r = log_yield(sql){conn.execute(sql)}
|
49
|
+
yield(r) if block_given?
|
50
|
+
r
|
51
|
+
end
|
52
|
+
rescue => e
|
53
|
+
raise_error(e, :classes=>[Fb::Error])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return primary key for the given table.
|
58
|
+
def primary_key(table, server=nil)
|
59
|
+
synchronize(server){|conn| primary_key_for_table(conn, table)}
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns primary key for the given table. This information is
|
63
|
+
# cached, and if the primary key for a table is changed, the
|
64
|
+
# @primary_keys instance variable should be reset manually.
|
65
|
+
def primary_key_for_table(conn, table)
|
66
|
+
@primary_keys[quote_identifier(table)] ||= conn.table_primary_key(quote_identifier(table))
|
67
|
+
end
|
68
|
+
|
69
|
+
def restart_sequence(*args)
|
70
|
+
self << restart_sequence_sql(*args)
|
71
|
+
end
|
72
|
+
|
73
|
+
def sequences(opts={})
|
74
|
+
ds = self[:"rdb$generators"].server(opts[:server]).filter(:"rdb$system_flag" => 0).select(:"rdb$generator_name")
|
75
|
+
block_given? ? yield(ds) : ds.map{|r| ds.send(:output_identifier, r[:"rdb$generator_name"])}
|
76
|
+
end
|
77
|
+
|
78
|
+
def tables(opts={})
|
79
|
+
ds = self[:"rdb$relations"].server(opts[:server]).filter(:"rdb$view_blr" => nil, Sequel::SQL::Function.new(:COALESCE, :"rdb$system_flag", 0) => 0).select(:"rdb$relation_name")
|
80
|
+
block_given? ? yield(ds) : ds.map{|r| ds.send(:output_identifier, r[:"rdb$relation_name"])}
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Use Firebird specific syntax for add column
|
86
|
+
def alter_table_sql(table, op)
|
87
|
+
case op[:op]
|
88
|
+
when :add_column
|
89
|
+
"ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
|
90
|
+
when :drop_column
|
91
|
+
"ALTER TABLE #{quote_schema_table(table)} DROP #{column_definition_sql(op)}"
|
92
|
+
when :rename_column
|
93
|
+
"ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
|
94
|
+
when :set_column_type
|
95
|
+
"ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TYPE #{type_literal(op)}"
|
96
|
+
else
|
97
|
+
super(table, op)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def auto_increment_sql()
|
102
|
+
AUTO_INCREMENT
|
103
|
+
end
|
104
|
+
|
105
|
+
def begin_transaction(conn)
|
106
|
+
log_yield(TRANSACTION_BEGIN){conn.transaction}
|
107
|
+
conn
|
108
|
+
end
|
109
|
+
|
110
|
+
def commit_transaction(conn)
|
111
|
+
log_yield(TRANSACTION_COMMIT){conn.commit}
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_sequence_sql(name, opts={})
|
115
|
+
"CREATE SEQUENCE #{quote_identifier(name)}"
|
116
|
+
end
|
117
|
+
|
118
|
+
# Firebird gets an override because of the mess of creating a
|
119
|
+
# sequence and trigger for auto-incrementing primary keys.
|
120
|
+
def create_table_from_generator(name, generator, options)
|
121
|
+
drop_statement, create_statements = create_table_sql_list(name, generator, options)
|
122
|
+
(execute_ddl(drop_statement) rescue nil) if drop_statement
|
123
|
+
create_statements.each{|sql| execute_ddl(sql)}
|
124
|
+
end
|
125
|
+
|
126
|
+
def create_table_sql_list(name, generator, options={})
|
127
|
+
statements = [create_table_sql(name, generator, options)]
|
128
|
+
drop_seq_statement = nil
|
129
|
+
generator.columns.each do |c|
|
130
|
+
if c[:auto_increment]
|
131
|
+
c[:sequence_name] ||= "seq_#{name}_#{c[:name]}"
|
132
|
+
unless c[:create_sequence] == false
|
133
|
+
drop_seq_statement = drop_sequence_sql(c[:sequence_name])
|
134
|
+
statements << create_sequence_sql(c[:sequence_name])
|
135
|
+
statements << restart_sequence_sql(c[:sequence_name], {:restart_position => c[:sequence_start_position]}) if c[:sequence_start_position]
|
136
|
+
end
|
137
|
+
unless c[:create_trigger] == false
|
138
|
+
c[:trigger_name] ||= "BI_#{name}_#{c[:name]}"
|
139
|
+
c[:quoted_name] = quote_identifier(c[:name])
|
140
|
+
trigger_definition = <<-END
|
141
|
+
begin
|
142
|
+
if ((new.#{c[:quoted_name]} is null) or (new.#{c[:quoted_name]} = 0)) then
|
143
|
+
begin
|
144
|
+
new.#{c[:quoted_name]} = next value for #{c[:sequence_name]};
|
145
|
+
end
|
146
|
+
end
|
147
|
+
END
|
148
|
+
statements << create_trigger_sql(name, c[:trigger_name], trigger_definition, {:events => [:insert]})
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
[drop_seq_statement, statements]
|
153
|
+
end
|
154
|
+
|
155
|
+
def create_trigger_sql(table, name, definition, opts={})
|
156
|
+
events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
|
157
|
+
whence = opts[:after] ? 'AFTER' : 'BEFORE'
|
158
|
+
inactive = opts[:inactive] ? 'INACTIVE' : 'ACTIVE'
|
159
|
+
position = opts.fetch(:position, 0)
|
160
|
+
sql = <<-end_sql
|
161
|
+
CREATE TRIGGER #{quote_identifier(name)} for #{quote_identifier(table)}
|
162
|
+
#{inactive} #{whence} #{events.map{|e| e.to_s.upcase}.join(' OR ')} position #{position}
|
163
|
+
as #{definition}
|
164
|
+
end_sql
|
165
|
+
sql
|
166
|
+
end
|
167
|
+
|
168
|
+
def database_error_classes
|
169
|
+
[Fb::Error]
|
170
|
+
end
|
171
|
+
|
172
|
+
def disconnect_connection(c)
|
173
|
+
c.close
|
174
|
+
end
|
175
|
+
|
176
|
+
def drop_sequence_sql(name)
|
177
|
+
"DROP SEQUENCE #{quote_identifier(name)}"
|
178
|
+
end
|
179
|
+
|
180
|
+
def restart_sequence_sql(name, opts={})
|
181
|
+
seq_name = quote_identifier(name)
|
182
|
+
"ALTER SEQUENCE #{seq_name} RESTART WITH #{opts[:restart_position]}"
|
183
|
+
end
|
184
|
+
|
185
|
+
def rollback_transaction(conn)
|
186
|
+
log_yield(TRANSACTION_ROLLBACK){conn.rollback}
|
187
|
+
end
|
188
|
+
|
189
|
+
def type_literal_generic_string(column)
|
190
|
+
column[:text] ? :"BLOB SUB_TYPE TEXT" : super
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Dataset class for Firebird datasets
|
195
|
+
class Dataset < Sequel::Dataset
|
196
|
+
BOOL_TRUE = '1'.freeze
|
197
|
+
BOOL_FALSE = '0'.freeze
|
198
|
+
NULL = LiteralString.new('NULL').freeze
|
199
|
+
COMMA_SEPARATOR = ', '.freeze
|
200
|
+
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'with distinct limit columns from join where group having compounds order')
|
201
|
+
|
202
|
+
# Yield all rows returned by executing the given SQL and converting
|
203
|
+
# the types.
|
204
|
+
def fetch_rows(sql, &block)
|
205
|
+
execute(sql) do |s|
|
206
|
+
begin
|
207
|
+
@columns = s.fields.map{|c| output_identifier(c.name)}
|
208
|
+
s.fetchall(:symbols_hash).each do |r|
|
209
|
+
h = {}
|
210
|
+
r.each{|k,v| h[output_identifier(k)] = v}
|
211
|
+
yield h
|
212
|
+
end
|
213
|
+
ensure
|
214
|
+
s.close
|
215
|
+
end
|
216
|
+
end
|
217
|
+
self
|
218
|
+
end
|
219
|
+
|
220
|
+
# Insert given values into the database.
|
221
|
+
def insert(*values)
|
222
|
+
if !@opts[:sql]
|
223
|
+
clone(default_server_opts(:sql=>insert_returning_pk_sql(*values))).single_value
|
224
|
+
else
|
225
|
+
execute_insert(insert_sql(*values), :table=>opts[:from].first,
|
226
|
+
:values=>values.size == 1 ? values.first : values)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Use the RETURNING clause to return the primary key of the inserted record, if it exists
|
231
|
+
def insert_returning_pk_sql(*values)
|
232
|
+
pk = db.primary_key(opts[:from].first)
|
233
|
+
insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) : NULL, *values)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Use the RETURNING clause to return the columns listed in returning.
|
237
|
+
def insert_returning_sql(returning, *values)
|
238
|
+
"#{insert_sql(*values)} RETURNING #{column_list(Array(returning))}"
|
239
|
+
end
|
240
|
+
|
241
|
+
# Insert a record returning the record inserted
|
242
|
+
def insert_select(*values)
|
243
|
+
naked.clone(default_server_opts(:sql=>insert_returning_sql(nil, *values))).single_record
|
244
|
+
end
|
245
|
+
|
246
|
+
def requires_sql_standard_datetimes?
|
247
|
+
true
|
248
|
+
end
|
249
|
+
|
250
|
+
# The order of clauses in the SELECT SQL statement
|
251
|
+
def select_clause_methods
|
252
|
+
SELECT_CLAUSE_METHODS
|
253
|
+
end
|
254
|
+
|
255
|
+
def select_limit_sql(sql)
|
256
|
+
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
257
|
+
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
258
|
+
end
|
259
|
+
|
260
|
+
# Firebird does not support INTERSECT or EXCEPT
|
261
|
+
def supports_intersect_except?
|
262
|
+
false
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
def hash_row(stmt, row)
|
268
|
+
@columns.inject({}) do |m, c|
|
269
|
+
m[c] = row.shift
|
270
|
+
m
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def literal_false
|
275
|
+
BOOL_FALSE
|
276
|
+
end
|
277
|
+
|
278
|
+
def literal_true
|
279
|
+
BOOL_TRUE
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'informix'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module Informix
|
5
|
+
class Database < Sequel::Database
|
6
|
+
set_adapter_scheme :informix
|
7
|
+
|
8
|
+
TEMPORARY = 'TEMP '.freeze
|
9
|
+
|
10
|
+
def connect(server)
|
11
|
+
opts = server_opts(server)
|
12
|
+
::Informix.connect(opts[:database], opts[:user], opts[:password])
|
13
|
+
end
|
14
|
+
|
15
|
+
def dataset(opts = nil)
|
16
|
+
Sequel::Informix::Dataset.new(self, opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns number of rows affected
|
20
|
+
def execute_dui(sql, opts={})
|
21
|
+
synchronize(opts[:server]){|c| log_yield(sql){c.immediate(sql)}}
|
22
|
+
end
|
23
|
+
alias_method :do, :execute_dui
|
24
|
+
|
25
|
+
def execute(sql, opts={})
|
26
|
+
synchronize(opts[:server]){|c| yield log_yield(sql){c.cursor(sql)}}
|
27
|
+
end
|
28
|
+
alias_method :query, :execute
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def disconnect_connection(c)
|
33
|
+
c.close
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Dataset < Sequel::Dataset
|
38
|
+
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'limit distinct columns from join where having group compounds order')
|
39
|
+
|
40
|
+
def fetch_rows(sql, &block)
|
41
|
+
execute(sql) do |cursor|
|
42
|
+
begin
|
43
|
+
col_map = nil
|
44
|
+
cursor.open.each_hash do |h|
|
45
|
+
unless col_map
|
46
|
+
col_map = {}
|
47
|
+
@columns = h.keys.map{|k| col_map[k] = output_identifier(k)}
|
48
|
+
end
|
49
|
+
h2 = {}
|
50
|
+
h.each{|k,v| h2[col_map[k]||k] = v}
|
51
|
+
yield h2
|
52
|
+
end
|
53
|
+
ensure
|
54
|
+
cursor.drop
|
55
|
+
end
|
56
|
+
end
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# Informix does not support INTERSECT or EXCEPT
|
63
|
+
def supports_intersect_except?
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def select_clause_methods
|
68
|
+
SELECT_CLAUSE_METHODS
|
69
|
+
end
|
70
|
+
|
71
|
+
def select_limit_sql(sql)
|
72
|
+
sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
|
73
|
+
sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|