sequel_core 2.2.0 → 3.8.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.
- metadata +30 -101
- data/CHANGELOG +0 -1519
- data/COPYING +0 -19
- data/README +0 -313
- data/Rakefile +0 -158
- data/bin/sequel +0 -117
- data/doc/cheat_sheet.rdoc +0 -225
- data/doc/dataset_filtering.rdoc +0 -182
- data/lib/sequel_core.rb +0 -136
- data/lib/sequel_core/adapters/adapter_skeleton.rb +0 -68
- data/lib/sequel_core/adapters/ado.rb +0 -90
- data/lib/sequel_core/adapters/db2.rb +0 -160
- data/lib/sequel_core/adapters/dbi.rb +0 -127
- data/lib/sequel_core/adapters/informix.rb +0 -89
- data/lib/sequel_core/adapters/jdbc.rb +0 -110
- data/lib/sequel_core/adapters/mysql.rb +0 -486
- data/lib/sequel_core/adapters/odbc.rb +0 -167
- data/lib/sequel_core/adapters/odbc_mssql.rb +0 -106
- data/lib/sequel_core/adapters/openbase.rb +0 -76
- data/lib/sequel_core/adapters/oracle.rb +0 -182
- data/lib/sequel_core/adapters/postgres.rb +0 -560
- data/lib/sequel_core/adapters/sqlite.rb +0 -270
- data/lib/sequel_core/connection_pool.rb +0 -194
- data/lib/sequel_core/core_ext.rb +0 -197
- data/lib/sequel_core/core_sql.rb +0 -184
- data/lib/sequel_core/database.rb +0 -462
- data/lib/sequel_core/database/schema.rb +0 -156
- data/lib/sequel_core/dataset.rb +0 -457
- data/lib/sequel_core/dataset/callback.rb +0 -13
- data/lib/sequel_core/dataset/convenience.rb +0 -245
- data/lib/sequel_core/dataset/pagination.rb +0 -96
- data/lib/sequel_core/dataset/query.rb +0 -41
- data/lib/sequel_core/dataset/schema.rb +0 -15
- data/lib/sequel_core/dataset/sql.rb +0 -889
- data/lib/sequel_core/deprecated.rb +0 -26
- data/lib/sequel_core/exceptions.rb +0 -42
- data/lib/sequel_core/migration.rb +0 -187
- data/lib/sequel_core/object_graph.rb +0 -216
- data/lib/sequel_core/pretty_table.rb +0 -71
- data/lib/sequel_core/schema.rb +0 -2
- data/lib/sequel_core/schema/generator.rb +0 -239
- data/lib/sequel_core/schema/sql.rb +0 -326
- data/lib/sequel_core/sql.rb +0 -812
- data/lib/sequel_core/worker.rb +0 -68
- data/spec/adapters/informix_spec.rb +0 -96
- data/spec/adapters/mysql_spec.rb +0 -765
- data/spec/adapters/oracle_spec.rb +0 -222
- data/spec/adapters/postgres_spec.rb +0 -441
- data/spec/adapters/sqlite_spec.rb +0 -413
- data/spec/connection_pool_spec.rb +0 -363
- data/spec/core_ext_spec.rb +0 -156
- data/spec/core_sql_spec.rb +0 -427
- data/spec/database_spec.rb +0 -963
- data/spec/dataset_spec.rb +0 -2933
- data/spec/expression_filters_spec.rb +0 -316
- data/spec/migration_spec.rb +0 -261
- data/spec/object_graph_spec.rb +0 -230
- data/spec/pretty_table_spec.rb +0 -58
- data/spec/rcov.opts +0 -6
- data/spec/schema_generator_spec.rb +0 -122
- data/spec/schema_spec.rb +0 -422
- data/spec/spec.opts +0 -0
- data/spec/spec_config.rb +0 -7
- data/spec/spec_config.rb.example +0 -8
- data/spec/spec_helper.rb +0 -55
- data/spec/worker_spec.rb +0 -96
@@ -1,71 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
module PrettyTable
|
3
|
-
# Prints nice-looking plain-text tables via puts
|
4
|
-
#
|
5
|
-
# +--+-------+
|
6
|
-
# |id|name |
|
7
|
-
# |--+-------|
|
8
|
-
# |1 |fasdfas|
|
9
|
-
# |2 |test |
|
10
|
-
# +--+-------+
|
11
|
-
def self.print(records, columns = nil) # records is an array of hashes
|
12
|
-
columns ||= records.first.keys.sort_by{|x|x.to_s}
|
13
|
-
sizes = column_sizes(records, columns)
|
14
|
-
sep_line = separator_line(columns, sizes)
|
15
|
-
|
16
|
-
puts sep_line
|
17
|
-
puts header_line(columns, sizes)
|
18
|
-
puts sep_line
|
19
|
-
records.each {|r| puts data_line(columns, sizes, r)}
|
20
|
-
puts sep_line
|
21
|
-
end
|
22
|
-
|
23
|
-
### Private Module Methods ###
|
24
|
-
|
25
|
-
# Hash of the maximum size of the value for each column
|
26
|
-
def self.column_sizes(records, columns) # :nodoc:
|
27
|
-
sizes = Hash.new {0}
|
28
|
-
columns.each do |c|
|
29
|
-
s = c.to_s.size
|
30
|
-
sizes[c.to_sym] = s if s > sizes[c.to_sym]
|
31
|
-
end
|
32
|
-
records.each do |r|
|
33
|
-
columns.each do |c|
|
34
|
-
s = r[c].to_s.size
|
35
|
-
sizes[c.to_sym] = s if s > sizes[c.to_sym]
|
36
|
-
end
|
37
|
-
end
|
38
|
-
sizes
|
39
|
-
end
|
40
|
-
|
41
|
-
# String for each data line
|
42
|
-
def self.data_line(columns, sizes, record) # :nodoc:
|
43
|
-
'|' << columns.map {|c| format_cell(sizes[c], record[c])}.join('|') << '|'
|
44
|
-
end
|
45
|
-
|
46
|
-
# Format the value so it takes up exactly size characters
|
47
|
-
def self.format_cell(size, v) # :nodoc:
|
48
|
-
case v
|
49
|
-
when Bignum, Fixnum
|
50
|
-
"%#{size}d" % v
|
51
|
-
when Float
|
52
|
-
"%#{size}g" % v
|
53
|
-
else
|
54
|
-
"%-#{size}s" % v.to_s
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# String for header line
|
59
|
-
def self.header_line(columns, sizes) # :nodoc:
|
60
|
-
'|' << columns.map {|c| "%-#{sizes[c]}s" % c.to_s}.join('|') << '|'
|
61
|
-
end
|
62
|
-
|
63
|
-
# String for separtor line
|
64
|
-
def self.separator_line(columns, sizes) # :nodoc:
|
65
|
-
'+' << columns.map {|c| '-' * sizes[c]}.join('+') << '+'
|
66
|
-
end
|
67
|
-
|
68
|
-
private_class_method :column_sizes, :data_line, :format_cell, :header_line, :separator_line
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
data/lib/sequel_core/schema.rb
DELETED
@@ -1,239 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
# The Schema module holds the schema generators and the SQL code relating
|
3
|
-
# to SQL DDL (Data Definition Language).
|
4
|
-
module Schema
|
5
|
-
# Schema::Generator is used to create tables. It takes a Database
|
6
|
-
# object and a block of column/index/constraint specifications, and
|
7
|
-
# creates a table in the database based on the specifications.
|
8
|
-
#
|
9
|
-
# Schema::Generator has some methods but also includes method_missing,
|
10
|
-
# allowing users to specify column type as a method instead of using
|
11
|
-
# the column method, which makes for a nicer DSL.
|
12
|
-
#
|
13
|
-
# See Database#create_table.
|
14
|
-
class Generator
|
15
|
-
# Set the database in which to create the table, and evaluate the block
|
16
|
-
# in the context of this object.
|
17
|
-
def initialize(db, &block)
|
18
|
-
@db = db
|
19
|
-
@columns = []
|
20
|
-
@indexes = []
|
21
|
-
@primary_key = nil
|
22
|
-
instance_eval(&block) if block
|
23
|
-
end
|
24
|
-
|
25
|
-
# Add a unnamed constraint to the DDL, specified by the given block
|
26
|
-
# or args.
|
27
|
-
def check(*args, &block)
|
28
|
-
constraint(nil, *args, &block)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Add a column with the given name, type, and opts to the DDL.
|
32
|
-
#
|
33
|
-
# You can also create columns via method missing, so the following are
|
34
|
-
# equivalent:
|
35
|
-
#
|
36
|
-
# column :number, :integer
|
37
|
-
# integer :number
|
38
|
-
#
|
39
|
-
# The following options are supported:
|
40
|
-
#
|
41
|
-
# * :default - The default value for the column.
|
42
|
-
# * :index - Create an index on this column.
|
43
|
-
# * :key - For foreign key columns, the column in the associated table
|
44
|
-
# that this column references. Unnecessary if this column
|
45
|
-
# references the primary key of the associated table.
|
46
|
-
# * :null - Mark the column as allowing NULL values (if true),
|
47
|
-
# or not allowing NULL values (if false). If unspecified, will default
|
48
|
-
# to whatever the database default is.
|
49
|
-
# * :on_delete - Specify the behavior of this column when being deleted.
|
50
|
-
# See Schema::SQL#on_delete_clause for options.
|
51
|
-
# * :size - The size of the column, generally used with string
|
52
|
-
# columns to specify the maximum number of characters the column will hold.
|
53
|
-
# * :unique - Mark the column is unique, generally has the same effect as
|
54
|
-
# creating a unique index on the column.
|
55
|
-
# * :unsigned - Make the column type unsigned, only useful for integer
|
56
|
-
# columns.
|
57
|
-
def column(name, type, opts = {})
|
58
|
-
@columns << {:name => name, :type => type}.merge(opts)
|
59
|
-
index(name) if opts[:index]
|
60
|
-
end
|
61
|
-
|
62
|
-
# Adds a named constraint (or unnamed if name is nil) to the DDL,
|
63
|
-
# with the given block or args.
|
64
|
-
def constraint(name, *args, &block)
|
65
|
-
@columns << {:name => name, :type => :check, :check => block || args}
|
66
|
-
end
|
67
|
-
|
68
|
-
# Return the DDL created by the generator as a array of two elements,
|
69
|
-
# the first being the columns and the second being the indexes.
|
70
|
-
def create_info
|
71
|
-
@columns.unshift(@primary_key) if @primary_key && !has_column?(primary_key_name)
|
72
|
-
[@columns, @indexes]
|
73
|
-
end
|
74
|
-
|
75
|
-
# Add a foreign key in the table that references another table to the DDL. See column
|
76
|
-
# for available options.
|
77
|
-
def foreign_key(name, table=nil, opts = {})
|
78
|
-
opts = case table
|
79
|
-
when Hash
|
80
|
-
table.merge(opts)
|
81
|
-
when Symbol
|
82
|
-
opts.merge(:table=>table)
|
83
|
-
when NilClass
|
84
|
-
opts
|
85
|
-
else
|
86
|
-
raise(Error, "The seconds argument to foreign_key should be a Hash, Symbol, or nil")
|
87
|
-
end
|
88
|
-
column(name, :integer, opts)
|
89
|
-
end
|
90
|
-
|
91
|
-
# Add a full text index on the given columns to the DDL.
|
92
|
-
def full_text_index(columns, opts = {})
|
93
|
-
index(columns, opts.merge(:type => :full_text))
|
94
|
-
end
|
95
|
-
|
96
|
-
# True if the DDL includes the creation of a column with the given name.
|
97
|
-
def has_column?(name)
|
98
|
-
@columns.any?{|c| c[:name] == name}
|
99
|
-
end
|
100
|
-
|
101
|
-
# Add an index on the given column(s) with the given options to the DDL.
|
102
|
-
# The available options are:
|
103
|
-
#
|
104
|
-
# * :type - The type of index to use (only supported by some databases)
|
105
|
-
# * :unique - Make the index unique, so duplicate values are not allowed.
|
106
|
-
# * :where - Create a partial index (only supported by some databases)
|
107
|
-
def index(columns, opts = {})
|
108
|
-
@indexes << {:columns => Array(columns)}.merge(opts)
|
109
|
-
end
|
110
|
-
|
111
|
-
# Add a column with the given type, name, and opts to the DDL. See column for available
|
112
|
-
# options.
|
113
|
-
def method_missing(type, name = nil, opts = {})
|
114
|
-
name ? column(name, type, opts) : super
|
115
|
-
end
|
116
|
-
|
117
|
-
# Add a column with the given name and primary key options to the DDL. You
|
118
|
-
# can optionally provide a type argument and/or an options hash argument
|
119
|
-
# to change the primary key options. See column for available options.
|
120
|
-
def primary_key(name, *args)
|
121
|
-
@primary_key = @db.serial_primary_key_options.merge({:name => name})
|
122
|
-
|
123
|
-
if opts = args.pop
|
124
|
-
opts = {:type => opts} unless opts.is_a?(Hash)
|
125
|
-
if type = args.pop
|
126
|
-
opts.merge!(:type => type)
|
127
|
-
end
|
128
|
-
@primary_key.merge!(opts)
|
129
|
-
end
|
130
|
-
@primary_key
|
131
|
-
end
|
132
|
-
|
133
|
-
# The name of the primary key for this table, if it has a primary key.
|
134
|
-
def primary_key_name
|
135
|
-
@primary_key[:name] if @primary_key
|
136
|
-
end
|
137
|
-
|
138
|
-
# Add a spatial index on the given columns to the DDL.
|
139
|
-
def spatial_index(columns, opts = {})
|
140
|
-
index(columns, opts.merge(:type => :spatial))
|
141
|
-
end
|
142
|
-
|
143
|
-
# Add a unique index on the given columns to the DDL.
|
144
|
-
def unique(columns, opts = {})
|
145
|
-
index(columns, opts.merge(:unique => true))
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# The Schema::AlterTableGenerator creates DDL operations on existing tables,
|
150
|
-
# such as adding/removing/modifying columns/indexes/constraints.
|
151
|
-
class AlterTableGenerator
|
152
|
-
# An array of DDL operations to perform
|
153
|
-
attr_reader :operations
|
154
|
-
|
155
|
-
# Set the Database object to which to apply the DDL, and evaluate the
|
156
|
-
# block in the context of this object.
|
157
|
-
def initialize(db, &block)
|
158
|
-
@db = db
|
159
|
-
@operations = []
|
160
|
-
instance_eval(&block) if block
|
161
|
-
end
|
162
|
-
|
163
|
-
# Add a column with the given name, type, and opts to the DDL for the table.
|
164
|
-
# See Generator#column for the available options.
|
165
|
-
def add_column(name, type, opts = {})
|
166
|
-
@operations << {:op => :add_column, :name => name, :type => type}.merge(opts)
|
167
|
-
end
|
168
|
-
|
169
|
-
# Add a constraint with the given name and args to the DDL for the table.
|
170
|
-
# See Generator#constraint.
|
171
|
-
def add_constraint(name, *args, &block)
|
172
|
-
@operations << {:op => :add_constraint, :name => name, :type => :check, \
|
173
|
-
:check => block || args}
|
174
|
-
end
|
175
|
-
|
176
|
-
# Add a foreign key with the given name and referencing the given table
|
177
|
-
# to the DDL for the table. See Generator#column for the available options.
|
178
|
-
def add_foreign_key(name, table, opts = {})
|
179
|
-
add_column(name, :integer, {:table=>table}.merge(opts))
|
180
|
-
end
|
181
|
-
|
182
|
-
# Add a full text index on the given columns to the DDL for the table.
|
183
|
-
# See Generator#index for available options.
|
184
|
-
def add_full_text_index(columns, opts = {})
|
185
|
-
add_index(columns, {:type=>:full_text}.merge(opts))
|
186
|
-
end
|
187
|
-
|
188
|
-
# Add an index on the given columns to the DDL for the table. See
|
189
|
-
# Generator#index for available options.
|
190
|
-
def add_index(columns, opts = {})
|
191
|
-
@operations << {:op => :add_index, :columns => Array(columns)}.merge(opts)
|
192
|
-
end
|
193
|
-
|
194
|
-
# Add a primary key to the DDL for the table. See Generator#column
|
195
|
-
# for the available options.
|
196
|
-
def add_primary_key(name, opts = {})
|
197
|
-
opts = @db.serial_primary_key_options.merge(opts)
|
198
|
-
add_column(name, opts.delete(:type), opts)
|
199
|
-
end
|
200
|
-
|
201
|
-
# Add a spatial index on the given columns to the DDL for the table.
|
202
|
-
# See Generator#index for available options.
|
203
|
-
def add_spatial_index(columns, opts = {})
|
204
|
-
add_index(columns, {:type=>:spatial}.merge(opts))
|
205
|
-
end
|
206
|
-
|
207
|
-
# Remove a column from the DDL for the table.
|
208
|
-
def drop_column(name)
|
209
|
-
@operations << {:op => :drop_column, :name => name}
|
210
|
-
end
|
211
|
-
|
212
|
-
# Remove a constraint from the DDL for the table.
|
213
|
-
def drop_constraint(name)
|
214
|
-
@operations << {:op => :drop_constraint, :name => name}
|
215
|
-
end
|
216
|
-
|
217
|
-
# Remove an index from the DDL for the table.
|
218
|
-
def drop_index(columns)
|
219
|
-
@operations << {:op => :drop_index, :columns => Array(columns)}
|
220
|
-
end
|
221
|
-
|
222
|
-
# Modify a column's name in the DDL for the table.
|
223
|
-
def rename_column(name, new_name, opts = {})
|
224
|
-
@operations << {:op => :rename_column, :name => name, :new_name => new_name}.merge(opts)
|
225
|
-
end
|
226
|
-
|
227
|
-
# Modify a column's default value in the DDL for the table.
|
228
|
-
def set_column_default(name, default)
|
229
|
-
@operations << {:op => :set_column_default, :name => name, :default => default}
|
230
|
-
end
|
231
|
-
|
232
|
-
# Modify a column's type in the DDL for the table.
|
233
|
-
def set_column_type(name, type)
|
234
|
-
@operations << {:op => :set_column_type, :name => name, :type => type}
|
235
|
-
end
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
@@ -1,326 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
module Schema
|
3
|
-
module SQL
|
4
|
-
AUTOINCREMENT = 'AUTOINCREMENT'.freeze
|
5
|
-
CASCADE = 'CASCADE'.freeze
|
6
|
-
COMMA_SEPARATOR = ', '.freeze
|
7
|
-
NO_ACTION = 'NO ACTION'.freeze
|
8
|
-
NOT_NULL = ' NOT NULL'.freeze
|
9
|
-
NULL = ' NULL'.freeze
|
10
|
-
PRIMARY_KEY = ' PRIMARY KEY'.freeze
|
11
|
-
RESTRICT = 'RESTRICT'.freeze
|
12
|
-
SET_DEFAULT = 'SET DEFAULT'.freeze
|
13
|
-
SET_NULL = 'SET NULL'.freeze
|
14
|
-
TYPES = Hash.new {|h, k| k}
|
15
|
-
TYPES[:double] = 'double precision'
|
16
|
-
UNDERSCORE = '_'.freeze
|
17
|
-
UNIQUE = ' UNIQUE'.freeze
|
18
|
-
UNSIGNED = ' UNSIGNED'.freeze
|
19
|
-
|
20
|
-
# The SQL to execute to modify the DDL for the given table name. op
|
21
|
-
# should be one of the operations returned by the AlterTableGenerator.
|
22
|
-
def alter_table_sql(table, op)
|
23
|
-
quoted_table = quote_identifier(table)
|
24
|
-
quoted_name = quote_identifier(op[:name]) if op[:name]
|
25
|
-
case op[:op]
|
26
|
-
when :add_column
|
27
|
-
"ALTER TABLE #{quoted_table} ADD COLUMN #{column_definition_sql(op)}"
|
28
|
-
when :drop_column
|
29
|
-
"ALTER TABLE #{quoted_table} DROP COLUMN #{quoted_name}"
|
30
|
-
when :rename_column
|
31
|
-
"ALTER TABLE #{quoted_table} RENAME COLUMN #{quoted_name} TO #{quote_identifier(op[:new_name])}"
|
32
|
-
when :set_column_type
|
33
|
-
"ALTER TABLE #{quoted_table} ALTER COLUMN #{quoted_name} TYPE #{op[:type]}"
|
34
|
-
when :set_column_default
|
35
|
-
"ALTER TABLE #{quoted_table} ALTER COLUMN #{quoted_name} SET DEFAULT #{literal(op[:default])}"
|
36
|
-
when :add_index
|
37
|
-
index_definition_sql(table, op)
|
38
|
-
when :drop_index
|
39
|
-
"DROP INDEX #{default_index_name(table, op[:columns])}"
|
40
|
-
when :add_constraint
|
41
|
-
"ALTER TABLE #{quoted_table} ADD #{constraint_definition_sql(op)}"
|
42
|
-
when :drop_constraint
|
43
|
-
"ALTER TABLE #{quoted_table} DROP CONSTRAINT #{quoted_name}"
|
44
|
-
else
|
45
|
-
raise Error, "Unsupported ALTER TABLE operation"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# Array of SQL DDL modification statements for the given table,
|
50
|
-
# corresponding to the DDL changes specified by the operations.
|
51
|
-
def alter_table_sql_list(table, operations)
|
52
|
-
operations.map{|op| alter_table_sql(table, op)}
|
53
|
-
end
|
54
|
-
|
55
|
-
# The SQL string specify the autoincrement property, generally used by
|
56
|
-
# primary keys.
|
57
|
-
def auto_increment_sql
|
58
|
-
AUTOINCREMENT
|
59
|
-
end
|
60
|
-
|
61
|
-
# SQL DDL fragment containing the column creation SQL for the given column.
|
62
|
-
def column_definition_sql(column)
|
63
|
-
return constraint_definition_sql(column) if column[:type] == :check
|
64
|
-
sql = "#{quote_identifier(column[:name])} #{type_literal(TYPES[column[:type]])}"
|
65
|
-
column[:size] ||= 255 if column[:type] == :varchar
|
66
|
-
elements = column[:size] || column[:elements]
|
67
|
-
sql << literal(Array(elements)) if elements
|
68
|
-
sql << UNSIGNED if column[:unsigned]
|
69
|
-
sql << UNIQUE if column[:unique]
|
70
|
-
sql << NOT_NULL if column[:null] == false
|
71
|
-
sql << NULL if column[:null] == true
|
72
|
-
sql << " DEFAULT #{literal(column[:default])}" if column.include?(:default)
|
73
|
-
sql << PRIMARY_KEY if column[:primary_key]
|
74
|
-
sql << " #{auto_increment_sql}" if column[:auto_increment]
|
75
|
-
if column[:table]
|
76
|
-
sql << " REFERENCES #{quote_identifier(column[:table])}"
|
77
|
-
sql << "(#{quote_identifier(column[:key])})" if column[:key]
|
78
|
-
sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete]
|
79
|
-
end
|
80
|
-
sql
|
81
|
-
end
|
82
|
-
|
83
|
-
# SQL DDL fragment containing the column creation
|
84
|
-
# SQL for all given columns, used instead a CREATE TABLE block.
|
85
|
-
def column_list_sql(columns)
|
86
|
-
columns.map{|c| column_definition_sql(c)}.join(COMMA_SEPARATOR)
|
87
|
-
end
|
88
|
-
|
89
|
-
# SQL DDL fragment specifying a constraint on a table.
|
90
|
-
def constraint_definition_sql(constraint)
|
91
|
-
sql = constraint[:name] ? "CONSTRAINT #{quote_identifier(constraint[:name])} " : ""
|
92
|
-
sql << "CHECK #{filter_expr(constraint[:check])}"
|
93
|
-
sql
|
94
|
-
end
|
95
|
-
|
96
|
-
# Array of SQL DDL statements, the first for creating a table with the given
|
97
|
-
# name and column specifications, and the others for specifying indexes on
|
98
|
-
# the table.
|
99
|
-
def create_table_sql_list(name, columns, indexes = nil)
|
100
|
-
sql = ["CREATE TABLE #{quote_identifier(name)} (#{column_list_sql(columns)})"]
|
101
|
-
sql.concat(index_list_sql_list(name, indexes)) if indexes && !indexes.empty?
|
102
|
-
sql
|
103
|
-
end
|
104
|
-
|
105
|
-
# Default index name for the table and columns, may be too long
|
106
|
-
# for certain databases.
|
107
|
-
def default_index_name(table_name, columns)
|
108
|
-
"#{table_name}_#{columns.join(UNDERSCORE)}_index"
|
109
|
-
end
|
110
|
-
|
111
|
-
# SQL DDL statement to drop the table with the given name.
|
112
|
-
def drop_table_sql(name)
|
113
|
-
"DROP TABLE #{quote_identifier(name)}"
|
114
|
-
end
|
115
|
-
|
116
|
-
# Proxy the filter_expr call to the dataset, used for creating constraints.
|
117
|
-
def filter_expr(*args, &block)
|
118
|
-
schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, *args, &block))
|
119
|
-
end
|
120
|
-
|
121
|
-
# SQL DDL statement for creating an index for the table with the given name
|
122
|
-
# and index specifications.
|
123
|
-
def index_definition_sql(table_name, index)
|
124
|
-
index_name = index[:name] || default_index_name(table_name, index[:columns])
|
125
|
-
if index[:type]
|
126
|
-
raise Error, "Index types are not supported for this database"
|
127
|
-
elsif index[:where]
|
128
|
-
raise Error, "Partial indexes are not supported for this database"
|
129
|
-
else
|
130
|
-
"CREATE #{'UNIQUE ' if index[:unique]}INDEX #{index_name} ON #{quote_identifier(table_name)} #{literal(index[:columns])}"
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# Array of SQL DDL statements, one for each index specification,
|
135
|
-
# for the given table.
|
136
|
-
def index_list_sql_list(table_name, indexes)
|
137
|
-
indexes.map{|i| index_definition_sql(table_name, i)}
|
138
|
-
end
|
139
|
-
|
140
|
-
# Proxy the literal call to the dataset, used for default values.
|
141
|
-
def literal(v)
|
142
|
-
schema_utility_dataset.literal(v)
|
143
|
-
end
|
144
|
-
|
145
|
-
# SQL DDL ON DELETE fragment to use, based on the given action.
|
146
|
-
# The following actions are recognized:
|
147
|
-
#
|
148
|
-
# * :cascade - Delete rows referencing this row.
|
149
|
-
# * :no_action (default) - Raise an error if other rows reference this
|
150
|
-
# row, allow deferring of the integrity check.
|
151
|
-
# * :restrict - Raise an error if other rows reference this row,
|
152
|
-
# but do not allow deferring the integrity check.
|
153
|
-
# * :set_default - Set columns referencing this row to their default value.
|
154
|
-
# * :set_null - Set columns referencing this row to NULL.
|
155
|
-
def on_delete_clause(action)
|
156
|
-
case action
|
157
|
-
when :restrict
|
158
|
-
RESTRICT
|
159
|
-
when :cascade
|
160
|
-
CASCADE
|
161
|
-
when :set_null
|
162
|
-
SET_NULL
|
163
|
-
when :set_default
|
164
|
-
SET_DEFAULT
|
165
|
-
else
|
166
|
-
NO_ACTION
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
# Proxy the quote_identifier method to the dataset, used for quoting tables and columns.
|
171
|
-
def quote_identifier(v)
|
172
|
-
schema_utility_dataset.quote_identifier(v)
|
173
|
-
end
|
174
|
-
|
175
|
-
# SQL DDL statement for renaming a table.
|
176
|
-
def rename_table_sql(name, new_name)
|
177
|
-
"ALTER TABLE #{quote_identifier(name)} RENAME TO #{quote_identifier(new_name)}"
|
178
|
-
end
|
179
|
-
|
180
|
-
# Parse the schema from the database using the SQL standard INFORMATION_SCHEMA.
|
181
|
-
# If the table_name is not given, returns the schema for all tables as a hash.
|
182
|
-
# If the table_name is given, returns the schema for a single table as an
|
183
|
-
# array with all members being arrays of length 2. Available options are:
|
184
|
-
#
|
185
|
-
# * :reload - Get fresh information from the database, instead of using
|
186
|
-
# cached information. If table_name is blank, :reload should be used
|
187
|
-
# unless you are sure that schema has not been called before with a
|
188
|
-
# table_name, otherwise you may only getting the schemas for tables
|
189
|
-
# that have been requested explicitly.
|
190
|
-
def schema(table_name = nil, opts={})
|
191
|
-
if opts[:reload] && @schemas
|
192
|
-
if table_name
|
193
|
-
@schemas.delete(table_name)
|
194
|
-
else
|
195
|
-
@schemas = nil
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
if table_name
|
200
|
-
return @schemas[table_name] if @schemas && @schemas[table_name]
|
201
|
-
else
|
202
|
-
return @schemas if @schemas
|
203
|
-
end
|
204
|
-
|
205
|
-
if table_name
|
206
|
-
@schemas ||= {}
|
207
|
-
@schemas[table_name] ||= schema_parse_table(table_name, opts)
|
208
|
-
else
|
209
|
-
@schemas = schema_parse_tables(opts)
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
# The dataset to use for proxying certain schema methods.
|
214
|
-
def schema_utility_dataset
|
215
|
-
@schema_utility_dataset ||= dataset
|
216
|
-
end
|
217
|
-
|
218
|
-
# SQL fragment specifying the type of a given column.
|
219
|
-
def type_literal(t)
|
220
|
-
t.is_a?(Symbol) ? t.to_s : literal(t)
|
221
|
-
end
|
222
|
-
|
223
|
-
private
|
224
|
-
|
225
|
-
# Match the database's column type to a ruby type via a
|
226
|
-
# regular expression. The following ruby types are supported:
|
227
|
-
# integer, string, date, datetime, boolean, and float.
|
228
|
-
def schema_column_type(db_type)
|
229
|
-
case db_type
|
230
|
-
when 'tinyint'
|
231
|
-
Sequel.convert_tinyint_to_bool ? :boolean : :integer
|
232
|
-
when /\A(int(eger)?|bigint|smallint)\z/
|
233
|
-
:integer
|
234
|
-
when /\A(character( varying)?|varchar|text)\z/
|
235
|
-
:string
|
236
|
-
when /\Adate\z/
|
237
|
-
:date
|
238
|
-
when /\A(datetime|timestamp( with(out)? time zone)?)\z/
|
239
|
-
:datetime
|
240
|
-
when /\Atime( with(out)? time zone)?\z/
|
241
|
-
:time
|
242
|
-
when "boolean"
|
243
|
-
:boolean
|
244
|
-
when /\A(real|float|double( precision)?)\z/
|
245
|
-
:float
|
246
|
-
when /\A(numeric|decimal|money)\z/
|
247
|
-
:decimal
|
248
|
-
when "bytea"
|
249
|
-
:blob
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
# The final dataset used by the schema parser, after all
|
254
|
-
# options have been applied.
|
255
|
-
def schema_ds(table_name, opts)
|
256
|
-
schema_ds_dataset.from(*schema_ds_from(table_name, opts)) \
|
257
|
-
.select(*schema_ds_select(table_name, opts)) \
|
258
|
-
.join(*schema_ds_join(table_name, opts)) \
|
259
|
-
.filter(*schema_ds_filter(table_name, opts))
|
260
|
-
end
|
261
|
-
|
262
|
-
# The blank dataset used by the schema parser.
|
263
|
-
def schema_ds_dataset
|
264
|
-
schema_utility_dataset
|
265
|
-
end
|
266
|
-
|
267
|
-
# Argument array for the schema dataset's filter method.
|
268
|
-
def schema_ds_filter(table_name, opts)
|
269
|
-
if table_name
|
270
|
-
[{:c__table_name=>table_name.to_s}]
|
271
|
-
else
|
272
|
-
[{:t__table_type=>'BASE TABLE'}]
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
# Argument array for the schema dataset's from method.
|
277
|
-
def schema_ds_from(table_name, opts)
|
278
|
-
[:information_schema__tables___t]
|
279
|
-
end
|
280
|
-
|
281
|
-
# Argument array for the schema dataset's join method.
|
282
|
-
def schema_ds_join(table_name, opts)
|
283
|
-
[:information_schema__columns, {:table_catalog=>:table_catalog,
|
284
|
-
:table_schema => :table_schema, :table_name => :table_name} , :c]
|
285
|
-
end
|
286
|
-
|
287
|
-
# Argument array for the schema dataset's select method.
|
288
|
-
def schema_ds_select(table_name, opts)
|
289
|
-
cols = [:column_name___column, :data_type___db_type, :character_maximum_length___max_chars, \
|
290
|
-
:numeric_precision, :column_default___default, :is_nullable___allow_null]
|
291
|
-
cols << :c__table_name unless table_name
|
292
|
-
cols
|
293
|
-
end
|
294
|
-
|
295
|
-
# Parse the schema for a given table.
|
296
|
-
def schema_parse_table(table_name, opts)
|
297
|
-
schema_parse_rows(schema_ds(table_name, opts))
|
298
|
-
end
|
299
|
-
|
300
|
-
# Parse the schema all tables in the database.
|
301
|
-
def schema_parse_tables(opts)
|
302
|
-
schemas = {}
|
303
|
-
schema_ds(nil, opts).each do |row|
|
304
|
-
(schemas[row.delete(:table_name).to_sym] ||= []) << row
|
305
|
-
end
|
306
|
-
schemas.each do |table, rows|
|
307
|
-
schemas[table] = schema_parse_rows(rows)
|
308
|
-
end
|
309
|
-
schemas
|
310
|
-
end
|
311
|
-
|
312
|
-
# Parse the output of the information schema columns into
|
313
|
-
# the hash used by Sequel.
|
314
|
-
def schema_parse_rows(rows)
|
315
|
-
schema = []
|
316
|
-
rows.each do |row|
|
317
|
-
row[:allow_null] = row[:allow_null] == 'YES' ? true : false
|
318
|
-
row[:default] = nil if row[:default].blank?
|
319
|
-
row[:type] = schema_column_type(row[:db_type])
|
320
|
-
schema << [row.delete(:column).to_sym, row]
|
321
|
-
end
|
322
|
-
schema
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|