sequel_core 1.4.0 → 1.5.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.
- data/CHANGELOG +74 -0
- data/COPYING +1 -0
- data/README +17 -6
- data/Rakefile +16 -21
- data/lib/sequel_core.rb +18 -28
- data/lib/sequel_core/adapters/ado.rb +3 -15
- data/lib/sequel_core/adapters/dbi.rb +1 -14
- data/lib/sequel_core/adapters/informix.rb +3 -3
- data/lib/sequel_core/adapters/jdbc.rb +2 -2
- data/lib/sequel_core/adapters/mysql.rb +39 -59
- data/lib/sequel_core/adapters/odbc.rb +18 -38
- data/lib/sequel_core/adapters/openbase.rb +1 -17
- data/lib/sequel_core/adapters/oracle.rb +1 -19
- data/lib/sequel_core/adapters/postgres.rb +20 -60
- data/lib/sequel_core/adapters/sqlite.rb +4 -8
- data/lib/sequel_core/connection_pool.rb +150 -0
- data/lib/sequel_core/core_ext.rb +41 -0
- data/lib/sequel_core/core_sql.rb +35 -38
- data/lib/sequel_core/database.rb +20 -17
- data/lib/sequel_core/dataset.rb +49 -80
- data/lib/sequel_core/dataset/callback.rb +11 -13
- data/lib/sequel_core/dataset/convenience.rb +18 -136
- data/lib/sequel_core/dataset/pagination.rb +81 -0
- data/lib/sequel_core/dataset/sequelizer.rb +5 -4
- data/lib/sequel_core/dataset/sql.rb +43 -33
- data/lib/sequel_core/deprecated.rb +200 -0
- data/lib/sequel_core/exceptions.rb +0 -14
- data/lib/sequel_core/object_graph.rb +199 -0
- data/lib/sequel_core/pretty_table.rb +27 -24
- data/lib/sequel_core/schema/generator.rb +16 -4
- data/lib/sequel_core/schema/sql.rb +5 -3
- data/lib/sequel_core/worker.rb +1 -1
- data/spec/adapters/informix_spec.rb +1 -47
- data/spec/adapters/mysql_spec.rb +85 -54
- data/spec/adapters/oracle_spec.rb +1 -57
- data/spec/adapters/postgres_spec.rb +66 -49
- data/spec/adapters/sqlite_spec.rb +4 -29
- data/spec/connection_pool_spec.rb +358 -0
- data/spec/core_sql_spec.rb +24 -19
- data/spec/database_spec.rb +13 -9
- data/spec/dataset_spec.rb +59 -78
- data/spec/object_graph_spec.rb +202 -0
- data/spec/pretty_table_spec.rb +1 -9
- data/spec/schema_generator_spec.rb +7 -1
- data/spec/schema_spec.rb +27 -0
- data/spec/sequelizer_spec.rb +2 -2
- data/spec/spec_helper.rb +4 -2
- metadata +16 -57
- data/lib/sequel_core/array_keys.rb +0 -322
- data/lib/sequel_core/model.rb +0 -8
- data/spec/array_keys_spec.rb +0 -682
@@ -1,19 +1,17 @@
|
|
1
1
|
module Sequel
|
2
2
|
class Dataset
|
3
|
+
# Module with empty methods that can be
|
4
|
+
# override to provide callback behavior
|
3
5
|
module Callback
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
return unless cbs = @opts[:callbacks]
|
14
|
-
return unless cb = cbs[name]
|
15
|
-
cb.each{|sym| send(sym, *args)}
|
16
|
-
end
|
6
|
+
private
|
7
|
+
# This is run inside .all, after all
|
8
|
+
# of the records have been loaded
|
9
|
+
# via .each, but before any block passed
|
10
|
+
# to all is called. It is called with
|
11
|
+
# a single argument, an array of all
|
12
|
+
# returned records.
|
13
|
+
def post_load(all_records)
|
14
|
+
end
|
17
15
|
end
|
18
16
|
end
|
19
17
|
end
|
@@ -3,15 +3,9 @@ require 'enumerator'
|
|
3
3
|
module Sequel
|
4
4
|
class Dataset
|
5
5
|
module Convenience
|
6
|
-
# Iterates through each record, converting it into a hash.
|
7
|
-
def each_hash(&block)
|
8
|
-
each {|a| block[a.to_hash]}
|
9
|
-
end
|
10
|
-
|
11
6
|
# Returns true if no records exists in the dataset
|
12
7
|
def empty?
|
13
8
|
db.dataset.where(exists).get(1) == nil
|
14
|
-
# count == 0
|
15
9
|
end
|
16
10
|
|
17
11
|
# Returns the first record in the dataset.
|
@@ -23,10 +17,10 @@ module Sequel
|
|
23
17
|
NAKED_HASH = {:naked => true}.freeze
|
24
18
|
|
25
19
|
# Returns the first value of the first reecord in the dataset.
|
26
|
-
# Returns
|
20
|
+
# Returns nil if dataset is empty.
|
27
21
|
def single_value(opts = nil)
|
28
22
|
opts = opts ? NAKED_HASH.merge(opts) : NAKED_HASH
|
29
|
-
#
|
23
|
+
# don't cache the columns
|
30
24
|
each(opts) {|r| @columns = nil; return r.values.first}
|
31
25
|
nil
|
32
26
|
end
|
@@ -104,97 +98,27 @@ module Sequel
|
|
104
98
|
end
|
105
99
|
end
|
106
100
|
|
107
|
-
# Returns a paginated dataset. The resulting dataset also provides the
|
108
|
-
# total number of pages (Dataset#page_count) and the current page number
|
109
|
-
# (Dataset#current_page), as well as Dataset#prev_page and Dataset#next_page
|
110
|
-
# for implementing pagination controls.
|
111
|
-
def paginate(page_no, page_size)
|
112
|
-
record_count = count
|
113
|
-
total_pages = (record_count / page_size.to_f).ceil
|
114
|
-
paginated = limit(page_size, (page_no - 1) * page_size)
|
115
|
-
paginated.set_pagination_info(page_no, page_size, record_count)
|
116
|
-
paginated
|
117
|
-
end
|
118
|
-
|
119
|
-
# Sets the pagination info
|
120
|
-
def set_pagination_info(page_no, page_size, record_count)
|
121
|
-
@current_page = page_no
|
122
|
-
@page_size = page_size
|
123
|
-
@pagination_record_count = record_count
|
124
|
-
@page_count = (record_count / page_size.to_f).ceil
|
125
|
-
end
|
126
|
-
|
127
|
-
def each_page(page_size)
|
128
|
-
record_count = count
|
129
|
-
total_pages = (record_count / page_size.to_f).ceil
|
130
|
-
|
131
|
-
(1..total_pages).each do |page_no|
|
132
|
-
paginated = limit(page_size, (page_no - 1) * page_size)
|
133
|
-
paginated.set_pagination_info(page_no, page_size, record_count)
|
134
|
-
yield paginated
|
135
|
-
end
|
136
|
-
|
137
|
-
self
|
138
|
-
end
|
139
|
-
|
140
|
-
attr_accessor :page_size, :page_count, :current_page, :pagination_record_count
|
141
|
-
|
142
|
-
# Returns the previous page number or nil if the current page is the first
|
143
|
-
def prev_page
|
144
|
-
current_page > 1 ? (current_page - 1) : nil
|
145
|
-
end
|
146
|
-
|
147
|
-
# Returns the next page number or nil if the current page is the last page
|
148
|
-
def next_page
|
149
|
-
current_page < page_count ? (current_page + 1) : nil
|
150
|
-
end
|
151
|
-
|
152
|
-
# Returns the page range
|
153
|
-
def page_range
|
154
|
-
1..page_count
|
155
|
-
end
|
156
|
-
|
157
|
-
# Returns the record range for the current page
|
158
|
-
def current_page_record_range
|
159
|
-
return (0..0) if @current_page > @page_count
|
160
|
-
|
161
|
-
a = 1 + (@current_page - 1) * @page_size
|
162
|
-
b = a + @page_size - 1
|
163
|
-
b = @pagination_record_count if b > @pagination_record_count
|
164
|
-
a..b
|
165
|
-
end
|
166
|
-
|
167
|
-
# Returns the number of records in the current page
|
168
|
-
def current_page_record_count
|
169
|
-
return 0 if @current_page > @page_count
|
170
|
-
|
171
|
-
a = 1 + (@current_page - 1) * @page_size
|
172
|
-
b = a + @page_size - 1
|
173
|
-
b = @pagination_record_count if b > @pagination_record_count
|
174
|
-
b - a + 1
|
175
|
-
end
|
176
|
-
|
177
101
|
# Returns the minimum value for the given column.
|
178
102
|
def min(column)
|
179
|
-
single_value(:select => [column.
|
103
|
+
single_value(:select => [:min[column].as(:v)])
|
180
104
|
end
|
181
105
|
|
182
106
|
# Returns the maximum value for the given column.
|
183
107
|
def max(column)
|
184
|
-
single_value(:select => [column.
|
108
|
+
single_value(:select => [:max[column].as(:v)])
|
185
109
|
end
|
186
110
|
|
187
111
|
# Returns the sum for the given column.
|
188
112
|
def sum(column)
|
189
|
-
single_value(:select => [column.
|
113
|
+
single_value(:select => [:sum[column].as(:v)])
|
190
114
|
end
|
191
115
|
|
192
116
|
# Returns the average value for the given column.
|
193
117
|
def avg(column)
|
194
|
-
single_value(:select => [column.
|
118
|
+
single_value(:select => [:avg[column].as(:v)])
|
195
119
|
end
|
196
120
|
|
197
|
-
COUNT_OF_ALL_AS_COUNT = :count['*'.lit].
|
121
|
+
COUNT_OF_ALL_AS_COUNT = :count['*'.lit].as(:count)
|
198
122
|
|
199
123
|
# Returns a dataset grouped by the given column with count by group.
|
200
124
|
def group_and_count(*columns)
|
@@ -204,15 +128,17 @@ module Sequel
|
|
204
128
|
# Returns a Range object made from the minimum and maximum values for the
|
205
129
|
# given column.
|
206
130
|
def range(column)
|
207
|
-
r = select(column.
|
208
|
-
|
131
|
+
if r = select(:min[column].as(:v1), :max[column].as(:v2)).first
|
132
|
+
(r[:v1]..r[:v2])
|
133
|
+
end
|
209
134
|
end
|
210
135
|
|
211
136
|
# Returns the interval between minimum and maximum values for the given
|
212
137
|
# column.
|
213
138
|
def interval(column)
|
214
|
-
r = select("(max(#{literal(column)}) - min(#{literal(column)})) AS v".lit).first
|
215
|
-
|
139
|
+
if r = select("(max(#{literal(column)}) - min(#{literal(column)})) AS v".lit).first
|
140
|
+
r[:v]
|
141
|
+
end
|
216
142
|
end
|
217
143
|
|
218
144
|
# Pretty prints the records in the dataset as plain-text table.
|
@@ -227,12 +153,11 @@ module Sequel
|
|
227
153
|
# first line. You can turn that off by passing false as the
|
228
154
|
# include_column_titles argument.
|
229
155
|
def to_csv(include_column_titles = true)
|
230
|
-
|
156
|
+
n = naked
|
157
|
+
cols = n.columns
|
231
158
|
csv = ''
|
232
|
-
if include_column_titles
|
233
|
-
|
234
|
-
end
|
235
|
-
records.each {|r| csv << "#{r.join(COMMA_SEPARATOR)}\r\n"}
|
159
|
+
csv << "#{cols.join(COMMA_SEPARATOR)}\r\n" if include_column_titles
|
160
|
+
n.each{|r| csv << "#{cols.collect{|c| r[c]}.join(COMMA_SEPARATOR)}\r\n"}
|
236
161
|
csv
|
237
162
|
end
|
238
163
|
|
@@ -317,49 +242,6 @@ module Sequel
|
|
317
242
|
clone(copy.opts)
|
318
243
|
end
|
319
244
|
|
320
|
-
MUTATION_RE = /^(.+)!$/.freeze
|
321
|
-
|
322
|
-
# Provides support for mutation methods (filter!, order!, etc.) and magic
|
323
|
-
# methods.
|
324
|
-
def method_missing(m, *args, &block)
|
325
|
-
if m.to_s =~ MUTATION_RE
|
326
|
-
m = $1.to_sym
|
327
|
-
super unless respond_to?(m)
|
328
|
-
copy = send(m, *args, &block)
|
329
|
-
super if copy.class != self.class
|
330
|
-
@opts.merge!(copy.opts)
|
331
|
-
self
|
332
|
-
elsif magic_method_missing(m)
|
333
|
-
send(m, *args)
|
334
|
-
else
|
335
|
-
super
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
MAGIC_METHODS = {
|
340
|
-
/^order_by_(.+)$/ => proc {|c| proc {order(c)}},
|
341
|
-
/^first_by_(.+)$/ => proc {|c| proc {order(c).first}},
|
342
|
-
/^last_by_(.+)$/ => proc {|c| proc {order(c).last}},
|
343
|
-
/^filter_by_(.+)$/ => proc {|c| proc {|v| filter(c => v)}},
|
344
|
-
/^all_by_(.+)$/ => proc {|c| proc {|v| filter(c => v).all}},
|
345
|
-
/^find_by_(.+)$/ => proc {|c| proc {|v| filter(c => v).first}},
|
346
|
-
/^group_by_(.+)$/ => proc {|c| proc {group(c)}},
|
347
|
-
/^count_by_(.+)$/ => proc {|c| proc {group_and_count(c)}}
|
348
|
-
}
|
349
|
-
|
350
|
-
# Checks if the given method name represents a magic method and
|
351
|
-
# defines it. Otherwise, nil is returned.
|
352
|
-
def magic_method_missing(m)
|
353
|
-
method_name = m.to_s
|
354
|
-
MAGIC_METHODS.each_pair do |r, p|
|
355
|
-
if method_name =~ r
|
356
|
-
impl = p[$1.to_sym]
|
357
|
-
return Dataset.class_def(m, &impl)
|
358
|
-
end
|
359
|
-
end
|
360
|
-
nil
|
361
|
-
end
|
362
|
-
|
363
245
|
def create_view(name)
|
364
246
|
@db.create_view(name, self)
|
365
247
|
end
|
@@ -386,4 +268,4 @@ module Sequel
|
|
386
268
|
end
|
387
269
|
end
|
388
270
|
end
|
389
|
-
end
|
271
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'enumerator'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
class Dataset
|
5
|
+
# Returns a paginated dataset. The resulting dataset also provides the
|
6
|
+
# total number of pages (Dataset#page_count) and the current page number
|
7
|
+
# (Dataset#current_page), as well as Dataset#prev_page and Dataset#next_page
|
8
|
+
# for implementing pagination controls.
|
9
|
+
def paginate(page_no, page_size)
|
10
|
+
raise(Error, "You cannot paginate a dataset that already has a limit") if @opts[:limit]
|
11
|
+
record_count = count
|
12
|
+
total_pages = (record_count / page_size.to_f).ceil
|
13
|
+
paginated = limit(page_size, (page_no - 1) * page_size)
|
14
|
+
paginated.extend(Pagination)
|
15
|
+
paginated.set_pagination_info(page_no, page_size, record_count)
|
16
|
+
paginated
|
17
|
+
end
|
18
|
+
|
19
|
+
def each_page(page_size)
|
20
|
+
raise(Error, "You cannot paginate a dataset that already has a limit") if @opts[:limit]
|
21
|
+
record_count = count
|
22
|
+
total_pages = (record_count / page_size.to_f).ceil
|
23
|
+
|
24
|
+
(1..total_pages).each do |page_no|
|
25
|
+
paginated = limit(page_size, (page_no - 1) * page_size)
|
26
|
+
paginated.extend(Pagination)
|
27
|
+
paginated.set_pagination_info(page_no, page_size, record_count)
|
28
|
+
yield paginated
|
29
|
+
end
|
30
|
+
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
module Pagination
|
35
|
+
attr_accessor :page_size, :page_count, :current_page, :pagination_record_count
|
36
|
+
|
37
|
+
# Sets the pagination info
|
38
|
+
def set_pagination_info(page_no, page_size, record_count)
|
39
|
+
@current_page = page_no
|
40
|
+
@page_size = page_size
|
41
|
+
@pagination_record_count = record_count
|
42
|
+
@page_count = (record_count / page_size.to_f).ceil
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the previous page number or nil if the current page is the first
|
46
|
+
def prev_page
|
47
|
+
current_page > 1 ? (current_page - 1) : nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the next page number or nil if the current page is the last page
|
51
|
+
def next_page
|
52
|
+
current_page < page_count ? (current_page + 1) : nil
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the page range
|
56
|
+
def page_range
|
57
|
+
1..page_count
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the record range for the current page
|
61
|
+
def current_page_record_range
|
62
|
+
return (0..0) if @current_page > @page_count
|
63
|
+
|
64
|
+
a = 1 + (@current_page - 1) * @page_size
|
65
|
+
b = a + @page_size - 1
|
66
|
+
b = @pagination_record_count if b > @pagination_record_count
|
67
|
+
a..b
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the number of records in the current page
|
71
|
+
def current_page_record_count
|
72
|
+
return 0 if @current_page > @page_count
|
73
|
+
|
74
|
+
a = 1 + (@current_page - 1) * @page_size
|
75
|
+
b = a + @page_size - 1
|
76
|
+
b = @pagination_record_count if b > @pagination_record_count
|
77
|
+
b - a + 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -4,7 +4,7 @@ class Sequel::Dataset
|
|
4
4
|
# blocks, e.g.:
|
5
5
|
#
|
6
6
|
# DB[:items].filter {:price < 100}
|
7
|
-
# DB[:items].filter {:category == 'ruby' && :date <
|
7
|
+
# DB[:items].filter {:category == 'ruby' && :date < Date.today - 7}
|
8
8
|
#
|
9
9
|
# Block filters can refer to literals, variables, constants, arguments,
|
10
10
|
# instance variables or anything else in order to create parameterized
|
@@ -20,6 +20,7 @@ class Sequel::Dataset
|
|
20
20
|
# sudo gem install parsetree
|
21
21
|
# sudo gem install ruby2ruby
|
22
22
|
module Sequelizer
|
23
|
+
private
|
23
24
|
# Formats an comparison expression involving a left value and a right
|
24
25
|
# value. Comparison expressions differ according to the class of the right
|
25
26
|
# value. The stock implementation supports Range (inclusive and exclusive),
|
@@ -311,7 +312,7 @@ class Sequel::Dataset
|
|
311
312
|
|
312
313
|
JOIN_AND = " AND ".freeze
|
313
314
|
JOIN_COMMA = ", ".freeze
|
314
|
-
|
315
|
+
|
315
316
|
def pt_expr(e, b, opts = {}) #:nodoc:
|
316
317
|
case e[0]
|
317
318
|
when :not # negation: !x, (x != y), (x !~ y)
|
@@ -346,7 +347,7 @@ end
|
|
346
347
|
|
347
348
|
class Proc
|
348
349
|
def to_sql(dataset, opts = {})
|
349
|
-
dataset.pt_expr
|
350
|
+
dataset.send(:pt_expr, to_sexp[2], self.binding, opts)
|
350
351
|
end
|
351
352
|
end
|
352
353
|
|
@@ -379,4 +380,4 @@ class Proc
|
|
379
380
|
c = Class.new {define_method(:m, &block)}
|
380
381
|
ParseTree.translate(c, :m)[2]
|
381
382
|
end
|
382
|
-
end
|
383
|
+
end
|
@@ -8,8 +8,8 @@ module Sequel
|
|
8
8
|
# behavior.
|
9
9
|
def quote_column_ref(name); name.to_s; end
|
10
10
|
|
11
|
-
ALIASED_REGEXP =
|
12
|
-
QUALIFIED_REGEXP =
|
11
|
+
ALIASED_REGEXP = /\A(.*)\s(.*)\z/.freeze
|
12
|
+
QUALIFIED_REGEXP = /\A(.*)\.(.*)\z/.freeze
|
13
13
|
|
14
14
|
# Returns a qualified column name (including a table name) if the column
|
15
15
|
# name isn't already qualified.
|
@@ -100,7 +100,7 @@ module Sequel
|
|
100
100
|
# Time (as an SQL TIMESTAMP), Date (as an SQL DATE), Dataset (as a
|
101
101
|
# subquery) and nil (AS NULL).
|
102
102
|
#
|
103
|
-
# dataset.literal("abc'def") #=> "'abc''def'"
|
103
|
+
# dataset.literal("abc'def\\") #=> "'abc''def\\\\'"
|
104
104
|
# dataset.literal(:items__id) #=> "items.id"
|
105
105
|
# dataset.literal([1, 2, 3]) => "(1, 2, 3)"
|
106
106
|
# dataset.literal(DB[:items]) => "(SELECT * FROM items)"
|
@@ -111,7 +111,7 @@ module Sequel
|
|
111
111
|
when LiteralString
|
112
112
|
v
|
113
113
|
when String
|
114
|
-
"'#{v.gsub(/'/, "''")}'"
|
114
|
+
"'#{v.gsub(/\\/, "\\\\\\\\").gsub(/'/, "''")}'"
|
115
115
|
when Integer, Float
|
116
116
|
v.to_s
|
117
117
|
when BigDecimal
|
@@ -161,6 +161,7 @@ module Sequel
|
|
161
161
|
end
|
162
162
|
parenthesize ? "(#{fmt})" : fmt
|
163
163
|
end
|
164
|
+
private :qualified_column_name, :column_list, :table_ref, :source_list, :expression_list
|
164
165
|
|
165
166
|
# Returns a copy of the dataset with the source changed.
|
166
167
|
def from(*source)
|
@@ -407,24 +408,18 @@ module Sequel
|
|
407
408
|
}
|
408
409
|
|
409
410
|
# Returns a join clause based on the specified join type and condition.
|
410
|
-
def join_expr(type, table, expr)
|
411
|
-
join_type = JOIN_TYPES[type || :inner]
|
412
|
-
unless join_type
|
413
|
-
raise Error::InvalidJoinType, "Invalid join type: #{type}"
|
414
|
-
end
|
411
|
+
def join_expr(type, table, expr, options)
|
412
|
+
raise(Error::InvalidJoinType, "Invalid join type: #{type}") unless join_type = JOIN_TYPES[type || :inner]
|
415
413
|
|
416
|
-
|
414
|
+
table_alias = options[:table_alias]
|
417
415
|
|
418
416
|
join_conditions = {}
|
419
417
|
expr.each do |k, v|
|
420
|
-
k = qualified_column_name(k, table) if k.is_a?(Symbol)
|
418
|
+
k = qualified_column_name(k, table_alias || table) if k.is_a?(Symbol)
|
421
419
|
v = qualified_column_name(v, @opts[:last_joined_table] || first_source) if v.is_a?(Symbol)
|
422
420
|
join_conditions[k] = v
|
423
421
|
end
|
424
|
-
if
|
425
|
-
table = "(#{table.sql}) t1"
|
426
|
-
end
|
427
|
-
" #{join_type} #{table} ON #{expression_list(join_conditions)}"
|
422
|
+
" #{join_type} #{table} #{"#{table_alias} " if table_alias}ON #{expression_list(join_conditions)}"
|
428
423
|
end
|
429
424
|
|
430
425
|
# Returns a joined dataset with the specified join type and condition.
|
@@ -432,9 +427,20 @@ module Sequel
|
|
432
427
|
unless expr.is_a?(Hash)
|
433
428
|
expr = {expr => :id}
|
434
429
|
end
|
435
|
-
|
436
|
-
|
437
|
-
|
430
|
+
options = {}
|
431
|
+
|
432
|
+
if Dataset === table
|
433
|
+
table = "(#{table.sql})"
|
434
|
+
table_alias_num = @opts[:num_dataset_joins] || 1
|
435
|
+
options[:table_alias] = "t#{table_alias_num}"
|
436
|
+
elsif table.respond_to?(:table_name)
|
437
|
+
table = table.table_name
|
438
|
+
end
|
439
|
+
|
440
|
+
clause = join_expr(type, table, expr, options)
|
441
|
+
opts = {:join => @opts[:join] ? @opts[:join] + clause : clause, :last_joined_table => options[:table_alias] || table}
|
442
|
+
opts[:num_dataset_joins] = table_alias_num + 1 if table_alias_num
|
443
|
+
clone(opts)
|
438
444
|
end
|
439
445
|
|
440
446
|
# Returns a LEFT OUTER joined dataset.
|
@@ -525,6 +531,11 @@ module Sequel
|
|
525
531
|
end
|
526
532
|
alias_method :sql, :select_sql
|
527
533
|
|
534
|
+
# Returns the SQL for formatting an insert statement with default values
|
535
|
+
def insert_default_values_sql
|
536
|
+
"INSERT INTO #{source_list(@opts[:from])} DEFAULT VALUES"
|
537
|
+
end
|
538
|
+
|
528
539
|
# Formats an INSERT statement using the given values. If a hash is given,
|
529
540
|
# the resulting statement includes column names. If no values are given,
|
530
541
|
# the resulting statement includes a DEFAULT VALUES clause.
|
@@ -535,7 +546,7 @@ module Sequel
|
|
535
546
|
# 'INSERT INTO items (a, b) VALUES (1, 2)'
|
536
547
|
def insert_sql(*values)
|
537
548
|
if values.empty?
|
538
|
-
|
549
|
+
insert_default_values_sql
|
539
550
|
else
|
540
551
|
values = values[0] if values.size == 1
|
541
552
|
|
@@ -543,32 +554,31 @@ module Sequel
|
|
543
554
|
if @transform && (values.is_a?(Hash) || (values.is_a?(Array) && values.keys))
|
544
555
|
values = transform_save(values)
|
545
556
|
end
|
557
|
+
from = source_list(@opts[:from])
|
546
558
|
|
547
559
|
case values
|
548
|
-
when Sequel::Model
|
549
|
-
insert_sql(values.values)
|
550
560
|
when Array
|
551
561
|
if values.empty?
|
552
|
-
|
553
|
-
elsif values.keys
|
554
|
-
fl = values.keys.map {|f| literal(f.is_a?(String) ? f.to_sym : f)}
|
555
|
-
vl = values.values.map {|v| literal(v)}
|
556
|
-
"INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
562
|
+
insert_default_values_sql
|
557
563
|
else
|
558
|
-
"INSERT INTO #{
|
564
|
+
"INSERT INTO #{from} VALUES (#{literal(values)})"
|
559
565
|
end
|
560
566
|
when Hash
|
561
567
|
if values.empty?
|
562
|
-
|
568
|
+
insert_default_values_sql
|
563
569
|
else
|
564
570
|
fl, vl = [], []
|
565
571
|
values.each {|k, v| fl << literal(k.is_a?(String) ? k.to_sym : k); vl << literal(v)}
|
566
|
-
"INSERT INTO #{
|
572
|
+
"INSERT INTO #{from} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
|
567
573
|
end
|
568
574
|
when Dataset
|
569
|
-
"INSERT INTO #{
|
575
|
+
"INSERT INTO #{from} #{literal(values)}"
|
570
576
|
else
|
571
|
-
|
577
|
+
if values.respond_to?(:values)
|
578
|
+
insert_sql(values.values)
|
579
|
+
else
|
580
|
+
"INSERT INTO #{from} VALUES (#{literal(values)})"
|
581
|
+
end
|
572
582
|
end
|
573
583
|
end
|
574
584
|
end
|
@@ -599,7 +609,7 @@ module Sequel
|
|
599
609
|
raise Error::InvalidOperation, "A joined dataset cannot be updated"
|
600
610
|
end
|
601
611
|
|
602
|
-
sql = "UPDATE #{@opts[:from]} SET "
|
612
|
+
sql = "UPDATE #{source_list(@opts[:from])} SET "
|
603
613
|
if block
|
604
614
|
sql << block.to_sql(self, :comma_separated => true)
|
605
615
|
else
|
@@ -639,7 +649,7 @@ module Sequel
|
|
639
649
|
raise Error::InvalidOperation, "Joined datasets cannot be deleted from"
|
640
650
|
end
|
641
651
|
|
642
|
-
sql = "DELETE FROM #{opts[:from]}"
|
652
|
+
sql = "DELETE FROM #{source_list(opts[:from])}"
|
643
653
|
|
644
654
|
if where = opts[:where]
|
645
655
|
sql << " WHERE #{where}"
|