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.
Constant Summary collapse
- FUNCTIONS =
{ char_length: "LENGTH", degrees: nil, radians: nil, pi: nil, log2: nil, log10: nil, now: nil, date_trunc: nil, rand: nil, format: nil, bit_and: nil, bit_or: nil, bit_xor: nil, }.freeze
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_keys(_document, model) ⇒ Object
No JSON_KEYS, and the keys reach only through a JSON_TABLE unnest not written yet.
-
#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.
20 21 22 23 24 25 26 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 20 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
102 103 104 105 106 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 102 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
54 55 56 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 54 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.
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 89 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
43 44 45 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 43 def json_has_key(document, _name, path, _model) Arel::Nodes::NamedFunction.new("JSON_EXISTS", [document, path]) end |
#json_keys(_document, model) ⇒ Object
No JSON_KEYS, and the keys reach only through a JSON_TABLE unnest not written yet.
49 50 51 52 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 49 def json_keys(_document, model) raise NotImplementedError, "keys has no equivalent on #{model.connection_db_config.adapter}" 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.
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 32 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
77 78 79 80 81 82 83 84 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 77 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.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/active_record/refined/dialect/oracle.rb', line 61 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 |