Class: ActiveRecord::Refined::Dialect::Oracle
- Inherits:
-
Dialect
- Object
- Dialect
- ActiveRecord::Refined::Dialect::Oracle
- Defined in:
- lib/active_record/refined/dialect/oracle.rb
Overview
Oracle, reached through oracle_enhanced. Loaded only when a query is built for it.
Instance Method Summary collapse
-
#add_interval(date, amount, unit, subtract, _date_only) ⇒ Object
An INTERVAL literal would do, but its leading field is two digits wide unless told otherwise, so INTERVAL '100' DAY is an error.
- #check_json_aggregate_window(source, model) ⇒ Object
- #json_argument(value, model) ⇒ Object
-
#json_build(kind, keys, args, model) ⇒ Object
Oracle pairs a key with its value by the VALUE keyword rather than by position, keeps a NULL only when told NULL ON NULL, and returns the native JSON type unless a RETURNING asks for text ruby-oci8 can fetch.
- #json_has_key(document, _name, path, _model) ⇒ Object
-
#json_path(document, dollar_path, _steps, json_value, model) ⇒ Object
Oracle keeps scalars and structures in different functions: JSON_VALUE reads a scalar out as text, JSON_QUERY a fragment as JSON.
- #json_remove(document, dollar_paths, _steps, model) ⇒ Object
-
#json_set(document, _steps, dollar_path, value, expression, model) ⇒ Object
JSON_TRANSFORM is Oracle's one editing function; its SET and the value beside it are grammar, so the call is written out, RETURNING text that ruby-oci8 can fetch.
Instance Method Details
#add_interval(date, amount, unit, subtract, _date_only) ⇒ Object
An INTERVAL literal would do, but its leading field is two digits wide unless told otherwise, so INTERVAL '100' DAY is an error. The functions that make an interval of a number take any size, one for the year-month intervals and one for the day-second.
21 22 23 24 25 26 27 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 21 def add_interval(date, amount, unit, subtract, _date_only) interval = Arel::Nodes::NamedFunction.new( unit == :year || unit == :month ? "NUMTOYMINTERVAL" : "NUMTODSINTERVAL", [Arel::Nodes.build_quoted(amount), Arel::Nodes.build_quoted(unit.to_s.upcase)]) Arel::Nodes::Grouping.new( Arel::Nodes::InfixOperation.new(subtract ? :- : :+, date, interval)) end |
#check_json_aggregate_window(source, model) ⇒ Object
96 97 98 99 100 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 96 def check_json_aggregate_window(source, model) raise NotImplementedError, "#{source} over a window has no equivalent on " \ "#{model.connection_db_config.adapter}" end |
#json_argument(value, model) ⇒ Object
48 49 50 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 48 def json_argument(value, model) Arel.sql("#{quote(JSON.generate(value), model)} FORMAT JSON") end |
#json_build(kind, keys, args, model) ⇒ Object
Oracle pairs a key with its value by the VALUE keyword rather than by position, keeps a NULL only when told NULL ON NULL, and returns the native JSON type unless a RETURNING asks for text ruby-oci8 can fetch.
83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 83 def json_build(kind, keys, args, model) model.with_connection do |connection| compiled = args.map { |arg| connection.visitor.compile(arg) } body = if kind == :array compiled.join(", ") else keys.zip(compiled).map { |key, arg| "#{connection.quote(key)} VALUE #{arg}" }.join(", ") end Arel.sql("JSON_#{kind.to_s.upcase}(#{body} NULL ON NULL RETURNING VARCHAR2(4000))") end end |
#json_has_key(document, _name, path, _model) ⇒ Object
44 45 46 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 44 def json_has_key(document, _name, path, _model) Arel::Nodes::NamedFunction.new("JSON_EXISTS", [document, path]) end |
#json_path(document, dollar_path, _steps, json_value, model) ⇒ Object
Oracle keeps scalars and structures in different functions: JSON_VALUE reads a scalar out as text, JSON_QUERY a fragment as JSON. dig keeps JSON, so it takes JSON_QUERY with 23ai's ALLOW SCALARS, which returns a scalar leaf as itself rather than wrapping or refusing it.
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 33 def json_path(document, dollar_path, _steps, json_value, model) unless json_value return Arel::Nodes::NamedFunction.new( "JSON_VALUE", [document, Arel::Nodes.build_quoted(dollar_path)]) end Arel.sql( "JSON_QUERY(#{compile(document, model)}, " \ "#{quote(dollar_path, model)} RETURNING VARCHAR2(4000) ALLOW SCALARS " \ "NULL ON EMPTY)") end |
#json_remove(document, dollar_paths, _steps, model) ⇒ Object
71 72 73 74 75 76 77 78 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 71 def json_remove(document, dollar_paths, _steps, model) model.with_connection do |connection| removes = dollar_paths.map { |path| "REMOVE #{connection.quote(path)}" } Arel.sql( "JSON_TRANSFORM(#{connection.visitor.compile(document)}, " \ "#{removes.join(', ')} RETURNING VARCHAR2(4000))") end end |
#json_set(document, _steps, dollar_path, value, expression, model) ⇒ Object
JSON_TRANSFORM is Oracle's one editing function; its SET and the value beside it are grammar, so the call is written out, RETURNING text that ruby-oci8 can fetch.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 55 def json_set(document, _steps, dollar_path, value, expression, model) model.with_connection do |connection| set = if expression connection.visitor.compile(expression) elsif json_document_value?(value) "#{connection.quote(JSON.generate(value))} FORMAT JSON" else connection.quote(value) end Arel.sql( "JSON_TRANSFORM(#{connection.visitor.compile(document)}, " \ "SET #{connection.quote(dollar_path)} = #{set} RETURNING VARCHAR2(4000))") end end |