sequel 3.40.0 → 3.41.0

Sign up to get free protection for your applications and to get access to all the features.
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