sequel 3.40.0 → 3.41.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 (89) hide show
  1. data/CHANGELOG +40 -0
  2. data/README.rdoc +2 -2
  3. data/doc/advanced_associations.rdoc +12 -0
  4. data/doc/bin_sequel.rdoc +144 -0
  5. data/doc/migration.rdoc +1 -1
  6. data/doc/object_model.rdoc +29 -0
  7. data/doc/release_notes/3.41.0.txt +155 -0
  8. data/lib/sequel/adapters/ado.rb +4 -4
  9. data/lib/sequel/adapters/amalgalite.rb +0 -5
  10. data/lib/sequel/adapters/cubrid.rb +2 -2
  11. data/lib/sequel/adapters/db2.rb +9 -5
  12. data/lib/sequel/adapters/dbi.rb +4 -6
  13. data/lib/sequel/adapters/do.rb +4 -5
  14. data/lib/sequel/adapters/firebird.rb +8 -4
  15. data/lib/sequel/adapters/ibmdb.rb +2 -3
  16. data/lib/sequel/adapters/informix.rb +0 -6
  17. data/lib/sequel/adapters/jdbc.rb +11 -7
  18. data/lib/sequel/adapters/jdbc/db2.rb +22 -0
  19. data/lib/sequel/adapters/jdbc/derby.rb +5 -5
  20. data/lib/sequel/adapters/jdbc/h2.rb +0 -5
  21. data/lib/sequel/adapters/jdbc/jtds.rb +1 -1
  22. data/lib/sequel/adapters/jdbc/sqlserver.rb +6 -0
  23. data/lib/sequel/adapters/mock.rb +3 -3
  24. data/lib/sequel/adapters/mysql.rb +7 -7
  25. data/lib/sequel/adapters/mysql2.rb +0 -5
  26. data/lib/sequel/adapters/odbc.rb +4 -4
  27. data/lib/sequel/adapters/openbase.rb +4 -6
  28. data/lib/sequel/adapters/oracle.rb +14 -6
  29. data/lib/sequel/adapters/postgres.rb +12 -8
  30. data/lib/sequel/adapters/shared/db2.rb +5 -0
  31. data/lib/sequel/adapters/shared/firebird.rb +10 -0
  32. data/lib/sequel/adapters/shared/mssql.rb +43 -1
  33. data/lib/sequel/adapters/shared/mysql.rb +1 -0
  34. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +1 -1
  35. data/lib/sequel/adapters/shared/postgres.rb +12 -0
  36. data/lib/sequel/adapters/shared/sqlite.rb +32 -0
  37. data/lib/sequel/adapters/sqlite.rb +9 -8
  38. data/lib/sequel/adapters/swift.rb +3 -8
  39. data/lib/sequel/adapters/tinytds.rb +5 -5
  40. data/lib/sequel/connection_pool.rb +13 -19
  41. data/lib/sequel/connection_pool/sharded_single.rb +12 -12
  42. data/lib/sequel/connection_pool/sharded_threaded.rb +37 -17
  43. data/lib/sequel/connection_pool/single.rb +6 -3
  44. data/lib/sequel/connection_pool/threaded.rb +33 -13
  45. data/lib/sequel/database/connecting.rb +28 -1
  46. data/lib/sequel/database/logging.rb +1 -1
  47. data/lib/sequel/database/misc.rb +2 -5
  48. data/lib/sequel/database/query.rb +2 -2
  49. data/lib/sequel/database/schema_generator.rb +1 -1
  50. data/lib/sequel/database/schema_methods.rb +3 -0
  51. data/lib/sequel/dataset/query.rb +8 -4
  52. data/lib/sequel/dataset/sql.rb +7 -0
  53. data/lib/sequel/extensions/arbitrary_servers.rb +1 -1
  54. data/lib/sequel/extensions/connection_validator.rb +109 -0
  55. data/lib/sequel/extensions/pg_array.rb +2 -0
  56. data/lib/sequel/extensions/pg_hstore.rb +2 -0
  57. data/lib/sequel/extensions/pg_json.rb +4 -0
  58. data/lib/sequel/extensions/pg_range.rb +1 -0
  59. data/lib/sequel/extensions/pg_row.rb +4 -0
  60. data/lib/sequel/plugins/prepared_statements.rb +2 -1
  61. data/lib/sequel/plugins/single_table_inheritance.rb +53 -10
  62. data/lib/sequel/plugins/touch.rb +18 -6
  63. data/lib/sequel/plugins/validation_class_methods.rb +1 -0
  64. data/lib/sequel/plugins/validation_helpers.rb +3 -1
  65. data/lib/sequel/sql.rb +61 -19
  66. data/lib/sequel/version.rb +1 -1
  67. data/spec/adapters/firebird_spec.rb +52 -38
  68. data/spec/adapters/mssql_spec.rb +67 -0
  69. data/spec/adapters/mysql_spec.rb +192 -116
  70. data/spec/adapters/postgres_spec.rb +133 -70
  71. data/spec/adapters/spec_helper.rb +7 -0
  72. data/spec/adapters/sqlite_spec.rb +34 -1
  73. data/spec/core/connection_pool_spec.rb +79 -75
  74. data/spec/core/database_spec.rb +9 -4
  75. data/spec/core/dataset_spec.rb +15 -0
  76. data/spec/core/expression_filters_spec.rb +40 -2
  77. data/spec/extensions/connection_validator_spec.rb +118 -0
  78. data/spec/extensions/pg_array_spec.rb +4 -0
  79. data/spec/extensions/single_table_inheritance_spec.rb +42 -0
  80. data/spec/extensions/touch_spec.rb +40 -0
  81. data/spec/extensions/validation_class_methods_spec.rb +19 -1
  82. data/spec/extensions/validation_helpers_spec.rb +17 -0
  83. data/spec/integration/database_test.rb +14 -0
  84. data/spec/integration/dataset_test.rb +3 -3
  85. data/spec/integration/plugin_test.rb +41 -12
  86. data/spec/integration/schema_test.rb +14 -0
  87. data/spec/integration/spec_helper.rb +7 -0
  88. data/spec/integration/type_test.rb +3 -0
  89. metadata +9 -3
@@ -147,11 +147,6 @@ module Sequel
147
147
  def database_error_classes
148
148
  [::Amalgalite::Error, ::Amalgalite::SQLite3::Error]
149
149
  end
150
-
151
- # Disconnect given connections from the database.
152
- def disconnect_connection(c)
153
- c.close
154
- end
155
150
  end
156
151
 
157
152
  # Dataset class for SQLite datasets that use the amalgalite driver.
@@ -97,8 +97,8 @@ module Sequel
97
97
  log_yield(TRANSACTION_COMMIT){conn.commit}
98
98
  end
99
99
 
100
- def disconnect_connection(c)
101
- c.close
100
+ def database_error_classes
101
+ [StandardError]
102
102
  end
103
103
 
104
104
  def remove_transaction(conn, committed)
@@ -57,6 +57,11 @@ module Sequel
57
57
  dbc
58
58
  end
59
59
 
60
+ def disconnect_connection(conn)
61
+ DB2CLI.SQLDisconnect(conn)
62
+ DB2CLI.SQLFreeHandle(DB2CLI::SQL_HANDLE_DBC, conn)
63
+ end
64
+
60
65
  def execute(sql, opts={}, &block)
61
66
  synchronize(opts[:server]){|conn| log_connection_execute(conn, sql, &block)}
62
67
  end
@@ -111,6 +116,10 @@ module Sequel
111
116
 
112
117
  private
113
118
 
119
+ def database_error_classes
120
+ [DB2Error]
121
+ end
122
+
114
123
  def begin_transaction(conn, opts={})
115
124
  log_yield(TRANSACTION_BEGIN){DB2CLI.SQLSetConnectAttr(conn, DB2CLI::SQL_ATTR_AUTOCOMMIT, DB2CLI::SQL_AUTOCOMMIT_OFF)}
116
125
  end
@@ -153,11 +162,6 @@ module Sequel
153
162
  super
154
163
  end
155
164
  end
156
-
157
- def disconnect_connection(conn)
158
- checked_error("Could not disconnect from database"){DB2CLI.SQLDisconnect(conn)}
159
- checked_error("Could not free Database handle"){DB2CLI.SQLFreeHandle(DB2CLI::SQL_HANDLE_DBC, conn)}
160
- end
161
165
  end
162
166
 
163
167
  class Dataset < Sequel::Dataset
@@ -62,6 +62,10 @@ module Sequel
62
62
  end
63
63
  ::DBI.connect(dbname, opts[:user], opts[:password])
64
64
  end
65
+
66
+ def disconnect_connection(c)
67
+ c.disconnect
68
+ end
65
69
 
66
70
  def execute(sql, opts={})
67
71
  synchronize(opts[:server]) do |conn|
@@ -75,12 +79,6 @@ module Sequel
75
79
  synchronize(opts[:server]){|conn| log_yield(sql){conn.do(sql)}}
76
80
  end
77
81
  alias_method :execute_dui, :do
78
-
79
- private
80
-
81
- def disconnect_connection(c)
82
- c.disconnect
83
- end
84
82
  end
85
83
 
86
84
  class Dataset < Sequel::Dataset
@@ -60,6 +60,10 @@ module Sequel
60
60
  def connect(server)
61
61
  setup_connection(::DataObjects::Connection.new(uri(server_opts(server))))
62
62
  end
63
+
64
+ def disconnect_connection(conn)
65
+ conn.dispose
66
+ end
63
67
 
64
68
  # Execute the given SQL. If a block is given, the DataObjects::Reader
65
69
  # created is yielded to it. A block should not be provided unless a
@@ -126,11 +130,6 @@ module Sequel
126
130
  [::DataObjects::Error]
127
131
  end
128
132
 
129
- # Close the given database connection.
130
- def disconnect_connection(c)
131
- c.close
132
- end
133
-
134
133
  # Recognize DataObjects::ConnectionError instances as disconnect errors.
135
134
  def disconnect_error?(e, opts)
136
135
  super || (e.is_a?(::DataObjects::Error) && (e.is_a?(::DataObjects::ConnectionError) || e.message =~ DISCONNECT_ERROR_RE))
@@ -28,6 +28,14 @@ module Sequel
28
28
  :password => opts[:password]).connect
29
29
  end
30
30
 
31
+ def disconnect_connection(conn)
32
+ begin
33
+ conn.close
34
+ rescue Fb::Error
35
+ nil
36
+ end
37
+ end
38
+
31
39
  def execute(sql, opts={})
32
40
  begin
33
41
  synchronize(opts[:server]) do |conn|
@@ -65,10 +73,6 @@ module Sequel
65
73
  [Fb::Error]
66
74
  end
67
75
 
68
- def disconnect_connection(c)
69
- c.close
70
- end
71
-
72
76
  def rollback_transaction(conn, opts={})
73
77
  log_yield(TRANSACTION_ROLLBACK){conn.rollback}
74
78
  end
@@ -309,9 +309,8 @@ module Sequel
309
309
  log_yield(TRANSACTION_COMMIT){conn.commit}
310
310
  end
311
311
 
312
- # Close the given connection.
313
- def disconnect_connection(conn)
314
- conn.close
312
+ def database_error_classes
313
+ [Connection::Error]
315
314
  end
316
315
 
317
316
  # Don't convert smallint to boolean for the metadata
@@ -23,12 +23,6 @@ module Sequel
23
23
  synchronize(opts[:server]){|c| yield log_yield(sql){c.cursor(sql)}}
24
24
  end
25
25
  alias_method :query, :execute
26
-
27
- private
28
-
29
- def disconnect_connection(c)
30
- c.close
31
- end
32
26
  end
33
27
 
34
28
  class Dataset < Sequel::Dataset
@@ -108,7 +108,7 @@ module Sequel
108
108
  :db2=>proc do |db|
109
109
  Sequel.ts_require 'adapters/jdbc/db2'
110
110
  db.extend(Sequel::JDBC::DB2::DatabaseMethods)
111
- db.extend_datasets Sequel::DB2::DatasetMethods
111
+ db.dataset_class = Sequel::JDBC::DB2::Dataset
112
112
  com.ibm.db2.jcc.DB2Driver
113
113
  end,
114
114
  :firebirdsql=>proc do |db|
@@ -239,6 +239,12 @@ module Sequel
239
239
  end
240
240
  setup_connection(conn)
241
241
  end
242
+
243
+ # Close given adapter connections, and delete any related prepared statements.
244
+ def disconnect_connection(c)
245
+ @connection_prepared_statements_mutex.synchronize{@connection_prepared_statements.delete(c)}
246
+ c.close
247
+ end
242
248
 
243
249
  # Execute the given SQL. If a block is given, if should be a SELECT
244
250
  # statement or something else that returns rows.
@@ -328,12 +334,10 @@ module Sequel
328
334
  @connection_prepared_statements_mutex.synchronize{yield(@connection_prepared_statements[conn] ||= {})}
329
335
  end
330
336
 
331
- # Close given adapter connections, and delete any related prepared statements.
332
- def disconnect_connection(c)
333
- @connection_prepared_statements_mutex.synchronize{@connection_prepared_statements.delete(c)}
334
- c.close
337
+ def database_error_classes
338
+ [NativeException]
335
339
  end
336
-
340
+
337
341
  # Raise a disconnect error if the SQL state of the cause of the exception indicates so.
338
342
  def disconnect_error?(exception, opts)
339
343
  cause = exception.respond_to?(:cause) ? exception.cause : exception
@@ -660,7 +664,7 @@ module Sequel
660
664
  def decimal(v) BigDecimal.new(v.to_string) end
661
665
  def byte_array(v) Sequel::SQL::Blob.new(String.from_java_bytes(v)) end
662
666
  def blob(v) Sequel::SQL::Blob.new(String.from_java_bytes(v.getBytes(1, v.length))) end
663
- def clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
667
+ def clob(v) v.getSubString(1, v.length) end
664
668
  def buffered_reader(v)
665
669
  lines = ""
666
670
  c = false
@@ -51,6 +51,28 @@ module Sequel
51
51
  PRIMARY_KEY_INDEX_RE
52
52
  end
53
53
  end
54
+
55
+ class Dataset < JDBC::Dataset
56
+ include Sequel::DB2::DatasetMethods
57
+
58
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
59
+ def db2_clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
60
+ end
61
+
62
+ DB2_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:db2_clob)
63
+
64
+ private
65
+
66
+ # Return clob as blob if use_clob_as_blob is true
67
+ def convert_type_proc(v)
68
+ case v
69
+ when JAVA_SQL_CLOB
70
+ ::Sequel::DB2::use_clob_as_blob ? DB2_CLOB_METHOD : super
71
+ else
72
+ super
73
+ end
74
+ end
75
+ end
54
76
  end
55
77
  end
56
78
  end
@@ -129,11 +129,6 @@ module Sequel
129
129
  PRIMARY_KEY_INDEX_RE
130
130
  end
131
131
 
132
- # Treat clob as string instead of blob
133
- def schema_column_type(db_type)
134
- db_type.downcase == 'clob' ? :string : super
135
- end
136
-
137
132
  # If an :identity option is present in the column, add the necessary IDENTITY SQL.
138
133
  def type_literal(column)
139
134
  if column[:identity]
@@ -153,6 +148,11 @@ module Sequel
153
148
  def uses_clob_for_text?
154
149
  true
155
150
  end
151
+
152
+ # The SQL query to issue to check if a connection is valid.
153
+ def valid_connection_sql
154
+ @valid_connection_sql ||= select(1).sql
155
+ end
156
156
  end
157
157
 
158
158
  # Dataset class for Derby datasets accessed via JDBC.
@@ -110,11 +110,6 @@ module Sequel
110
110
  PRIMARY_KEY_INDEX_RE
111
111
  end
112
112
 
113
- # Treat clob as string instead of blob
114
- def schema_column_type(db_type)
115
- db_type.downcase == 'clob' ? :string : super
116
- end
117
-
118
113
  # Use BIGINT IDENTITY for identity columns that use bigint, fixes
119
114
  # the case where primary_key :column, :type=>Bignum is used.
120
115
  def type_literal_generic_bignum(column)
@@ -21,7 +21,7 @@ module Sequel
21
21
  include Sequel::MSSQL::DatasetMethods
22
22
 
23
23
  class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
24
- def jtds_clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
24
+ def jtds_clob(v) v.getSubString(1, v.length) end
25
25
  end
26
26
 
27
27
  JTDS_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:jtds_clob)
@@ -60,6 +60,12 @@ module Sequel
60
60
  def metadata_dataset
61
61
  super.extend(MetadataDatasetMethods)
62
62
  end
63
+
64
+ private
65
+
66
+ def disconnect_error?(exception, opts)
67
+ super || (exception.message =~ /connection is closed/)
68
+ end
63
69
  end
64
70
  end
65
71
  end
@@ -160,6 +160,9 @@ module Sequel
160
160
  Connection.new(self, server, server_opts(server))
161
161
  end
162
162
 
163
+ def disconnect_connection(c)
164
+ end
165
+
163
166
  # Store the sql used for later retrieval with #sqls, and return
164
167
  # the appropriate value using either the #autoid, #fetch, or
165
168
  # #numrows methods.
@@ -306,9 +309,6 @@ module Sequel
306
309
  end
307
310
  end
308
311
 
309
- def disconnect_connection(c)
310
- end
311
-
312
312
  def quote_identifiers_default
313
313
  shared_adapter? ? super : false
314
314
  end
@@ -129,6 +129,13 @@ module Sequel
129
129
  conn
130
130
  end
131
131
 
132
+ # Closes given database connection.
133
+ def disconnect_connection(c)
134
+ c.close
135
+ rescue Mysql::Error
136
+ nil
137
+ end
138
+
132
139
  # Modify the type translators for the date, time, and timestamp types
133
140
  # depending on the value given.
134
141
  def convert_invalid_date_time=(v)
@@ -266,13 +273,6 @@ module Sequel
266
273
  @opts[:database]
267
274
  end
268
275
 
269
- # Closes given database connection.
270
- def disconnect_connection(c)
271
- c.close
272
- rescue Mysql::Error
273
- nil
274
- end
275
-
276
276
  # Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
277
277
  def schema_column_type(db_type)
278
278
  convert_tinyint_to_bool && db_type == 'tinyint(1)' ? :boolean : super
@@ -122,11 +122,6 @@ module Sequel
122
122
  @opts[:database]
123
123
  end
124
124
 
125
- # Closes given database connection.
126
- def disconnect_connection(c)
127
- c.close
128
- end
129
-
130
125
  # Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
131
126
  def schema_column_type(db_type)
132
127
  convert_tinyint_to_bool && db_type == 'tinyint(1)' ? :boolean : super
@@ -48,6 +48,10 @@ module Sequel
48
48
  conn
49
49
  end
50
50
 
51
+ def disconnect_connection(c)
52
+ c.disconnect
53
+ end
54
+
51
55
  def execute(sql, opts={})
52
56
  synchronize(opts[:server]) do |conn|
53
57
  begin
@@ -83,10 +87,6 @@ module Sequel
83
87
  [::ODBC::Error]
84
88
  end
85
89
 
86
- def disconnect_connection(c)
87
- c.disconnect
88
- end
89
-
90
90
  def disconnect_error?(e, opts)
91
91
  super || (e.is_a?(::ODBC::Error) && DISCONNECT_ERRORS.match(e.message))
92
92
  end
@@ -14,6 +14,10 @@ module Sequel
14
14
  opts[:password]
15
15
  )
16
16
  end
17
+
18
+ def disconnect_connection(c)
19
+ c.disconnect
20
+ end
17
21
 
18
22
  def execute(sql, opts={})
19
23
  synchronize(opts[:server]) do |conn|
@@ -23,12 +27,6 @@ module Sequel
23
27
  end
24
28
  end
25
29
  alias_method :do, :execute
26
-
27
- private
28
-
29
- def disconnect_connection(c)
30
- c.disconnect
31
- end
32
30
  end
33
31
 
34
32
  class Dataset < Sequel::Dataset
@@ -60,6 +60,12 @@ module Sequel
60
60
  conn
61
61
  end
62
62
 
63
+ def disconnect_connection(c)
64
+ c.logoff
65
+ rescue OCIInvalidHandle
66
+ nil
67
+ end
68
+
63
69
  def execute(sql, opts={}, &block)
64
70
  _execute(nil, sql, opts, &block)
65
71
  end
@@ -128,6 +134,14 @@ module Sequel
128
134
  end
129
135
  end
130
136
 
137
+ def connection_execute_method
138
+ :exec
139
+ end
140
+
141
+ def database_error_classes
142
+ [OCIException, RuntimeError]
143
+ end
144
+
131
145
  def execute_prepared_statement(conn, type, name, opts)
132
146
  ps = prepared_statement(name)
133
147
  sql = ps.prepared_sql
@@ -187,12 +201,6 @@ module Sequel
187
201
  log_yield(TRANSACTION_COMMIT){conn.commit}
188
202
  end
189
203
 
190
- def disconnect_connection(c)
191
- c.logoff
192
- rescue OCIInvalidHandle
193
- nil
194
- end
195
-
196
204
  def disconnect_error?(e, opts)
197
205
  super || (e.is_a?(::OCIError) && CONNECTION_ERROR_CODES.include?(e.code))
198
206
  end