sequel_core 1.5.1 → 2.0.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.
Files changed (68) hide show
  1. data/CHANGELOG +116 -0
  2. data/COPYING +19 -19
  3. data/README +83 -32
  4. data/Rakefile +9 -20
  5. data/bin/sequel +43 -112
  6. data/doc/cheat_sheet.rdoc +225 -0
  7. data/doc/dataset_filtering.rdoc +257 -0
  8. data/lib/sequel_core/adapters/adapter_skeleton.rb +4 -2
  9. data/lib/sequel_core/adapters/ado.rb +3 -1
  10. data/lib/sequel_core/adapters/db2.rb +4 -2
  11. data/lib/sequel_core/adapters/dbi.rb +127 -113
  12. data/lib/sequel_core/adapters/informix.rb +4 -2
  13. data/lib/sequel_core/adapters/jdbc.rb +5 -3
  14. data/lib/sequel_core/adapters/mysql.rb +112 -46
  15. data/lib/sequel_core/adapters/odbc.rb +5 -7
  16. data/lib/sequel_core/adapters/odbc_mssql.rb +12 -3
  17. data/lib/sequel_core/adapters/openbase.rb +3 -1
  18. data/lib/sequel_core/adapters/oracle.rb +11 -9
  19. data/lib/sequel_core/adapters/postgres.rb +261 -262
  20. data/lib/sequel_core/adapters/sqlite.rb +72 -22
  21. data/lib/sequel_core/connection_pool.rb +140 -73
  22. data/lib/sequel_core/core_ext.rb +201 -66
  23. data/lib/sequel_core/core_sql.rb +123 -153
  24. data/lib/sequel_core/database/schema.rb +156 -0
  25. data/lib/sequel_core/database.rb +321 -338
  26. data/lib/sequel_core/dataset/callback.rb +11 -12
  27. data/lib/sequel_core/dataset/convenience.rb +213 -240
  28. data/lib/sequel_core/dataset/pagination.rb +58 -43
  29. data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +331 -0
  30. data/lib/sequel_core/dataset/query.rb +41 -0
  31. data/lib/sequel_core/dataset/schema.rb +15 -0
  32. data/lib/sequel_core/dataset/sequelizer.rb +41 -373
  33. data/lib/sequel_core/dataset/sql.rb +741 -632
  34. data/lib/sequel_core/dataset.rb +183 -168
  35. data/lib/sequel_core/deprecated.rb +1 -169
  36. data/lib/sequel_core/exceptions.rb +24 -19
  37. data/lib/sequel_core/migration.rb +44 -52
  38. data/lib/sequel_core/object_graph.rb +43 -42
  39. data/lib/sequel_core/pretty_table.rb +71 -76
  40. data/lib/sequel_core/schema/generator.rb +163 -105
  41. data/lib/sequel_core/schema/sql.rb +250 -93
  42. data/lib/sequel_core/schema.rb +2 -8
  43. data/lib/sequel_core/sql.rb +394 -0
  44. data/lib/sequel_core/worker.rb +37 -27
  45. data/lib/sequel_core.rb +99 -45
  46. data/spec/adapters/informix_spec.rb +0 -1
  47. data/spec/adapters/mysql_spec.rb +177 -124
  48. data/spec/adapters/oracle_spec.rb +0 -1
  49. data/spec/adapters/postgres_spec.rb +98 -58
  50. data/spec/adapters/sqlite_spec.rb +45 -4
  51. data/spec/blockless_filters_spec.rb +269 -0
  52. data/spec/connection_pool_spec.rb +21 -18
  53. data/spec/core_ext_spec.rb +169 -19
  54. data/spec/core_sql_spec.rb +56 -49
  55. data/spec/database_spec.rb +78 -17
  56. data/spec/dataset_spec.rb +300 -428
  57. data/spec/migration_spec.rb +1 -1
  58. data/spec/object_graph_spec.rb +5 -11
  59. data/spec/rcov.opts +1 -1
  60. data/spec/schema_generator_spec.rb +16 -4
  61. data/spec/schema_spec.rb +89 -10
  62. data/spec/sequelizer_spec.rb +56 -56
  63. data/spec/spec.opts +0 -5
  64. data/spec/spec_config.rb +7 -0
  65. data/spec/spec_config.rb.example +5 -5
  66. data/spec/spec_helper.rb +6 -0
  67. data/spec/worker_spec.rb +1 -1
  68. metadata +78 -63
@@ -1,6 +1,19 @@
1
1
  module Sequel
2
+ # The Schema module holds the schema generators and the SQL code relating
3
+ # to SQL DDL (Data Definition Language).
2
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.
3
14
  class Generator
15
+ # Set the database in which to create the table, and evaluate the block
16
+ # in the context of this object.
4
17
  def initialize(db, &block)
5
18
  @db = db
6
19
  @columns = []
@@ -9,171 +22,216 @@ module Sequel
9
22
  instance_eval(&block) if block
10
23
  end
11
24
 
12
- def method_missing(type, name = nil, opts = {})
13
- name ? column(name, type, opts) : super
14
- end
15
-
16
- def primary_key_name
17
- @primary_key ? @primary_key[:name] : nil
18
- end
19
-
20
- def primary_key(name, *args)
21
- @primary_key = @db.serial_primary_key_options.merge({:name => name})
22
-
23
- if opts = args.pop
24
- opts = {:type => opts} unless opts.is_a?(Hash)
25
- if type = args.pop
26
- opts.merge!(:type => type)
27
- end
28
- @primary_key.merge!(opts)
29
- end
30
- @primary_key
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)
31
29
  end
32
-
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.
33
57
  def column(name, type, opts = {})
34
58
  @columns << {:name => name, :type => type}.merge(opts)
35
59
  index(name) if opts[:index]
36
60
  end
37
61
 
38
- def foreign_key(name, opts = {})
39
- @columns << {:name => name, :type => :integer}.merge(opts)
40
- index(name) if opts[:index]
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}
41
66
  end
42
67
 
43
- def check(*args, &block)
44
- @columns << {:name => nil, :type => :check, :check => block || args}
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]
45
73
  end
46
74
 
47
- def constraint(name, *args, &block)
48
- @columns << {:name => name, :type => :check, :check => block || args}
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))
49
94
  end
50
95
 
96
+ # True if the DDL includes the creation of a column with the given name.
51
97
  def has_column?(name)
52
- @columns.each {|c| return true if c[:name] == name}
53
- false
98
+ @columns.any?{|c| c[:name] == name}
54
99
  end
55
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)
56
107
  def index(columns, opts = {})
57
- columns = [columns] unless columns.is_a?(Array)
58
- @indexes << {:columns => columns}.merge(opts)
108
+ @indexes << {:columns => Array(columns)}.merge(opts)
59
109
  end
60
110
 
61
- def full_text_index(columns, opts = {})
62
- index(columns, opts.merge(:type => :full_text))
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
63
115
  end
64
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.
65
139
  def spatial_index(columns, opts = {})
66
140
  index(columns, opts.merge(:type => :spatial))
67
141
  end
68
142
 
143
+ # Add a unique index on the given columns to the DDL.
69
144
  def unique(columns, opts = {})
70
145
  index(columns, opts.merge(:unique => true))
71
146
  end
72
-
73
- def create_info
74
- if @primary_key && !has_column?(@primary_key[:name])
75
- @columns.unshift(@primary_key)
76
- end
77
- [@columns, @indexes]
78
- end
79
147
  end
80
148
 
149
+ # The Schema::AlterTableGenerator creates DDL operations on existing tables,
150
+ # such as adding/removing/modifying columns/indexes/constraints.
81
151
  class AlterTableGenerator
152
+ # An array of DDL operations to perform
82
153
  attr_reader :operations
83
154
 
155
+ # Set the Database object to which to apply the DDL, and evaluate the
156
+ # block in the context of this object.
84
157
  def initialize(db, &block)
85
158
  @db = db
86
159
  @operations = []
87
160
  instance_eval(&block) if block
88
161
  end
89
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.
90
165
  def add_column(name, type, opts = {})
91
- @operations << { \
92
- :op => :add_column, \
93
- :name => name, \
94
- :type => type \
95
- }.merge(opts)
166
+ @operations << {:op => :add_column, :name => name, :type => type}.merge(opts)
96
167
  end
97
168
 
98
- def drop_column(name)
99
- @operations << { \
100
- :op => :drop_column, \
101
- :name => name \
102
- }
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))
103
180
  end
104
181
 
105
- def rename_column(name, new_name, opts = {})
106
- @operations << { \
107
- :op => :rename_column, \
108
- :name => name, \
109
- :new_name => new_name \
110
- }.merge(opts)
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))
111
186
  end
112
187
 
113
- def set_column_type(name, type)
114
- @operations << { \
115
- :op => :set_column_type, \
116
- :name => name, \
117
- :type => type \
118
- }
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)
119
192
  end
120
193
 
121
- def set_column_default(name, default)
122
- @operations << { \
123
- :op => :set_column_default, \
124
- :name => name, \
125
- :default => default \
126
- }
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)
127
199
  end
128
200
 
129
- def add_index(columns, opts = {})
130
- columns = [columns] unless columns.is_a?(Array)
131
- @operations << { \
132
- :op => :add_index, \
133
- :columns => columns \
134
- }.merge(opts)
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))
135
205
  end
136
206
 
137
- def add_full_text_index(columns, opts = {})
138
- columns = [columns] unless columns.is_a?(Array)
139
- @operations << { \
140
- :op => :add_index, \
141
- :columns => columns, \
142
- :type => :full_text \
143
- }.merge(opts)
207
+ # Remove a column from the DDL for the table.
208
+ def drop_column(name)
209
+ @operations << {:op => :drop_column, :name => name}
144
210
  end
145
211
 
146
- def add_spatial_index(columns, opts = {})
147
- columns = [columns] unless columns.is_a?(Array)
148
- @operations << { \
149
- :op => :add_index, \
150
- :columns => columns, \
151
- :type => :spatial \
152
- }.merge(opts)
212
+ # Remove a constraint from the DDL for the table.
213
+ def drop_constraint(name)
214
+ @operations << {:op => :drop_constraint, :name => name}
153
215
  end
154
216
 
217
+ # Remove an index from the DDL for the table.
155
218
  def drop_index(columns)
156
- columns = [columns] unless columns.is_a?(Array)
157
- @operations << { \
158
- :op => :drop_index, \
159
- :columns => columns \
160
- }
219
+ @operations << {:op => :drop_index, :columns => Array(columns)}
161
220
  end
162
221
 
163
- def add_constraint(name, *args, &block)
164
- @operations << { \
165
- :op => :add_constraint, \
166
- :name => name, \
167
- :type => :check, \
168
- :check => block || args \
169
- }
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}
170
230
  end
171
231
 
172
- def drop_constraint(name)
173
- @operations << { \
174
- :op => :drop_constraint, \
175
- :name => name \
176
- }
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}
177
235
  end
178
236
  end
179
237
  end