Class BinaryOperationTypes

java.lang.Object
dev.frostlake.executor.expressions.BinaryOperationTypes

public final class BinaryOperationTypes extends Object
The type an arithmetic or concatenation expression is statically KNOWN to produce. Every rule below was measured against a live account with both operand types pinned by an explicit cast, so the precision algebra is read off real answers rather than derived from the documentation. Writing L for an operand's leading digits (p - s):
  • + and -: scale is max(s1, s2) and precision max(L1, L2) + 1 + scale — the carry digit is why (1,0) + (1,0) answers NUMBER(2,0) and (5,1) + (3,2) answers NUMBER(7,2).
  • *: scale is s1 + s2 and precision p1 + p2 — (10,4) * (10,4) answers NUMBER(20,8).
  • /: the DIVIDEND alone drives the scale, which gains six digits — scale is s1 + 6 and precision L1 + s2 + scale, so (1,0) / (1,0) answers NUMBER(7,6) and (5,1) / (3,2) NUMBER(13,7).
  • %: scale is max(s1, s2) and the leading digits max(L1, L2, 2) — the floor of TWO leading digits is what makes (1,0) % (1,0) answer NUMBER(2,0) and (3,3) % (3,3) answer NUMBER(5,3), where the operands' own widths would give one and three.
  • Precision saturates at 38 rather than overflowing: (38,0) + (1,0) stays NUMBER(38,0), (38,0) / (1,0) answers NUMBER(38,6) and (38,0) % (11,10) NUMBER(38,10).
  • ||: two strings add their lengths, saturating at a VARCHAR's maximum — VARCHAR(4) with VARCHAR(9) answers VARCHAR(13) — and two binaries add theirs. A string beside a number, a temporal, a boolean or a VARIANT answers the FULL-WIDTH VARCHAR in either order, and a BINARY beside anything else is refused by live rather than typed.
  • FLOAT is contagious: mixed with any exact numeric the answer is FLOAT.
  • A DATE plus or minus a number of days is still a DATE, in either order for addition, and a DATE difference is a day count — NUMBER(9,0).

Anything not on that list answers null, which leaves the expression untyped rather than guessed at.

  • Method Details

    • resultOf

      public static DataType resultOf(BinaryOperator operator, DataType left, DataType right)
      The result type of left operator right, or null when it cannot be determined.
      Parameters:
      operator - the operator applied
      left - the left operand's static type, or null when it has none
      right - the right operand's static type, or null when it has none
      Returns:
      the statically known result type, or null
    • refusalFor

      public static String refusalFor(BinaryOperator operator, DataType left, DataType right)
      The refusal an operand pair earns, or null when the pair is legal or unjudged. Live answers Invalid argument types for function '||': (BINARY(4), VARCHAR(4)) — the operator quoted, both DECLARED types spelled in the order written. Deriving it from the static types rather than from the runtime values is what makes those declared widths available at all: a X'AB' sitting in a BINARY(4) column is one byte long, so a value-based check could only ever say BINARY(1).

      Only the BINARY concatenation mix is judged here so far. Two binaries concatenate legally, and every other pairing this class knows about is either legal or was measured without its full sentence being captured.

      Parameters:
      operator - the operator applied
      left - the left operand's static type, or null when it has none
      right - the right operand's static type, or null when it has none
      Returns:
      the refusal detail, or null
    • isArithmeticOperand

      public static boolean isArithmeticOperand(DataType type)
      Whether a family may stand beside an arithmetic operator: a number, a text or a VARIANT it converts, or a temporal value the measured temporal table then judges. BOOLEAN, BINARY, ARRAY and OBJECT are refused before any row (live-verified).
      Parameters:
      type - the operand's type, or null when it could not be typed
      Returns:
      whether arithmetic takes it
    • isLogicalOperand

      public static boolean isLogicalOperand(DataType type)
      Whether a family may stand beside a logical operator. BOOLEAN and NUMBER are read directly, and a text is converted where it is READ — TRUE OR 'a' is true on the account because OR never reads the second operand, while 'a' OR 'a' raises the conversion at run time. Everything else — BINARY, ARRAY, OBJECT and the temporal families — is refused before any row (live-verified).
      Parameters:
      type - the operand's type, or null when it could not be typed
      Returns:
      whether the operator takes it