sequel 3.20.0 → 3.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/CHANGELOG +32 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +1 -1
  4. data/Rakefile +13 -3
  5. data/bin/sequel +18 -5
  6. data/doc/active_record.rdoc +4 -4
  7. data/doc/opening_databases.rdoc +38 -1
  8. data/doc/release_notes/3.21.0.txt +87 -0
  9. data/doc/validations.rdoc +2 -2
  10. data/lib/sequel/adapters/informix.rb +1 -1
  11. data/lib/sequel/adapters/jdbc/h2.rb +2 -5
  12. data/lib/sequel/adapters/jdbc/mssql.rb +1 -4
  13. data/lib/sequel/adapters/jdbc/mysql.rb +1 -4
  14. data/lib/sequel/adapters/jdbc/postgresql.rb +1 -6
  15. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -8
  16. data/lib/sequel/adapters/shared/mssql.rb +8 -0
  17. data/lib/sequel/adapters/shared/mysql.rb +23 -3
  18. data/lib/sequel/adapters/shared/oracle.rb +2 -2
  19. data/lib/sequel/adapters/tinytds.rb +125 -0
  20. data/lib/sequel/database/connecting.rb +1 -1
  21. data/lib/sequel/database/schema_methods.rb +37 -5
  22. data/lib/sequel/dataset/sql.rb +6 -6
  23. data/lib/sequel/extensions/schema_dumper.rb +1 -1
  24. data/lib/sequel/model/base.rb +50 -0
  25. data/lib/sequel/model/plugins.rb +0 -55
  26. data/lib/sequel/plugins/association_autoreloading.rb +48 -0
  27. data/lib/sequel/plugins/validation_class_methods.rb +6 -5
  28. data/lib/sequel/plugins/validation_helpers.rb +2 -2
  29. data/lib/sequel/version.rb +1 -1
  30. data/spec/adapters/firebird_spec.rb +6 -6
  31. data/spec/adapters/informix_spec.rb +2 -2
  32. data/spec/adapters/mssql_spec.rb +18 -13
  33. data/spec/adapters/mysql_spec.rb +47 -20
  34. data/spec/adapters/oracle_spec.rb +40 -4
  35. data/spec/adapters/postgres_spec.rb +14 -14
  36. data/spec/adapters/spec_helper.rb +1 -1
  37. data/spec/adapters/sqlite_spec.rb +8 -8
  38. data/spec/core/connection_pool_spec.rb +18 -17
  39. data/spec/core/core_sql_spec.rb +18 -18
  40. data/spec/core/database_spec.rb +62 -62
  41. data/spec/core/dataset_spec.rb +105 -92
  42. data/spec/core/expression_filters_spec.rb +2 -2
  43. data/spec/core/schema_spec.rb +6 -6
  44. data/spec/core/version_spec.rb +1 -1
  45. data/spec/extensions/association_autoreloading_spec.rb +94 -0
  46. data/spec/extensions/blank_spec.rb +6 -6
  47. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  48. data/spec/extensions/migration_spec.rb +6 -6
  49. data/spec/extensions/pagination_spec.rb +2 -2
  50. data/spec/extensions/pretty_table_spec.rb +2 -2
  51. data/spec/extensions/query_spec.rb +2 -2
  52. data/spec/extensions/schema_dumper_spec.rb +2 -1
  53. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  54. data/spec/extensions/sql_expr_spec.rb +1 -1
  55. data/spec/extensions/string_date_time_spec.rb +4 -4
  56. data/spec/extensions/validation_class_methods_spec.rb +2 -2
  57. data/spec/integration/dataset_test.rb +8 -3
  58. data/spec/integration/plugin_test.rb +5 -5
  59. data/spec/integration/prepared_statement_test.rb +1 -1
  60. data/spec/integration/schema_test.rb +7 -0
  61. data/spec/integration/spec_helper.rb +14 -1
  62. data/spec/integration/timezone_test.rb +4 -4
  63. data/spec/integration/type_test.rb +1 -1
  64. data/spec/model/model_spec.rb +3 -3
  65. metadata +9 -4
data/CHANGELOG CHANGED
@@ -1,3 +1,35 @@
1
+ === 3.21.0 (2011-03-01)
2
+
3
+ * Make symbol splitting (:table__column___alias) work correctly for identifiers that are not in the \w character class (authorNari)
4
+
5
+ * Enable row locks in Oracle (authorNari)
6
+
7
+ * Prefer cover? over include? for validates_includes/validates_inclusion_of (jeremyevans)
8
+
9
+ * Make using NULL/NOT NULL, DEFAULT, and UNIQUE column options work correctly on H2 and possibly Oracle (jeremyevans)
10
+
11
+ * Make bin/sequel accept file arguments and work correctly when $stdin is not a tty (jeremyevans)
12
+
13
+ * Add support for -I and -r options to bin/sequel (jeremyevans)
14
+
15
+ * Sequel::Model.plugin can now be overridden just like the other Model methods (jeremyevans)
16
+
17
+ * Add tinytds adapter, the best way to connect to MSSQL from a C based ruby running on *nix (jeremyevans)
18
+
19
+ * Recognize bigint unsigned as a Bignum type in the schema dumper (gamespy-tech) (#327)
20
+
21
+ * Add Dataset#calc_found_rows for MySQL datasets (macks)
22
+
23
+ * Add association_autoreloading plugin for clearing association cache when foreign key value changes (jfirebaugh, jeremyevans)
24
+
25
+ * Fix join_table on MySQL ignoring the block (jfirebaugh)
26
+
27
+ * Transfer CTE WITH clauses in subselect to main query when joining on MSSQL (jfirebaugh)
28
+
29
+ * Make specs support both RSpec 1 and RSpec 2 (jeremyevans)
30
+
31
+ * Work with ruby-informix versions >= 0.7.3 in the informix adapter (jeremyevans) (#326)
32
+
1
33
  === 3.20.0 (2011-02-01)
2
34
 
3
35
  * Allow a :partial option to Database#indexes on MySQL to include partial indexes (roland.swingler) (#324)
data/MIT-LICENSE CHANGED
@@ -1,5 +1,5 @@
1
1
  Copyright (c) 2007-2008 Sharon Rosner
2
- Copyright (c) 2008-2010 Jeremy Evans
2
+ Copyright (c) 2008-2011 Jeremy Evans
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to
data/README.rdoc CHANGED
@@ -13,7 +13,7 @@ toolkit for Ruby.
13
13
  configurations, and database sharding.
14
14
  * Sequel currently has adapters for ADO, Amalgalite, DataObjects,
15
15
  DB2, DBI, Firebird, Informix, JDBC, MySQL, Mysql2, ODBC, OpenBase,
16
- Oracle, PostgreSQL, SQLite3, and Swift.
16
+ Oracle, PostgreSQL, SQLite3, Swift, and TinyTDS.
17
17
 
18
18
  == Resources
19
19
 
data/Rakefile CHANGED
@@ -87,14 +87,24 @@ end
87
87
  ### Specs
88
88
 
89
89
  begin
90
- require "spec/rake/spectask"
90
+ begin
91
+ # RSpec 1
92
+ require "spec/rake/spectask"
93
+ spec_class = Spec::Rake::SpecTask
94
+ spec_files_meth = :spec_files=
95
+ rescue LoadError
96
+ # RSpec 2
97
+ require "rspec/core/rake_task"
98
+ spec_class = RSpec::Core::RakeTask
99
+ spec_files_meth = :pattern=
100
+ end
91
101
 
92
102
  spec = lambda do |name, files, d|
93
103
  lib_dir = File.join(File.dirname(File.expand_path(__FILE__)), 'lib')
94
104
  ENV['RUBYLIB'] ? (ENV['RUBYLIB'] += ":#{lib_dir}") : (ENV['RUBYLIB'] = lib_dir)
95
105
  desc d
96
- Spec::Rake::SpecTask.new(name) do |t|
97
- t.spec_files = files
106
+ spec_class.new(name) do |t|
107
+ t.send spec_files_meth, files
98
108
  t.spec_opts = ENV['SEQUEL_SPEC_OPTS'].split if ENV['SEQUEL_SPEC_OPTS']
99
109
  end
100
110
  end
data/bin/sequel CHANGED
@@ -53,6 +53,10 @@ opts = OptionParser.new do |opts|
53
53
  echo = true
54
54
  end
55
55
 
56
+ opts.on("-I", "--include dir", "specify $LOAD_PATH directory") do |v|
57
+ $: << v
58
+ end
59
+
56
60
  opts.on("-l", "--log logfile", "log SQL statements to log file") do |v|
57
61
  logfile = v
58
62
  end
@@ -73,6 +77,10 @@ opts = OptionParser.new do |opts|
73
77
  db_opts[:test] = false
74
78
  end
75
79
 
80
+ opts.on("-r", "--require lib", "require the library, before executing your script") do |v|
81
+ load_dirs << [v]
82
+ end
83
+
76
84
  opts.on("-t", "--trace", "Output the full backtrace if an exception is raised") do
77
85
  backtrace = true
78
86
  end
@@ -124,6 +132,7 @@ end
124
132
 
125
133
  begin
126
134
  DB = connect_proc[db]
135
+ load_dirs.each{|d| d.is_a?(Array) ? require(d.first) : Dir["#{d}/**/*.rb"].each{|f| load(f)}}
127
136
  if migrate_dir
128
137
  Sequel.extension :migration
129
138
  Sequel::Migrator.apply(DB, migrate_dir, migrate_ver)
@@ -189,8 +198,12 @@ rescue => e
189
198
  error_proc["Error: #{e.class}: #{e.message}#{e.backtrace.first}"]
190
199
  end
191
200
 
192
- load_dirs.each{|d| Dir["#{d}/**/*.rb"].each{|f| load(f)}}
193
-
194
- require 'irb'
195
- puts "Your database is stored in DB..."
196
- IRB.start
201
+ if !ARGV.empty?
202
+ ARGV.each{|v| load(v)}
203
+ elsif !$stdin.isatty
204
+ eval($stdin.read)
205
+ else
206
+ require 'irb'
207
+ puts "Your database is stored in DB..."
208
+ IRB.start
209
+ end
@@ -427,12 +427,12 @@ You can think of <tt>Sequel::Model::Errors</tt> as a subset of <tt>ActiveRecord:
427
427
  Unlike ActiveRecord, Sequel's behavior depends on how you configure it. In Sequel, you can set flags at the global, class, and instance level that change the behavior of Sequel. Here's a brief description of the flags:
428
428
 
429
429
  +raise_on_save_failure+ :: Whether to raise an error instead of returning nil on a failure to save/create/save_changes/etc due to a validation failure or a before_* hook returning false. By default, an error is raised, when this is set to false, nil is returned instead.
430
- +raise_on_typecast_failure+ :: Whether to raise an error when unable to typecast data for a column (default: true). This should be set to false if you want to use validations to display nice error messages to the user (e.g. most web applications). You can use the +validates_not_string+ validation in connection with this option to check for typecast failures for columns that arent blobs or strings.
430
+ +raise_on_typecast_failure+ :: Whether to raise an error when unable to typecast data for a column (default: true). This should be set to false if you want to use validations to display nice error messages to the user (e.g. most web applications). You can use the +validates_not_string+ validation in connection with this option to check for typecast failures for columns that aren't blobs or strings.
431
431
  +require_modification+ :: Whether to raise an error if an UPDATE or DELETE query related to a model instance does not modify exactly 1 row. If set to false, Sequel will not check the number of rows modified (default: true if the database supports it).
432
- +strict_param_setting+ :: Whether new/set/update and their variants should raise an error if an invalid key is used. A key is invalid if no setter method exists for that key or the access to the setter method is restricted (e.g. due to it being a primary key field). If set to false, silently skip any key where the setter method doesnt exist or access to it is restricted.
433
- +typecast_empty_string_to_nil+ :: Whether to typecast the empty string ('') to nil for columns that are not string or blob. In most cases the empty string would be the way to specify a NULL SQL value in string form (nil.to_s == ��), and an empty string would not usually be typecast correctly for other types, so the default is true.
432
+ +strict_param_setting+ :: Whether new/set/update and their variants should raise an error if an invalid key is used. A key is invalid if no setter method exists for that key or the access to the setter method is restricted (e.g. due to it being a primary key field). If set to false, silently skip any key where the setter method doesn't exist or access to it is restricted.
433
+ +typecast_empty_string_to_nil+ :: Whether to typecast the empty string ('') to nil for columns that are not string or blob. In most cases the empty string would be the way to specify a NULL SQL value in string form (nil.to_s == ''), and an empty string would not usually be typecast correctly for other types, so the default is true.
434
434
  +typecast_on_assignment+ :: Whether to typecast attribute values on assignment (default: true). If set to false, no typecasting is done, so it will be left up to the database to typecast the value correctly.
435
- +use_transactions+ :: Whether to use a transaction by default when saving/deleting records (default: true). If you are sending database queries in before or after hooks, you shouldnt change the default setting without a good reason.
435
+ +use_transactions+ :: Whether to use a transaction by default when saving/deleting records (default: true). If you are sending database queries in before or after hooks, you shouldn't change the default setting without a good reason.
436
436
 
437
437
  == ActiveRecord Method to Sequel Method Mapping
438
438
 
@@ -203,8 +203,17 @@ Does not support the :port option.
203
203
 
204
204
  === informix
205
205
 
206
- Does not support the :host or :port options.
206
+ Does not support the :host or :port options. Depending on the configuration of your server
207
+ it may be necessary to either set
208
+
209
+ DB.quote_identifier = false
207
210
 
211
+ or set
212
+
213
+ export DELIMIDENT=y
214
+
215
+ in the scripts environment.
216
+
208
217
  === jdbc
209
218
 
210
219
  Requires: java
@@ -329,3 +338,31 @@ Examples:
329
338
  The following additional options are supported:
330
339
 
331
340
  * :timeout - the busy timeout to use in milliseconds (default: 5000).
341
+
342
+ === swift
343
+
344
+ swift is a ruby 1.9 only library, so you'll need to be running ruby 1.9. It
345
+ can connect to SQLite, MySQL, and PostgreSQL, and you must specify which
346
+ database using the db_type option.
347
+
348
+ Examples:
349
+
350
+ swift:///?database=:memory:&db_type=sqlite
351
+ swift://root:root@localhost/test?db_type=mysql
352
+ swift://root:root@localhost/test?db_type=postgres
353
+
354
+ === tinytds
355
+
356
+ Because the underscore is not a valid character in a URI schema, the adapter
357
+ is named tinytds instead of tiny_tds. The connection options are passed directly
358
+ to tiny_tds, except that the tiny_tds :dataserver and :username options are set to
359
+ the Sequel :host and :user options. The :host option should be an entry in the
360
+ freetds.conf file, it's not currently possible to a host not present in the
361
+ freetds.conf file. Some options that you may want to set are
362
+ :login_timeout, :timeout, :appname, and :encoding, see the tiny_tds README for details.
363
+ For highest performance, you should disable any identifier output method when
364
+ using the tinytds adapter, which probably means disabling any identifier input method
365
+ as well. The default for Microsoft SQL Server is to :downcase identifiers on output
366
+ and :upcase them on input, so the highest performance will require changing the setting
367
+ from the default.
368
+
@@ -0,0 +1,87 @@
1
+ = New Features
2
+
3
+ * A tinytds adapter was added, enabling Sequel users on a C-based
4
+ ruby running on *nix easy access to Microsoft SQL Server.
5
+ Previously, the best way to connect to Microsoft SQL Server from
6
+ a C-based ruby on *nix was to use the ODBC adapter with unixodbc
7
+ and freetds. However, setting that up is nontrivial, while
8
+ setting up tinytds is very easy.
9
+
10
+ Note that the tinytds adapter currently requires the git master
11
+ branch of tiny_tds, but tiny_tds 0.4.0 should include the related
12
+ changes.
13
+
14
+ * An association_autoreloading plugin has been added to Sequel,
15
+ which removes stale many_to_one associations from the cache when
16
+ the associated foreign key setter is used to change the value of
17
+ the foreign key.
18
+
19
+ * bin/sequel now operates more like a standard *nix utility.
20
+ If given a file on the command line after the connection
21
+ string, it will assume that file has ruby code and load it.
22
+ If stdin is not a tty, it will read from stdin and execute it
23
+ as ruby code.
24
+
25
+ For recent Linux users, this means you can have a shebang line
26
+ such as:
27
+
28
+ #!/usr/bin/sequel postgres://user:pass@host/db
29
+
30
+ to create a self contained script.
31
+
32
+ * bin/sequel now supports -r and -I options similar to ruby's
33
+ -r and -I options.
34
+
35
+ * MySQL datasets now have a calc_found_rows method that uses
36
+ SQL_CALC_FOUND_ROWS, which provides a fast way to limit the
37
+ number of results returned by a dataset while having an easy
38
+ way to determine how many rows would have been returned if no
39
+ limit was applied.
40
+
41
+ = Other Improvements
42
+
43
+ * The Sequel::Model.plugin method can now be overridden just like
44
+ any other method. Previously, it was the only method that
45
+ was defined directly on the class. This allows the creation
46
+ of plugins that can modify the plugin system itself.
47
+
48
+ * Symbol splitting (:table__column___alias) now works correctly
49
+ for identifiers that include characters that aren't in [\w ].
50
+ Among other things, this means that identifiers with accented
51
+ characters or even kanji characters can be used with symbol
52
+ splitting.
53
+
54
+ * If cover? is defined, it is now used in preference to include?
55
+ for the validates_includes/validates_inclusion_of validations.
56
+ ruby 1.9 defines include? differently for some ranges and can
57
+ be very slow, while cover? is similar to the 1.8 behavior of
58
+ just checking the beginning and end of the range.
59
+
60
+ * The bin/sequel -L option now takes effect even if the -m,
61
+ -C, -d, or -D options are used.
62
+
63
+ * The schema_dumper extension now recognizes the "bigint unsigned"
64
+ type.
65
+
66
+ * On Microsoft SQL Server, if joining to a subselect that uses a
67
+ common table expression, that common table expression is
68
+ promoted to the main dataset. This allows most queries to work
69
+ correctly, but is vulnerable to issues if both the current
70
+ dataset and the joined dataset use common table expressions with
71
+ the same name. Unfortunately, unlike PostgreSQL, Microsoft SQL
72
+ Server does not allow common table expressions to occur in
73
+ subselects.
74
+
75
+ * The NULL/NOT NULL, DEFAULT, and UNIQUE column options now
76
+ use the proper order on H2 and Oracle, so they can now be
77
+ used in conjunction with each other.
78
+
79
+ * Row locks are now enabled on Oracle.
80
+
81
+ * The join_table method on MySQL no longer ignores the block it was
82
+ given.
83
+
84
+ * The informix adapter now supports ruby-informix version >= 0.7.3,
85
+ while still being backwards compatible with older versions.
86
+
87
+ * The specs now run under both RSpec 2 and RSpec 1.
data/doc/validations.rdoc CHANGED
@@ -301,7 +301,7 @@ All +validation_helpers+ methods except +validates_unique+ accept the following
301
301
 
302
302
  === <tt>:message</tt>
303
303
 
304
- The most commonly used option, used to override the default validation message. Can be either a string or a proc. If a string, it is used directly. If a proc, the proc is called and should return a string. If the validation method takes an argument before the array of attributes, that argument is passed as an argument to the proc. The exception is the +validates_not_string+ method, which doesnt take an argument, but passes the schema type symbol as the argument to the proc.
304
+ The most commonly used option, used to override the default validation message. Can be either a string or a proc. If a string, it is used directly. If a proc, the proc is called and should return a string. If the validation method takes an argument before the array of attributes, that argument is passed as an argument to the proc. The exception is the +validates_not_string+ method, which doesn't take an argument, but passes the schema type symbol as the argument to the proc.
305
305
 
306
306
  class Album < Sequel::Model
307
307
  def validate
@@ -340,7 +340,7 @@ The <tt>:allow_blank</tt> is similar to the <tt>:allow_nil</tt> option, but inst
340
340
 
341
341
  The <tt>:allow_missing</tt> option is different from the <tt>:allow_nil</tt> option, in that instead of checking if the attribute value is nil, it checks if the attribute is present in the model instance's values hash. <tt>:allow_nil</tt> will skip the validation when the attribute is in the values hash and has a nil value and when the attribute is not in the values hash. <tt>:allow_missing</tt> will only skip the validation when the attribute is not in the values hash. If the attribute is in the values hash but has a nil value, <tt>:allow_missing</tt> will not skip it.
342
342
 
343
- The purpose of this option is to work correctly with missing columns when inserting or updating records. Sequel only sends the attributes in the values hash when doing an insert or update. If the attribute is not present in the values hash, Sequel doesnt specify it, so the database will use the tables default value when inserting the record, or not modify the value when saving it. This is different from having an attribute in the values hash with a value of nil, which Sequel will send as NULL. If your database table has a non NULL default, this may be a good option to use. You dont want to use allow_nil, because if the attribute is in values but has a value nil, Sequel will attempt to insert a NULL value into the database, instead of using the databases default.
343
+ The purpose of this option is to work correctly with missing columns when inserting or updating records. Sequel only sends the attributes in the values hash when doing an insert or update. If the attribute is not present in the values hash, Sequel doesn't specify it, so the database will use the table's default value when inserting the record, or not modify the value when saving it. This is different from having an attribute in the values hash with a value of nil, which Sequel will send as NULL. If your database table has a non NULL default, this may be a good option to use. You don't want to use allow_nil, because if the attribute is in values but has a value nil, Sequel will attempt to insert a NULL value into the database, instead of using the database's default.
344
344
 
345
345
  == Conditional Validation
346
346
 
@@ -51,7 +51,7 @@ module Sequel
51
51
  yield h2
52
52
  end
53
53
  ensure
54
- cursor.drop
54
+ cursor.respond_to?(:free) ? cursor.free : cursor.drop
55
55
  end
56
56
  end
57
57
  self
@@ -89,14 +89,11 @@ module Sequel
89
89
 
90
90
  # Use IDENTITY() to get the last inserted id.
91
91
  def last_insert_id(conn, opts={})
92
- stmt = conn.createStatement
93
- begin
92
+ statement(conn) do |stmt|
94
93
  rs = stmt.executeQuery('SELECT IDENTITY();')
95
94
  rs.next
96
95
  rs.getInt(1)
97
- ensure
98
- stmt.close
99
- end
96
+ end
100
97
  end
101
98
 
102
99
  def primary_key_index_re
@@ -25,14 +25,11 @@ module Sequel
25
25
 
26
26
  # Get the last inserted id using SCOPE_IDENTITY().
27
27
  def last_insert_id(conn, opts={})
28
- stmt = conn.createStatement
29
- begin
28
+ statement(conn) do |stmt|
30
29
  sql = opts[:prepared] ? 'SELECT @@IDENTITY' : 'SELECT SCOPE_IDENTITY()'
31
30
  rs = log_yield(sql){stmt.executeQuery(sql)}
32
31
  rs.next
33
32
  rs.getInt(1)
34
- ensure
35
- stmt.close
36
33
  end
37
34
  end
38
35
 
@@ -38,13 +38,10 @@ module Sequel
38
38
  rs.close
39
39
  end
40
40
  else
41
- stmt = conn.createStatement
42
- begin
41
+ statement(conn) do |stmt|
43
42
  rs = stmt.executeQuery('SELECT LAST_INSERT_ID()')
44
43
  rs.next
45
44
  rs.getInt(1)
46
- ensure
47
- stmt.close
48
45
  end
49
46
  end
50
47
  end
@@ -16,14 +16,9 @@ module Sequel
16
16
  # a statement with the given sql and executes it.
17
17
  def execute(sql, args=nil)
18
18
  method = block_given? ? :executeQuery : :execute
19
- stmt = createStatement
20
- begin
19
+ @db.send(:statement, self) do |stmt|
21
20
  rows = @db.log_yield(sql){stmt.send(method, sql)}
22
21
  yield(rows) if block_given?
23
- rescue NativeException => e
24
- raise_error(e)
25
- ensure
26
- stmt.close
27
22
  end
28
23
  end
29
24
 
@@ -17,13 +17,10 @@ module Sequel
17
17
 
18
18
  # Use last_insert_rowid() to get the last inserted id.
19
19
  def last_insert_id(conn, opts={})
20
- stmt = conn.createStatement
21
- begin
20
+ statement(conn) do |stmt|
22
21
  rs = stmt.executeQuery('SELECT last_insert_rowid()')
23
22
  rs.next
24
23
  rs.getInt(1)
25
- ensure
26
- stmt.close
27
24
  end
28
25
  end
29
26
 
@@ -36,11 +33,8 @@ module Sequel
36
33
  # Execute the connection pragmas on the connection.
37
34
  def setup_connection(conn)
38
35
  conn = super(conn)
39
- begin
40
- stmt = conn.createStatement
36
+ statement(conn) do |stmt|
41
37
  connection_pragmas.each{|s| log_yield(s){stmt.execute(s)}}
42
- ensure
43
- stmt.close if stmt
44
38
  end
45
39
  conn
46
40
  end
@@ -266,6 +266,14 @@ module Sequel
266
266
  clone(:into => table)
267
267
  end
268
268
 
269
+ # SQL Server does not support CTEs on subqueries, so move any CTEs
270
+ # on joined datasets to the top level. The user is responsible for
271
+ # resolving any name clashes this may cause.
272
+ def join_table(type, table, expr=nil, table_alias={}, &block)
273
+ return super unless Dataset === table && table.opts[:with]
274
+ clone(:with => (opts[:with] || []) + table.opts[:with]).join_table(type, table.clone(:with => nil), expr, table_alias, &block)
275
+ end
276
+
269
277
  # MSSQL uses a UNION ALL statement to insert multiple values at once.
270
278
  def multi_insert_sql(columns, values)
271
279
  [insert_sql(columns, LiteralString.new(values.map {|r| "SELECT #{expression_list(r)}" }.join(" UNION ALL ")))]
@@ -30,6 +30,7 @@ module Sequel
30
30
  module DatabaseMethods
31
31
  AUTO_INCREMENT = 'AUTO_INCREMENT'.freeze
32
32
  CAST_TYPES = {String=>:CHAR, Integer=>:SIGNED, Time=>:DATETIME, DateTime=>:DATETIME, Numeric=>:DECIMAL, BigDecimal=>:DECIMAL, File=>:BINARY}
33
+ COLUMN_DEFINITION_ORDER = [:null, :default, :unique, :primary_key, :auto_increment, :references]
33
34
  PRIMARY = 'PRIMARY'.freeze
34
35
 
35
36
  # MySQL's cast rules are restrictive in that you can't just cast to any possible
@@ -168,6 +169,11 @@ module Sequel
168
169
  end
169
170
  end
170
171
 
172
+ # The order of the column definition, as an array of symbols.
173
+ def column_definition_order
174
+ COLUMN_DEFINITION_ORDER
175
+ end
176
+
171
177
  # MySQL doesn't allow default values on text columns, so ignore if it the
172
178
  # generic text type is used
173
179
  def column_definition_sql(column)
@@ -296,9 +302,10 @@ module Sequel
296
302
  BOOL_FALSE = '0'.freeze
297
303
  COMMA_SEPARATOR = ', '.freeze
298
304
  FOR_SHARE = ' LOCK IN SHARE MODE'.freeze
305
+ SQL_CALC_FOUND_ROWS = ' SQL_CALC_FOUND_ROWS'.freeze
299
306
  DELETE_CLAUSE_METHODS = Dataset.clause_methods(:delete, %w'from where order limit')
300
307
  INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'ignore into columns values on_duplicate_key_update')
301
- SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'distinct columns from join where group having compounds order limit lock')
308
+ SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'distinct calc_found_rows columns from join where group having compounds order limit lock')
302
309
  UPDATE_CLAUSE_METHODS = Dataset.clause_methods(:update, %w'table set where order limit')
303
310
 
304
311
  # MySQL specific syntax for LIKE/REGEXP searches, as well as
@@ -324,6 +331,14 @@ module Sequel
324
331
  def distinct(*args)
325
332
  args.empty? ? super : group(*args)
326
333
  end
334
+
335
+ # Sets up the select methods to use SQL_CALC_FOUND_ROWS option.
336
+ #
337
+ # dataset.calc_found_rows.limit(10)
338
+ # # SELECT SQL_CALC_FOUND_ROWS * FROM table LIMIT 10
339
+ def calc_found_rows
340
+ clone(:calc_found_rows => true)
341
+ end
327
342
 
328
343
  # Return a cloned dataset which will use LOCK IN SHARE MODE to lock returned rows.
329
344
  def for_share
@@ -347,10 +362,10 @@ module Sequel
347
362
 
348
363
  # Transforms an CROSS JOIN to an INNER JOIN if the expr is not nil.
349
364
  # Raises an error on use of :full_outer type, since MySQL doesn't support it.
350
- def join_table(type, table, expr=nil, table_alias={})
365
+ def join_table(type, table, expr=nil, table_alias={}, &block)
351
366
  type = :inner if (type == :cross) && !expr.nil?
352
367
  raise(Sequel::Error, "MySQL doesn't support FULL OUTER JOIN") if type == :full_outer
353
- super(type, table, expr, table_alias)
368
+ super(type, table, expr, table_alias, &block)
354
369
  end
355
370
 
356
371
  # Transforms :natural_inner to NATURAL LEFT JOIN and straight to
@@ -550,6 +565,11 @@ module Sequel
550
565
  @opts[:lock] == :share ? (sql << FOR_SHARE) : super
551
566
  end
552
567
 
568
+ # MySQL specific SQL_CALC_FOUND_ROWS option
569
+ def select_calc_found_rows_sql(sql)
570
+ sql << SQL_CALC_FOUND_ROWS if opts[:calc_found_rows]
571
+ end
572
+
553
573
  # MySQL supports the ORDER BY and LIMIT clauses for UPDATE statements
554
574
  def update_clause_methods
555
575
  UPDATE_CLAUSE_METHODS