sequel 3.48.0 → 4.0.0

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