sequel 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +48 -0
- data/Rakefile +16 -6
- data/bin/sequel +0 -0
- data/doc/cheat_sheet.rdoc +4 -4
- data/doc/schema.rdoc +9 -0
- data/lib/sequel_core/adapters/jdbc.rb +7 -7
- data/lib/sequel_core/adapters/mysql.rb +6 -11
- data/lib/sequel_core/adapters/shared/mssql.rb +21 -1
- data/lib/sequel_core/adapters/shared/mysql.rb +19 -27
- data/lib/sequel_core/adapters/shared/postgres.rb +67 -11
- data/lib/sequel_core/adapters/shared/sqlite.rb +11 -22
- data/lib/sequel_core/adapters/sqlite.rb +8 -4
- data/lib/sequel_core/core_sql.rb +4 -4
- data/lib/sequel_core/database.rb +56 -31
- data/lib/sequel_core/database/schema.rb +13 -5
- data/lib/sequel_core/dataset/convenience.rb +1 -1
- data/lib/sequel_core/dataset/sql.rb +30 -15
- data/lib/sequel_core/migration.rb +7 -0
- data/lib/sequel_core/schema/generator.rb +13 -2
- data/lib/sequel_core/schema/sql.rb +27 -81
- data/lib/sequel_core/sql.rb +5 -2
- data/lib/sequel_model.rb +8 -2
- data/lib/sequel_model/associations.rb +7 -4
- data/lib/sequel_model/base.rb +10 -1
- data/lib/sequel_model/eager_loading.rb +29 -10
- data/lib/sequel_model/record.rb +19 -5
- data/spec/adapters/mysql_spec.rb +2 -2
- data/spec/adapters/postgres_spec.rb +26 -5
- data/spec/adapters/sqlite_spec.rb +42 -8
- data/spec/integration/eager_loader_test.rb +51 -58
- data/spec/integration/schema_test.rb +28 -4
- data/spec/sequel_core/core_sql_spec.rb +3 -0
- data/spec/sequel_core/database_spec.rb +24 -0
- data/spec/sequel_core/dataset_spec.rb +25 -17
- data/spec/sequel_core/schema_spec.rb +58 -26
- data/spec/sequel_model/eager_loading_spec.rb +65 -0
- data/spec/sequel_model/hooks_spec.rb +1 -1
- data/spec/sequel_model/model_spec.rb +1 -0
- data/spec/sequel_model/record_spec.rb +74 -1
- data/spec/sequel_model/spec_helper.rb +8 -0
- metadata +5 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,51 @@
|
|
1
|
+
=== 2.6.0 (2008-10-11)
|
2
|
+
|
3
|
+
* Make the sqlite adapter respect the Sequel.datetime_class setting, for timestamp and datetime types (jeremyevans)
|
4
|
+
|
5
|
+
* Enhance the CASE statement support to include an optional expression (jarredholman)
|
6
|
+
|
7
|
+
* Default to using the simple language if no language is specified for a full text index on PostgreSQL (michalbugno)
|
8
|
+
|
9
|
+
* Add Model.raise_on_typecast_failure=, which makes it possible to not raise errors on invalid typecasts (michalbugno)
|
10
|
+
|
11
|
+
* Add schema.rdoc file, which provides an brief description of the various parts of Sequel related to schema modification (jeremyevans)
|
12
|
+
|
13
|
+
* Fix constraint generation when not using a proc or interpolated string (jeremyevans)
|
14
|
+
|
15
|
+
* Make eager_graph respect associations' :order options (use :order_eager_graph=>false to disable) (jeremyevans)
|
16
|
+
|
17
|
+
* Cache negative lookup when eagerly loading many_to_one associations where no objects have an associated object (jeremyevans)
|
18
|
+
|
19
|
+
* Allow string keys to be used when using Dataset#multi_insert (jeremyevans)
|
20
|
+
|
21
|
+
* Fix join_table when doing the first join for a dataset where the first source is a dataset when using unqualified columns (jeremyevans)
|
22
|
+
|
23
|
+
* Fix a few corner cases in eager_graph (jeremyevans)
|
24
|
+
|
25
|
+
* Support transactions on MSSQL (jeremyevans)
|
26
|
+
|
27
|
+
* Use string literals in AS clauses on SQLite (jeremyevans) (#241)
|
28
|
+
|
29
|
+
* AlterTableGenerator#set_column_allow_null was added to SET/DROP NOT NULL for columns (divoxx)
|
30
|
+
|
31
|
+
* Database#tables now works for MySQL databases using the JDBC adapter (jeremyevans)
|
32
|
+
|
33
|
+
* Database#drop_view can now take multiple arguments to drop multiple views at once (jeremyevans)
|
34
|
+
|
35
|
+
* Schema modification methods (e.g. drop_table, create_table!) now remove the cached schema entry (jeremyevans)
|
36
|
+
|
37
|
+
* Models can now determine their primary keys by looking at the schema (jeremyevans)
|
38
|
+
|
39
|
+
* No longer include :numeric_precision and :max_chars entries in the schema column hashes, use the :db_type entry instead (jeremyevans)
|
40
|
+
|
41
|
+
* Make schema parsing on PostgreSQL handle implicit schemas (e.g. schema(:schema__table)), so it works with models for tables outside the public schema (jeremyevans)
|
42
|
+
|
43
|
+
* Significantly speed up schema parsing on MySQL (jeremyevans)
|
44
|
+
|
45
|
+
* Include primary key information when parsing the schema (jeremyevans)
|
46
|
+
|
47
|
+
* Fix schema generation of composite foreign keys on MySQL (clivecrous, jeremyevans)
|
48
|
+
|
1
49
|
=== 2.5.0 (2008-09-03)
|
2
50
|
|
3
51
|
* Add Dataset #set_defaults and #set_overrides, used for scoping the values used in insert/update statements (jeremyevans)
|
data/Rakefile
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
require "rake"
|
2
2
|
require "rake/clean"
|
3
3
|
require "rake/gempackagetask"
|
4
|
-
require "rake/rdoctask"
|
5
|
-
require "fileutils"
|
6
4
|
require "spec/rake/spectask"
|
5
|
+
begin
|
6
|
+
require "hanna/rdoctask"
|
7
|
+
rescue LoadError
|
8
|
+
require "rake/rdoctask"
|
9
|
+
end
|
10
|
+
require "fileutils"
|
7
11
|
|
8
12
|
include FileUtils
|
9
13
|
|
10
14
|
NAME = 'sequel'
|
11
|
-
VERS = '2.
|
15
|
+
VERS = '2.6.0'
|
12
16
|
CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage", "www/public/*.html"]
|
13
17
|
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
|
14
18
|
'Sequel: The Database Toolkit for Ruby', '--main', 'README']
|
@@ -73,14 +77,20 @@ end
|
|
73
77
|
|
74
78
|
### Website
|
75
79
|
|
76
|
-
desc "Update sequel.rubyforge.org"
|
77
|
-
task :
|
78
|
-
task :website do
|
80
|
+
desc "Update Non-RDoc section of sequel.rubyforge.org"
|
81
|
+
task :website_base do
|
79
82
|
sh %{www/make_www.rb}
|
80
83
|
sh %{scp -r www/public/* rubyforge.org:/var/www/gforge-projects/sequel/}
|
84
|
+
end
|
85
|
+
|
86
|
+
desc "Update RDoc section of sequel.rubyforge.org"
|
87
|
+
task :website_rdoc=>[:rerdoc] do
|
81
88
|
sh %{scp -r rdoc/* rubyforge.org:/var/www/gforge-projects/sequel/rdoc/}
|
82
89
|
end
|
83
90
|
|
91
|
+
desc "Update sequel.rubyforge.org"
|
92
|
+
task :website=>[:website_base, :website_rdoc]
|
93
|
+
|
84
94
|
### Specs
|
85
95
|
|
86
96
|
lib_dir = File.join(File.dirname(__FILE__), 'lib')
|
data/bin/sequel
CHANGED
File without changes
|
data/doc/cheat_sheet.rdoc
CHANGED
@@ -5,10 +5,10 @@
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'sequel'
|
7
7
|
|
8
|
-
DB = Sequel.sqlite
|
9
|
-
DB = Sequel('postgres://user:password@localhost/my_db')
|
10
|
-
DB = Sequel.mysql
|
11
|
-
DB = Sequel.ado
|
8
|
+
DB = Sequel.sqlite('my_blog.db')
|
9
|
+
DB = Sequel.connect('postgres://user:password@localhost/my_db')
|
10
|
+
DB = Sequel.mysql('my_db', :user => 'user', :password => 'password', :host => 'localhost')
|
11
|
+
DB = Sequel.ado('mydb')
|
12
12
|
|
13
13
|
== Open an SQLite memory database
|
14
14
|
|
data/doc/schema.rdoc
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
= Schema Modifications with Sequel
|
2
|
+
|
3
|
+
In addition to its support for getting data from databases, Sequel has good support for modifying the schema of databases. Unfortunately, the documentation from this is spread out in various places in the Sequel RDoc.
|
4
|
+
|
5
|
+
The recommended way to set up schema modifications in Sequel is through migrations. Migrations are modifications to the schema that handle modifying the schema in two directions, up and down, with down reversing the changes made by up. Migrations are stored in sequentially numbered files inside a directory (see the Sequel::Migrator documentation for file naming format details). The migrations can be run on the database using the sequel command line tool (the -m and -M switches).
|
6
|
+
|
7
|
+
The format of the individual migration files themselves is explained in the Sequel::Migration documentation. Each migration file contains a single migration class. The migration class acts a proxy for the related database (given on the command line if the sequel command line tool is used, or by the db argument to Sequel::Migration#apply if the API is used). The methods that can be used inside Sequel::Migration#up or Sequel::Migration#down are just Sequel::Database instance methods, such as create_table, drop_table, and alter_table. Most database methods that alter the schema take regular arguments, but create_table and alter_table take a block. The methods you can use inside the create_table block are documented in Sequel::Schema::Generator, and the methods you can use inside the alter_table block are documented in Sequel::Schema::AlterTableGenerator.
|
8
|
+
|
9
|
+
Migrations are not required, you can just call the schema modification methods directly on the database object. This is often done in test code and examples. However, it is recommended that you use the migration framework unless the database schema will not be changing in the future, as it provides a way to easily handle modifications to existing database schema.
|
@@ -154,18 +154,18 @@ module Sequel
|
|
154
154
|
return yield(conn) if @transactions.include?(Thread.current)
|
155
155
|
stmt = conn.createStatement
|
156
156
|
begin
|
157
|
-
log_info(
|
158
|
-
stmt.execute(
|
157
|
+
log_info(begin_transaction_sql)
|
158
|
+
stmt.execute(begin_transaction_sql)
|
159
159
|
@transactions << Thread.current
|
160
160
|
yield(conn)
|
161
161
|
rescue Exception => e
|
162
|
-
log_info(
|
163
|
-
stmt.execute(
|
164
|
-
|
162
|
+
log_info(rollback_transaction_sql)
|
163
|
+
stmt.execute(rollback_transaction_sql)
|
164
|
+
transaction_error(e)
|
165
165
|
ensure
|
166
166
|
unless e
|
167
|
-
log_info(
|
168
|
-
stmt.execute(
|
167
|
+
log_info(commit_transaction_sql)
|
168
|
+
stmt.execute(commit_transaction_sql)
|
169
169
|
end
|
170
170
|
stmt.close
|
171
171
|
@transactions.delete(Thread.current)
|
@@ -146,28 +146,23 @@ module Sequel
|
|
146
146
|
@server_version ||= (synchronize(server){|conn| conn.server_version if conn.respond_to?(:server_version)} || super)
|
147
147
|
end
|
148
148
|
|
149
|
-
# Return an array of symbols specifying table names in the current database.
|
150
|
-
def tables(server=nil)
|
151
|
-
synchronize(server){|conn| conn.list_tables.map {|t| t.to_sym}}
|
152
|
-
end
|
153
|
-
|
154
149
|
# Support single level transactions on MySQL.
|
155
150
|
def transaction(server=nil)
|
156
151
|
synchronize(server) do |conn|
|
157
152
|
return yield(conn) if @transactions.include?(Thread.current)
|
158
|
-
log_info(
|
159
|
-
conn.query(
|
153
|
+
log_info(begin_transaction_sql)
|
154
|
+
conn.query(begin_transaction_sql)
|
160
155
|
begin
|
161
156
|
@transactions << Thread.current
|
162
157
|
yield(conn)
|
163
158
|
rescue ::Exception => e
|
164
|
-
log_info(
|
165
|
-
conn.query(
|
159
|
+
log_info(rollback_transaction_sql)
|
160
|
+
conn.query(rollback_transaction_sql)
|
166
161
|
transaction_error(e, Mysql::Error)
|
167
162
|
ensure
|
168
163
|
unless e
|
169
|
-
log_info(
|
170
|
-
conn.query(
|
164
|
+
log_info(commit_transaction_sql)
|
165
|
+
conn.query(commit_transaction_sql)
|
171
166
|
end
|
172
167
|
@transactions.delete(Thread.current)
|
173
168
|
end
|
@@ -2,16 +2,36 @@ module Sequel
|
|
2
2
|
module MSSQL
|
3
3
|
module DatabaseMethods
|
4
4
|
AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
|
5
|
+
SQL_BEGIN = "BEGIN TRANSACTION".freeze
|
6
|
+
SQL_COMMIT = "COMMIT TRANSACTION".freeze
|
7
|
+
SQL_ROLLBACK = "ROLLBACK TRANSACTION".freeze
|
5
8
|
|
6
9
|
def auto_increment_sql
|
7
10
|
AUTO_INCREMENT
|
8
11
|
end
|
9
|
-
|
12
|
+
|
10
13
|
def dataset(opts = nil)
|
11
14
|
ds = super
|
12
15
|
ds.extend(DatasetMethods)
|
13
16
|
ds
|
14
17
|
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# SQL to BEGIN a transaction.
|
22
|
+
def begin_transaction_sql
|
23
|
+
SQL_BEGIN
|
24
|
+
end
|
25
|
+
|
26
|
+
# SQL to COMMIT a transaction.
|
27
|
+
def commit_transaction_sql
|
28
|
+
SQL_COMMIT
|
29
|
+
end
|
30
|
+
|
31
|
+
# SQL to ROLLBACK a transaction.
|
32
|
+
def rollback_transaction_sql
|
33
|
+
SQL_ROLLBACK
|
34
|
+
end
|
15
35
|
end
|
16
36
|
|
17
37
|
module DatasetMethods
|
@@ -7,9 +7,6 @@ module Sequel
|
|
7
7
|
NOT_NULL = Sequel::Schema::SQL::NOT_NULL
|
8
8
|
NULL = Sequel::Schema::SQL::NULL
|
9
9
|
PRIMARY_KEY = Sequel::Schema::SQL::PRIMARY_KEY
|
10
|
-
SQL_BEGIN = Sequel::Database::SQL_BEGIN
|
11
|
-
SQL_COMMIT = Sequel::Database::SQL_COMMIT
|
12
|
-
SQL_ROLLBACK = Sequel::Database::SQL_ROLLBACK
|
13
10
|
TYPES = Sequel::Schema::SQL::TYPES
|
14
11
|
UNIQUE = Sequel::Schema::SQL::UNIQUE
|
15
12
|
UNSIGNED = Sequel::Schema::SQL::UNSIGNED
|
@@ -38,7 +35,7 @@ module Sequel
|
|
38
35
|
|
39
36
|
# Handle MySQL specific syntax for column references
|
40
37
|
def column_references_sql(column)
|
41
|
-
", FOREIGN KEY (#{quote_identifier(column[:name])})#{super(column)}"
|
38
|
+
"#{", FOREIGN KEY (#{quote_identifier(column[:name])})" unless column[:type] == :check}#{super(column)}"
|
42
39
|
end
|
43
40
|
|
44
41
|
# Handle MySQL specific index SQL syntax
|
@@ -62,6 +59,11 @@ module Sequel
|
|
62
59
|
@server_version ||= (m[1].to_i * 10000) + (m[2].to_i * 100) + m[3].to_i
|
63
60
|
end
|
64
61
|
|
62
|
+
# Return an array of symbols specifying table names in the current database.
|
63
|
+
def tables(server=nil)
|
64
|
+
self['SHOW TABLES'].server(server).map{|r| r.values.first.to_sym}
|
65
|
+
end
|
66
|
+
|
65
67
|
# Changes the database in use by issuing a USE statement. I would be
|
66
68
|
# very careful if I used this.
|
67
69
|
def use(db_name)
|
@@ -73,27 +75,18 @@ module Sequel
|
|
73
75
|
|
74
76
|
private
|
75
77
|
|
76
|
-
#
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
filt = super
|
89
|
-
# Restrict it to the given or current database, unless specifically requesting :database = nil
|
90
|
-
filt = SQL::BooleanExpression.new(:AND, filt, {:c__table_schema=>opts[:database] || database_name}) if opts[:database] || !opts.include?(:database)
|
91
|
-
filt
|
92
|
-
end
|
93
|
-
|
94
|
-
# MySQL doesn't support table catalogs, so just join on schema and table name.
|
95
|
-
def schema_ds_join(table_name, opts)
|
96
|
-
[:information_schema__columns, {:table_schema => :table_schema, :table_name => :table_name}, :c]
|
78
|
+
# Use the MySQL specific DESCRIBE syntax to get a table description.
|
79
|
+
def schema_parse_table(table_name, opts)
|
80
|
+
self["DESCRIBE ?", table_name].map do |row|
|
81
|
+
row.delete(:Extra)
|
82
|
+
row[:allow_null] = row.delete(:Null) == 'YES'
|
83
|
+
row[:default] = row.delete(:Default)
|
84
|
+
row[:primary_key] = row.delete(:Key) == 'PRI'
|
85
|
+
row[:default] = nil if row[:default].blank?
|
86
|
+
row[:db_type] = row.delete(:Type)
|
87
|
+
row[:type] = schema_column_type(row[:db_type])
|
88
|
+
[row.delete(:Field).to_sym, row]
|
89
|
+
end
|
97
90
|
end
|
98
91
|
end
|
99
92
|
|
@@ -193,9 +186,8 @@ module Sequel
|
|
193
186
|
|
194
187
|
# MySQL specific syntax for inserting multiple values at once.
|
195
188
|
def multi_insert_sql(columns, values)
|
196
|
-
columns = column_list(columns)
|
197
189
|
values = values.map {|r| literal(Array(r))}.join(COMMA_SEPARATOR)
|
198
|
-
["INSERT INTO #{source_list(@opts[:from])} (#{columns}) VALUES #{values}"]
|
190
|
+
["INSERT INTO #{source_list(@opts[:from])} (#{identifier_list(columns)}) VALUES #{values}"]
|
199
191
|
end
|
200
192
|
|
201
193
|
# MySQL uses the nonstandard ` (backtick) for quoting identifiers.
|
@@ -128,7 +128,7 @@ module Sequel
|
|
128
128
|
filter = " WHERE #{filter_expr(filter)}" if filter
|
129
129
|
case index_type
|
130
130
|
when :full_text
|
131
|
-
lang =
|
131
|
+
lang = "#{literal(index[:language] || 'simple')}, "
|
132
132
|
cols = index[:columns].map {|c| literal(c)}.join(" || ")
|
133
133
|
expr = "(to_tsvector(#{lang}#{cols}))"
|
134
134
|
index_type = :gin
|
@@ -150,6 +150,22 @@ module Sequel
|
|
150
150
|
synchronize(server){|conn| primary_key_for_table(conn, table)}
|
151
151
|
end
|
152
152
|
|
153
|
+
# Support :schema__table format for table
|
154
|
+
def schema(table_name=nil, opts={})
|
155
|
+
case table_name
|
156
|
+
when Symbol
|
157
|
+
t, c, a = dataset.send(:split_symbol, table_name)
|
158
|
+
opts[:schema] ||= t
|
159
|
+
table_name = c
|
160
|
+
when SQL::QualifiedIdentifier
|
161
|
+
opts[:schema] ||= table_name.table
|
162
|
+
table_name = table_name.column
|
163
|
+
when SQL::Identifier
|
164
|
+
table_name = table_name.value
|
165
|
+
end
|
166
|
+
super(table_name, opts)
|
167
|
+
end
|
168
|
+
|
153
169
|
# PostgreSQL uses SERIAL psuedo-type instead of AUTOINCREMENT for
|
154
170
|
# managing incrementing primary keys.
|
155
171
|
def serial_primary_key_options
|
@@ -267,14 +283,55 @@ module Sequel
|
|
267
283
|
@primary_key_sequences.include?(table) ? @primary_key_sequences[table] : (@primary_key_sequences[table] = conn.sequence(table))
|
268
284
|
end
|
269
285
|
|
270
|
-
#
|
271
|
-
#
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
286
|
+
# Set the default of the row to NULL if it is blank, and set
|
287
|
+
# the ruby type for the column based on the database type.
|
288
|
+
def schema_parse_rows(rows)
|
289
|
+
rows.map do |row|
|
290
|
+
row[:default] = nil if row[:default].blank?
|
291
|
+
row[:type] = schema_column_type(row[:db_type])
|
292
|
+
[row.delete(:name).to_sym, row]
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# Parse the schema for a single table.
|
297
|
+
def schema_parse_table(table_name, opts)
|
298
|
+
schema_parse_rows(schema_parser_dataset(table_name, opts))
|
299
|
+
end
|
300
|
+
|
301
|
+
# Parse the schema for multiple tables.
|
302
|
+
def schema_parse_tables(opts)
|
303
|
+
schemas = {}
|
304
|
+
schema_parser_dataset(nil, opts).each do |row|
|
305
|
+
(schemas[row.delete(:table).to_sym] ||= []) << row
|
306
|
+
end
|
307
|
+
schemas.each do |table, rows|
|
308
|
+
schemas[table] = schema_parse_rows(rows)
|
309
|
+
end
|
310
|
+
schemas
|
311
|
+
end
|
312
|
+
|
313
|
+
# The dataset used for parsing table schemas, using the pg_* system catalogs.
|
314
|
+
def schema_parser_dataset(table_name, opts)
|
315
|
+
ds = dataset.select(:pg_attribute__attname___name,
|
316
|
+
SQL::Function.new(:format_type, :pg_type__oid, :pg_attribute__atttypmod).as(:db_type),
|
317
|
+
SQL::Function.new(:pg_get_expr, :pg_attrdef__adbin, :pg_class__oid).as(:default),
|
318
|
+
SQL::BooleanExpression.new(:NOT, :pg_attribute__attnotnull).as(:allow_null),
|
319
|
+
SQL::Function.new(:COALESCE, {:pg_attribute__attnum => SQL::Function.new(:ANY, :pg_index__indkey)}.sql_expr, false).as(:primary_key)).
|
320
|
+
from(:pg_class).
|
321
|
+
join(:pg_attribute, :attrelid=>:oid).
|
322
|
+
join(:pg_type, :oid=>:atttypid).
|
323
|
+
left_outer_join(:pg_attrdef, :adrelid=>:pg_class__oid, :adnum=>:pg_attribute__attnum).
|
324
|
+
left_outer_join(:pg_index, :indrelid=>:pg_class__oid, :indisprimary=>true).
|
325
|
+
filter(:pg_attribute__attisdropped=>false).
|
326
|
+
filter(:pg_attribute__attnum > 0).
|
327
|
+
order(:pg_attribute__attnum)
|
328
|
+
if table_name
|
329
|
+
ds.filter!(:pg_class__relname=>table_name.to_s)
|
330
|
+
else
|
331
|
+
ds.select_more!(:pg_class__relname___table)
|
332
|
+
end
|
333
|
+
ds.join!(:pg_namespace, :oid=>:pg_class__relnamespace, :nspname=>opts[:schema] || 'public') if opts[:schema] || !opts.include?(:schema)
|
334
|
+
ds
|
278
335
|
end
|
279
336
|
end
|
280
337
|
|
@@ -409,9 +466,8 @@ module Sequel
|
|
409
466
|
return super if server_version < 80200
|
410
467
|
|
411
468
|
# postgresql 8.2 introduces support for multi-row insert
|
412
|
-
columns = column_list(columns)
|
413
469
|
values = values.map {|r| literal(Array(r))}.join(COMMA_SEPARATOR)
|
414
|
-
["INSERT INTO #{source_list(@opts[:from])} (#{columns}) VALUES #{values}"]
|
470
|
+
["INSERT INTO #{source_list(@opts[:from])} (#{identifier_list(columns)}) VALUES #{values}"]
|
415
471
|
end
|
416
472
|
|
417
473
|
# PostgreSQL assumes unquoted identifiers are lower case by default,
|
@@ -2,7 +2,6 @@ module Sequel
|
|
2
2
|
module SQLite
|
3
3
|
module DatabaseMethods
|
4
4
|
AUTO_VACUUM = {'0' => :none, '1' => :full, '2' => :incremental}.freeze
|
5
|
-
SCHEMA_TYPE_RE = /\A(\w+)\((\d+)\)\z/
|
6
5
|
SYNCHRONOUS = {'0' => :off, '1' => :normal, '2' => :full}.freeze
|
7
6
|
TABLES_FILTER = "type = 'table' AND NOT name = 'sqlite_sequence'"
|
8
7
|
TEMP_STORE = {'0' => :default, '1' => :file, '2' => :memory}.freeze
|
@@ -86,31 +85,16 @@ module Sequel
|
|
86
85
|
# SQLite supports schema parsing using the table_info PRAGMA, so
|
87
86
|
# parse the output of that into the format Sequel expects.
|
88
87
|
def schema_parse_table(table_name, opts)
|
89
|
-
|
88
|
+
self["PRAGMA table_info(?)", table_name].map do |row|
|
90
89
|
row.delete(:cid)
|
91
|
-
row[:
|
92
|
-
row[:allow_null] = row.delete(:notnull).to_i == 0 ? 'YES' : 'NO'
|
90
|
+
row[:allow_null] = row.delete(:notnull).to_i == 0
|
93
91
|
row[:default] = row.delete(:dflt_value)
|
94
|
-
row[:primary_key] = row.delete(:pk).to_i == 1
|
92
|
+
row[:primary_key] = row.delete(:pk).to_i == 1
|
93
|
+
row[:default] = nil if row[:default].blank?
|
95
94
|
row[:db_type] = row.delete(:type)
|
96
|
-
|
97
|
-
|
98
|
-
row[:max_chars] = m[2].to_i
|
99
|
-
else
|
100
|
-
row[:max_chars] = nil
|
101
|
-
end
|
102
|
-
row[:numeric_precision] = nil
|
103
|
-
row
|
95
|
+
row[:type] = schema_column_type(row[:db_type])
|
96
|
+
[row.delete(:name).to_sym, row]
|
104
97
|
end
|
105
|
-
schema_parse_rows(rows)
|
106
|
-
end
|
107
|
-
|
108
|
-
# SQLite doesn't support getting the schema of all tables at once,
|
109
|
-
# so loop through the output of #tables to get them.
|
110
|
-
def schema_parse_tables(opts)
|
111
|
-
schemas = {}
|
112
|
-
tables.each{|table| schemas[table] = schema_parse_table(table, opts)}
|
113
|
-
schemas
|
114
98
|
end
|
115
99
|
end
|
116
100
|
|
@@ -169,6 +153,11 @@ module Sequel
|
|
169
153
|
|
170
154
|
private
|
171
155
|
|
156
|
+
# SQLite uses string literals instead of identifiers in AS clauses.
|
157
|
+
def as_sql(expression, aliaz)
|
158
|
+
"#{expression} AS #{literal(aliaz.to_s)}"
|
159
|
+
end
|
160
|
+
|
172
161
|
# Call execute_insert on the database with the given SQL.
|
173
162
|
def execute_insert(sql, opts={})
|
174
163
|
@db.execute_insert(sql, {:server=>@opts[:server] || :default}.merge(opts))
|