Class SystemTypeOfDescription

java.lang.Object
dev.frostlake.executor.SystemTypeOfDescription

public final class SystemTypeOfDescription extends Object
What SYSTEM$TYPEOF answers: a DECLARED type name and a physical storage tag, and the two come from different places — which is the whole point of this class.
   SYSTEM$TYPEOF(<NUMBER(10,2) holding 1.00>)      NUMBER(10,2)[SB1]
   SYSTEM$TYPEOF(<NUMBER(10,2) holding 1000.00>)   NUMBER(10,2)[SB4]
   SYSTEM$TYPEOF(<VARCHAR(5)>)                      VARCHAR(5)[LOB]
   SYSTEM$TYPEOF(UPPER(<VARCHAR(5)>))               VARCHAR(15)[LOB]
 

★ THE NAME IS THE DECLARED TYPE, THE TAG IS THE INTERVAL OF VALUES THE PLAN CAN SEE. The two cells above share a declaration and differ only in what they hold, and their tags differ — so the tag cannot be derived from the type, and the name cannot be derived from the value. Frostlake used to read the VALUE for both, which is why a DATE answered TIMESTAMP_NTZ, a TIME and a BINARY answered VARCHAR, and any expression that happened to evaluate to NULL answered NULL however well typed.

★ THE TAG IS NOT THE ROW'S OWN VALUE EITHER. A column is tagged by its statistics — the widest value anywhere in the table, on every row alike, whatever a WHERE keeps — and an expression by the interval those statistics propagate through it (ValueRange): c + 1 widens the interval by one, SUM(c) multiplies it by a trillion, MAX(c) narrows it to the greatest value, COUNT(c) runs from zero to the row count. Where no interval can be known — a ROUND, a LENGTH, a ROW_NUMBER, a cast from text — the tag is the declared width's own.

★ SBn IS THE SMALLEST SIGNED-INTEGER WIDTH THAT HOLDS THE UNSCALED VALUE — the rule itself lives in SignedStorageWidth, shared with the out-of-representable-range refusal, which reads the same tag off the value it could not store. Measured at the byte boundaries rather than guessed: 127 is SB1 and 128 is SB2; 32767 is SB2 and 32768 is SB4; eleven digits are SB8 and twenty-six are SB16. A NUMBER(38,0) holding only 1 is SB1, so the DECLARED precision enters only when nothing narrower is known.

★ EVERY OTHER FAMILY'S TAG IS FIXED: BOOLEAN is SB1, DATE is SB4, TIME is SB8, all three TIMESTAMP flavours are SB16, FLOAT is DOUBLE, and the variable-length families — VARCHAR, BINARY, ARRAY, OBJECT, VARIANT — are LOB. So [LOB] is not the universal tag it looked like from the string cells alone. The one exception is a boolean PREDICATE — a comparison, IS NULL, IN, LIKE, a predicate function, or NOT / AND / OR over one — which the plan carries as ROWINDEX: SYSTEM$TYPEOF(1 = 2) is BOOLEAN[ROWINDEX] where SYSTEM$TYPEOF(NOT TRUE) is BOOLEAN[SB1].

★ A NULL VALUE KEEPS ITS DECLARED TYPE and takes the family's smallest tag, so CAST(NULL AS NUMBER(10,2)) is NUMBER(10,2)[SB1]. Only an argument with no type at all — a bare NULL — answers NULL[LOB].

  • Method Details

    • of

      public static String of(DataType declared, String typeText, ValueRange range, boolean predicate)
      The description for an argument of declared type whose values lie in range.
      Parameters:
      declared - the argument's declared type, or null when it has none
      typeText - the declared type as live spells it, e.g. NUMBER(10,2)
      range - the interval the argument's values lie in, or null when none is known — that decides an exact numeric's tag and nothing else
      predicate - whether the argument is a predicate, which a BOOLEAN is tagged ROWINDEX for