viking-sequel 3.10.0

Sign up to get free protection for your applications and to get access to all the features.
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