sequel 3.48.0 → 4.0.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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +114 -0
  3. data/Rakefile +10 -7
  4. data/doc/association_basics.rdoc +25 -23
  5. data/doc/code_order.rdoc +7 -0
  6. data/doc/core_extensions.rdoc +0 -10
  7. data/doc/object_model.rdoc +4 -1
  8. data/doc/querying.rdoc +3 -3
  9. data/doc/release_notes/4.0.0.txt +262 -0
  10. data/doc/security.rdoc +0 -28
  11. data/doc/testing.rdoc +8 -14
  12. data/lib/sequel/adapters/ado.rb +7 -11
  13. data/lib/sequel/adapters/ado/access.rb +8 -8
  14. data/lib/sequel/adapters/ado/mssql.rb +4 -4
  15. data/lib/sequel/adapters/amalgalite.rb +6 -6
  16. data/lib/sequel/adapters/cubrid.rb +7 -7
  17. data/lib/sequel/adapters/db2.rb +5 -9
  18. data/lib/sequel/adapters/dbi.rb +2 -6
  19. data/lib/sequel/adapters/do.rb +4 -4
  20. data/lib/sequel/adapters/firebird.rb +4 -4
  21. data/lib/sequel/adapters/ibmdb.rb +8 -8
  22. data/lib/sequel/adapters/informix.rb +2 -10
  23. data/lib/sequel/adapters/jdbc.rb +17 -17
  24. data/lib/sequel/adapters/jdbc/as400.rb +2 -2
  25. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
  26. data/lib/sequel/adapters/jdbc/db2.rb +1 -1
  27. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  28. data/lib/sequel/adapters/jdbc/h2.rb +2 -2
  29. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
  30. data/lib/sequel/adapters/jdbc/informix.rb +1 -1
  31. data/lib/sequel/adapters/jdbc/mssql.rb +2 -2
  32. data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
  33. data/lib/sequel/adapters/jdbc/oracle.rb +5 -1
  34. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -3
  35. data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
  36. data/lib/sequel/adapters/jdbc/transactions.rb +3 -3
  37. data/lib/sequel/adapters/mock.rb +7 -7
  38. data/lib/sequel/adapters/mysql.rb +3 -3
  39. data/lib/sequel/adapters/mysql2.rb +4 -4
  40. data/lib/sequel/adapters/odbc.rb +2 -6
  41. data/lib/sequel/adapters/odbc/mssql.rb +1 -1
  42. data/lib/sequel/adapters/openbase.rb +1 -5
  43. data/lib/sequel/adapters/oracle.rb +13 -17
  44. data/lib/sequel/adapters/postgres.rb +20 -25
  45. data/lib/sequel/adapters/shared/cubrid.rb +3 -3
  46. data/lib/sequel/adapters/shared/db2.rb +2 -2
  47. data/lib/sequel/adapters/shared/firebird.rb +7 -7
  48. data/lib/sequel/adapters/shared/mssql.rb +9 -9
  49. data/lib/sequel/adapters/shared/mysql.rb +29 -13
  50. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +7 -7
  51. data/lib/sequel/adapters/shared/oracle.rb +22 -13
  52. data/lib/sequel/adapters/shared/postgres.rb +61 -46
  53. data/lib/sequel/adapters/shared/sqlite.rb +9 -9
  54. data/lib/sequel/adapters/sqlite.rb +17 -11
  55. data/lib/sequel/adapters/swift.rb +3 -3
  56. data/lib/sequel/adapters/swift/mysql.rb +1 -1
  57. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  58. data/lib/sequel/adapters/tinytds.rb +8 -8
  59. data/lib/sequel/ast_transformer.rb +3 -1
  60. data/lib/sequel/connection_pool.rb +4 -2
  61. data/lib/sequel/connection_pool/sharded_single.rb +2 -2
  62. data/lib/sequel/connection_pool/sharded_threaded.rb +5 -5
  63. data/lib/sequel/connection_pool/threaded.rb +7 -7
  64. data/lib/sequel/core.rb +4 -67
  65. data/lib/sequel/database.rb +1 -0
  66. data/lib/sequel/database/connecting.rb +2 -8
  67. data/lib/sequel/database/dataset.rb +2 -7
  68. data/lib/sequel/database/dataset_defaults.rb +0 -18
  69. data/lib/sequel/database/features.rb +4 -4
  70. data/lib/sequel/database/misc.rb +6 -8
  71. data/lib/sequel/database/query.rb +5 -61
  72. data/lib/sequel/database/schema_generator.rb +22 -20
  73. data/lib/sequel/database/schema_methods.rb +48 -20
  74. data/lib/sequel/database/transactions.rb +7 -17
  75. data/lib/sequel/dataset.rb +2 -0
  76. data/lib/sequel/dataset/actions.rb +23 -91
  77. data/lib/sequel/dataset/features.rb +1 -4
  78. data/lib/sequel/dataset/graph.rb +3 -47
  79. data/lib/sequel/dataset/misc.rb +4 -33
  80. data/lib/sequel/dataset/prepared_statements.rb +3 -1
  81. data/lib/sequel/dataset/query.rb +116 -240
  82. data/lib/sequel/dataset/sql.rb +19 -97
  83. data/lib/sequel/deprecated.rb +0 -16
  84. data/lib/sequel/exceptions.rb +0 -3
  85. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  86. data/lib/sequel/extensions/columns_introspection.rb +1 -12
  87. data/lib/sequel/extensions/constraint_validations.rb +3 -3
  88. data/lib/sequel/extensions/core_extensions.rb +0 -9
  89. data/lib/sequel/extensions/date_arithmetic.rb +1 -2
  90. data/lib/sequel/extensions/graph_each.rb +11 -0
  91. data/lib/sequel/extensions/migration.rb +5 -5
  92. data/lib/sequel/extensions/null_dataset.rb +11 -13
  93. data/lib/sequel/extensions/pagination.rb +3 -6
  94. data/lib/sequel/extensions/pg_array.rb +6 -4
  95. data/lib/sequel/extensions/pg_array_ops.rb +35 -1
  96. data/lib/sequel/extensions/pg_json.rb +12 -2
  97. data/lib/sequel/extensions/pg_json_ops.rb +266 -0
  98. data/lib/sequel/extensions/pg_range.rb +2 -2
  99. data/lib/sequel/extensions/pg_range_ops.rb +0 -8
  100. data/lib/sequel/extensions/pg_row.rb +2 -2
  101. data/lib/sequel/extensions/pretty_table.rb +0 -4
  102. data/lib/sequel/extensions/query.rb +3 -8
  103. data/lib/sequel/extensions/schema_caching.rb +0 -7
  104. data/lib/sequel/extensions/schema_dumper.rb +10 -17
  105. data/lib/sequel/extensions/select_remove.rb +0 -4
  106. data/lib/sequel/extensions/set_overrides.rb +28 -0
  107. data/lib/sequel/extensions/to_dot.rb +6 -10
  108. data/lib/sequel/model.rb +6 -7
  109. data/lib/sequel/model/associations.rb +127 -182
  110. data/lib/sequel/model/base.rb +88 -211
  111. data/lib/sequel/model/errors.rb +0 -13
  112. data/lib/sequel/model/plugins.rb +2 -2
  113. data/lib/sequel/no_core_ext.rb +0 -1
  114. data/lib/sequel/plugins/after_initialize.rb +11 -17
  115. data/lib/sequel/plugins/association_autoreloading.rb +1 -47
  116. data/lib/sequel/plugins/association_dependencies.rb +2 -2
  117. data/lib/sequel/plugins/auto_validations.rb +2 -8
  118. data/lib/sequel/plugins/blacklist_security.rb +32 -2
  119. data/lib/sequel/plugins/caching.rb +1 -1
  120. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  121. data/lib/sequel/plugins/composition.rb +10 -8
  122. data/lib/sequel/plugins/constraint_validations.rb +2 -2
  123. data/lib/sequel/plugins/dataset_associations.rb +4 -0
  124. data/lib/sequel/plugins/defaults_setter.rb +8 -6
  125. data/lib/sequel/plugins/dirty.rb +6 -6
  126. data/lib/sequel/plugins/force_encoding.rb +13 -8
  127. data/lib/sequel/plugins/hook_class_methods.rb +1 -7
  128. data/lib/sequel/plugins/json_serializer.rb +13 -74
  129. data/lib/sequel/plugins/lazy_attributes.rb +2 -4
  130. data/lib/sequel/plugins/list.rb +1 -1
  131. data/lib/sequel/plugins/many_through_many.rb +4 -11
  132. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +1 -49
  133. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  134. data/lib/sequel/plugins/optimistic_locking.rb +3 -5
  135. data/lib/sequel/plugins/pg_array_associations.rb +453 -0
  136. data/lib/sequel/plugins/pg_typecast_on_load.rb +23 -7
  137. data/lib/sequel/plugins/prepared_statements.rb +1 -1
  138. data/lib/sequel/plugins/prepared_statements_associations.rb +20 -14
  139. data/lib/sequel/plugins/prepared_statements_safe.rb +2 -2
  140. data/lib/sequel/plugins/rcte_tree.rb +1 -1
  141. data/lib/sequel/plugins/serialization.rb +5 -4
  142. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  143. data/lib/sequel/plugins/sharding.rb +7 -1
  144. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  145. data/lib/sequel/plugins/timestamps.rb +1 -1
  146. data/lib/sequel/plugins/touch.rb +2 -2
  147. data/lib/sequel/plugins/tree.rb +1 -1
  148. data/lib/sequel/plugins/typecast_on_load.rb +19 -4
  149. data/lib/sequel/plugins/validation_class_methods.rb +0 -30
  150. data/lib/sequel/plugins/validation_helpers.rb +13 -31
  151. data/lib/sequel/plugins/xml_serializer.rb +18 -57
  152. data/lib/sequel/sql.rb +20 -22
  153. data/lib/sequel/version.rb +2 -2
  154. data/spec/adapters/db2_spec.rb +14 -23
  155. data/spec/adapters/firebird_spec.rb +25 -29
  156. data/spec/adapters/informix_spec.rb +11 -14
  157. data/spec/adapters/mssql_spec.rb +71 -77
  158. data/spec/adapters/mysql_spec.rb +165 -172
  159. data/spec/adapters/oracle_spec.rb +36 -39
  160. data/spec/adapters/postgres_spec.rb +175 -100
  161. data/spec/adapters/spec_helper.rb +13 -11
  162. data/spec/adapters/sqlite_spec.rb +36 -44
  163. data/spec/core/connection_pool_spec.rb +2 -1
  164. data/spec/core/database_spec.rb +55 -55
  165. data/spec/core/dataset_spec.rb +45 -249
  166. data/spec/core/deprecated_spec.rb +0 -8
  167. data/spec/core/expression_filters_spec.rb +23 -5
  168. data/spec/core/object_graph_spec.rb +4 -66
  169. data/spec/core/schema_spec.rb +35 -12
  170. data/spec/core/spec_helper.rb +3 -2
  171. data/spec/core_extensions_spec.rb +17 -19
  172. data/spec/extensions/arbitrary_servers_spec.rb +2 -3
  173. data/spec/extensions/association_dependencies_spec.rb +14 -14
  174. data/spec/extensions/auto_validations_spec.rb +7 -0
  175. data/spec/extensions/blacklist_security_spec.rb +5 -5
  176. data/spec/extensions/blank_spec.rb +2 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +2 -2
  178. data/spec/extensions/columns_introspection_spec.rb +2 -29
  179. data/spec/extensions/composition_spec.rb +10 -17
  180. data/spec/extensions/core_refinements_spec.rb +5 -1
  181. data/spec/extensions/dataset_associations_spec.rb +18 -0
  182. data/spec/extensions/date_arithmetic_spec.rb +2 -2
  183. data/spec/extensions/defaults_setter_spec.rb +9 -9
  184. data/spec/extensions/dirty_spec.rb +0 -5
  185. data/spec/extensions/eval_inspect_spec.rb +2 -0
  186. data/spec/extensions/force_encoding_spec.rb +2 -18
  187. data/spec/extensions/hash_aliases_spec.rb +8 -0
  188. data/spec/extensions/hook_class_methods_spec.rb +39 -58
  189. data/spec/extensions/inflector_spec.rb +2 -0
  190. data/spec/extensions/instance_filters_spec.rb +8 -8
  191. data/spec/extensions/json_serializer_spec.rb +1 -41
  192. data/spec/extensions/list_spec.rb +1 -1
  193. data/spec/extensions/many_through_many_spec.rb +106 -109
  194. data/spec/extensions/migration_spec.rb +2 -0
  195. data/spec/extensions/named_timezones_spec.rb +1 -0
  196. data/spec/extensions/pg_array_associations_spec.rb +603 -0
  197. data/spec/extensions/pg_array_ops_spec.rb +25 -0
  198. data/spec/extensions/pg_array_spec.rb +9 -1
  199. data/spec/extensions/pg_hstore_ops_spec.rb +13 -0
  200. data/spec/extensions/pg_hstore_spec.rb +1 -0
  201. data/spec/extensions/pg_json_ops_spec.rb +131 -0
  202. data/spec/extensions/pg_json_spec.rb +10 -4
  203. data/spec/extensions/pg_range_ops_spec.rb +2 -5
  204. data/spec/extensions/pg_range_spec.rb +6 -2
  205. data/spec/extensions/pg_row_ops_spec.rb +2 -0
  206. data/spec/extensions/prepared_statements_associations_spec.rb +26 -5
  207. data/spec/extensions/rcte_tree_spec.rb +15 -15
  208. data/spec/extensions/schema_dumper_spec.rb +0 -1
  209. data/spec/extensions/schema_spec.rb +9 -9
  210. data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
  211. data/spec/extensions/serialization_spec.rb +18 -29
  212. data/spec/extensions/set_overrides_spec.rb +4 -0
  213. data/spec/extensions/{many_to_one_pk_lookup_spec.rb → shared_caching_spec.rb} +1 -4
  214. data/spec/extensions/single_table_inheritance_spec.rb +4 -4
  215. data/spec/extensions/spec_helper.rb +8 -9
  216. data/spec/extensions/sql_expr_spec.rb +2 -0
  217. data/spec/extensions/string_date_time_spec.rb +2 -0
  218. data/spec/extensions/string_stripper_spec.rb +2 -0
  219. data/spec/extensions/tactical_eager_loading_spec.rb +12 -12
  220. data/spec/extensions/thread_local_timezones_spec.rb +2 -0
  221. data/spec/extensions/timestamps_spec.rb +1 -1
  222. data/spec/extensions/to_dot_spec.rb +1 -1
  223. data/spec/extensions/touch_spec.rb +24 -24
  224. data/spec/extensions/tree_spec.rb +7 -7
  225. data/spec/extensions/typecast_on_load_spec.rb +8 -1
  226. data/spec/extensions/update_primary_key_spec.rb +10 -10
  227. data/spec/extensions/validation_class_methods_spec.rb +10 -39
  228. data/spec/extensions/validation_helpers_spec.rb +29 -47
  229. data/spec/extensions/xml_serializer_spec.rb +1 -23
  230. data/spec/integration/associations_test.rb +231 -40
  231. data/spec/integration/database_test.rb +1 -1
  232. data/spec/integration/dataset_test.rb +64 -64
  233. data/spec/integration/eager_loader_test.rb +28 -28
  234. data/spec/integration/migrator_test.rb +1 -1
  235. data/spec/integration/model_test.rb +2 -2
  236. data/spec/integration/plugin_test.rb +21 -21
  237. data/spec/integration/prepared_statement_test.rb +7 -7
  238. data/spec/integration/schema_test.rb +115 -110
  239. data/spec/integration/spec_helper.rb +17 -27
  240. data/spec/integration/timezone_test.rb +1 -1
  241. data/spec/integration/transaction_test.rb +10 -10
  242. data/spec/integration/type_test.rb +2 -2
  243. data/spec/model/association_reflection_spec.rb +2 -28
  244. data/spec/model/associations_spec.rb +239 -188
  245. data/spec/model/base_spec.rb +27 -68
  246. data/spec/model/dataset_methods_spec.rb +4 -4
  247. data/spec/model/eager_loading_spec.rb +160 -172
  248. data/spec/model/hooks_spec.rb +62 -79
  249. data/spec/model/model_spec.rb +36 -51
  250. data/spec/model/plugins_spec.rb +5 -19
  251. data/spec/model/record_spec.rb +125 -151
  252. data/spec/model/spec_helper.rb +8 -6
  253. data/spec/model/validations_spec.rb +4 -17
  254. data/spec/spec_config.rb +2 -10
  255. metadata +50 -56
  256. data/lib/sequel/deprecated_core_extensions.rb +0 -135
  257. data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -185
  258. data/lib/sequel/extensions/pg_statement_cache.rb +0 -318
  259. data/lib/sequel/plugins/identity_map.rb +0 -260
  260. data/lib/sequel_core.rb +0 -2
  261. data/lib/sequel_model.rb +0 -2
  262. data/spec/extensions/association_autoreloading_spec.rb +0 -102
  263. data/spec/extensions/identity_map_spec.rb +0 -337
  264. data/spec/extensions/pg_auto_parameterize_spec.rb +0 -70
  265. data/spec/extensions/pg_statement_cache_spec.rb +0 -208
  266. data/spec/rcov.opts +0 -8
  267. data/spec/spec_config.rb.example +0 -10
@@ -164,7 +164,7 @@ module Sequel
164
164
  # to DatabaseMethods.
165
165
  #
166
166
  # If a block is given, it is treated as the :converter option.
167
- def self.register(db_type, opts={}, &block)
167
+ def self.register(db_type, opts=OPTS, &block)
168
168
  db_type = db_type.to_s
169
169
  typecast_method = opts[:typecast_method]
170
170
  type = (typecast_method || opts[:type_symbol] || db_type).to_sym
@@ -248,7 +248,7 @@ module Sequel
248
248
  # different array types per Database. Use of this method does not
249
249
  # affect global state, unlike PGArray.register. See PGArray.register for
250
250
  # possible options.
251
- def register_array_type(db_type, opts={}, &block)
251
+ def register_array_type(db_type, opts=OPTS, &block)
252
252
  opts = {:type_procs=>conversion_procs, :typecast_method_map=>@pg_array_schema_types, :typecast_methods_module=>(class << self; self; end)}.merge(opts)
253
253
  unless (opts.has_key?(:scalar_oid) || block) && opts.has_key?(:oid)
254
254
  array_oid, scalar_oid = from(:pg_type).where(:typname=>db_type.to_s).get([:typarray, :oid])
@@ -285,8 +285,10 @@ module Sequel
285
285
  # Automatically handle array types for the given named types.
286
286
  def convert_named_procs_to_procs(named_procs)
287
287
  h = super
288
- from(:pg_type).where(:oid=>h.keys).select_map([:typname, :oid, :typarray]).each do |name, scalar_oid, array_oid|
289
- register_array_type(name, :type_procs=>h, :oid=>array_oid.to_i, :scalar_oid=>scalar_oid.to_i)
288
+ unless h.empty?
289
+ from(:pg_type).where(:oid=>h.keys).select_map([:typname, :oid, :typarray]).each do |name, scalar_oid, array_oid|
290
+ register_array_type(name, :type_procs=>h, :oid=>array_oid.to_i, :scalar_oid=>scalar_oid.to_i)
291
+ end
290
292
  end
291
293
  h
292
294
  end
@@ -76,7 +76,9 @@ module Sequel
76
76
  #
77
77
  # array_op[1] # array[1]
78
78
  def [](key)
79
- Sequel::SQL::Subscript.new(self, [key])
79
+ s = Sequel::SQL::Subscript.new(self, [key])
80
+ s = ArrayOp.new(s) if key.is_a?(Range)
81
+ s
80
82
  end
81
83
 
82
84
  # Call the ALL function:
@@ -124,6 +126,23 @@ module Sequel
124
126
  function(:array_dims)
125
127
  end
126
128
 
129
+ # Convert the array into an hstore using the hstore function.
130
+ # If given an argument, use the two array form:
131
+ #
132
+ # array_op.hstore # hstore(array)
133
+ # array_op.hstore(:array2) # hstore(array, array2)
134
+ def hstore(arg=(no_arg_given=true; nil))
135
+ v = if no_arg_given
136
+ Sequel.function(:hstore, self)
137
+ else
138
+ Sequel.function(:hstore, self, wrap_array(arg))
139
+ end
140
+ if Sequel.respond_to?(:hstore_op)
141
+ v = Sequel.hstore_op(v)
142
+ end
143
+ v
144
+ end
145
+
127
146
  # Call the array_length method:
128
147
  #
129
148
  # array_op.length # array_length(array, 1)
@@ -161,6 +180,21 @@ module Sequel
161
180
  self
162
181
  end
163
182
 
183
+ # Remove the given element from the array:
184
+ #
185
+ # array_op.remove(1) # array_remove(array, 1)
186
+ def remove(element)
187
+ ArrayOp.new(function(:array_remove, element))
188
+ end
189
+
190
+ # Replace the given element in the array with another
191
+ # element:
192
+ #
193
+ # array_op.replace(1, 2) # array_replace(array, 1, 2)
194
+ def replace(element, replacement)
195
+ ArrayOp.new(function(:array_replace, element, replacement))
196
+ end
197
+
164
198
  # Call the array_to_string method:
165
199
  #
166
200
  # array_op.join # array_to_string(array, '', NULL)
@@ -100,6 +100,16 @@ module Sequel
100
100
  end
101
101
  end
102
102
 
103
+ # Parse JSON data coming from the database. Since PostgreSQL allows
104
+ # non JSON data in JSON fields (such as plain numbers and strings),
105
+ # we don't want to raise an exception for that.
106
+ def self.db_parse_json(s)
107
+ parse_json(s)
108
+ rescue Sequel::InvalidValue
109
+ raise unless s.is_a?(String)
110
+ parse_json("[#{s}]").first
111
+ end
112
+
103
113
  # Parse the given string as json, returning either a JSONArray
104
114
  # or JSONHash instance, and raising an error if the JSON
105
115
  # parsing does not yield an array or hash.
@@ -174,7 +184,7 @@ module Sequel
174
184
  end
175
185
  end
176
186
 
177
- PG_TYPES[114] = JSONDatabaseMethods.method(:parse_json)
187
+ PG_TYPES[114] = JSONDatabaseMethods.method(:db_parse_json)
178
188
  if defined?(PGArray) && PGArray.respond_to?(:register)
179
189
  PGArray.register('json', :oid=>199, :scalar_oid=>114)
180
190
  end
@@ -191,7 +201,7 @@ module Sequel
191
201
  when Hash
192
202
  Postgres::JSONHash.new(v)
193
203
  else
194
- raise Error, "Sequel.pg_json requires a hash or array argument"
204
+ Sequel.pg_json_op(v)
195
205
  end
196
206
  end
197
207
  end
@@ -0,0 +1,266 @@
1
+ # The pg_json_ops extension adds support to Sequel's DSL to make
2
+ # it easier to call PostgreSQL JSON functions and operators (added
3
+ # first in PostgreSQL 9.3).
4
+ #
5
+ # To load the extension:
6
+ #
7
+ # Sequel.extension :pg_json_ops
8
+ #
9
+ # The most common usage is passing an expression to Sequel.pg_json_op:
10
+ #
11
+ # j = Sequel.pg_json_op(:json_column)
12
+ #
13
+ # If you have also loaded the pg_json extension, you can use
14
+ # Sequel.pg_json as well:
15
+ #
16
+ # j = Sequel.pg_json(:json_column)
17
+ #
18
+ # Also, on most Sequel expression objects, you can call the pg_json
19
+ # method:
20
+ #
21
+ # j = Sequel.expr(:json_column).pg_json
22
+ #
23
+ # If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
24
+ # or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
25
+ # and have activated refinements for the file, you can also use Symbol#pg_json:
26
+ #
27
+ # j = :json_column.pg_json
28
+ #
29
+ # This creates a Sequel::Postgres::JSONOp object that can be used
30
+ # for easier querying:
31
+ #
32
+ # j[1] # (json_column -> 1)
33
+ # j[%w'a b'] # (json_column #> ARRAY['a','b'])
34
+ # j.get_text(1) # (json_column ->> 1)
35
+ # j.get_text(%w'a b') # (json_column #>> ARRAY['a','b'])
36
+ # j.extract('a', 'b') # json_extract_path(json_column, 'a', 'b')
37
+ # j.extract_text('a', 'b') # json_extract_path_text(json_column, 'a', 'b')
38
+ #
39
+ # j.array_length # json_array_length(json_column)
40
+ # j.array_elements # json_array_elements(json_column)
41
+ # j.each # json_each(json_column)
42
+ # j.each_text # json_each_text(json_column)
43
+ # j.keys # json_object_keys(json_column)
44
+ #
45
+ # j.populate(:a) # json_populate_record(:a, json_column)
46
+ # j.populate_set(:a) # json_populate_recordset(:a, json_column)
47
+ #
48
+ # If you are also using the pg_json extension, you should load it before
49
+ # loading this extension. Doing so will allow you to use JSONHash#op and
50
+ # JSONArray#op to get a JSONOp, allowing you to perform json operations
51
+ # on json literals.
52
+ module Sequel
53
+ module Postgres
54
+ # The JSONOp class is a simple container for a single object that
55
+ # defines methods that yield Sequel expression objects representing
56
+ # PostgreSQL json operators and functions.
57
+ #
58
+ # In the method documentation examples, assume that:
59
+ #
60
+ # json_op = Sequel.pg_json(:json)
61
+ class JSONOp < Sequel::SQL::Wrapper
62
+ GET = ["(".freeze, " -> ".freeze, ")".freeze].freeze
63
+ GET_TEXT = ["(".freeze, " ->> ".freeze, ")".freeze].freeze
64
+ GET_PATH = ["(".freeze, " #> ".freeze, ")".freeze].freeze
65
+ GET_PATH_TEXT = ["(".freeze, " #>> ".freeze, ")".freeze].freeze
66
+
67
+ # Get JSON array element or object field as json. If an array is given,
68
+ # gets the object at the specified path.
69
+ #
70
+ # json_op[1] # (json -> 1)
71
+ # json_op['a'] # (json -> 'a')
72
+ # json_op[%w'a b'] # (json #> ARRAY['a', 'b'])
73
+ def [](key)
74
+ if is_array?(key)
75
+ json_op(GET_PATH, wrap_array(key))
76
+ else
77
+ json_op(GET, key)
78
+ end
79
+ end
80
+ alias get []
81
+
82
+ # Returns a set of json values for the elements in the json array.
83
+ #
84
+ # json_op.array_elements # json_oarray_elements(json)
85
+ def array_elements
86
+ function(:json_array_elements)
87
+ end
88
+
89
+ # Get the length of the outermost json array.
90
+ #
91
+ # json_op.array_length # json_array_length(json)
92
+ def array_length
93
+ Sequel::SQL::NumericExpression.new(:NOOP, function(:json_array_length))
94
+ end
95
+
96
+ # Returns a set of key and value pairs, where the keys
97
+ # are text and the values are JSON.
98
+ #
99
+ # json_op.each # json_each(json)
100
+ def each
101
+ function(:json_each)
102
+ end
103
+
104
+ # Returns a set of key and value pairs, where the keys
105
+ # and values are both text.
106
+ #
107
+ # json_op.each_text # json_each_text(json)
108
+ def each_text
109
+ function(:json_each_text)
110
+ end
111
+
112
+ # Returns a json value for the object at the given path.
113
+ #
114
+ # json_op.extract('a') # json_extract_path(json, 'a')
115
+ # json_op.extract('a', 'b') # json_extract_path(json, 'a', 'b')
116
+ def extract(*a)
117
+ JSONOp.new(function(:json_extract_path, *a))
118
+ end
119
+
120
+ # Returns a text value for the object at the given path.
121
+ #
122
+ # json_op.extract_text('a') # json_extract_path_text(json, 'a')
123
+ # json_op.extract_text('a', 'b') # json_extract_path_text(json, 'a', 'b')
124
+ def extract_text(*a)
125
+ Sequel::SQL::StringExpression.new(:NOOP, function(:json_extract_path_text, *a))
126
+ end
127
+
128
+ # Get JSON array element or object field as text. If an array is given,
129
+ # gets the object at the specified path.
130
+ #
131
+ # json_op.get_text(1) # (json ->> 1)
132
+ # json_op.get_text('a') # (json ->> 'a')
133
+ # json_op.get_text(%w'a b') # (json #>> ARRAY['a', 'b'])
134
+ def get_text(key)
135
+ if is_array?(key)
136
+ json_op(GET_PATH_TEXT, wrap_array(key))
137
+ else
138
+ json_op(GET_TEXT, key)
139
+ end
140
+ end
141
+
142
+ # Returns a set of keys AS text in the json object.
143
+ #
144
+ # json_op.keys # json_object_keys(json)
145
+ def keys
146
+ function(:json_object_keys)
147
+ end
148
+
149
+ # Return the receiver, since it is already a JSONOp.
150
+ def pg_json
151
+ self
152
+ end
153
+
154
+ # Expands the given argument using the columns in the json.
155
+ #
156
+ # json_op.populate(arg) # json_populate_record(arg, json)
157
+ def populate(arg)
158
+ SQL::Function.new(:json_populate_record, arg, self)
159
+ end
160
+
161
+ # Expands the given argument using the columns in the json.
162
+ #
163
+ # json_op.populate_set(arg) # json_populate_recordset(arg, json)
164
+ def populate_set(arg)
165
+ SQL::Function.new(:json_populate_recordset, arg, self)
166
+ end
167
+
168
+ private
169
+
170
+ # Return a placeholder literal with the given str and args, wrapped
171
+ # in an JSONOp, used by operators that return json.
172
+ def json_op(str, args)
173
+ JSONOp.new(Sequel::SQL::PlaceholderLiteralString.new(str, [self, args]))
174
+ end
175
+
176
+ # Return a function with the given name, and the receiver as the first
177
+ # argument, with any additional arguments given.
178
+ def function(name, *args)
179
+ SQL::Function.new(name, self, *args)
180
+ end
181
+
182
+ # Whether the given object represents an array in PostgreSQL.
183
+ def is_array?(a)
184
+ a.is_a?(Array) || (defined?(PGArray) && a.is_a?(PGArray)) || (defined?(ArrayOp) && a.is_a?(ArrayOp))
185
+ end
186
+
187
+ # Return a placeholder literal with the given str and args, wrapped
188
+ # in an SQL::StringExpression, used by operators that return text.
189
+ def text_op(str, args)
190
+ Sequel::SQL::StringExpression.new(:NOOP, Sequel::SQL::PlaceholderLiteralString.new(str, [self, args]))
191
+ end
192
+
193
+ # Automatically wrap argument in a PGArray if it is a plain Array.
194
+ # Requires that the pg_array extension has been loaded to work.
195
+ def wrap_array(arg)
196
+ if arg.instance_of?(Array) && Sequel.respond_to?(:pg_array)
197
+ Sequel.pg_array(arg)
198
+ else
199
+ arg
200
+ end
201
+ end
202
+ end
203
+
204
+ module JSONOpMethods
205
+ # Wrap the receiver in an JSONOp so you can easily use the PostgreSQL
206
+ # json functions and operators with it.
207
+ def pg_json
208
+ JSONOp.new(self)
209
+ end
210
+ end
211
+
212
+ if defined?(JSONArray)
213
+ class JSONArray
214
+ # Wrap the JSONHash instance in an JSONOp, allowing you to easily use
215
+ # the PostgreSQL json functions and operators with literal jsons.
216
+ def op
217
+ JSONOp.new(self)
218
+ end
219
+ end
220
+
221
+ class JSONHash
222
+ # Wrap the JSONHash instance in an JSONOp, allowing you to easily use
223
+ # the PostgreSQL json functions and operators with literal jsons.
224
+ def op
225
+ JSONOp.new(self)
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ module SQL::Builders
232
+ # Return the object wrapped in an Postgres::JSONOp.
233
+ def pg_json_op(v)
234
+ case v
235
+ when Postgres::JSONOp
236
+ v
237
+ else
238
+ Postgres::JSONOp.new(v)
239
+ end
240
+ end
241
+ end
242
+
243
+ class SQL::GenericExpression
244
+ include Sequel::Postgres::JSONOpMethods
245
+ end
246
+
247
+ class LiteralString
248
+ include Sequel::Postgres::JSONOpMethods
249
+ end
250
+ end
251
+
252
+ # :nocov:
253
+ if Sequel.core_extensions?
254
+ class Symbol
255
+ include Sequel::Postgres::JSONOpMethods
256
+ end
257
+ end
258
+
259
+ if defined?(Sequel::CoreRefinements)
260
+ module Sequel::CoreRefinements
261
+ refine Symbol do
262
+ include Sequel::Postgres::JSONOpMethods
263
+ end
264
+ end
265
+ end
266
+ # :nocov:
@@ -92,7 +92,7 @@ module Sequel
92
92
  # proc.
93
93
  #
94
94
  # If a block is given, it is treated as the :converter option.
95
- def self.register(db_type, opts={}, &block)
95
+ def self.register(db_type, opts=OPTS, &block)
96
96
  db_type = db_type.to_s.dup.freeze
97
97
 
98
98
  if converter = opts[:converter]
@@ -328,7 +328,7 @@ module Sequel
328
328
  # :empty :: Whether the range is empty (has no points)
329
329
  # :exclude_begin :: Whether the beginning element is excluded from the range.
330
330
  # :exclude_end :: Whether the ending element is excluded from the range.
331
- def initialize(beg, en, opts={})
331
+ def initialize(beg, en, opts=OPTS)
332
332
  @begin = beg
333
333
  @end = en
334
334
  @empty = !!opts[:empty]
@@ -79,14 +79,6 @@ module Sequel
79
79
  OPERATORS.keys.each do |f|
80
80
  class_eval("def #{f}(v); operator(:#{f}, v) end", __FILE__, __LINE__)
81
81
  end
82
- def starts_before(v)
83
- Sequel::Deprecation.deprecate('Postgres::PGRangeOp#starts_before', "Please switch to Postgres::PGRangeOp#ends_before")
84
- ends_before(v)
85
- end
86
- def ends_after(v)
87
- Sequel::Deprecation.deprecate('Postgres::PGRangeOp#ends_after', "Please switch to Postgres::PGRangeOp#starts_after")
88
- starts_after(v)
89
- end
90
82
 
91
83
  # These operators are already supported by the wrapper, but for ranges they
92
84
  # return ranges, so wrap the results in another RangeOp.
@@ -290,7 +290,7 @@ module Sequel
290
290
 
291
291
  # Sets each of the parser's attributes, using options with
292
292
  # the same name (e.g. :columns sets the columns attribute).
293
- def initialize(h={})
293
+ def initialize(h=OPTS)
294
294
  @columns = h[:columns]
295
295
  @column_converters = h[:column_converters]
296
296
  @column_oids = h[:column_oids]
@@ -417,7 +417,7 @@ module Sequel
417
417
  #
418
418
  # :converter :: Use a custom converter for the parser.
419
419
  # :typecaster :: Use a custom typecaster for the parser.
420
- def register_row_type(db_type, opts={})
420
+ def register_row_type(db_type, opts=OPTS)
421
421
  procs = @conversion_procs
422
422
  rel_oid = nil
423
423
  array_oid = nil
@@ -23,12 +23,8 @@ module Sequel
23
23
  extension :_pretty_table
24
24
 
25
25
  module DatasetPrinter
26
- end
27
-
28
- class Dataset
29
26
  # Pretty prints the records in the dataset as plain-text table.
30
27
  def print(*cols)
31
- Sequel::Deprecation.deprecate('Loading the pretty_table extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(DatasetPrinter)
32
28
  ds = naked
33
29
  rows = ds.all
34
30
  Sequel::PrettyTable.print(rows, cols.empty? ? ds.columns : cols)