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,139 @@
1
+ require 'db2/db2cli'
2
+
3
+ module Sequel
4
+ module DB2
5
+ class Database < Sequel::Database
6
+ set_adapter_scheme :db2
7
+
8
+ include DB2CLI
9
+
10
+ TEMPORARY = 'GLOBAL TEMPORARY '.freeze
11
+
12
+ rc, @@env = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE)
13
+ #check_error(rc, "Could not allocate DB2 environment")
14
+
15
+ def connect(server)
16
+ opts = server_opts(server)
17
+ rc, dbc = SQLAllocHandle(SQL_HANDLE_DBC, @@env)
18
+ check_error(rc, "Could not allocate database connection")
19
+
20
+ rc = SQLConnect(dbc, opts[:database], opts[:user], opts[:password])
21
+ check_error(rc, "Could not connect to database")
22
+
23
+ dbc
24
+ end
25
+
26
+ def test_connection(server=nil)
27
+ synchronize(server){|conn|}
28
+ true
29
+ end
30
+
31
+ def dataset(opts = nil)
32
+ DB2::Dataset.new(self, opts)
33
+ end
34
+
35
+ def execute(sql, opts={})
36
+ synchronize(opts[:server]) do |conn|
37
+ rc, sth = SQLAllocHandle(SQL_HANDLE_STMT, @handle)
38
+ check_error(rc, "Could not allocate statement")
39
+
40
+ begin
41
+ rc = log_yield(sql){SQLExecDirect(sth, sql)}
42
+ check_error(rc, "Could not execute statement")
43
+
44
+ yield(sth) if block_given?
45
+
46
+ rc, rpc = SQLRowCount(sth)
47
+ check_error(rc, "Could not get RPC")
48
+ rpc
49
+ ensure
50
+ rc = SQLFreeHandle(SQL_HANDLE_STMT, sth)
51
+ check_error(rc, "Could not free statement")
52
+ end
53
+ end
54
+ end
55
+ alias_method :do, :execute
56
+
57
+ private
58
+
59
+ def check_error(rc, msg)
60
+ case rc
61
+ when SQL_SUCCESS, SQL_SUCCESS_WITH_INFO
62
+ nil
63
+ else
64
+ raise DatabaseError, msg
65
+ end
66
+ end
67
+
68
+ def disconnect_connection(conn)
69
+ rc = SQLDisconnect(conn)
70
+ check_error(rc, "Could not disconnect from database")
71
+
72
+ rc = SQLFreeHandle(SQL_HANDLE_DBC, conn)
73
+ check_error(rc, "Could not free Database handle")
74
+ end
75
+ end
76
+
77
+ class Dataset < Sequel::Dataset
78
+ MAX_COL_SIZE = 256
79
+
80
+ def fetch_rows(sql)
81
+ execute(sql) do |sth|
82
+ @column_info = get_column_info(sth)
83
+ @columns = @column_info.map {|c| output_identifier(c[:name])}
84
+ while (rc = SQLFetch(@handle)) != SQL_NO_DATA_FOUND
85
+ @db.check_error(rc, "Could not fetch row")
86
+ yield hash_row(sth)
87
+ end
88
+ end
89
+ self
90
+ end
91
+
92
+ # DB2 supports window functions
93
+ def supports_window_functions?
94
+ true
95
+ end
96
+
97
+ private
98
+
99
+ def get_column_info(sth)
100
+ rc, column_count = SQLNumResultCols(sth)
101
+ @db.check_error(rc, "Could not get number of result columns")
102
+
103
+ (1..column_count).map do |i|
104
+ rc, name, buflen, datatype, size, digits, nullable = SQLDescribeCol(sth, i, MAX_COL_SIZE)
105
+ @b.check_error(rc, "Could not describe column")
106
+
107
+ {:name => name, :db2_type => datatype, :precision => size}
108
+ end
109
+ end
110
+
111
+ def hash_row(sth)
112
+ row = {}
113
+ @column_info.each_with_index do |c, i|
114
+ rc, v = SQLGetData(sth, i+1, c[:db2_type], c[:precision])
115
+ @db.check_error(rc, "Could not get data")
116
+
117
+ row[output_identifier(c[:name])] = convert_type(v)
118
+ end
119
+ row
120
+ end
121
+
122
+ def convert_type(v)
123
+ case v
124
+ when DB2CLI::Date
125
+ DBI::Date.new(v.year, v.month, v.day)
126
+ when DB2CLI::Time
127
+ DBI::Time.new(v.hour, v.minute, v.second)
128
+ when DB2CLI::Timestamp
129
+ DBI::Timestamp.new(v.year, v.month, v.day,
130
+ v.hour, v.minute, v.second, v.fraction)
131
+ when DB2CLI::Null
132
+ nil
133
+ else
134
+ v
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,113 @@
1
+ require 'dbi'
2
+
3
+ module Sequel
4
+ module DBI
5
+ class Database < Sequel::Database
6
+ set_adapter_scheme :dbi
7
+
8
+ DBI_ADAPTERS = {
9
+ :ado => "ADO",
10
+ :db2 => "DB2",
11
+ :frontbase => "FrontBase",
12
+ :interbase => "InterBase",
13
+ :msql => "Msql",
14
+ :mysql => "Mysql",
15
+ :odbc => "ODBC",
16
+ :oracle => "Oracle",
17
+ :pg => "pg",
18
+ :proxy => "Proxy",
19
+ :sqlite => "SQLite",
20
+ :sqlrelay => "SQLRelay"
21
+ }
22
+
23
+ def initialize(opts)
24
+ super
25
+ case @opts[:db_type]
26
+ when 'mssql'
27
+ Sequel.ts_require 'adapters/shared/mssql'
28
+ extend Sequel::MSSQL::DatabaseMethods
29
+ def self.dataset(*args)
30
+ ds = super
31
+ ds.extend Sequel::MSSQL::DatasetMethods
32
+ ds
33
+ end
34
+ end
35
+ end
36
+
37
+ # Converts a uri to an options hash. These options are then passed
38
+ # to a newly created database object.
39
+ def self.uri_to_options(uri) # :nodoc:
40
+ database = (m = /\/(.*)/.match(uri.path)) && (m[1])
41
+ if m = /dbi-(.+)/.match(uri.scheme)
42
+ adapter = DBI_ADAPTERS[m[1].to_sym] || m[1]
43
+ database = "#{adapter}:dbname=#{database}"
44
+ end
45
+ {
46
+ :user => uri.user,
47
+ :password => uri.password,
48
+ :host => uri.host,
49
+ :port => uri.port,
50
+ :database => database
51
+ }
52
+ end
53
+
54
+ private_class_method :uri_to_options
55
+
56
+ def connect(server)
57
+ opts = server_opts(server)
58
+ dbname = opts[:database]
59
+ if dbname !~ /^DBI:/ then
60
+ dbname = "DBI:#{dbname}"
61
+ [:host, :port].each{|sym| dbname += ";#{sym}=#{opts[sym]}" unless blank_object?(opts[sym])}
62
+ end
63
+ ::DBI.connect(dbname, opts[:user], opts[:password])
64
+ end
65
+
66
+ def dataset(opts = nil)
67
+ DBI::Dataset.new(self, opts)
68
+ end
69
+
70
+ def execute(sql, opts={})
71
+ synchronize(opts[:server]) do |conn|
72
+ r = log_yield(sql){conn.execute(sql)}
73
+ yield(r) if block_given?
74
+ r
75
+ end
76
+ end
77
+
78
+ def do(sql, opts={})
79
+ synchronize(opts[:server]){|conn| log_yield(sql){conn.do(sql)}}
80
+ end
81
+ alias_method :execute_dui, :do
82
+
83
+ private
84
+
85
+ def disconnect_connection(c)
86
+ c.disconnect
87
+ end
88
+ end
89
+
90
+ class Dataset < Sequel::Dataset
91
+ def fetch_rows(sql, &block)
92
+ execute(sql) do |s|
93
+ begin
94
+ @columns = s.column_names.map{|c| output_identifier(c)}
95
+ s.fetch{|r| yield hash_row(s, r)}
96
+ ensure
97
+ s.finish rescue nil
98
+ end
99
+ end
100
+ self
101
+ end
102
+
103
+ private
104
+
105
+ def hash_row(stmt, row)
106
+ @columns.inject({}) do |m, c|
107
+ m[c] = row.shift
108
+ m
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,188 @@
1
+ require 'data_objects'
2
+
3
+ module Sequel
4
+ # Module holding the DataObjects support for Sequel. DataObjects is a
5
+ # ruby library with a standard API for accessing databases.
6
+ #
7
+ # The DataObjects adapter currently supports PostgreSQL, MySQL, and
8
+ # SQLite:
9
+ #
10
+ # * Sequel.connect('do:sqlite3::memory:')
11
+ # * Sequel.connect('do:postgres://user:password@host/database')
12
+ # * Sequel.connect('do:mysql://user:password@host/database')
13
+ module DataObjects
14
+ # Contains procs keyed on sub adapter type that extend the
15
+ # given database object so it supports the correct database type.
16
+ DATABASE_SETUP = {:postgres=>proc do |db|
17
+ Sequel.tsk_require 'do_postgres'
18
+ Sequel.ts_require 'adapters/do/postgres'
19
+ db.extend(Sequel::DataObjects::Postgres::DatabaseMethods)
20
+ end,
21
+ :mysql=>proc do |db|
22
+ Sequel.tsk_require 'do_mysql'
23
+ Sequel.ts_require 'adapters/do/mysql'
24
+ db.extend(Sequel::DataObjects::MySQL::DatabaseMethods)
25
+ end,
26
+ :sqlite3=>proc do |db|
27
+ Sequel.tsk_require 'do_sqlite3'
28
+ Sequel.ts_require 'adapters/do/sqlite'
29
+ db.extend(Sequel::DataObjects::SQLite::DatabaseMethods)
30
+ end
31
+ }
32
+
33
+ # DataObjects uses it's own internal connection pooling in addition to the
34
+ # pooling that Sequel uses. You should make sure that you don't set
35
+ # the connection pool size to more than 8 for a
36
+ # Sequel::DataObjects::Database object, or hack DataObjects (or Extlib) to
37
+ # use a pool size at least as large as the pool size being used by Sequel.
38
+ class Database < Sequel::Database
39
+ set_adapter_scheme :do
40
+
41
+ # Call the DATABASE_SETUP proc directly after initialization,
42
+ # so the object always uses sub adapter specific code. Also,
43
+ # raise an error immediately if the connection doesn't have a
44
+ # uri, since DataObjects requires one.
45
+ def initialize(opts)
46
+ super
47
+ raise(Error, "No connection string specified") unless uri
48
+ if prok = DATABASE_SETUP[subadapter.to_sym]
49
+ prok.call(self)
50
+ end
51
+ end
52
+
53
+ # Setup a DataObjects::Connection to the database.
54
+ def connect(server)
55
+ setup_connection(::DataObjects::Connection.new(uri(server_opts(server))))
56
+ end
57
+
58
+ # Return a Sequel::DataObjects::Dataset object for this database.
59
+ def dataset(opts = nil)
60
+ DataObjects::Dataset.new(self, opts)
61
+ end
62
+
63
+ # Execute the given SQL. If a block is given, the DataObjects::Reader
64
+ # created is yielded to it. A block should not be provided unless a
65
+ # a SELECT statement is being used (or something else that returns rows).
66
+ # Otherwise, the return value is the insert id if opts[:type] is :insert,
67
+ # or the number of affected rows, otherwise.
68
+ def execute(sql, opts={})
69
+ synchronize(opts[:server]) do |conn|
70
+ begin
71
+ command = conn.create_command(sql)
72
+ res = log_yield(sql){block_given? ? command.execute_reader : command.execute_non_query}
73
+ rescue ::DataObjects::Error => e
74
+ raise_error(e)
75
+ end
76
+ if block_given?
77
+ begin
78
+ yield(res)
79
+ ensure
80
+ res.close if res
81
+ end
82
+ elsif opts[:type] == :insert
83
+ res.insert_id
84
+ else
85
+ res.affected_rows
86
+ end
87
+ end
88
+ end
89
+
90
+ # Execute the SQL on the this database, returning the number of affected
91
+ # rows.
92
+ def execute_dui(sql, opts={})
93
+ execute(sql, opts)
94
+ end
95
+
96
+ # Execute the SQL on this database, returning the primary key of the
97
+ # table being inserted to.
98
+ def execute_insert(sql, opts={})
99
+ execute(sql, opts.merge(:type=>:insert))
100
+ end
101
+
102
+ # Return the subadapter type for this database, i.e. sqlite3 for
103
+ # do:sqlite3::memory:.
104
+ def subadapter
105
+ uri.split(":").first
106
+ end
107
+
108
+ # Return the DataObjects URI for the Sequel URI, removing the do:
109
+ # prefix.
110
+ def uri(opts={})
111
+ opts = @opts.merge(opts)
112
+ (opts[:uri] || opts[:url]).sub(/\Ado:/, '')
113
+ end
114
+
115
+ private
116
+
117
+ # DataObjects uses a special transaction object to keep track of
118
+ # transactions. Unfortunately, it tries to create a new connection
119
+ # to do a transaction. So we close the connection created and
120
+ # substitute our own.
121
+ def begin_transaction(conn)
122
+ return super if supports_savepoints?
123
+ log_yield(TRANSACTION_BEGIN) do
124
+ t = ::DataObjects::Transaction.create_for_uri(uri)
125
+ t.instance_variable_get(:@connection).close
126
+ t.instance_variable_set(:@connection, conn)
127
+ t.begin
128
+ t
129
+ end
130
+ end
131
+
132
+ # DataObjects requires transactions be prepared before being
133
+ # committed, so we do that.
134
+ def commit_transaction(t)
135
+ return super if supports_savepoints?
136
+ log_yield(TRANSACTION_ROLLBACK) do
137
+ t.prepare
138
+ t.commit
139
+ end
140
+ end
141
+
142
+ # Method to call on a statement object to execute SQL that does
143
+ # not return any rows.
144
+ def connection_execute_method
145
+ :execute_non_query
146
+ end
147
+
148
+ # Close the given database connection.
149
+ def disconnect_connection(c)
150
+ c.close
151
+ end
152
+
153
+ # Execute SQL on the connection by creating a command first
154
+ def log_connection_execute(conn, sql)
155
+ log_yield(sql){conn.create_command(sql).execute_non_query}
156
+ end
157
+
158
+ # We use the transactions rollback method to rollback.
159
+ def rollback_transaction(t)
160
+ return super if supports_savepoints?
161
+ log_yield(TRANSACTION_COMMIT){t.rollback}
162
+ end
163
+
164
+ # Allow extending the given connection when it is first created.
165
+ # By default, just returns the connection.
166
+ def setup_connection(conn)
167
+ conn
168
+ end
169
+ end
170
+
171
+ # Dataset class for Sequel::DataObjects::Database objects.
172
+ class Dataset < Sequel::Dataset
173
+ # Execute the SQL on the database and yield the rows as hashes
174
+ # with symbol keys.
175
+ def fetch_rows(sql)
176
+ execute(sql) do |reader|
177
+ cols = @columns = reader.fields.map{|f| output_identifier(f)}
178
+ while(reader.next!) do
179
+ h = {}
180
+ cols.zip(reader.values).each{|k, v| h[k] = v}
181
+ yield h
182
+ end
183
+ end
184
+ self
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,49 @@
1
+ Sequel.require 'adapters/shared/mysql'
2
+
3
+ module Sequel
4
+ module DataObjects
5
+ # Database and Dataset instance methods for MySQL specific
6
+ # support via DataObjects.
7
+ module MySQL
8
+ # Database instance methods for MySQL databases accessed via DataObjects.
9
+ module DatabaseMethods
10
+ include Sequel::MySQL::DatabaseMethods
11
+
12
+ # Return instance of Sequel::DataObjects::MySQL::Dataset with the given opts.
13
+ def dataset(opts=nil)
14
+ Sequel::DataObjects::MySQL::Dataset.new(self, opts)
15
+ end
16
+
17
+ private
18
+
19
+ # The database name for the given database. Need to parse it out
20
+ # of the connection string, since the DataObjects does no parsing on the
21
+ # given connection string by default.
22
+ def database_name
23
+ (m = /\/(.*)/.match(URI.parse(uri).path)) && m[1]
24
+ end
25
+
26
+ def schema_column_type(db_type)
27
+ db_type == 'tinyint(1)' ? :boolean : super
28
+ end
29
+ end
30
+
31
+ # Dataset class for MySQL datasets accessed via DataObjects.
32
+ class Dataset < DataObjects::Dataset
33
+ include Sequel::MySQL::DatasetMethods
34
+
35
+ # Use execute_insert to execute the replace_sql.
36
+ def replace(*args)
37
+ execute_insert(replace_sql(*args))
38
+ end
39
+
40
+ private
41
+
42
+ # do_mysql sets NO_BACKSLASH_ESCAPES, so use standard SQL string escaping
43
+ def literal_string(s)
44
+ "'#{s.gsub("'", "''")}'"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end