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.
Files changed (237) hide show
  1. data/CHANGELOG +3134 -0
  2. data/COPYING +19 -0
  3. data/README.rdoc +723 -0
  4. data/Rakefile +193 -0
  5. data/bin/sequel +196 -0
  6. data/doc/advanced_associations.rdoc +644 -0
  7. data/doc/cheat_sheet.rdoc +218 -0
  8. data/doc/dataset_basics.rdoc +106 -0
  9. data/doc/dataset_filtering.rdoc +158 -0
  10. data/doc/opening_databases.rdoc +296 -0
  11. data/doc/prepared_statements.rdoc +104 -0
  12. data/doc/reflection.rdoc +84 -0
  13. data/doc/release_notes/1.0.txt +38 -0
  14. data/doc/release_notes/1.1.txt +143 -0
  15. data/doc/release_notes/1.3.txt +101 -0
  16. data/doc/release_notes/1.4.0.txt +53 -0
  17. data/doc/release_notes/1.5.0.txt +155 -0
  18. data/doc/release_notes/2.0.0.txt +298 -0
  19. data/doc/release_notes/2.1.0.txt +271 -0
  20. data/doc/release_notes/2.10.0.txt +328 -0
  21. data/doc/release_notes/2.11.0.txt +215 -0
  22. data/doc/release_notes/2.12.0.txt +534 -0
  23. data/doc/release_notes/2.2.0.txt +253 -0
  24. data/doc/release_notes/2.3.0.txt +88 -0
  25. data/doc/release_notes/2.4.0.txt +106 -0
  26. data/doc/release_notes/2.5.0.txt +137 -0
  27. data/doc/release_notes/2.6.0.txt +157 -0
  28. data/doc/release_notes/2.7.0.txt +166 -0
  29. data/doc/release_notes/2.8.0.txt +171 -0
  30. data/doc/release_notes/2.9.0.txt +97 -0
  31. data/doc/release_notes/3.0.0.txt +221 -0
  32. data/doc/release_notes/3.1.0.txt +406 -0
  33. data/doc/release_notes/3.10.0.txt +286 -0
  34. data/doc/release_notes/3.2.0.txt +268 -0
  35. data/doc/release_notes/3.3.0.txt +192 -0
  36. data/doc/release_notes/3.4.0.txt +325 -0
  37. data/doc/release_notes/3.5.0.txt +510 -0
  38. data/doc/release_notes/3.6.0.txt +366 -0
  39. data/doc/release_notes/3.7.0.txt +179 -0
  40. data/doc/release_notes/3.8.0.txt +151 -0
  41. data/doc/release_notes/3.9.0.txt +233 -0
  42. data/doc/schema.rdoc +36 -0
  43. data/doc/sharding.rdoc +113 -0
  44. data/doc/virtual_rows.rdoc +205 -0
  45. data/lib/sequel.rb +1 -0
  46. data/lib/sequel/adapters/ado.rb +90 -0
  47. data/lib/sequel/adapters/ado/mssql.rb +30 -0
  48. data/lib/sequel/adapters/amalgalite.rb +176 -0
  49. data/lib/sequel/adapters/db2.rb +139 -0
  50. data/lib/sequel/adapters/dbi.rb +113 -0
  51. data/lib/sequel/adapters/do.rb +188 -0
  52. data/lib/sequel/adapters/do/mysql.rb +49 -0
  53. data/lib/sequel/adapters/do/postgres.rb +91 -0
  54. data/lib/sequel/adapters/do/sqlite.rb +40 -0
  55. data/lib/sequel/adapters/firebird.rb +283 -0
  56. data/lib/sequel/adapters/informix.rb +77 -0
  57. data/lib/sequel/adapters/jdbc.rb +587 -0
  58. data/lib/sequel/adapters/jdbc/as400.rb +58 -0
  59. data/lib/sequel/adapters/jdbc/h2.rb +133 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
  61. data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
  62. data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
  64. data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
  65. data/lib/sequel/adapters/mysql.rb +421 -0
  66. data/lib/sequel/adapters/odbc.rb +143 -0
  67. data/lib/sequel/adapters/odbc/mssql.rb +42 -0
  68. data/lib/sequel/adapters/openbase.rb +64 -0
  69. data/lib/sequel/adapters/oracle.rb +131 -0
  70. data/lib/sequel/adapters/postgres.rb +504 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +490 -0
  72. data/lib/sequel/adapters/shared/mysql.rb +498 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +195 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +830 -0
  75. data/lib/sequel/adapters/shared/progress.rb +44 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +389 -0
  77. data/lib/sequel/adapters/sqlite.rb +224 -0
  78. data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
  79. data/lib/sequel/connection_pool.rb +99 -0
  80. data/lib/sequel/connection_pool/sharded_single.rb +84 -0
  81. data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
  82. data/lib/sequel/connection_pool/single.rb +29 -0
  83. data/lib/sequel/connection_pool/threaded.rb +150 -0
  84. data/lib/sequel/core.rb +293 -0
  85. data/lib/sequel/core_sql.rb +241 -0
  86. data/lib/sequel/database.rb +1079 -0
  87. data/lib/sequel/database/schema_generator.rb +327 -0
  88. data/lib/sequel/database/schema_methods.rb +203 -0
  89. data/lib/sequel/database/schema_sql.rb +320 -0
  90. data/lib/sequel/dataset.rb +32 -0
  91. data/lib/sequel/dataset/actions.rb +441 -0
  92. data/lib/sequel/dataset/features.rb +86 -0
  93. data/lib/sequel/dataset/graph.rb +254 -0
  94. data/lib/sequel/dataset/misc.rb +119 -0
  95. data/lib/sequel/dataset/mutation.rb +64 -0
  96. data/lib/sequel/dataset/prepared_statements.rb +227 -0
  97. data/lib/sequel/dataset/query.rb +709 -0
  98. data/lib/sequel/dataset/sql.rb +996 -0
  99. data/lib/sequel/exceptions.rb +51 -0
  100. data/lib/sequel/extensions/blank.rb +43 -0
  101. data/lib/sequel/extensions/inflector.rb +242 -0
  102. data/lib/sequel/extensions/looser_typecasting.rb +21 -0
  103. data/lib/sequel/extensions/migration.rb +239 -0
  104. data/lib/sequel/extensions/named_timezones.rb +61 -0
  105. data/lib/sequel/extensions/pagination.rb +100 -0
  106. data/lib/sequel/extensions/pretty_table.rb +82 -0
  107. data/lib/sequel/extensions/query.rb +52 -0
  108. data/lib/sequel/extensions/schema_dumper.rb +271 -0
  109. data/lib/sequel/extensions/sql_expr.rb +122 -0
  110. data/lib/sequel/extensions/string_date_time.rb +46 -0
  111. data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
  112. data/lib/sequel/metaprogramming.rb +9 -0
  113. data/lib/sequel/model.rb +120 -0
  114. data/lib/sequel/model/associations.rb +1514 -0
  115. data/lib/sequel/model/base.rb +1069 -0
  116. data/lib/sequel/model/default_inflections.rb +45 -0
  117. data/lib/sequel/model/errors.rb +39 -0
  118. data/lib/sequel/model/exceptions.rb +21 -0
  119. data/lib/sequel/model/inflections.rb +162 -0
  120. data/lib/sequel/model/plugins.rb +70 -0
  121. data/lib/sequel/plugins/active_model.rb +59 -0
  122. data/lib/sequel/plugins/association_dependencies.rb +103 -0
  123. data/lib/sequel/plugins/association_proxies.rb +41 -0
  124. data/lib/sequel/plugins/boolean_readers.rb +53 -0
  125. data/lib/sequel/plugins/caching.rb +141 -0
  126. data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
  127. data/lib/sequel/plugins/composition.rb +138 -0
  128. data/lib/sequel/plugins/force_encoding.rb +72 -0
  129. data/lib/sequel/plugins/hook_class_methods.rb +126 -0
  130. data/lib/sequel/plugins/identity_map.rb +116 -0
  131. data/lib/sequel/plugins/instance_filters.rb +98 -0
  132. data/lib/sequel/plugins/instance_hooks.rb +57 -0
  133. data/lib/sequel/plugins/lazy_attributes.rb +77 -0
  134. data/lib/sequel/plugins/many_through_many.rb +208 -0
  135. data/lib/sequel/plugins/nested_attributes.rb +206 -0
  136. data/lib/sequel/plugins/optimistic_locking.rb +81 -0
  137. data/lib/sequel/plugins/rcte_tree.rb +281 -0
  138. data/lib/sequel/plugins/schema.rb +66 -0
  139. data/lib/sequel/plugins/serialization.rb +166 -0
  140. data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
  141. data/lib/sequel/plugins/subclasses.rb +45 -0
  142. data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
  143. data/lib/sequel/plugins/timestamps.rb +87 -0
  144. data/lib/sequel/plugins/touch.rb +118 -0
  145. data/lib/sequel/plugins/typecast_on_load.rb +72 -0
  146. data/lib/sequel/plugins/validation_class_methods.rb +405 -0
  147. data/lib/sequel/plugins/validation_helpers.rb +223 -0
  148. data/lib/sequel/sql.rb +1020 -0
  149. data/lib/sequel/timezones.rb +161 -0
  150. data/lib/sequel/version.rb +12 -0
  151. data/lib/sequel_core.rb +1 -0
  152. data/lib/sequel_model.rb +1 -0
  153. data/spec/adapters/firebird_spec.rb +407 -0
  154. data/spec/adapters/informix_spec.rb +97 -0
  155. data/spec/adapters/mssql_spec.rb +403 -0
  156. data/spec/adapters/mysql_spec.rb +1019 -0
  157. data/spec/adapters/oracle_spec.rb +286 -0
  158. data/spec/adapters/postgres_spec.rb +969 -0
  159. data/spec/adapters/spec_helper.rb +51 -0
  160. data/spec/adapters/sqlite_spec.rb +432 -0
  161. data/spec/core/connection_pool_spec.rb +808 -0
  162. data/spec/core/core_sql_spec.rb +417 -0
  163. data/spec/core/database_spec.rb +1662 -0
  164. data/spec/core/dataset_spec.rb +3827 -0
  165. data/spec/core/expression_filters_spec.rb +595 -0
  166. data/spec/core/object_graph_spec.rb +296 -0
  167. data/spec/core/schema_generator_spec.rb +159 -0
  168. data/spec/core/schema_spec.rb +830 -0
  169. data/spec/core/spec_helper.rb +56 -0
  170. data/spec/core/version_spec.rb +7 -0
  171. data/spec/extensions/active_model_spec.rb +76 -0
  172. data/spec/extensions/association_dependencies_spec.rb +127 -0
  173. data/spec/extensions/association_proxies_spec.rb +50 -0
  174. data/spec/extensions/blank_spec.rb +67 -0
  175. data/spec/extensions/boolean_readers_spec.rb +92 -0
  176. data/spec/extensions/caching_spec.rb +250 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +252 -0
  178. data/spec/extensions/composition_spec.rb +194 -0
  179. data/spec/extensions/force_encoding_spec.rb +117 -0
  180. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  181. data/spec/extensions/identity_map_spec.rb +202 -0
  182. data/spec/extensions/inflector_spec.rb +181 -0
  183. data/spec/extensions/instance_filters_spec.rb +55 -0
  184. data/spec/extensions/instance_hooks_spec.rb +133 -0
  185. data/spec/extensions/lazy_attributes_spec.rb +153 -0
  186. data/spec/extensions/looser_typecasting_spec.rb +39 -0
  187. data/spec/extensions/many_through_many_spec.rb +884 -0
  188. data/spec/extensions/migration_spec.rb +332 -0
  189. data/spec/extensions/named_timezones_spec.rb +72 -0
  190. data/spec/extensions/nested_attributes_spec.rb +396 -0
  191. data/spec/extensions/optimistic_locking_spec.rb +100 -0
  192. data/spec/extensions/pagination_spec.rb +99 -0
  193. data/spec/extensions/pretty_table_spec.rb +91 -0
  194. data/spec/extensions/query_spec.rb +85 -0
  195. data/spec/extensions/rcte_tree_spec.rb +205 -0
  196. data/spec/extensions/schema_dumper_spec.rb +357 -0
  197. data/spec/extensions/schema_spec.rb +127 -0
  198. data/spec/extensions/serialization_spec.rb +209 -0
  199. data/spec/extensions/single_table_inheritance_spec.rb +96 -0
  200. data/spec/extensions/spec_helper.rb +91 -0
  201. data/spec/extensions/sql_expr_spec.rb +89 -0
  202. data/spec/extensions/string_date_time_spec.rb +93 -0
  203. data/spec/extensions/subclasses_spec.rb +52 -0
  204. data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
  205. data/spec/extensions/thread_local_timezones_spec.rb +45 -0
  206. data/spec/extensions/timestamps_spec.rb +150 -0
  207. data/spec/extensions/touch_spec.rb +155 -0
  208. data/spec/extensions/typecast_on_load_spec.rb +69 -0
  209. data/spec/extensions/validation_class_methods_spec.rb +984 -0
  210. data/spec/extensions/validation_helpers_spec.rb +438 -0
  211. data/spec/integration/associations_test.rb +281 -0
  212. data/spec/integration/database_test.rb +26 -0
  213. data/spec/integration/dataset_test.rb +963 -0
  214. data/spec/integration/eager_loader_test.rb +734 -0
  215. data/spec/integration/model_test.rb +130 -0
  216. data/spec/integration/plugin_test.rb +814 -0
  217. data/spec/integration/prepared_statement_test.rb +213 -0
  218. data/spec/integration/schema_test.rb +361 -0
  219. data/spec/integration/spec_helper.rb +73 -0
  220. data/spec/integration/timezone_test.rb +55 -0
  221. data/spec/integration/transaction_test.rb +122 -0
  222. data/spec/integration/type_test.rb +96 -0
  223. data/spec/model/association_reflection_spec.rb +175 -0
  224. data/spec/model/associations_spec.rb +2633 -0
  225. data/spec/model/base_spec.rb +418 -0
  226. data/spec/model/dataset_methods_spec.rb +78 -0
  227. data/spec/model/eager_loading_spec.rb +1391 -0
  228. data/spec/model/hooks_spec.rb +240 -0
  229. data/spec/model/inflector_spec.rb +26 -0
  230. data/spec/model/model_spec.rb +593 -0
  231. data/spec/model/plugins_spec.rb +236 -0
  232. data/spec/model/record_spec.rb +1500 -0
  233. data/spec/model/spec_helper.rb +97 -0
  234. data/spec/model/validations_spec.rb +153 -0
  235. data/spec/rcov.opts +6 -0
  236. data/spec/spec_config.rb.example +10 -0
  237. 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