sequel 0.1.9.9 → 0.1.9.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +18 -0
- data/Rakefile +1 -1
- data/lib/sequel.rb +2 -2
- data/lib/sequel/ado.rb +10 -4
- data/lib/sequel/connection_pool.rb +22 -0
- data/lib/sequel/core_ext.rb +43 -6
- data/lib/sequel/database.rb +2 -45
- data/lib/sequel/dataset/dataset_convenience.rb +10 -0
- data/lib/sequel/dataset/dataset_sql.rb +17 -3
- data/lib/sequel/mysql.rb +9 -11
- data/lib/sequel/schema/schema_sql.rb +8 -6
- data/lib/sequel/sqlite.rb +11 -4
- data/spec/adapters/mysql_spec.rb +3 -1
- data/spec/adapters/sqlite_spec.rb +48 -2
- data/spec/core_ext_spec.rb +19 -0
- data/spec/database_spec.rb +6 -1
- data/spec/dataset_spec.rb +16 -0
- data/spec/schema_spec.rb +5 -5
- metadata +2 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
=== 0.19.10 (2007-08-22)
|
2
|
+
|
3
|
+
* Changed schema generation code to generate separate statements for CREATE TABLE and each CREATE INDEX (#34).
|
4
|
+
|
5
|
+
* Refactored Dataset::SQL#field_name for better support of different quoting schemes by specific adapters.
|
6
|
+
|
7
|
+
* Added #current_page_record_count for paginated datasets.
|
8
|
+
|
9
|
+
* Removed Database#literal and included Dataset::SQL instead.
|
10
|
+
|
11
|
+
* Sequel::Dataset:SQL#field_name can now take a hash (as well as #select and any method that uses #field_name) for aliasing column names. E.g. Dataset.new(nil).from(:test).select(:_qqa => 'Date').sql #=> 'SELECT _qqa AS 'Date' FROM test'.
|
12
|
+
|
13
|
+
* Moved SingleThreadedPool to lib/sequel/connection_pool.rb.
|
14
|
+
|
15
|
+
* Changed SQLite::Dataset to return affected rows for #delete and #update (#33).
|
16
|
+
|
17
|
+
* ADO adapter: Added use of Enumerable for Recordset#Fields, playing it safe and moving to the first row before getting results, and changing the auto_increment constant to work for MSSQL.
|
18
|
+
|
1
19
|
=== 0.1.9.9 (2007-08-18)
|
2
20
|
|
3
21
|
* New ADO adapter by cdcarter (#31).
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
|
|
6
6
|
include FileUtils
|
7
7
|
|
8
8
|
NAME = "sequel"
|
9
|
-
VERS = "0.1.9.
|
9
|
+
VERS = "0.1.9.10"
|
10
10
|
CLEAN.include ['**/.*.sw?', 'pkg/*', '.config', 'doc/*', 'coverage/*']
|
11
11
|
RDOC_OPTS = ['--quiet', '--title', "Sequel: Concise ORM for Ruby",
|
12
12
|
"--opname", "index.html",
|
data/lib/sequel.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'metaid'
|
2
2
|
|
3
3
|
files = %w[
|
4
|
-
core_ext error
|
5
|
-
dataset migration model
|
4
|
+
core_ext error connection_pool pretty_table expressions
|
5
|
+
dataset migration model schema database
|
6
6
|
]
|
7
7
|
dir = File.join(File.dirname(__FILE__), 'sequel')
|
8
8
|
files.each {|f| require(File.join(dir, f))}
|
data/lib/sequel/ado.rb
CHANGED
@@ -9,6 +9,12 @@ module Sequel
|
|
9
9
|
class Database < Sequel::Database
|
10
10
|
set_adapter_scheme :ado
|
11
11
|
|
12
|
+
AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
|
13
|
+
|
14
|
+
def auto_increment_sql
|
15
|
+
AUTO_INCREMENT
|
16
|
+
end
|
17
|
+
|
12
18
|
def connect
|
13
19
|
dbname = @opts[:database]
|
14
20
|
handle = WIN32OLE.new('ADODB.Connection')
|
@@ -41,11 +47,11 @@ module Sequel
|
|
41
47
|
@db.synchronize do
|
42
48
|
s = @db.execute sql
|
43
49
|
|
44
|
-
|
45
|
-
@columns =
|
46
|
-
0.upto(num_cols-1) {|x| @columns[x] = s.Fields(x).Name.to_sym}
|
50
|
+
fields = s.Fields.extend(Enumerable)
|
51
|
+
@columns = fields.map {|x| x.Name.to_sym}
|
47
52
|
|
48
|
-
s.
|
53
|
+
s.moveFirst
|
54
|
+
s.getRows.transpose.each {|r| yield hash_row(r)}
|
49
55
|
end
|
50
56
|
self
|
51
57
|
end
|
@@ -105,5 +105,27 @@ module Sequel
|
|
105
105
|
@allocated.delete(thread)
|
106
106
|
end
|
107
107
|
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# A SingleThreadedPool acts as a replacement for a ConnectionPool for use
|
111
|
+
# in single-threaded applications. ConnectionPool imposes a substantial
|
112
|
+
# performance penalty, so SingleThreadedPool is used to gain some speed.
|
113
|
+
class SingleThreadedPool
|
114
|
+
attr_writer :connection_proc
|
115
|
+
|
116
|
+
# Initializes the instance with the supplied block as the connection_proc.
|
117
|
+
def initialize(&block)
|
118
|
+
@connection_proc = block
|
119
|
+
end
|
120
|
+
|
121
|
+
# Yields the connection to the supplied block. This method simulates the
|
122
|
+
# ConnectionPool#hold API.
|
123
|
+
def hold
|
124
|
+
@conn ||= @connection_proc.call
|
125
|
+
yield @conn
|
126
|
+
rescue Exception => e
|
127
|
+
# if the error is not a StandardError it is converted into RuntimeError.
|
128
|
+
raise e.is_a?(StandardError) ? e : e.message
|
108
129
|
end
|
130
|
+
end
|
109
131
|
end
|
data/lib/sequel/core_ext.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Enumerable extensions.
|
2
2
|
module Enumerable
|
3
|
+
# Invokes the specified method for each item, along with the supplied
|
4
|
+
# arguments.
|
3
5
|
def send_each(sym, *args)
|
4
6
|
each {|i| i.send(sym, *args)}
|
5
7
|
end
|
@@ -16,6 +18,9 @@ class Array
|
|
16
18
|
end
|
17
19
|
|
18
20
|
module Sequel
|
21
|
+
# ExpressionString is used to represent literal SQL expressions. An
|
22
|
+
# ExpressionString is copied verbatim into an SQL statement. Instances of
|
23
|
+
# ExpressionString can be created by calling String#expr.
|
19
24
|
class ExpressionString < ::String
|
20
25
|
end
|
21
26
|
end
|
@@ -33,50 +38,72 @@ class String
|
|
33
38
|
def split_sql
|
34
39
|
to_sql.split(';').map {|s| s.strip}
|
35
40
|
end
|
36
|
-
|
37
|
-
#
|
41
|
+
|
42
|
+
# Converts a string into an ExpressionString, in order to override string
|
43
|
+
# literalization, e.g.:
|
44
|
+
#
|
45
|
+
# DB[:items].filter(:abc => 'def').sql #=>
|
46
|
+
# "SELECT * FROM items WHERE (abc = 'def')"
|
47
|
+
#
|
48
|
+
# DB[:items].filter(:abc => 'def'.expr).sql #=>
|
49
|
+
# "SELECT * FROM items WHERE (abc = def)"
|
50
|
+
#
|
38
51
|
def expr
|
39
52
|
Sequel::ExpressionString.new(self)
|
40
53
|
end
|
41
54
|
|
42
|
-
#
|
55
|
+
# Converts a string into a Time object.
|
43
56
|
def to_time
|
44
57
|
Time.parse(self)
|
45
58
|
end
|
46
59
|
|
60
|
+
# Converts a string into a field name.
|
47
61
|
def to_field_name
|
48
62
|
self
|
49
63
|
end
|
50
64
|
end
|
51
65
|
|
66
|
+
# Methods to format field names and associated constructs. This module is
|
67
|
+
# included in String and Symbol.
|
52
68
|
module FieldCompositionMethods
|
69
|
+
# Constructs a DESC clause for use in an ORDER BY clause.
|
53
70
|
def DESC
|
54
71
|
"#{to_field_name} DESC"
|
55
72
|
end
|
56
73
|
|
74
|
+
# Constructs an AS clause for field aliasing.
|
57
75
|
def AS(target)
|
58
76
|
"#{to_field_name} AS #{target}"
|
59
77
|
end
|
60
78
|
|
79
|
+
# Constructs a qualified wildcard (*) clause.
|
61
80
|
def ALL
|
62
81
|
"#{to_s}.*"
|
63
82
|
end
|
64
83
|
|
65
|
-
FIELD_TITLE_RE1 = /^(.*)\sAS\s(.+)
|
84
|
+
FIELD_TITLE_RE1 = /^(.*)\sAS\s(.+)$/i.freeze
|
66
85
|
FIELD_TITLE_RE2 = /^([^\.]+)\.([^\.]+)$/.freeze
|
67
86
|
|
87
|
+
# Returns the field name. If the field name is aliased, the alias is
|
88
|
+
# returned.
|
68
89
|
def field_title
|
69
|
-
s = to_field_name
|
70
|
-
case s
|
90
|
+
case s = to_field_name
|
71
91
|
when FIELD_TITLE_RE1, FIELD_TITLE_RE2: $2
|
72
92
|
else
|
73
93
|
s
|
74
94
|
end
|
75
95
|
end
|
76
96
|
|
97
|
+
# Formats a min(x) expression.
|
77
98
|
def MIN; "min(#{to_field_name})"; end
|
99
|
+
|
100
|
+
# Formats a max(x) expression.
|
78
101
|
def MAX; "max(#{to_field_name})"; end
|
102
|
+
|
103
|
+
# Formats a sum(x) expression.
|
79
104
|
def SUM; "sum(#{to_field_name})"; end
|
105
|
+
|
106
|
+
# Formats an avg(x) expression.
|
80
107
|
def AVG; "avg(#{to_field_name})"; end
|
81
108
|
end
|
82
109
|
|
@@ -92,6 +119,16 @@ class Symbol
|
|
92
119
|
FIELD_REF_RE1 = /^([a-z_]+)__([a-z_]+)___([a-z_]+)/.freeze
|
93
120
|
FIELD_REF_RE2 = /^([a-z_]+)___([a-z_]+)$/.freeze
|
94
121
|
FIELD_REF_RE3 = /^([a-z_]+)__([a-z_]+)$/.freeze
|
122
|
+
|
123
|
+
# Converts a symbol into a field name. This method supports underscore
|
124
|
+
# notation in order to express qualified (two underscores) and aliased
|
125
|
+
# (three underscores) fields:
|
126
|
+
#
|
127
|
+
# :abc.to_field_name #=> "abc"
|
128
|
+
# :abc___a.to_field_name #=> "abc AS a"
|
129
|
+
# :items__abc.to_field_name #=> "items.abc"
|
130
|
+
# :items__abc___a.to_field_name #=> "items.abc AS a"
|
131
|
+
#
|
95
132
|
def to_field_name
|
96
133
|
s = to_s
|
97
134
|
case s
|
data/lib/sequel/database.rb
CHANGED
@@ -1,25 +1,6 @@
|
|
1
1
|
require 'uri'
|
2
2
|
|
3
3
|
module Sequel
|
4
|
-
# A SingleThreadedPool acts as a replacement for a ConnectionPool for use
|
5
|
-
# in single-threaded applications. ConnectionPool imposes a substantial
|
6
|
-
# performance penalty, so SingleThreadedPool is used to gain some speed.
|
7
|
-
class SingleThreadedPool
|
8
|
-
attr_writer :connection_proc
|
9
|
-
|
10
|
-
def initialize(&block)
|
11
|
-
@connection_proc = block
|
12
|
-
end
|
13
|
-
|
14
|
-
def hold
|
15
|
-
@conn ||= @connection_proc.call
|
16
|
-
yield @conn
|
17
|
-
rescue Exception => e
|
18
|
-
# if the error is not a StandardError it is converted into RuntimeError.
|
19
|
-
raise e.is_a?(StandardError) ? e : e.message
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
4
|
# A Database object represents a virtual connection to a database.
|
24
5
|
# The Database class is meant to be subclassed by database adapters in order
|
25
6
|
# to provide the functionality needed for executing queries.
|
@@ -110,33 +91,9 @@ module Sequel
|
|
110
91
|
true
|
111
92
|
end
|
112
93
|
|
94
|
+
include Dataset::SQL
|
113
95
|
include Schema::SQL
|
114
96
|
|
115
|
-
NULL = "NULL".freeze
|
116
|
-
TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S'".freeze
|
117
|
-
DATE_FORMAT = "DATE '%Y-%m-%d'".freeze
|
118
|
-
TRUE = "'t'".freeze
|
119
|
-
FALSE = "'f'".freeze
|
120
|
-
|
121
|
-
# default literal implementation for use in schema definitions
|
122
|
-
def literal(v)
|
123
|
-
case v
|
124
|
-
when ExpressionString: v
|
125
|
-
when String: "'#{v.gsub(/'/, "''")}'"
|
126
|
-
when Integer, Float: v.to_s
|
127
|
-
when NilClass: NULL
|
128
|
-
when TrueClass: TRUE
|
129
|
-
when FalseClass: FALSE
|
130
|
-
when Symbol: v.to_field_name
|
131
|
-
when Array: v.empty? ? NULL : v.map {|i| literal(i)}.join(COMMA_SEPARATOR)
|
132
|
-
when Time: v.strftime(TIMESTAMP_FORMAT)
|
133
|
-
when Date: v.strftime(DATE_FORMAT)
|
134
|
-
when Dataset: "(#{v.sql})"
|
135
|
-
else
|
136
|
-
raise SequelError, "can't express #{v.inspect} as a SQL literal"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
97
|
# default serial primary key definition. this should be overriden for each adapter.
|
141
98
|
def serial_primary_key_options
|
142
99
|
{:primary_key => true, :type => :integer, :auto_increment => true}
|
@@ -152,7 +109,7 @@ module Sequel
|
|
152
109
|
# end
|
153
110
|
def create_table(name, &block)
|
154
111
|
g = Schema::Generator.new(self, name, &block)
|
155
|
-
|
112
|
+
create_table_sql_list(*g.create_info).each {|sta| execute(sta)}
|
156
113
|
end
|
157
114
|
|
158
115
|
# Drops a table.
|
@@ -129,6 +129,16 @@ module Sequel
|
|
129
129
|
a..b
|
130
130
|
end
|
131
131
|
|
132
|
+
# Returns the number of records in the current page
|
133
|
+
def current_page_record_count
|
134
|
+
return 0 if @current_page > @page_count
|
135
|
+
|
136
|
+
a = 1 + (@current_page - 1) * @page_size
|
137
|
+
b = a + @page_size - 1
|
138
|
+
b = @pagination_record_count if b > @pagination_record_count
|
139
|
+
b - a + 1
|
140
|
+
end
|
141
|
+
|
132
142
|
# Returns the minimum value for the given field.
|
133
143
|
def min(field)
|
134
144
|
single_value(:select => [field.MIN.AS(:v)])
|
@@ -7,9 +7,23 @@ module Sequel
|
|
7
7
|
# symbols can include double underscores to denote a dot separator, e.g.
|
8
8
|
# :posts__id will be converted into posts.id.
|
9
9
|
def field_name(field)
|
10
|
-
|
10
|
+
case field
|
11
|
+
when Symbol, String:
|
12
|
+
quoted_field_name(field.to_field_name)
|
13
|
+
when Hash:
|
14
|
+
field.map {|f,a| "#{field_name(f)} AS #{field_name(a)}"}.join(COMMA_SEPARATOR)
|
15
|
+
else
|
16
|
+
field
|
17
|
+
end
|
11
18
|
end
|
12
19
|
|
20
|
+
# Adds quoting to field references. This method is just a stub and can
|
21
|
+
# be overriden in adapters in order to provide correct field quoting
|
22
|
+
# behavior.
|
23
|
+
def quoted_field_name(name)
|
24
|
+
name
|
25
|
+
end
|
26
|
+
|
13
27
|
ALIASED_REGEXP = /^(.*)\s(.*)$/.freeze
|
14
28
|
QUALIFIED_REGEXP = /^(.*)\.(.*)$/.freeze
|
15
29
|
|
@@ -203,7 +217,7 @@ module Sequel
|
|
203
217
|
# Returns a copy of the dataset with the order reversed. If no order is
|
204
218
|
# given, the existing order is inverted.
|
205
219
|
def reverse_order(*order)
|
206
|
-
order(invert_order(order.empty? ? @opts[:order] : order))
|
220
|
+
order(*invert_order(order.empty? ? @opts[:order] : order))
|
207
221
|
end
|
208
222
|
|
209
223
|
DESC_ORDER_REGEXP = /(.*)\sDESC/.freeze
|
@@ -420,7 +434,7 @@ module Sequel
|
|
420
434
|
sql = opts[:distinct] ? \
|
421
435
|
"SELECT DISTINCT #{select_fields} FROM #{select_source}" : \
|
422
436
|
"SELECT #{select_fields} FROM #{select_source}"
|
423
|
-
|
437
|
+
|
424
438
|
if join = opts[:join]
|
425
439
|
sql << join
|
426
440
|
end
|
data/lib/sequel/mysql.rb
CHANGED
@@ -137,27 +137,25 @@ module Sequel
|
|
137
137
|
end
|
138
138
|
|
139
139
|
class Dataset < Sequel::Dataset
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
def quote_field(field)
|
145
|
-
field =~ FIELD_NOT_QUOTABLE_RE ? field : "`#{field}`"
|
140
|
+
UNQUOTABLE_FIELD_RE = /^(`(.+)`)|\*$/.freeze
|
141
|
+
def quote_field(f)
|
142
|
+
f =~ UNQUOTABLE_FIELD_RE ? f : "`#{f}`"
|
146
143
|
end
|
147
144
|
|
148
|
-
|
149
|
-
|
150
|
-
|
145
|
+
FIELD_EXPR_RE = /^([^\(]+\()?([^\.]+\.)?([^\s\)]+)(\))?(\sAS\s(.+))?$/i.freeze
|
146
|
+
FIELD_ORDER_RE = /^(.*) (DESC|ASC)$/i.freeze
|
147
|
+
def quoted_field_name(name)
|
148
|
+
case name
|
151
149
|
when FIELD_EXPR_RE:
|
152
150
|
$6 ? \
|
153
151
|
"#{$1}#{$2}#{quote_field($3)}#{$4} AS #{quote_field($6)}" : \
|
154
152
|
"#{$1}#{$2}#{quote_field($3)}#{$4}"
|
155
153
|
when FIELD_ORDER_RE: "#{quote_field($1)} #{$2}"
|
156
154
|
else
|
157
|
-
quote_field(
|
155
|
+
quote_field(name)
|
158
156
|
end
|
159
157
|
end
|
160
|
-
|
158
|
+
|
161
159
|
def literal(v)
|
162
160
|
case v
|
163
161
|
when true: '1'
|
@@ -66,16 +66,18 @@ module Sequel
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
70
|
-
indexes.map {|i| index_definition_sql(table_name, i)}
|
69
|
+
def index_list_sql_list(table_name, indexes)
|
70
|
+
indexes.map {|i| index_definition_sql(table_name, i)}
|
71
71
|
end
|
72
72
|
|
73
|
-
def
|
74
|
-
sql = "CREATE TABLE #{name} (#{column_list_sql(columns)});"
|
75
|
-
|
73
|
+
def create_table_sql_list(name, columns, indexes = nil)
|
74
|
+
sql = ["CREATE TABLE #{name} (#{column_list_sql(columns)});"]
|
75
|
+
if indexes && !indexes.empty?
|
76
|
+
sql.concat(index_list_sql_list(name, indexes))
|
77
|
+
end
|
76
78
|
sql
|
77
79
|
end
|
78
|
-
|
80
|
+
|
79
81
|
def drop_table_sql(name)
|
80
82
|
"DROP TABLE #{name};"
|
81
83
|
end
|
data/lib/sequel/sqlite.rb
CHANGED
@@ -34,7 +34,7 @@ module Sequel
|
|
34
34
|
|
35
35
|
def execute(sql)
|
36
36
|
@logger.info(sql) if @logger
|
37
|
-
@pool.hold {|conn| conn.execute_batch(sql)}
|
37
|
+
@pool.hold {|conn| conn.execute_batch(sql); conn.changes}
|
38
38
|
end
|
39
39
|
|
40
40
|
def execute_insert(sql)
|
@@ -122,12 +122,19 @@ module Sequel
|
|
122
122
|
|
123
123
|
def update(values, opts = nil)
|
124
124
|
@db.execute update_sql(values, opts)
|
125
|
-
self
|
126
125
|
end
|
127
126
|
|
128
127
|
def delete(opts = nil)
|
129
|
-
|
130
|
-
|
128
|
+
# check if no filter is specified
|
129
|
+
unless (opts && opts[:where]) || @opts[:where]
|
130
|
+
@db.transaction do
|
131
|
+
unfiltered_count = count
|
132
|
+
@db.execute delete_sql(opts)
|
133
|
+
unfiltered_count
|
134
|
+
end
|
135
|
+
else
|
136
|
+
@db.execute delete_sql(opts)
|
137
|
+
end
|
131
138
|
end
|
132
139
|
|
133
140
|
EXPLAIN = 'EXPLAIN %s'.freeze
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -7,6 +7,8 @@ end
|
|
7
7
|
MYSQL_DB.create_table :items do
|
8
8
|
text :name
|
9
9
|
integer :value
|
10
|
+
|
11
|
+
index :value
|
10
12
|
end
|
11
13
|
|
12
14
|
context "A MySQL dataset" do
|
@@ -94,7 +96,7 @@ context "A MySQL dataset" do
|
|
94
96
|
'SELECT max(items.`name`) AS `max_name` FROM items'
|
95
97
|
|
96
98
|
@d.insert_sql(:value => 333).should == \
|
97
|
-
'INSERT INTO items (`value`) VALUES (333)'
|
99
|
+
'INSERT INTO items (`value`) VALUES (333);'
|
98
100
|
end
|
99
101
|
|
100
102
|
specify "should support ORDER clause in UPDATE statements" do
|
@@ -115,7 +115,7 @@ context "An SQLite dataset" do
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
-
context "An
|
118
|
+
context "An SQLite dataset" do
|
119
119
|
setup do
|
120
120
|
@d = SQLITE_DB[:items]
|
121
121
|
@d.delete # remove all records
|
@@ -139,4 +139,50 @@ context "An SQLITE dataset" do
|
|
139
139
|
specify "should correctly return min" do
|
140
140
|
@d.min(:value).should == 1.23.to_s
|
141
141
|
end
|
142
|
-
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "SQLite::Dataset#delete" do
|
145
|
+
setup do
|
146
|
+
@d = SQLITE_DB[:items]
|
147
|
+
@d.delete # remove all records
|
148
|
+
@d << {:name => 'abc', :value => 1.23}
|
149
|
+
@d << {:name => 'def', :value => 4.56}
|
150
|
+
@d << {:name => 'ghi', :value => 7.89}
|
151
|
+
end
|
152
|
+
|
153
|
+
specify "should return the number of records affected when filtered" do
|
154
|
+
@d.count.should == 3
|
155
|
+
@d.filter {value < 3}.delete.should == 1
|
156
|
+
@d.count.should == 2
|
157
|
+
|
158
|
+
@d.filter {value < 3}.delete.should == 0
|
159
|
+
@d.count.should == 2
|
160
|
+
end
|
161
|
+
|
162
|
+
specify "should return the number of records affected when unfiltered" do
|
163
|
+
@d.count.should == 3
|
164
|
+
@d.delete.should == 3
|
165
|
+
@d.count.should == 0
|
166
|
+
|
167
|
+
@d.delete.should == 0
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "SQLite::Dataset#update" do
|
172
|
+
setup do
|
173
|
+
@d = SQLITE_DB[:items]
|
174
|
+
@d.delete # remove all records
|
175
|
+
@d << {:name => 'abc', :value => 1.23}
|
176
|
+
@d << {:name => 'def', :value => 4.56}
|
177
|
+
@d << {:name => 'ghi', :value => 7.89}
|
178
|
+
end
|
179
|
+
|
180
|
+
specify "should return the number of records affected" do
|
181
|
+
@d.filter(:name => 'abc').update(:value => 2).should == 1
|
182
|
+
|
183
|
+
@d.update(:value => 10).should == 3
|
184
|
+
|
185
|
+
@d.filter(:name => 'xxx').update(:value => 23).should == 0
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
data/spec/core_ext_spec.rb
CHANGED
@@ -115,6 +115,25 @@ context "Symbol#to_field_name" do
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
context "FieldCompositionMethods#field_title" do
|
119
|
+
specify "should return the field name for non aliased fields" do
|
120
|
+
:xyz.field_title.should == 'xyz'
|
121
|
+
:abc__xyz.field_title.should == 'xyz'
|
122
|
+
|
123
|
+
'abc'.field_title.should == 'abc'
|
124
|
+
'abc.def'.field_title.should == 'def'
|
125
|
+
end
|
126
|
+
|
127
|
+
specify "should return the field alias for aliased fields" do
|
128
|
+
:xyz___x.field_title.should == 'x'
|
129
|
+
:abc__xyz___y.field_title.should == 'y'
|
130
|
+
|
131
|
+
'abc AS x'.field_title.should == 'x'
|
132
|
+
'abc as y'.field_title.should == 'y'
|
133
|
+
'abc.def AS d'.field_title.should == 'd'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
118
137
|
context "Symbol" do
|
119
138
|
specify "should support MIN for specifying min function" do
|
120
139
|
:abc__def.MIN.should == 'min(abc.def)'
|
data/spec/database_spec.rb
CHANGED
data/spec/dataset_spec.rb
CHANGED
@@ -551,6 +551,11 @@ context "Dataset#select" do
|
|
551
551
|
specify "should use the wildcard if no arguments are given" do
|
552
552
|
@d.select.sql.should == 'SELECT * FROM test'
|
553
553
|
end
|
554
|
+
|
555
|
+
specify "should accept a hash for AS values" do
|
556
|
+
@d.select(:name => 'n', :__ggh => 'age').sql.should =~
|
557
|
+
/SELECT ((name AS n, __ggh AS age)|(__ggh AS age, name AS n)) FROM test/
|
558
|
+
end
|
554
559
|
|
555
560
|
specify "should overrun the previous select option" do
|
556
561
|
@d.select(:a, :b, :c).select.sql.should == 'SELECT * FROM test'
|
@@ -1199,6 +1204,10 @@ context "Dataset#set_model" do
|
|
1199
1204
|
all[3].class.should == @m1
|
1200
1205
|
#...
|
1201
1206
|
end
|
1207
|
+
|
1208
|
+
specify "should raise an error if more than two arguments are supplied" do
|
1209
|
+
proc {@dataset.set_model(1, 2, 3)}.should raise_error(SequelError)
|
1210
|
+
end
|
1202
1211
|
end
|
1203
1212
|
|
1204
1213
|
context "Dataset#model_classes" do
|
@@ -1420,6 +1429,13 @@ context "A paginated dataset" do
|
|
1420
1429
|
@d.paginate(4, 50).current_page_record_range.should == (151..153)
|
1421
1430
|
@d.paginate(5, 50).current_page_record_range.should == (0..0)
|
1422
1431
|
end
|
1432
|
+
|
1433
|
+
specify "should return the record count for the current page" do
|
1434
|
+
@paginated.current_page_record_count.should == 20
|
1435
|
+
@d.paginate(3, 50).current_page_record_count.should == 50
|
1436
|
+
@d.paginate(4, 50).current_page_record_count.should == 3
|
1437
|
+
@d.paginate(5, 50).current_page_record_count.should == 0
|
1438
|
+
end
|
1423
1439
|
end
|
1424
1440
|
|
1425
1441
|
context "Dataset#columns" do
|
data/spec/schema_spec.rb
CHANGED
@@ -136,7 +136,7 @@ context "DB#create_table" do
|
|
136
136
|
integer :id
|
137
137
|
index :id
|
138
138
|
end
|
139
|
-
@db.sqls.should == ["CREATE TABLE cats (id integer);CREATE INDEX cats_id_index ON cats (id);"]
|
139
|
+
@db.sqls.should == ["CREATE TABLE cats (id integer);", "CREATE INDEX cats_id_index ON cats (id);"]
|
140
140
|
end
|
141
141
|
|
142
142
|
specify "should accept multiple index definitions" do
|
@@ -145,7 +145,7 @@ context "DB#create_table" do
|
|
145
145
|
index :id
|
146
146
|
index :name
|
147
147
|
end
|
148
|
-
@db.sqls.should == ["CREATE TABLE cats (id integer);CREATE INDEX cats_id_index ON cats (id);CREATE INDEX cats_name_index ON cats (name);"]
|
148
|
+
@db.sqls.should == ["CREATE TABLE cats (id integer);", "CREATE INDEX cats_id_index ON cats (id);", "CREATE INDEX cats_name_index ON cats (name);"]
|
149
149
|
end
|
150
150
|
|
151
151
|
specify "should accept custom index names" do
|
@@ -153,7 +153,7 @@ context "DB#create_table" do
|
|
153
153
|
integer :id
|
154
154
|
index :id, :name => 'abc'
|
155
155
|
end
|
156
|
-
@db.sqls.should == ["CREATE TABLE cats (id integer);CREATE INDEX abc ON cats (id);"]
|
156
|
+
@db.sqls.should == ["CREATE TABLE cats (id integer);", "CREATE INDEX abc ON cats (id);"]
|
157
157
|
end
|
158
158
|
|
159
159
|
specify "should accept unique index definitions" do
|
@@ -161,7 +161,7 @@ context "DB#create_table" do
|
|
161
161
|
integer :id
|
162
162
|
index :id, :unique => true
|
163
163
|
end
|
164
|
-
@db.sqls.should == ["CREATE TABLE cats (id integer);CREATE UNIQUE INDEX cats_id_index ON cats (id);"]
|
164
|
+
@db.sqls.should == ["CREATE TABLE cats (id integer);", "CREATE UNIQUE INDEX cats_id_index ON cats (id);"]
|
165
165
|
end
|
166
166
|
|
167
167
|
specify "should accept compound index definitions" do
|
@@ -169,7 +169,7 @@ context "DB#create_table" do
|
|
169
169
|
integer :id
|
170
170
|
index [:id, :name], :unique => true
|
171
171
|
end
|
172
|
-
@db.sqls.should == ["CREATE TABLE cats (id integer);CREATE UNIQUE INDEX cats_id_name_index ON cats (id, name);"]
|
172
|
+
@db.sqls.should == ["CREATE TABLE cats (id integer);", "CREATE UNIQUE INDEX cats_id_name_index ON cats (id, name);"]
|
173
173
|
end
|
174
174
|
end
|
175
175
|
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: sequel
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.9.
|
7
|
-
date: 2007-08-
|
6
|
+
version: 0.1.9.10
|
7
|
+
date: 2007-08-23 00:00:00 +03:00
|
8
8
|
summary: Lightweight ORM library for Ruby
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -33,7 +33,6 @@ files:
|
|
33
33
|
- README
|
34
34
|
- Rakefile
|
35
35
|
- bin/sequel
|
36
|
-
- doc/rdoc
|
37
36
|
- spec/adapters
|
38
37
|
- spec/connection_pool_spec.rb
|
39
38
|
- spec/core_ext_spec.rb
|