Class: ActiveRecord::Refined::Dialect::SqlServer

Inherits:
Dialect
  • Object
show all
Defined in:
lib/active_record/refined/dialect/sql_server.rb

Overview

Microsoft SQL Server, reached through the sqlserver adapter over tiny_tds. Loaded only when a query is built for it.

Constant Summary collapse

FUNCTIONS =

LEN is its length; it has no printf FORMAT, no per-row random it would spell RAND, no date_trunc, and none of the bit aggregates. Of the datetime value functions it has CURRENT_TIMESTAMP alone: the other four are reserved words there that stand for nothing.

{
  char_length: "LEN",
  format: nil, rand: nil, date_trunc: nil,
  bit_and: nil, bit_or: nil, bit_xor: nil,
  current_date: nil, current_time: nil, localtime: nil, localtimestamp: nil,
}.freeze

Instance Method Summary collapse

Instance Method Details

#add_interval(date, amount, unit, subtract, _date_only) ⇒ Object

DATEADD(day, 3, x), the unit a bare keyword; a subtraction is a negative amount, there being no DATESUB.



41
42
43
44
45
46
# File 'lib/active_record/refined/dialect/sql_server.rb', line 41

def add_interval(date, amount, unit, subtract, _date_only)
  Arel::Nodes::NamedFunction.new(
    "DATEADD",
    [Arel::Nodes::SqlLiteral.new(unit.to_s),
     Arel::Nodes.build_quoted(subtract ? -amount : amount), date])
end

#check_string_aggregate_window(model) ⇒ Object

Raises:

  • (NotImplementedError)


58
59
60
61
# File 'lib/active_record/refined/dialect/sql_server.rb', line 58

def check_string_aggregate_window(model)
  raise NotImplementedError,
    "string_agg over a window has no equivalent on #{model.connection_db_config.adapter}"
end

#datetime_precision_supported?Boolean

Returns:

  • (Boolean)


26
# File 'lib/active_record/refined/dialect/sql_server.rb', line 26

def datetime_precision_supported? = false

#extract_supported?Boolean

No EXTRACT (it has DATEPART), and its datetime value functions take no precision.

Returns:

  • (Boolean)


25
# File 'lib/active_record/refined/dialect/sql_server.rb', line 25

def extract_supported? = false

#filter_supported?Boolean

No FILTER clause, so the aggregate node builds the CASE instead.

Returns:

  • (Boolean)


21
# File 'lib/active_record/refined/dialect/sql_server.rb', line 21

def filter_supported? = false

#json_argument(value, _model) ⇒ Object

A document, a boolean or a bare scalar written where JSON is wanted rides in through JSON_QUERY as the JSON it spells.



80
81
82
83
# File 'lib/active_record/refined/dialect/sql_server.rb', line 80

def json_argument(value, _model)
  Arel::Nodes::NamedFunction.new(
    "JSON_QUERY", [Arel::Nodes.build_quoted(JSON.generate(value))])
end

#json_has_key(document, _name, path, _model) ⇒ Object

JSON_PATH_EXISTS returns a bit, which the condition compares to 1.



72
73
74
75
76
# File 'lib/active_record/refined/dialect/sql_server.rb', line 72

def json_has_key(document, _name, path, _model)
  Arel::Nodes::Equality.new(
    Arel::Nodes::NamedFunction.new("JSON_PATH_EXISTS", [document, path]),
    Arel::Nodes.build_quoted(1))
end

#json_path(document, dollar_path, _steps, json_value, _model) ⇒ Object

dig_text reads a scalar out with JSON_VALUE; dig keeps JSON with JSON_QUERY, which returns a fragment and NULL for a scalar leaf.



65
66
67
68
69
# File 'lib/active_record/refined/dialect/sql_server.rb', line 65

def json_path(document, dollar_path, _steps, json_value, _model)
  Arel::Nodes::NamedFunction.new(
    json_value ? "JSON_QUERY" : "JSON_VALUE",
    [document, Arel::Nodes.build_quoted(dollar_path)])
end

#json_remove(document, dollar_paths, _steps, _model) ⇒ Object

except: JSON_MODIFY deletes a key when it sets it to a literal NULL, one nested call per key.



95
96
97
98
99
100
101
# File 'lib/active_record/refined/dialect/sql_server.rb', line 95

def json_remove(document, dollar_paths, _steps, _model)
  dollar_paths.reduce(document) do |doc, path|
    Arel::Nodes::NamedFunction.new(
      "JSON_MODIFY",
      [doc, Arel::Nodes.build_quoted(path), Arel::Nodes::SqlLiteral.new("NULL")])
  end
end

#json_set(document, _steps, dollar_path, value, expression, model) ⇒ Object

bury: JSON_MODIFY sets a value at a path.



86
87
88
89
90
91
# File 'lib/active_record/refined/dialect/sql_server.rb', line 86

def json_set(document, _steps, dollar_path, value, expression, model)
  Arel::Nodes::NamedFunction.new(
    "JSON_MODIFY",
    [document, Arel::Nodes.build_quoted(dollar_path),
     json_modify_value(value, expression, model)])
end

#string_agg(operand, separator, orders, _string, model) ⇒ Object

STRING_AGG, with the WITHIN GROUP only when there is an order to put in it.



50
51
52
53
54
55
56
# File 'lib/active_record/refined/dialect/sql_server.rb', line 50

def string_agg(operand, separator, orders, _string, model)
  call = Arel::Nodes::NamedFunction.new(
    "STRING_AGG", [operand, Arel::Nodes.build_quoted(separator)])
  return call if orders.empty?
  Arel.sql("#{compile(call, model)} WITHIN GROUP " \
           "(ORDER BY #{compile_list(orders, model)})")
end

#truth_value(operand, value, negated, _model) ⇒ Object

No boolean type: the column is a bit. ISNULL reads a NULL as the value the test is not looking for -- 0 for true?, 1 for false? -- so the plain form drops it and, being never NULL itself, the negation is exactly NOT of the plain form, matching what ! builds.



32
33
34
35
36
37
# File 'lib/active_record/refined/dialect/sql_server.rb', line 32

def truth_value(operand, value, negated, _model)
  equals = Arel::Nodes::Equality.new(
    Arel::Nodes::NamedFunction.new("ISNULL", [operand, value ? 0 : 1]),
    value ? 1 : 0)
  negated ? Arel::Nodes::Not.new(equals) : equals
end