sequel_core 2.2.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. metadata +30 -101
  2. data/CHANGELOG +0 -1519
  3. data/COPYING +0 -19
  4. data/README +0 -313
  5. data/Rakefile +0 -158
  6. data/bin/sequel +0 -117
  7. data/doc/cheat_sheet.rdoc +0 -225
  8. data/doc/dataset_filtering.rdoc +0 -182
  9. data/lib/sequel_core.rb +0 -136
  10. data/lib/sequel_core/adapters/adapter_skeleton.rb +0 -68
  11. data/lib/sequel_core/adapters/ado.rb +0 -90
  12. data/lib/sequel_core/adapters/db2.rb +0 -160
  13. data/lib/sequel_core/adapters/dbi.rb +0 -127
  14. data/lib/sequel_core/adapters/informix.rb +0 -89
  15. data/lib/sequel_core/adapters/jdbc.rb +0 -110
  16. data/lib/sequel_core/adapters/mysql.rb +0 -486
  17. data/lib/sequel_core/adapters/odbc.rb +0 -167
  18. data/lib/sequel_core/adapters/odbc_mssql.rb +0 -106
  19. data/lib/sequel_core/adapters/openbase.rb +0 -76
  20. data/lib/sequel_core/adapters/oracle.rb +0 -182
  21. data/lib/sequel_core/adapters/postgres.rb +0 -560
  22. data/lib/sequel_core/adapters/sqlite.rb +0 -270
  23. data/lib/sequel_core/connection_pool.rb +0 -194
  24. data/lib/sequel_core/core_ext.rb +0 -197
  25. data/lib/sequel_core/core_sql.rb +0 -184
  26. data/lib/sequel_core/database.rb +0 -462
  27. data/lib/sequel_core/database/schema.rb +0 -156
  28. data/lib/sequel_core/dataset.rb +0 -457
  29. data/lib/sequel_core/dataset/callback.rb +0 -13
  30. data/lib/sequel_core/dataset/convenience.rb +0 -245
  31. data/lib/sequel_core/dataset/pagination.rb +0 -96
  32. data/lib/sequel_core/dataset/query.rb +0 -41
  33. data/lib/sequel_core/dataset/schema.rb +0 -15
  34. data/lib/sequel_core/dataset/sql.rb +0 -889
  35. data/lib/sequel_core/deprecated.rb +0 -26
  36. data/lib/sequel_core/exceptions.rb +0 -42
  37. data/lib/sequel_core/migration.rb +0 -187
  38. data/lib/sequel_core/object_graph.rb +0 -216
  39. data/lib/sequel_core/pretty_table.rb +0 -71
  40. data/lib/sequel_core/schema.rb +0 -2
  41. data/lib/sequel_core/schema/generator.rb +0 -239
  42. data/lib/sequel_core/schema/sql.rb +0 -326
  43. data/lib/sequel_core/sql.rb +0 -812
  44. data/lib/sequel_core/worker.rb +0 -68
  45. data/spec/adapters/informix_spec.rb +0 -96
  46. data/spec/adapters/mysql_spec.rb +0 -765
  47. data/spec/adapters/oracle_spec.rb +0 -222
  48. data/spec/adapters/postgres_spec.rb +0 -441
  49. data/spec/adapters/sqlite_spec.rb +0 -413
  50. data/spec/connection_pool_spec.rb +0 -363
  51. data/spec/core_ext_spec.rb +0 -156
  52. data/spec/core_sql_spec.rb +0 -427
  53. data/spec/database_spec.rb +0 -963
  54. data/spec/dataset_spec.rb +0 -2933
  55. data/spec/expression_filters_spec.rb +0 -316
  56. data/spec/migration_spec.rb +0 -261
  57. data/spec/object_graph_spec.rb +0 -230
  58. data/spec/pretty_table_spec.rb +0 -58
  59. data/spec/rcov.opts +0 -6
  60. data/spec/schema_generator_spec.rb +0 -122
  61. data/spec/schema_spec.rb +0 -422
  62. data/spec/spec.opts +0 -0
  63. data/spec/spec_config.rb +0 -7
  64. data/spec/spec_config.rb.example +0 -8
  65. data/spec/spec_helper.rb +0 -55
  66. data/spec/worker_spec.rb +0 -96
@@ -1,270 +0,0 @@
1
- require 'sqlite3'
2
-
3
- module Sequel
4
- module SQLite
5
- class Database < Sequel::Database
6
- set_adapter_scheme :sqlite
7
-
8
- def serial_primary_key_options
9
- {:primary_key => true, :type => :integer, :auto_increment => true}
10
- end
11
-
12
- def connect
13
- @opts[:database] = ':memory:' if @opts[:database].blank?
14
- db = ::SQLite3::Database.new(@opts[:database])
15
- db.busy_timeout(@opts.fetch(:timeout, 5000))
16
- db.type_translation = true
17
- # fix for timestamp translation
18
- db.translator.add_translator("timestamp") do |t, v|
19
- v =~ /^\d+$/ ? Time.at(v.to_i) : Time.parse(v)
20
- end
21
- db
22
- end
23
-
24
- def disconnect
25
- @pool.disconnect {|c| c.close}
26
- end
27
-
28
- def dataset(opts = nil)
29
- SQLite::Dataset.new(self, opts)
30
- end
31
-
32
- TABLES_FILTER = "type = 'table' AND NOT name = 'sqlite_sequence'"
33
-
34
- def tables
35
- self[:sqlite_master].filter(TABLES_FILTER).map {|r| r[:name].to_sym}
36
- end
37
-
38
- def execute(sql)
39
- begin
40
- log_info(sql)
41
- @pool.hold {|conn| conn.execute_batch(sql); conn.changes}
42
- rescue SQLite3::Exception => e
43
- raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
44
- end
45
- end
46
-
47
- def execute_insert(sql)
48
- begin
49
- log_info(sql)
50
- @pool.hold {|conn| conn.execute(sql); conn.last_insert_row_id}
51
- rescue SQLite3::Exception => e
52
- raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
53
- end
54
- end
55
-
56
- def single_value(sql)
57
- begin
58
- log_info(sql)
59
- @pool.hold {|conn| conn.get_first_value(sql)}
60
- rescue SQLite3::Exception => e
61
- raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
62
- end
63
- end
64
-
65
- def execute_select(sql, &block)
66
- begin
67
- log_info(sql)
68
- @pool.hold {|conn| conn.query(sql, &block)}
69
- rescue SQLite3::Exception => e
70
- raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
71
- end
72
- end
73
-
74
- def pragma_get(name)
75
- single_value("PRAGMA #{name}")
76
- end
77
-
78
- def pragma_set(name, value)
79
- execute("PRAGMA #{name} = #{value}")
80
- end
81
-
82
- AUTO_VACUUM = {'0' => :none, '1' => :full, '2' => :incremental}.freeze
83
-
84
- def auto_vacuum
85
- AUTO_VACUUM[pragma_get(:auto_vacuum)]
86
- end
87
-
88
- def auto_vacuum=(value)
89
- value = AUTO_VACUUM.index(value) || (raise Error, "Invalid value for auto_vacuum option. Please specify one of :none, :full, :incremental.")
90
- pragma_set(:auto_vacuum, value)
91
- end
92
-
93
- SYNCHRONOUS = {'0' => :off, '1' => :normal, '2' => :full}.freeze
94
-
95
- def synchronous
96
- SYNCHRONOUS[pragma_get(:synchronous)]
97
- end
98
-
99
- def synchronous=(value)
100
- value = SYNCHRONOUS.index(value) || (raise Error, "Invalid value for synchronous option. Please specify one of :off, :normal, :full.")
101
- pragma_set(:synchronous, value)
102
- end
103
-
104
- TEMP_STORE = {'0' => :default, '1' => :file, '2' => :memory}.freeze
105
-
106
- def temp_store
107
- TEMP_STORE[pragma_get(:temp_store)]
108
- end
109
-
110
- def temp_store=(value)
111
- value = TEMP_STORE.index(value) || (raise Error, "Invalid value for temp_store option. Please specify one of :default, :file, :memory.")
112
- pragma_set(:temp_store, value)
113
- end
114
-
115
- def alter_table_sql(table, op)
116
- case op[:op]
117
- when :add_column
118
- "ALTER TABLE #{table} ADD #{column_definition_sql(op)}"
119
- when :add_index
120
- index_definition_sql(table, op)
121
- when :drop_column
122
- columns_str = (schema_parse_table(table, {}).map {|c| c[0] } - (Array === op[:name] ? op[:name] : [op[:name]])).join(",")
123
- sql = "BEGIN TRANSACTION;\n"
124
- sql += "CREATE TEMPORARY TABLE #{table}_backup(#{columns_str});\n"
125
- sql += "INSERT INTO #{table}_backup SELECT #{columns_str} FROM #{table};\n"
126
- sql += "DROP TABLE #{table};\n"
127
- sql += "CREATE TABLE #{table}(#{columns_str});\n"
128
- sql += "INSERT INTO #{table} SELECT #{columns_str} FROM #{table}_backup;\n"
129
- sql += "DROP TABLE #{table}_backup;\n"
130
- sql += "COMMIT;\n"
131
- else
132
- raise Error, "Unsupported ALTER TABLE operation"
133
- end
134
- end
135
-
136
- def transaction(&block)
137
- @pool.hold do |conn|
138
- if conn.transaction_active?
139
- return yield(conn)
140
- end
141
- begin
142
- result = nil
143
- conn.transaction {result = yield(conn)}
144
- result
145
- rescue ::Exception => e
146
- raise (SQLite3::Exception === e ? Error.new(e.message) : e) unless Error::Rollback === e
147
- end
148
- end
149
- end
150
-
151
- private
152
- def connection_pool_default_options
153
- o = super.merge(:pool_convert_exceptions=>false)
154
- # Default to only a single connection if a memory database is used,
155
- # because otherwise each connection will get a separate database
156
- o[:max_connections] = 1 if @opts[:database] == ':memory:' || @opts[:database].blank?
157
- o
158
- end
159
-
160
- SCHEMA_TYPE_RE = /\A(\w+)\((\d+)\)\z/
161
- def schema_parse_table(table_name, opts)
162
- rows = self["PRAGMA table_info('#{::SQLite3::Database.quote(table_name.to_s)}')"].collect do |row|
163
- row.delete(:cid)
164
- row[:column] = row.delete(:name)
165
- row[:allow_null] = row.delete(:notnull).to_i == 0 ? 'YES' : 'NO'
166
- row[:default] = row.delete(:dflt_value)
167
- row[:primary_key] = row.delete(:pk).to_i == 1 ? true : false
168
- row[:db_type] = row.delete(:type)
169
- if m = SCHEMA_TYPE_RE.match(row[:db_type])
170
- row[:db_type] = m[1]
171
- row[:max_chars] = m[2].to_i
172
- else
173
- row[:max_chars] = nil
174
- end
175
- row[:numeric_precision] = nil
176
- row
177
- end
178
- schema_parse_rows(rows)
179
- end
180
-
181
- def schema_parse_tables(opts)
182
- schemas = {}
183
- tables.each{|table| schemas[table] = schema_parse_table(table, opts)}
184
- schemas
185
- end
186
- end
187
-
188
- class Dataset < Sequel::Dataset
189
- def quoted_identifier(c)
190
- "`#{c}`"
191
- end
192
-
193
- def literal(v)
194
- case v
195
- when LiteralString
196
- v
197
- when String
198
- "'#{::SQLite3::Database.quote(v)}'"
199
- when Time
200
- literal(v.iso8601)
201
- when Date, DateTime
202
- literal(v.to_s)
203
- else
204
- super
205
- end
206
- end
207
-
208
- def complex_expression_sql(op, args)
209
- case op
210
- when :~, :'!~', :'~*', :'!~*'
211
- raise Error, "SQLite does not support pattern matching via regular expressions"
212
- when :LIKE, :'NOT LIKE', :ILIKE, :'NOT ILIKE'
213
- # SQLite is case insensitive for ASCII, and non case sensitive for other character sets
214
- "#{'NOT ' if [:'NOT LIKE', :'NOT ILIKE'].include?(op)}(#{literal(args.at(0))} LIKE #{literal(args.at(1))})"
215
- else
216
- super(op, args)
217
- end
218
- end
219
-
220
- def insert_sql(*values)
221
- if (values.size == 1) && values.first.is_a?(Sequel::Dataset)
222
- "INSERT INTO #{source_list(@opts[:from])} #{values.first.sql};"
223
- else
224
- super(*values)
225
- end
226
- end
227
-
228
- def fetch_rows(sql, &block)
229
- @db.execute_select(sql) do |result|
230
- @columns = result.columns.map {|c| c.to_sym}
231
- column_count = @columns.size
232
- result.each do |values|
233
- row = {}
234
- column_count.times {|i| row[@columns[i]] = values[i]}
235
- block.call(row)
236
- end
237
- end
238
- end
239
-
240
- def insert(*values)
241
- @db.execute_insert insert_sql(*values)
242
- end
243
-
244
- def update(*args, &block)
245
- @db.execute update_sql(*args, &block)
246
- end
247
-
248
- def delete(opts = nil)
249
- # check if no filter is specified
250
- unless (opts && opts[:where]) || @opts[:where]
251
- @db.transaction do
252
- unfiltered_count = count
253
- @db.execute delete_sql(opts)
254
- unfiltered_count
255
- end
256
- else
257
- @db.execute delete_sql(opts)
258
- end
259
- end
260
-
261
- EXPLAIN = 'EXPLAIN %s'.freeze
262
-
263
- def explain
264
- res = []
265
- @db.result_set(EXPLAIN % select_sql(opts), nil) {|r| res << r}
266
- res
267
- end
268
- end
269
- end
270
- end
@@ -1,194 +0,0 @@
1
- # A ConnectionPool manages access to database connections by keeping
2
- # multiple connections and giving threads exclusive access to each
3
- # connection.
4
- class Sequel::ConnectionPool
5
- # A hash of connections currently being used, key is the Thread,
6
- # value is the connection.
7
- attr_reader :allocated
8
-
9
- # An array of connections opened but not currently used
10
- attr_reader :available_connections
11
-
12
- # The proc used to create a new database connection.
13
- attr_accessor :connection_proc
14
-
15
- # The total number of connections opened, should
16
- # be equal to available_connections.length +
17
- # allocated.length
18
- attr_reader :created_count
19
- alias_method :size, :created_count
20
-
21
- # The maximum number of connections.
22
- attr_reader :max_size
23
-
24
- # The mutex that protects access to the other internal vairables. You must use
25
- # this if you want to manipulate the variables safely.
26
- attr_reader :mutex
27
-
28
-
29
- # Constructs a new pool with a maximum size. If a block is supplied, it
30
- # is used to create new connections as they are needed.
31
- #
32
- # pool = ConnectionPool.new(:max_connections=>10) {MyConnection.new(opts)}
33
- #
34
- # The connection creation proc can be changed at any time by assigning a
35
- # Proc to pool#connection_proc.
36
- #
37
- # pool = ConnectionPool.new(:max_connections=>10)
38
- # pool.connection_proc = proc {MyConnection.new(opts)}
39
- #
40
- # The connection pool takes the following options:
41
- #
42
- # * :max_connections - The maximum number of connections the connection pool
43
- # will open (default 4)
44
- # * :pool_convert_exceptions - Whether to convert non-StandardError based exceptions
45
- # to RuntimeError exceptions (default true)
46
- # * :pool_sleep_time - The amount of time to sleep before attempting to acquire
47
- # a connection again (default 0.001)
48
- # * :pool_timeout - The amount of seconds to wait to acquire a connection
49
- # before raising a PoolTimeoutError (default 5)
50
- def initialize(opts = {}, &block)
51
- @max_size = opts[:max_connections] || 4
52
- @mutex = Mutex.new
53
- @connection_proc = block
54
-
55
- @available_connections = []
56
- @allocated = {}
57
- @created_count = 0
58
- @timeout = opts[:pool_timeout] || 5
59
- @sleep_time = opts[:pool_sleep_time] || 0.001
60
- @convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true
61
- end
62
-
63
- # Chooses the first available connection, or if none are available,
64
- # creates a new connection. Passes the connection to the supplied block:
65
- #
66
- # pool.hold {|conn| conn.execute('DROP TABLE posts')}
67
- #
68
- # Pool#hold is re-entrant, meaning it can be called recursively in
69
- # the same thread without blocking.
70
- #
71
- # If no connection is immediately available and the pool is already using the maximum
72
- # number of connections, Pool#hold will block until a connection
73
- # is available or the timeout expires. If the timeout expires before a
74
- # connection can be acquired, a Sequel::Error::PoolTimeoutError is
75
- # raised.
76
- def hold
77
- begin
78
- t = Thread.current
79
- time = Time.new
80
- timeout = time + @timeout
81
- sleep_time = @sleep_time
82
- if conn = owned_connection(t)
83
- return yield(conn)
84
- end
85
- until conn = acquire(t)
86
- raise(::Sequel::Error::PoolTimeoutError) if Time.new > timeout
87
- sleep sleep_time
88
- end
89
- begin
90
- yield conn
91
- ensure
92
- release(t, conn)
93
- end
94
- rescue Exception => e
95
- raise(@convert_exceptions && !e.is_a?(StandardError) ? RuntimeError.new(e.message) : e)
96
- end
97
- end
98
-
99
- # Removes all connection currently available, optionally yielding each
100
- # connection to the given block. This method has the effect of
101
- # disconnecting from the database. Once a connection is requested using
102
- # #hold, the connection pool creates new connections to the database.
103
- def disconnect(&block)
104
- @mutex.synchronize do
105
- @available_connections.each {|c| block[c]} if block
106
- @available_connections = []
107
- @created_count = @allocated.size
108
- end
109
- end
110
-
111
- private
112
-
113
- # Returns the connection owned by the supplied thread, if any.
114
- def owned_connection(thread)
115
- @mutex.synchronize{@allocated[thread]}
116
- end
117
-
118
- # Assigns a connection to the supplied thread, if one is available.
119
- def acquire(thread)
120
- @mutex.synchronize do
121
- if conn = available
122
- @allocated[thread] = conn
123
- end
124
- end
125
- end
126
-
127
- # Returns an available connection. If no connection is available,
128
- # tries to create a new connection.
129
- def available
130
- @available_connections.pop || make_new
131
- end
132
-
133
- # Creates a new connection if the size of the pool is less than the
134
- # maximum size.
135
- def make_new
136
- if @created_count < @max_size
137
- @created_count += 1
138
- @connection_proc ? @connection_proc.call : \
139
- (raise Error, "No connection proc specified")
140
- end
141
- end
142
-
143
- # Releases the connection assigned to the supplied thread.
144
- def release(thread, conn)
145
- @mutex.synchronize do
146
- @allocated.delete(thread)
147
- @available_connections << conn
148
- end
149
- end
150
- end
151
-
152
- # A SingleThreadedPool acts as a replacement for a ConnectionPool for use
153
- # in single-threaded applications. ConnectionPool imposes a substantial
154
- # performance penalty, so SingleThreadedPool is used to gain some speed.
155
- #
156
- # Note that using a single threaded pool with some adapters can cause
157
- # errors in certain cases, see Sequel.single_threaded=.
158
- class Sequel::SingleThreadedPool
159
- # The single database connection for the pool
160
- attr_reader :conn
161
-
162
- # The proc used to create a new database connection
163
- attr_writer :connection_proc
164
-
165
- # Initializes the instance with the supplied block as the connection_proc.
166
- #
167
- # The single threaded pool takes the following options:
168
- #
169
- # * :pool_convert_exceptions - Whether to convert non-StandardError based exceptions
170
- # to RuntimeError exceptions (default true)
171
- def initialize(opts={}, &block)
172
- @connection_proc = block
173
- @convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true
174
- end
175
-
176
- # Yields the connection to the supplied block. This method simulates the
177
- # ConnectionPool#hold API.
178
- def hold
179
- begin
180
- @conn ||= @connection_proc.call
181
- yield @conn
182
- rescue Exception => e
183
- # if the error is not a StandardError it is converted into RuntimeError.
184
- raise(@convert_exceptions && !e.is_a?(StandardError) ? RuntimeError.new(e.message) : e)
185
- end
186
- end
187
-
188
- # Disconnects from the database. Once a connection is requested using
189
- # #hold, the connection is reestablished.
190
- def disconnect(&block)
191
- block[@conn] if block && @conn
192
- @conn = nil
193
- end
194
- end