sequel 5.6.0 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -5099
  3. data/Rakefile +1 -1
  4. data/doc/opening_databases.rdoc +0 -2
  5. data/doc/postgresql.rdoc +31 -0
  6. data/doc/querying.rdoc +2 -2
  7. data/doc/release_notes/5.7.0.txt +108 -0
  8. data/doc/testing.rdoc +1 -0
  9. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  10. data/lib/sequel/adapters/jdbc/oracle.rb +11 -0
  11. data/lib/sequel/adapters/postgres.rb +1 -0
  12. data/lib/sequel/adapters/shared/postgres.rb +117 -13
  13. data/lib/sequel/connection_pool/sharded_threaded.rb +7 -6
  14. data/lib/sequel/connection_pool/threaded.rb +6 -6
  15. data/lib/sequel/core.rb +20 -0
  16. data/lib/sequel/database/logging.rb +3 -2
  17. data/lib/sequel/database/schema_generator.rb +1 -2
  18. data/lib/sequel/dataset/actions.rb +15 -5
  19. data/lib/sequel/extensions/connection_expiration.rb +3 -3
  20. data/lib/sequel/extensions/connection_validator.rb +3 -3
  21. data/lib/sequel/extensions/integer64.rb +30 -0
  22. data/lib/sequel/extensions/migration.rb +2 -3
  23. data/lib/sequel/plugins/pg_array_associations.rb +5 -3
  24. data/lib/sequel/plugins/validate_associated.rb +18 -0
  25. data/lib/sequel/version.rb +1 -1
  26. data/spec/adapters/mssql_spec.rb +6 -6
  27. data/spec/adapters/mysql_spec.rb +1 -1
  28. data/spec/adapters/oracle_spec.rb +15 -1
  29. data/spec/adapters/postgres_spec.rb +78 -1
  30. data/spec/adapters/spec_helper.rb +3 -1
  31. data/spec/bin_spec.rb +1 -0
  32. data/spec/core/dataset_spec.rb +10 -0
  33. data/spec/extensions/integer64_spec.rb +22 -0
  34. data/spec/extensions/pg_array_associations_spec.rb +14 -2
  35. data/spec/extensions/spec_helper.rb +1 -0
  36. data/spec/integration/associations_test.rb +4 -4
  37. data/spec/integration/dataset_test.rb +2 -0
  38. data/spec/integration/spec_helper.rb +5 -11
  39. data/spec/model/spec_helper.rb +1 -0
  40. metadata +35 -165
  41. data/doc/release_notes/1.0.txt +0 -38
  42. data/doc/release_notes/1.1.txt +0 -143
  43. data/doc/release_notes/1.3.txt +0 -101
  44. data/doc/release_notes/1.4.0.txt +0 -53
  45. data/doc/release_notes/1.5.0.txt +0 -155
  46. data/doc/release_notes/2.0.0.txt +0 -298
  47. data/doc/release_notes/2.1.0.txt +0 -271
  48. data/doc/release_notes/2.10.0.txt +0 -328
  49. data/doc/release_notes/2.11.0.txt +0 -215
  50. data/doc/release_notes/2.12.0.txt +0 -534
  51. data/doc/release_notes/2.2.0.txt +0 -253
  52. data/doc/release_notes/2.3.0.txt +0 -88
  53. data/doc/release_notes/2.4.0.txt +0 -106
  54. data/doc/release_notes/2.5.0.txt +0 -137
  55. data/doc/release_notes/2.6.0.txt +0 -157
  56. data/doc/release_notes/2.7.0.txt +0 -166
  57. data/doc/release_notes/2.8.0.txt +0 -171
  58. data/doc/release_notes/2.9.0.txt +0 -97
  59. data/doc/release_notes/3.0.0.txt +0 -221
  60. data/doc/release_notes/3.1.0.txt +0 -406
  61. data/doc/release_notes/3.10.0.txt +0 -286
  62. data/doc/release_notes/3.11.0.txt +0 -254
  63. data/doc/release_notes/3.12.0.txt +0 -304
  64. data/doc/release_notes/3.13.0.txt +0 -210
  65. data/doc/release_notes/3.14.0.txt +0 -118
  66. data/doc/release_notes/3.15.0.txt +0 -78
  67. data/doc/release_notes/3.16.0.txt +0 -45
  68. data/doc/release_notes/3.17.0.txt +0 -58
  69. data/doc/release_notes/3.18.0.txt +0 -120
  70. data/doc/release_notes/3.19.0.txt +0 -67
  71. data/doc/release_notes/3.2.0.txt +0 -268
  72. data/doc/release_notes/3.20.0.txt +0 -41
  73. data/doc/release_notes/3.21.0.txt +0 -87
  74. data/doc/release_notes/3.22.0.txt +0 -39
  75. data/doc/release_notes/3.23.0.txt +0 -172
  76. data/doc/release_notes/3.24.0.txt +0 -420
  77. data/doc/release_notes/3.25.0.txt +0 -88
  78. data/doc/release_notes/3.26.0.txt +0 -88
  79. data/doc/release_notes/3.27.0.txt +0 -82
  80. data/doc/release_notes/3.28.0.txt +0 -304
  81. data/doc/release_notes/3.29.0.txt +0 -459
  82. data/doc/release_notes/3.3.0.txt +0 -192
  83. data/doc/release_notes/3.30.0.txt +0 -135
  84. data/doc/release_notes/3.31.0.txt +0 -146
  85. data/doc/release_notes/3.32.0.txt +0 -202
  86. data/doc/release_notes/3.33.0.txt +0 -157
  87. data/doc/release_notes/3.34.0.txt +0 -671
  88. data/doc/release_notes/3.35.0.txt +0 -144
  89. data/doc/release_notes/3.36.0.txt +0 -245
  90. data/doc/release_notes/3.37.0.txt +0 -338
  91. data/doc/release_notes/3.38.0.txt +0 -234
  92. data/doc/release_notes/3.39.0.txt +0 -237
  93. data/doc/release_notes/3.4.0.txt +0 -325
  94. data/doc/release_notes/3.40.0.txt +0 -73
  95. data/doc/release_notes/3.41.0.txt +0 -155
  96. data/doc/release_notes/3.42.0.txt +0 -74
  97. data/doc/release_notes/3.43.0.txt +0 -105
  98. data/doc/release_notes/3.44.0.txt +0 -152
  99. data/doc/release_notes/3.45.0.txt +0 -179
  100. data/doc/release_notes/3.46.0.txt +0 -122
  101. data/doc/release_notes/3.47.0.txt +0 -270
  102. data/doc/release_notes/3.48.0.txt +0 -477
  103. data/doc/release_notes/3.5.0.txt +0 -510
  104. data/doc/release_notes/3.6.0.txt +0 -366
  105. data/doc/release_notes/3.7.0.txt +0 -179
  106. data/doc/release_notes/3.8.0.txt +0 -151
  107. data/doc/release_notes/3.9.0.txt +0 -233
@@ -1,234 +0,0 @@
1
- = New Features
2
-
3
- * A pg_row extension has been added that supports PostgreSQL's
4
- row-valued/composite types. You can register support for
5
- specific row types:
6
-
7
- DB.register_row_type(:address)
8
-
9
- Then you can create values of that row type:
10
-
11
- ad = DB.row_type(:address, ['555 Foo St.', 'Bar City', '98765'])
12
- # or
13
- ad = DB.row_type(:address, :street=>'555 Foo St.',
14
- :city=>'Bar City', :zip=>'98765')
15
-
16
- Which you can use in your datasets:
17
-
18
- DB[:people].insert(:name=>'Me', :address=>ad)
19
-
20
- If you are using the native postgres adapter, when retreiving
21
- row type values, they will be returned as instances of the row
22
- type, which are hash-like objects:
23
-
24
- ad = DB[:people].get(:address)
25
- ad[:street] # => '555 Foo St.'
26
- ad[:city] # => 'Bar City'
27
- ad[:zip] # => '98765'
28
-
29
- If you are also using the pg_array extension, then arrays of
30
- composite types are supported automatically. Composite
31
- types can also include arrays of other types as well as other
32
- composite types, though recursive composite types are not
33
- allowed by PostgreSQL.
34
-
35
- Using arrays and composite types brings one of the benefits
36
- of document databases to PostgreSQL, allowing you to store
37
- nested structures inside a single row.
38
-
39
- * A pg_row_ops extension has been added that adds DSL support
40
- for accessing members of row-valued/composite types. You
41
- first create a row op:
42
-
43
- r = Sequel.pg_row_op(:row_column)
44
-
45
- Then you can get DSL support for accessing members of that
46
- row_column via the #[] method:
47
-
48
- r[:a] # (row_column).a
49
-
50
- This works with composite types containing composite types:
51
-
52
- r[:a][:b] # ((row_column).a).b
53
-
54
- When used in conjunction with the pg_array_ops extension,
55
- there is support for composite types that include arrays,
56
- as well as arrays of composite types:
57
-
58
- r[1][:a] # (row_column[1]).a
59
- r[:a][1] # (row_column).a[1]
60
-
61
- The extension offers additional support for referencing
62
- a table's type when it contains a column with the same
63
- name, see the RDoc for details.
64
-
65
- * A pg_row plugin has been added, that works with the pg_row
66
- extension, and allows you to represent row-valued types as
67
- Sequel::Model objects (instead of the hash-like objects
68
- they use by default). In your model class, you load the
69
- plugin:
70
-
71
- class Address < Sequel::Model(:address)
72
- plugin :pg_row
73
- end
74
-
75
- Then you can use Address instances in your datasets:
76
-
77
- ad = Address.new(:street=>'555 Foo St.',
78
- :city=>'Bar City', :zip=>'98765')
79
- DB[:people].insert(:name=>'Me', :address=>ad)
80
-
81
- And if you are using the native postgres adapter, the dataset
82
- will return the type as a model instance:
83
-
84
- ad = DB[:people].get(:address)
85
- ad.street # => '555 Foo St.'
86
- ad.city # => 'Bar City'
87
- ad.zip # => '98765'
88
-
89
- * A pg_typecast_on_load plugin has been added. This plugin is
90
- designed for use with the jdbc/postgres, do/postgres, and
91
- swift/postgres adapters, and it is similar to the
92
- typecast_on_load plugin. However, while the typecast_on_load
93
- plugin uses setter methods, the pg_typecast_on_load plugin
94
- uses the same code that the native postgres adapter uses for
95
- typecasting.
96
-
97
- * The tinytds adapter now supports a :textsize option to override
98
- the default TEXTSIZE setting. The FreeTDS default is fairly
99
- small (~64k), so if you want to use large blob or text columns,
100
- you should probably set this to a value larger than the
101
- largest text/blob you want to use.
102
-
103
- * Sequel.expr when called with a symbol now splits the symbol and
104
- returns an Identifier, QualifiedIdentifier, or AliasedExpression,
105
- depending on the content of the symbol. Previously, it only
106
- wrapped the symbol using a Wrapper.
107
-
108
- * Identifier#* and QualifiedIdentifier#* when called without any
109
- argument now represent a selection of all columns from the
110
- represented table:
111
-
112
- Sequel.expr(:table).* # table.*
113
- Sequel.expr(:schema__table).* # schema.table.*
114
-
115
- This makes it easier to represent the selection of all columns
116
- in a table without using the core extensions.
117
-
118
- * Model#values now has a Model#to_hash alias.
119
-
120
- * SQL::Blob values now have as, cast, and lit methods even if the
121
- core extensions are not loaded.
122
-
123
- = Other Improvements
124
-
125
- * When loading multiple pg_* extensions into a Database instance,
126
- the conversion procs are only reset once instead of once per
127
- extension.
128
-
129
- * All adapters that access PostgreSQL now store type conversion
130
- procs, similar to the native postgres adapter. This has been
131
- added to make it easier to write extensions that support
132
- advanced PostgreSQL types.
133
-
134
- * Database#schema output on PostgreSQL now includes the type oid
135
- for each column.
136
-
137
- * You can now register custom array types to specific Database
138
- instances, using the :type_procs and :typecast_methods_module
139
- options, so it is now possible to have custom array types
140
- without affecting global state.
141
-
142
- * Dropping of columns with defaults now works correctly on
143
- Microsoft SQL Server. Before, it would fail as the related
144
- constraint was not dropped first.
145
-
146
- * The MySQL type "double(x,y)" is now recognized as a float type.
147
-
148
- * The jdbc/jtds and jdbc/derby adapters now handle nil prepared
149
- statement values in more cases.
150
-
151
- * Blob prepared statement arguments are now handled correctly on
152
- jdbc/db2 and jdbc/oracle.
153
-
154
- * Sequel now works around a Time#nsec bug in JRuby 1.6 ruby 1.9 mode
155
- when using Time values in prepared statements in the jdbc adapter.
156
-
157
- * Java::JavaUtil::UUID types are now returned as ruby strings
158
- when converting types in the jdbc adapter.
159
-
160
- * Real boolean literals are now used on derby 10.7+. On derby <10.7
161
- Sequel still uses (1 = 1) and (1 != 1) for true and false. This
162
- allows you to use boolean columns with a true/false default on
163
- derby 10.7+.
164
-
165
- * Clobs are now treated as string types instead of blobs on derby,
166
- since treating clob as blob doesn't work there.
167
-
168
- * The swift adapter now supports an output identifier method.
169
-
170
- * The swift adapter now returns blobs as SQL::Blob instances.
171
-
172
- * The schema_dumper extension no longer produces code that requires
173
- the core extensions.
174
-
175
- * All of Sequel's specs now run without the core extensions loaded,
176
- ensuring that none of the internals depend on the core extensions.
177
- The only exception is the specs for the core extensions themselves.
178
-
179
- = Backwards Compatibility
180
-
181
- * The pg_* extensions no longer modify core classes if the
182
- core_extensions extension is not loaded. All methods they added now
183
- have equivalent methods on the main Sequel module:
184
-
185
- Sequel.pg_array
186
- Sequel.pg_array_op
187
- Sequel.hstore
188
- Sequel.hstore_op
189
- Sequel.pg_json
190
- Sequel.pg_range
191
- Sequel.pg_range_op
192
-
193
- * The Sequel::SQL::IdentifierMethods module has been removed. This
194
- module was only included in Symbol if the core_extensions were
195
- enabled. Since it only defined a single method, now the core
196
- extensions just define that method directly on Symbol.
197
-
198
- * The swift adapter now requires swift-db-{postgres,mysql,sqlite3}
199
- gems instead of the swift gem. swift/postgres requires
200
- swift-db-postgres 0.2.0+, swift/sqlite requires swift-db-sqlite
201
- 0.1.2+, and swift/mysql requires swift-db-mysql.
202
-
203
- * Sequel will no longer typecast a string to a PostgreSQL array
204
- or hstore column in a model column setter. This is because the
205
- parsers that Sequel uses were designed to support only
206
- PostgreSQL's output format. It's unlikely that a user would
207
- provide that format for typecasting, and while there aren't known
208
- security issues with the parsers, they were not designed to handle
209
- arbtirary user input, so typecasting from string is no longer
210
- allowed and will now raise an error.
211
-
212
- The only reason such typecasting was allowed in the first place
213
- was to work around issues in the jdbc/postgres, do/postgres, and
214
- swift/postgres adapters, using the the typecast_on_load plugin.
215
- If you were previously using the typecast_on_load plugin for
216
- hstore or array columns, you need to switch to using the new
217
- pg_typecast_on_load plugin.
218
-
219
- * The private get_conversion_procs method in the postgres adapter
220
- no longer accepts an argument.
221
-
222
- * The Sequel::Postgres::PGArray::DatabaseMethods singleton
223
- define_array_typecast_method method has been removed. This
224
- method was designed for internal use.
225
-
226
- * The change to make Sequel.expr split symbols can cause the
227
- following type of code to break:
228
-
229
- Sequel.expr(:column___alias).desc
230
-
231
- This is because expr now returns an AliasedExpression, which
232
- doesn't support the desc method. However, as you can't
233
- apply an order to an aliased expression, nobody should be
234
- relying on this.
@@ -1,237 +0,0 @@
1
- = New Features
2
-
3
- * A constraint_validations extension and plugin have been added,
4
- which allow you to define validations when creating tables,
5
- which are enforced by database constraints, and have those
6
- validations be automatically discovered and used by your
7
- Sequel::Model classes.
8
-
9
- The extension is designed to be used in your migrations/schema
10
- modification code:
11
-
12
- DB.extension(:constraint_validations)
13
- DB.create_constraint_validations_table
14
- DB.create_table(:foos) do
15
- primary_key :id
16
- String :name
17
-
18
- validate do
19
- min_length 5, :name
20
- end
21
- end
22
-
23
- This creates a database CHECK constraint that ensures that the
24
- minimum length for the column is 5 characters. It also adds
25
- metadata about the validation to the
26
- sequel_constraint_validations table.
27
-
28
- To have the model class automatically create validations, just
29
- include the plugin in the model:
30
-
31
- class Foo < Sequel::Model
32
- plugin :constraint_validations
33
- end
34
-
35
- Note that MySQL does not enforce CHECK constraints (it parses
36
- but ignores them), so using the extension on MySQL does not
37
- actually enforce constraints at the database level, though it
38
- still does support the automatic model validations if the plugin
39
- is used.
40
-
41
- * Dataset#count now takes an argument or a virtual row block,
42
- allowing you to do:
43
-
44
- DB[:table].count(:column_name)
45
- DB[:table].count{function_name(column1, column2)}
46
-
47
- When count is given an argument, instead of returning the total
48
- number of rows, it returns the number of rows where the
49
- argument has a non-NULL value.
50
-
51
- * Database#copy_into has been added to the postgres adapter when
52
- the pg driver is being used, and can be used for very fast
53
- inserts into tables if you already have the input preformatted
54
- in PostgreSQL text or CSV format.
55
-
56
- * set_table_not_null has been added to the alter table generator,
57
- for a nicer API:
58
-
59
- alter_table(:t){set_column_not_null :col}
60
- # instead of
61
- alter_table(:t){set_column_allow_null :col, false}
62
-
63
- Additionally, set_column_allow_null now defaults the second
64
- argument to true for a nicer API:
65
-
66
- alter_table(:t){set_column_allow_null :col}
67
- # instead of
68
- alter_table(:t){set_column_allow_null :col, true}
69
-
70
- * Database#supports_regexp? has been added for checking if the
71
- database supports Regexp in filters. Currently, only MySQL and
72
- PostgreSQL support Regexps.
73
-
74
- Attempting to use a Regexp on a database that doesn't support it
75
- now raises an error when attempting to generate the SQL, instead
76
- of sending invalid SQL to the database.
77
-
78
- * Sequel.char_length has been added for a cross platform
79
- char_length function (emulated when char_length is not supported
80
- natively by the database).
81
-
82
- * Sequel.trim has been added for a cross platform trim function
83
- (emulated when trim is not supported natively by the database).
84
-
85
- * ValidationFailed and HookFailed exceptions now have a model method
86
- that returns the model instance related to the exception. This
87
- makes it possible to use Model.create inside a begin/rescue block
88
- and get access to the underlying instance if there is a validation
89
- or before/around hook error.
90
-
91
- * The subclasses plugin now accepts a block, which is called with
92
- each model class created. This is useful if you want to apply
93
- changes to classes created in the future instead of just existing
94
- classes.
95
-
96
- * The validates_unique validation in the validation_helpers plugin
97
- now accepts a :where option for a custom uniqueness filter. Among
98
- other things this makes it easy to implement a case insensitive
99
- uniqueness validation on a case sensitive column.
100
-
101
- * The threaded connection pools now support a
102
- :connection_handling=>:disconnect option, which makes them disconnect
103
- connections after use instead of returning them to the pool. This
104
- makes it possible to completely control connection lifetime using
105
- Database#synchronize.
106
-
107
- * The pg_row_op extension now has support for PGRowOp#*, for referencing
108
- the members of the composite type as separate columns.
109
-
110
- * MySQL's set type and default value are now recognized.
111
-
112
- * bin/sequel now accepts a -c argument for running an arbitrary
113
- code string instead of using an IRB prompt.
114
-
115
- = Other Improvements
116
-
117
- * Sequel now parses current date/timestamp column defaults when
118
- parsing the schema for a table. The values will be returned
119
- as Sequel::CURRENT_DATE for date columns and
120
- Sequel::CURRENT_TIMESTAMP for timestamp columns.
121
-
122
- The schema_dumper extension will work with these defaults, so
123
- if you dump the schema for a table with a column that uses
124
- a current timestamp default, the dumped schema will include
125
- the default.
126
-
127
- The defaults setter plugin also works with these changes, so
128
- that when new model objects are instantiated, they get the
129
- current Date/Time/DateTime values set.
130
-
131
- * On MySQL and PostgreSQL, Sequel will now by default attempt
132
- to combine multiple alter_table operations into a single
133
- query where it believes it can do so correctly. This can
134
- potentially improve performance ~N times, where N is the number
135
- of alter table operations.
136
-
137
- This can change the SQL used for old migrations (though it
138
- shouldn't change the result), and is a potentially risky
139
- change. This may be disabled by default in future versions
140
- if it causes problems.
141
-
142
- * The defaults_setter plugin now correctly sets false default
143
- values.
144
-
145
- * The schema_dumper plugin now preserves fractional seconds
146
- in timestamp column defaults when dumping.
147
-
148
- * Time->DateTime and DateTime->Time typecasts now retain
149
- fractional seconds on ruby 1.8.
150
-
151
- * Array arguments passed to most PGArrayOp methods are now
152
- automatically wrapped in a PGArray. If you want to use this
153
- support, you need to make sure to load both the pg_array
154
- and pg_array_op extensions.
155
-
156
- * Sequel now does a better job of finding the sequence for a
157
- given table on PostgreSQL, handling more corner cases. A small
158
- side effect of this is sometimes sequence names will be quoted.
159
-
160
- * Some potential thread-safety issues when using Sequel with
161
- PostgreSQL on a non-GVL ruby implementation have been fixed.
162
-
163
- * Sequel now correctly caches the server version query on MySQL.
164
-
165
- * Sets of alter_table operations on MySQL and Microsoft SQL Server
166
- that require parsing the current database schema, where later
167
- alter_table operations depend on earlier ones, should now work
168
- correctly.
169
-
170
- * You can now drop check constraints on tables on SQLite, though
171
- doing so drops all check constraints on the table, not only the
172
- specific check constraint given.
173
-
174
- * The identity_map plugin no longer breaks if used with a model
175
- without a primary key.
176
-
177
- * Sequel::SQL::NegativeBooleanConstant now inherits from Constant
178
- instead of BooleanConstant. This means that
179
-
180
- Sequel::NULL == Sequel::NOTNULL
181
-
182
- is now false instead of true.
183
-
184
- * You can now override the convert_tinyint_to_bool settings on a
185
- per-Dataset basis in the mysql and mysql2 adapters, though
186
- the overriding is different depending on the adapter. Check the
187
- commit log for details.
188
-
189
- * timestamp(N) types are now recognized as datetime, which should
190
- fix certain cases on Oracle.
191
-
192
- * Dataset#insert now handles a single model instance argument
193
- as a single value if the model uses the pg_row plugin.
194
-
195
- * When joining a model dataset using a model class as the table
196
- argument, a subselect is used unless the model is a simple select
197
- from the underlying table.
198
-
199
- * The specs now cleanup after themselves, dropping the tables that
200
- they create for testing.
201
-
202
- = Backwards Compatibility
203
-
204
- * The defaults_setter plugin's behavior changed due to the
205
- current date/timestamp support. Previously, it would not set
206
- a value for the column, since the default wasn't recognized.
207
- Therefore, the database would use the default value on insert,
208
- which would be the database's current timestamp.
209
-
210
- Now, the value is set to the current Date/Time/DateTime on
211
- model object instantiation, so the database wouldn't use the
212
- column default. Instead of the database's current timestamp
213
- on insert, the column value will be the application's
214
- current timestamp on model instantiation.
215
-
216
- Users who don't want this behavior can remove the default values
217
- in the model:
218
-
219
- Model.default_values.delete(:column_name)
220
-
221
- * Plain (non-model) datasets no longer allow insert to accept
222
- a single model instance argument. Also, they no longer call
223
- values on a single argument if the object responds to it.
224
-
225
- * Plain (non-model) datasets no longer accept model classes as
226
- tables in the join/graph methods. Also, they no longer call
227
- table_name on the argument if the object responds to it.
228
-
229
- * The schema_dumper extension now requires the eval_inspect
230
- extension, which changes inspect output for
231
- Sequel::SQL::Expression objects.
232
-
233
- * Custom adapters that override Database#alter_table_sql_list now
234
- need to make sure it returns an already flattened array.
235
-
236
- * The identity_map_key method in the identity_map plugin now returns
237
- nil instead of a random string if the given pk is nil.