sequel 4.42.1 → 4.43.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +35 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/doc/release_notes/4.43.0.txt +87 -0
  6. data/doc/sql.rdoc +26 -27
  7. data/doc/testing.rdoc +2 -0
  8. data/doc/validations.rdoc +1 -1
  9. data/lib/sequel/adapters/ado.rb +5 -0
  10. data/lib/sequel/adapters/cubrid.rb +5 -0
  11. data/lib/sequel/adapters/ibmdb.rb +5 -0
  12. data/lib/sequel/adapters/jdbc.rb +6 -0
  13. data/lib/sequel/adapters/jdbc/derby.rb +5 -0
  14. data/lib/sequel/adapters/jdbc/hsqldb.rb +9 -5
  15. data/lib/sequel/adapters/jdbc/postgresql.rb +1 -1
  16. data/lib/sequel/adapters/jdbc/sqlite.rb +5 -0
  17. data/lib/sequel/adapters/jdbc/transactions.rb +5 -0
  18. data/lib/sequel/adapters/mock.rb +12 -9
  19. data/lib/sequel/adapters/mysql.rb +6 -0
  20. data/lib/sequel/adapters/mysql2.rb +7 -2
  21. data/lib/sequel/adapters/oracle.rb +5 -0
  22. data/lib/sequel/adapters/shared/db2.rb +7 -1
  23. data/lib/sequel/adapters/shared/mssql.rb +5 -0
  24. data/lib/sequel/adapters/shared/mysql.rb +8 -1
  25. data/lib/sequel/adapters/shared/oracle.rb +20 -12
  26. data/lib/sequel/adapters/shared/postgres.rb +11 -2
  27. data/lib/sequel/adapters/shared/sqlanywhere.rb +6 -0
  28. data/lib/sequel/adapters/shared/sqlite.rb +29 -0
  29. data/lib/sequel/adapters/sqlanywhere.rb +5 -0
  30. data/lib/sequel/adapters/sqlite.rb +13 -0
  31. data/lib/sequel/connection_pool/sharded_single.rb +5 -0
  32. data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
  33. data/lib/sequel/connection_pool/single.rb +15 -6
  34. data/lib/sequel/database/dataset.rb +3 -0
  35. data/lib/sequel/database/misc.rb +22 -1
  36. data/lib/sequel/database/query.rb +2 -4
  37. data/lib/sequel/dataset/actions.rb +0 -1
  38. data/lib/sequel/dataset/misc.rb +2 -4
  39. data/lib/sequel/dataset/query.rb +23 -6
  40. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  41. data/lib/sequel/extensions/_model_pg_row.rb +47 -0
  42. data/lib/sequel/extensions/looser_typecasting.rb +2 -0
  43. data/lib/sequel/extensions/migration.rb +12 -1
  44. data/lib/sequel/extensions/pg_array.rb +6 -0
  45. data/lib/sequel/extensions/pg_enum.rb +2 -1
  46. data/lib/sequel/extensions/pg_range.rb +6 -0
  47. data/lib/sequel/extensions/pg_row.rb +8 -0
  48. data/lib/sequel/model/associations.rb +3 -1
  49. data/lib/sequel/model/base.rb +14 -3
  50. data/lib/sequel/plugins/constraint_validations.rb +1 -8
  51. data/lib/sequel/plugins/instance_filters.rb +1 -1
  52. data/lib/sequel/plugins/pg_row.rb +1 -40
  53. data/lib/sequel/plugins/prepared_statements.rb +51 -20
  54. data/lib/sequel/plugins/prepared_statements_associations.rb +22 -4
  55. data/lib/sequel/plugins/prepared_statements_with_pk.rb +9 -1
  56. data/lib/sequel/plugins/sharding.rb +5 -0
  57. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  58. data/lib/sequel/version.rb +2 -2
  59. data/spec/adapters/spec_helper.rb +4 -0
  60. data/spec/core/connection_pool_spec.rb +10 -0
  61. data/spec/core/database_spec.rb +29 -0
  62. data/spec/extensions/blacklist_security_spec.rb +4 -4
  63. data/spec/extensions/defaults_setter_spec.rb +1 -1
  64. data/spec/extensions/force_encoding_spec.rb +3 -2
  65. data/spec/extensions/identifier_mangling_spec.rb +7 -0
  66. data/spec/extensions/instance_filters_spec.rb +1 -0
  67. data/spec/extensions/migration_spec.rb +19 -0
  68. data/spec/extensions/pg_array_spec.rb +5 -0
  69. data/spec/extensions/pg_range_spec.rb +5 -0
  70. data/spec/extensions/pg_row_spec.rb +9 -0
  71. data/spec/extensions/prepared_statements_associations_spec.rb +45 -1
  72. data/spec/extensions/prepared_statements_spec.rb +138 -41
  73. data/spec/extensions/prepared_statements_with_pk_spec.rb +7 -0
  74. data/spec/extensions/serialization_spec.rb +6 -6
  75. data/spec/extensions/single_table_inheritance_spec.rb +3 -3
  76. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  77. data/spec/integration/associations_test.rb +2 -2
  78. data/spec/integration/dataset_test.rb +0 -4
  79. data/spec/integration/eager_loader_test.rb +5 -5
  80. data/spec/integration/plugin_test.rb +8 -6
  81. data/spec/integration/schema_test.rb +2 -2
  82. data/spec/integration/spec_helper.rb +10 -0
  83. data/spec/integration/timezone_test.rb +1 -1
  84. data/spec/integration/transaction_test.rb +5 -5
  85. data/spec/model/associations_spec.rb +13 -6
  86. data/spec/model/base_spec.rb +1 -1
  87. data/spec/model/hooks_spec.rb +4 -4
  88. data/spec/model/model_spec.rb +2 -2
  89. data/spec/model/record_spec.rb +17 -18
  90. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d84f8a9b0d5ee524d044add19f1c9adca2c642a
4
- data.tar.gz: 5139deab1c3ddfc8e6a9482f8f711d86f35ab261
3
+ metadata.gz: f5f04eb2ea922da521a4e67f1cf8fd4346d034df
4
+ data.tar.gz: 39ea6ce91593a98832c7e53c03c4ec1ea5607fb8
5
5
  SHA512:
6
- metadata.gz: 12202167088c4caef4db81fc6fa6ed35d2104dc993f1be93d45984b887ba9b698395e576be6537457f2cf8123abed75c85175fa1193e5ef7d3c313584908be06
7
- data.tar.gz: 9a4d6933538023d4d7b0ea38c18b317557e01a1c2df0391e9a06a8732ac1d9a1f7525e82fe338ff57052c93973a8f979c757c2bcc1730df9f22ad3f28abad665
6
+ metadata.gz: e449fabbb5ec97c98df590e9afcd6378e392513509dfcb95fbc503cf668029bf31a3e120adf906af3040c695e7998f8ab24d7883409965379ef242498b988b3f
7
+ data.tar.gz: 2829985707e14c79044a296d34fa62300053e1a279f232da1aa08cd93217eb001ccb78117c049a287b6c370091b8dfb1b5e3a7424d18fdff5ff289081fa2ec58
data/CHANGELOG CHANGED
@@ -1,7 +1,41 @@
1
- === 4.42.1 (2017-01-12)
1
+ === 4.43.0 (2017-02-01)
2
+
3
+ * Make jdbc/postgresql adapter work if pg_hstore extension is loaded first (jeremyevans) (#1296)
4
+
5
+ * Make prepared_statements_associations plugin work correctly on some instance specific associations (jeremyevans)
6
+
7
+ * Make prepared_statements plugin not use prepared statements in cases where it is probably slower (jeremyevans)
8
+
9
+ * Optimize Model#refresh similar to Model.with_pk (jeremyevans)
10
+
11
+ * Make Database#extension not attempt to load the same extension more than once (jeremyevans)
12
+
13
+ * Implement Database#freeze such that it can be used in production (jeremyevans)
14
+
15
+ * Freeze enum_labels in the pg_enum extension (jeremyevans)
16
+
17
+ * Handle Database#type_supported? thread-safely on PostgreSQL (jeremyevans)
18
+
19
+ * Handle primary_key_sequences thread-safely on Oracle (jeremyevans)
20
+
21
+ * Handle sharding better when using mysql2 native prepared statements (jeremyevans)
22
+
23
+ * Use thread-safe incrementor for mock adapter autoid handling (jeremyevans)
24
+
25
+ * Make Model#freeze not freeze associations hash until after validating the model instance (jeremyevans)
26
+
27
+ * Make prepared_statements_associations plugin work correctly when model object explicitly specifies server to use when also using sharding plugin (jeremyevans)
28
+
29
+ * Make prepared_statements_with_pk plugin work correctly when dataset explicitly specifies server to use (jeremyevans)
30
+
31
+ * Make prepared_statements plugin work correctly when model object explicitly specifies server to use (jeremyevans)
2
32
 
3
33
  * Make dataset_module inherited to subclasses when using the single_table_inheritance plugin (jeremyevans) (#1284)
4
34
 
35
+ * Support use of SQLite result codes in the jdbc-sqlite adapter, if the jdbc sqlite driver supports them (flash-gordon, jeremyevans) (#1283)
36
+
37
+ * Make timestamp migrator handle key length limitations when using MySQL with InnoDB engine and utf8mb4 charset default (jeremyevans) (#1282)
38
+
5
39
  === 4.42.0 (2017-01-01)
6
40
 
7
41
  * Handle eager load callbacks correctly for one_to_one associations with orders or offsets when window functions are not supported (jeremyevans)
@@ -1,5 +1,5 @@
1
1
  Copyright (c) 2007-2008 Sharon Rosner
2
- Copyright (c) 2008-2016 Jeremy Evans
2
+ Copyright (c) 2008-2017 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
@@ -175,7 +175,7 @@ You can retrieve all records by using the +all+ method:
175
175
  posts.all
176
176
  # SELECT * FROM posts
177
177
 
178
- The all method returns an array of hashes, where each hash corresponds to a record.
178
+ The +all+ method returns an array of hashes, where each hash corresponds to a record.
179
179
 
180
180
  You can also iterate through records one at a time using +each+:
181
181
 
@@ -318,7 +318,7 @@ You can also specify descending order:
318
318
 
319
319
  === Core Extensions
320
320
 
321
- Note the use of <tt>Sequel.desc(:stamp)</tt> in the above example. Much of Sequel's DSL uses this style, calling methods on the Sequel module that return SQL expression objects. Sequel also ships with a {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc]) that integrates Sequel's DSL better into the ruby language, allowing you to write:
321
+ Note the use of <tt>Sequel.desc(:stamp)</tt> in the above example. Much of Sequel's DSL uses this style, calling methods on the Sequel module that return SQL expression objects. Sequel also ships with a {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc] that integrates Sequel's DSL better into the Ruby language, allowing you to write:
322
322
 
323
323
  :stamp.desc
324
324
 
@@ -749,7 +749,7 @@ Associations can be eagerly loaded via +eager+ and the <tt>:eager</tt> associati
749
749
 
750
750
  In addition to using +eager+, you can also use +eager_graph+, which will use a single query to get the object and all associated objects. This may be necessary if you want to filter or order the result set based on columns in associated tables. It works with cascading as well, the API is very similar. Note that using +eager_graph+ to eagerly load multiple <tt>*_to_many</tt> associations will cause the result set to be a cartesian product, so you should be very careful with your filters when using it in that case.
751
751
 
752
- You can dynamically customize the eagerly loaded dataset by using using a proc. This proc is passed the dataset used for eager loading, and should return a modified copy of that dataset:
752
+ You can dynamically customize the eagerly loaded dataset by using a proc. This proc is passed the dataset used for eager loading, and should return a modified copy of that dataset:
753
753
 
754
754
  # Eagerly load only replies containing 'foo'
755
755
  Post.eager(:replies=>proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
@@ -765,7 +765,7 @@ You can dynamically customize eager loads for both +eager+ and +eager_graph+ whi
765
765
 
766
766
  === Joining with Associations
767
767
 
768
- You can use the association_join method to add a join to the model's dataset based on the assocation:
768
+ You can use the +association_join+ method to add a join to the model's dataset based on the assocation:
769
769
 
770
770
  Post.association_join(:author)
771
771
  # SELECT * FROM posts
@@ -0,0 +1,87 @@
1
+ = New Features
2
+
3
+ * Database#freeze has now been implemented. It is now recommended
4
+ to use it in production and during testing, after loading
5
+ extensions and making other changes to Database state. Once frozen,
6
+ the Database settings cannot be modified, but the Database can
7
+ execute queries and return results. By freezing the Database, you
8
+ gain greater thread-safety assurance and will be alerted via an
9
+ exception if runtime code attempts to modify Database state.
10
+
11
+ = Other Improvements
12
+
13
+ * Model#refresh now uses the same optimization that Model.with_pk
14
+ uses, resulting in faster refreshing for most models.
15
+
16
+ * The prepared_statements plugin no longer automatically uses
17
+ prepared statements in cases where it is likely to be slower.
18
+ Now, prepared statements are only used by default for INSERT
19
+ and UPDATE statements (and DELETE on Oracle and DB2). This
20
+ change was made after benchmarking showed that using prepared
21
+ statements for primary key lookups, refreshes, and deletes is
22
+ significantly slower than non-prepared statements across almost
23
+ all adapters.
24
+
25
+ * Database#extension no longer attempts to load the same extension
26
+ more than once.
27
+
28
+ * The timestamp migrator now handles key length limitations when
29
+ using MySQL with InnoDB engine and utf8mb4 charset default.
30
+
31
+ * The jdbc/sqlite adapter will now use SQLite result codes for
32
+ more accurate exception types, if the jdbc-sqlite driver
33
+ supports them.
34
+
35
+ * dataset_module is now inherited correctly if using the
36
+ single_table_inheritance plugin. This was broken in 4.42.0,
37
+ and fixed in 4.42.1.
38
+
39
+ * The prepared_statements plugin now respects a server specified
40
+ for the model instance, instead of always using the default
41
+ server.
42
+
43
+ * The prepared_statements_associations plugin now respects a
44
+ server specified for the model instance if using the sharding
45
+ plugin, instead of always using the default server.
46
+
47
+ * The prepared_statements_associations plugin now works correctly
48
+ when using some instance-specific associations, such as
49
+ many_to_one associations using a nil :key option.
50
+
51
+ * The prepared_statements_with_pk plugin now respects a server
52
+ specified for the dataset, instead of always using the default
53
+ server.
54
+
55
+ * Model#freeze now freezes the associations hash after validating
56
+ the model instance, instead of before, fixing cases where
57
+ validation calls association methods.
58
+
59
+ * Sequel no longer continually tries to determine the server
60
+ version on HSQLDB, if the first attempt fails.
61
+
62
+ * The mock adapter now uses a thread-safe incrementor for autoid.
63
+
64
+ * Mysql2 native prepared statement support now better handles
65
+ sharding where connection options differ per shard.
66
+
67
+ * On Oracle, Database#sequence_for_table is now thread-safe.
68
+
69
+ * On PostgreSQL, Database#type_supported? is now thread-safe.
70
+
71
+ * On MySQL, Database#supports_timestamp_usecs? now correctly
72
+ memoizes false values.
73
+
74
+ * The jdbc/postgresql adapter now works correctly if the
75
+ pg_hstore extension is loaded first.
76
+
77
+ = Backwards Compatibility
78
+
79
+ * Maintainers of external adapters and Database extensions
80
+ should update their code to support Database#freeze.
81
+
82
+ * Code that relies on Database extensions being loaded multiple
83
+ times if called multiple times needs to be updated, because
84
+ now the extension only gets loaded the first time
85
+ Database#extension is called.
86
+
87
+ * @enum_labels in the pg_enum extension is now frozen by default.
@@ -14,7 +14,7 @@ For SELECT queries, you should probably use <tt>Database#fetch</tt> with a strin
14
14
  puts row[:name]
15
15
  end
16
16
 
17
- <tt>Database#fetch</tt> will take the query you give it, execute it on the database, and yield a hash with column symbol keys for each row returned. If you want to use some placeholder variables, you can set the placeholders with ? and add the arguments to fetch:
17
+ <tt>Database#fetch</tt> will take the query you give it, execute it on the database, and yield a hash with column symbol keys for each row returned. If you want to use some placeholder variables, you can set the placeholders with ? and add the corresponding arguments to +fetch+:
18
18
 
19
19
  DB.fetch("SELECT * FROM albums WHERE name LIKE ?", 'A%') do |row|
20
20
  puts row[:name]
@@ -26,9 +26,9 @@ You can also use named placeholders by starting the placeholder with a colon, an
26
26
  puts row[:name]
27
27
  end
28
28
 
29
- This can be helpful for long queries where it is difficult to match the ? with the arguments.
29
+ This can be helpful for long queries where it is difficult to match the question marks in the query with the arguments.
30
30
 
31
- What Sequel actually does internally is two separate things. It first creates a dataset representing the query, and then it executes the dataset's SQL code to retrieve the objects. Often, you want to define a dataset at some point, but not execute it till later. You can do this by leaving off the block, and storing the dataset in a variable:
31
+ What Sequel actually does internally is two separate things. It first creates a dataset representing the query, and then it executes the dataset's SQL code to retrieve the objects. Often, you want to define a dataset at some point, but not execute it until later. You can do this by leaving off the block, and storing the dataset in a variable:
32
32
 
33
33
  ds = DB.fetch("SELECT * FROM albums")
34
34
 
@@ -41,7 +41,7 @@ You should note that <tt>Database#[]</tt> calls <tt>Database#fetch</tt> if a str
41
41
  ds = DB["SELECT * FROM albums"]
42
42
  ds.each{|r| puts r[:name]}
43
43
 
44
- However, note that <tt>Database#[]</tt> cannot take a block directly, you have to call +each+ on the returned dataset. There are plenty of other methods besides +each+, one is +all+ which returns all records as an array:
44
+ However, note that <tt>Database#[]</tt> cannot take a block directly, you have to call +each+ on the returned dataset. There are plenty of other methods besides +each+. For example, the +all+ method returns all records in the dataset as an array:
45
45
 
46
46
  DB["SELECT * FROM albums"].all # [{:id=>1, :name=>'RF', ...}, ...]
47
47
 
@@ -78,7 +78,7 @@ Almost everywhere in Sequel, you can drop down to literal SQL by providing a lit
78
78
  DB[:albums].select('name') # SELECT 'name' FROM albums
79
79
  DB[:albums].select(Sequel.lit('name')) # SELECT name FROM albums
80
80
 
81
- For a simpler way of creating literal strings, you can also use the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc], which adds the <tt>String#lit</tt> method, and other methods that integrate Sequel's DSL with the ruby language:
81
+ For a simpler way of creating literal strings, you can also use the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc], which adds the <tt>String#lit</tt> method, and other methods that integrate Sequel's DSL with the Ruby language:
82
82
 
83
83
  DB[:albums].select('name'.lit)
84
84
 
@@ -113,7 +113,7 @@ Now that you know how to see what SQL is being used, let's jump in and see how t
113
113
 
114
114
  === Identifiers
115
115
 
116
- In Sequel, SQL identifiers are usually specified as ruby symbols:
116
+ In Sequel, SQL identifiers are usually specified as Ruby symbols:
117
117
 
118
118
  :column # "column"
119
119
 
@@ -121,7 +121,7 @@ As you can see, Sequel quotes identifiers by default. Depending on your databas
121
121
 
122
122
  :column # "COLUMN" on some databases
123
123
 
124
- A plain symbol is usually treated as an unqualified identifier. However, if you are using multiple tables in a query, and you want to reference a column in one of the tables that has the same name as a column in another one of the tables, you need to qualify that reference. There's two main ways in Sequel to do that. The first is implicit qualification inside the symbol, using the double underscore:
124
+ A plain symbol is usually treated as an unqualified identifier. However, if you are using multiple tables in a query, and you want to reference a column in one of the tables that has the same name as a column in another one of the tables, you need to qualify that reference. There are two main ways in Sequel to do that. The first is implicit qualification inside the symbol, using the double underscore:
125
125
 
126
126
  :table__column # "table"."column"
127
127
 
@@ -135,8 +135,7 @@ Also note that specifying the period inside the symbol doesn't work if you are q
135
135
 
136
136
  :"table.column" # "table.column"
137
137
 
138
- A couple other ways two create a qualified identifier are to use <tt>Sequel.[]</tt> to create an identifier,
139
- and call <tt>[]</tt> or +qualify+ on that, or to use the <tt>Sequel.qualify</tt> with the table and column symbols:
138
+ The second way is to explicitly create a qualified identifier either by using <tt>Sequel.[]</tt> to create an identifier and call <tt>[]</tt> or +qualify+ on that, or by using the <tt>Sequel.qualify</tt> method with the table and column symbols:
140
139
 
141
140
  Sequel[:table][:column] # "table"."column"
142
141
  Sequel[:column].qualify(:table) # "table"."column"
@@ -153,7 +152,7 @@ You can also use the symbol_aref extension for creating qualified identifiers:
153
152
 
154
153
  === Numbers
155
154
 
156
- In general, ruby numbers map directly to SQL numbers:
155
+ In general, Ruby numbers map directly to SQL numbers:
157
156
 
158
157
  # Integers
159
158
  1 # 1
@@ -167,7 +166,7 @@ In general, ruby numbers map directly to SQL numbers:
167
166
 
168
167
  === Strings
169
168
 
170
- In general, ruby strings map directly to SQL strings:
169
+ In general, Ruby strings map directly to SQL strings:
171
170
 
172
171
  'name' # 'name'
173
172
  "name" # 'name'
@@ -182,7 +181,7 @@ You can combine this with implicit qualification:
182
181
 
183
182
  :table__column___alias # "table"."column" AS "alias"
184
183
 
185
- As with creating qualified identifiers via a double underscore, This works by default, but it is possible to turn off by setting <tt>Sequel.split_symbols = false</tt>.
184
+ As with creating qualified identifiers via a double underscore, this works by default, but it is possible to turn off by setting <tt>Sequel.split_symbols = false</tt>.
186
185
 
187
186
  You can also use the <tt>Sequel.as</tt> method to create an alias, and the +as+ method on most Sequel-specific expression objects:
188
187
 
@@ -216,7 +215,7 @@ Aggregate functions work the same way as normal functions, since they share the
216
215
 
217
216
  Sequel.function(:sum, :column) # sum(column)
218
217
 
219
- To use the DISTINCT modifier to an aggregate function, call the distinct method on the function:
218
+ To use the DISTINCT modifier to an aggregate function, call the +distinct+ method on the function:
220
219
 
221
220
  DB[:albums].select{sum(:column).distinct} # SELECT sum(DISTINCT column) FROM albums
222
221
 
@@ -229,7 +228,7 @@ Note that Sequel provides helper methods for aggregate functions such as +count+
229
228
 
230
229
  === Window Functions
231
230
 
232
- If the database supports window functions, Sequel can handle them by calling the over method on a Function:
231
+ If the database supports window functions, Sequel can handle them by calling the +over+ method on a Function:
233
232
 
234
233
  DB[:albums].select{function.function.over}
235
234
  # SELECT function() OVER () FROM albums
@@ -245,7 +244,7 @@ If the database supports window functions, Sequel can handle them by calling the
245
244
 
246
245
  === Schema Qualified Functions
247
246
 
248
- If the database supports schema qualified functions, Sequel can handle them by calling the function method on a QuailfiedIdentifier:
247
+ If the database supports schema qualified functions, Sequel can handle them by calling the +function+ method on a QuailfiedIdentifier:
249
248
 
250
249
  DB[:albums].select{schema[:function].function}
251
250
  # SELECT schema.function() FROM albums
@@ -285,7 +284,7 @@ You can specify a not equals condition by inverting the hash or array of two ele
285
284
  Sequel.~(:column => 1) # ("column" != 1)
286
285
  Sequel.~([[:column, 1]]) # ("column" != 1)
287
286
 
288
- The difference between the two is that negate only works on hashes and arrays of element arrays, and it negates all entries in the hash or array, while ~ does a general inversion. This is best shown by an example with multiple entries:
287
+ The difference between the two is that +negate+ only works on hashes and arrays of element arrays, and it negates all entries in the hash or array, while ~ does a general inversion. This is best shown by an example with multiple entries:
289
288
 
290
289
  Sequel.negate(:column => 1, :foo => 2) # (("column" != 1) AND (foo != 2))
291
290
  Sequel.~(:column => 1, :foo => 2) # (("column" != 1) OR (foo != 2))
@@ -330,7 +329,7 @@ Sequel also supports the SQL EXISTS operator using <tt>Dataset#exists</tt>:
330
329
 
331
330
  === Identity Operators (IS, IS NOT)
332
331
 
333
- Hashes in Sequel use IS if the value is true, false, or nil:
332
+ Hashes in Sequel use IS if the value is +true+, +false+, or +nil+:
334
333
 
335
334
  {:column=>nil} # ("column" IS NULL)
336
335
  {:column=>true} # ("column" IS TRUE)
@@ -394,7 +393,7 @@ You can also call the operator methods directly on the Sequel module:
394
393
  Sequel./(:column, 1) # "column" / 1
395
394
  Sequel.**(:column, 1) # power("column", 1)
396
395
 
397
- Note that since Sequel implements support for ruby's coercion protocol, the following also works:
396
+ Note that since Sequel implements support for Ruby's coercion protocol, the following also works:
398
397
 
399
398
  1 + Sequel[:column]
400
399
  1 - Sequel[:table][:column]
@@ -416,7 +415,7 @@ is parsed as:
416
415
 
417
416
  Sequel.function(:func) > (1 & :column3)
418
417
 
419
- You and also use the <tt>Sequel.&</tt> and <tt>Sequel.|</tt> methods:
418
+ You can also use the <tt>Sequel.&</tt> and <tt>Sequel.|</tt> methods:
420
419
 
421
420
  Sequel.&(:column1, :column2) # ("column1" AND "column2")
422
421
  Sequel.|({:column1=>1}, {:column2=>2}) # (("column1" = 1) OR ("column2" = 2))
@@ -482,7 +481,7 @@ Sequel allows the use of the string concatenation operator on Sequel::SQL::Strin
482
481
 
483
482
  Sequel[:name].sql_string + ' - Name' # ("name" || ' - Name')
484
483
 
485
- Just like for the bitwise operators, Sequel allows you do do the cast and conversion at the same time via +cast_string+:
484
+ Just like for the bitwise operators, Sequel allows you to do the cast and conversion at the same time via +cast_string+:
486
485
 
487
486
  Sequel[:number].cast_string + ' - Number' # (CAST(number AS varchar(255)) || ' - Number')
488
487
 
@@ -498,7 +497,7 @@ The <tt>Sequel.join</tt> method concatenates all of the elements in the array:
498
497
 
499
498
  Sequel.join(['Name', :name]) # ('Name' || "name")
500
499
 
501
- Just like ruby's <tt>String#join</tt>, you can provide an argument for a string used to join each element:
500
+ Just like Ruby's <tt>String#join</tt>, you can provide an argument for a string used to join each element:
502
501
 
503
502
  Sequel.join(['Name', :name], ' - ') # ('Name' || ' - ' || "name")
504
503
 
@@ -512,13 +511,13 @@ You can also use the <tt>Sequel.like</tt> and <tt>Sequel.ilike</tt> methods:
512
511
  Sequel.like(:name, 'A%') # ("name" LIKE 'A%' ESCAPE '\')
513
512
  Sequel.ilike(:name, 'A%') # ("name" ILIKE 'A%' ESCAPE '\')
514
513
 
515
- Note the above syntax for ilike, while Sequel's default, is specific to PostgreSQL. However, most other adapters override the behavior. For example, on MySQL, Sequel uses LIKE BINARY for +like+, and LIKE for +ilike+. If the database supports both case sensitive and case insensitive LIKE, then +like+ will use a case sensitive LIKE, and +ilike+ will use a case insensitive LIKE.
514
+ Note the above syntax for +ilike+, while Sequel's default, is specific to PostgreSQL. However, most other adapters override the behavior. For example, on MySQL, Sequel uses LIKE BINARY for +like+, and LIKE for +ilike+. If the database supports both case sensitive and case insensitive LIKE, then +like+ will use a case sensitive LIKE, and +ilike+ will use a case insensitive LIKE.
516
515
 
517
516
  Inverting the LIKE operator works like other inversions:
518
517
 
519
518
  ~Sequel.like(:name, 'A%') # ("name" NOT LIKE 'A%' ESCAPE '\')
520
519
 
521
- Sequel also supports SQL regular expressions on MySQL and PostgreSQL. You can use these by passing a ruby regular expression to +like+ or +ilike+, or by making the regular expression a hash value:
520
+ Sequel also supports SQL regular expressions on MySQL and PostgreSQL. You can use these by passing a Ruby regular expression to +like+ or +ilike+, or by making the regular expression a hash value:
522
521
 
523
522
  Sequel.like(:name, /^A/) # ("name" ~ '^A')
524
523
  ~Sequel.ilike(:name, /^A/) # ("name" !~* '^A')
@@ -552,7 +551,7 @@ To select all columns in a table, Sequel supports the * method on identifiers wi
552
551
 
553
552
  === CASE statements
554
553
 
555
- Sequel allows the easy production of SQL CASE statements using the <tt>Sequel.case</tt> method. The first argument is a hash or array of two element arrays representing the conditions, the second argument is the default value (ELSE). The keys of the hash (or first element in each array) is the WHEN condition, and the values of the hash (or second element in each array) is the THEN result. Here are some examples:
554
+ Sequel allows the easy production of SQL CASE statements using the <tt>Sequel.case</tt> method. The first argument is a hash or array of two element arrays representing the conditions, the second argument is the default value (ELSE). The keys of the hash (or first element in each array) is the WHEN condition, and the values of the hash (or second element in each array) is the THEN result. Here are some examples:
556
555
 
557
556
  Sequel.case({:column=>1}, 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
558
557
  Sequel.case([[column, 1]], 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
@@ -588,7 +587,7 @@ In Sequel, the SQL queries are build with method chaining.
588
587
 
589
588
  === Creating Datasets
590
589
 
591
- You generally start by creating a dataset by calling <tt>Dataset#[]</tt> with a symbol specifying the table name:
590
+ You generally start creating a dataset by calling <tt>Dataset#[]</tt> with a symbol specifying the table name:
592
591
 
593
592
  DB[:albums] # SELECT * FROM albums
594
593
 
@@ -596,7 +595,7 @@ If you want to select from multiple FROM tables, use multiple arguments:
596
595
 
597
596
  DB[:albums, :artists] # SELECT * FROM albums, artists
598
597
 
599
- If you don't want to select from any FROM tables, just call dataset:
598
+ If you don't want to select from any FROM tables, just call +dataset+:
600
599
 
601
600
  DB.dataset # SELECT *
602
601
 
@@ -630,7 +629,7 @@ In general, the +insert+, +update+, and +delete+ methods use the appropriate cla
630
629
  ds.update(:name=>'RF') # UPDATE albums SET name = 'RF' WHERE (id = 1)
631
630
  ds.delete # DELETE FROM albums WHERE (id = 1)
632
631
 
633
- Note how +update+ and +delete+ used the +where+ argument, but that +insert+ did not, because INSERT doesn't use a WHERE clause.
632
+ Note how +update+ and +delete+ used the +where+ argument, but +insert+ did not, because INSERT doesn't use a WHERE clause.
634
633
 
635
634
  === Methods Used for Each SQL Clause
636
635
 
@@ -157,6 +157,8 @@ SEQUEL_CONNECTION_VALIDATOR :: Use the connection validator extension when runni
157
157
  SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
158
158
  SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
159
159
  SEQUEL_FREEZE_DATASETS :: Use the freeze_datasets extension when running the specs
160
+ SEQUEL_FREEZE_DATABASE :: Freeze the database before running the integration specs
161
+ SEQUEL_MODEL_PREPARED_STATEMENTS :: Use the prepared_statements and prepared_statements_associations plugins when running the specs
160
162
  SEQUEL_NO_AUTO_LITERAL_STRINGS :: Use the no_auto_string_literals extension when running the specs
161
163
  SEQUEL_NO_CACHE_ASSOCIATIONS :: Don't cache association metadata when running the specs
162
164
  SEQUEL_NO_CHECK_SQLS :: Don't check for specific SQL syntax when running the specs
@@ -153,7 +153,7 @@ You can call simple methods such as:
153
153
  end
154
154
  end
155
155
 
156
- Other than +validates_unique+, which has it's own API, the methods defined by
156
+ Other than +validates_unique+, which has its own API, the methods defined by
157
157
  +validation_helpers+ have one of the following two APIs:
158
158
 
159
159
  <tt>(atts, opts={})</tt>:: For methods such as +validates_presence+, which do not
@@ -127,6 +127,11 @@ module Sequel
127
127
  nil
128
128
  end
129
129
 
130
+ def freeze
131
+ @conversion_procs.freeze
132
+ super
133
+ end
134
+
130
135
  # Just execute so it doesn't attempt to return the number of rows modified.
131
136
  def execute_ddl(sql, opts=OPTS)
132
137
  execute(sql, opts)
@@ -89,6 +89,11 @@ module Sequel
89
89
  execute(sql, opts.merge(:type=>:insert))
90
90
  end
91
91
 
92
+ def freeze
93
+ server_version
94
+ super
95
+ end
96
+
92
97
  private
93
98
 
94
99
  def begin_transaction(conn, opts=OPTS)
@@ -264,6 +264,11 @@ module Sequel
264
264
  end
265
265
  end
266
266
 
267
+ def freeze
268
+ @conversion_procs.freeze
269
+ super
270
+ end
271
+
267
272
  private
268
273
 
269
274
  # Execute the given SQL on the database.