Class BuiltInFunction

java.lang.Object
dev.frostlake.functions.BuiltInFunction
Direct Known Subclasses:
AddMonths, AggregateFunction, AggregationConstraint, ApproxPercentileEstimate, ApproxTopKEstimate, ArrayCat, ArrayCompact, ArrayConstruct, ArrayConstructCompact, ArrayContains, ArrayDistinct, ArrayExcept, ArrayFlatten, ArrayGenerateRange, ArrayInsert, ArrayIntersection, ArrayMax, ArrayMin, ArrayPosition, ArrayPrepend, ArrayRemove, ArrayRemoveAt, ArrayRepeat, ArrayReverse, ArraySlice, ArraySort, ArraysOverlap, ArraysToObject, ArraysZip, AsDecimal, AsInteger, AsTimestampNtz, Base64Decode, Base64DecodeBinary, Base64Encode, BinaryAsString, BitCount, BoolAnd, BoolNot, BoolOr, BoolXor, Cast, CheckJson, CheckXml, Coalesce, Collate, Collation, Compress, ConvertTimezone, CurrentAccount, CurrentAccountName, CurrentAvailableRoles, CurrentClient, CurrentDatabase, CurrentDate, CurrentIpAddress, CurrentOrganizationName, CurrentRegion, CurrentRole, CurrentRoleType, CurrentSchema, CurrentSchemas, CurrentSecondaryRoles, CurrentSession, CurrentStatement, CurrentTime, CurrentTimestamp, CurrentTransaction, CurrentUser, CurrentVersion, CurrentWarehouse, DateAdd, DateDiff, DateFromParts, DatePart, DateTrunc, DayFn, DayName, DayOfWeekFn, DayOfWeekIso, DayOfYear, Decode, DecompressBinary, DecompressString, Decrypt, DecryptRaw, Encrypt, EncryptRaw, EqualNull, Extract, FlGetContentType, FlGetEtag, FlGetFileType, FlGetLastModified, FlGetRelativePath, FlGetScopedFileUrl, FlGetSize, FlGetStage, FlGetStageFileUrl, FlIsAudio, FlIsCompressed, FlIsDocument, FlIsImage, FlIsVideo, Getdate, GetDdl, GetIgnoreCase, Greatest, GreatestIgnoreNulls, GroupingFn, GroupingIdFn, HashFn, HexDecode, HexDecodeBinary, HexEncode, HourFn, Iff, IfNull, Ilike, InvokerRole, IsRoleInSession, IsVector, JoinConstraint, JsonExtractPathText, LastDay, LastQueryId, LastTransaction, Least, LeastIgnoreNulls, Like, MapCat, MapConstruct, MapContainsKey, MapDelete, MapEntries, MapInsert, MapKeys, MapPick, MapSize, Md5, Md5Binary, Md5Hex, Md5NumberLower64, Md5NumberUpper64, MinuteFn, MonthFn, MonthName, MonthsBetween, Negate, NextDay, NextVal, NoAggregationConstraint, Normal, NowFn, NullIf, NullIfZero, NumericArgumentFunction, Nvl, Nvl2, ObjectConstruct, ObjectDelete, ObjectPick, ParseJson, ParseXml, Pi, PreviousDay, ProjectionConstraint, QuarterFn, Random, RegrValx, RegrValy, Search, SecondFn, SeqFn, Sha1, Sha1Binary, Sha1Hex, Sha2, Sha2Binary, Sha2Hex, StringAsBinary, StripNullValue, StructuredArgumentFunction, Sysdate, Systimestamp, TextArgumentFunction, TimeAdd, TimeDiff, TimeFromParts, TimeSlice, TimestampFromParts, ToArray, ToBinary, ToBoolean, ToChar, ToDate, ToDecfloat, ToDouble, ToFile, ToNumber, ToObject, ToTime, ToTimestamp, ToTimestampNtz, ToUuid, ToVariant, TryBase64Decode, TryBase64DecodeBinary, TryCast, TryDecrypt, TryDecryptRaw, TryHexDecode, TryHexDecodeBinary, TryParseJson, TryToBinary, TryToBoolean, TryToDate, TryToDecfloat, TryToDouble, TryToFile, TryToNumber, TryToTime, TryToTimestamp, TryToUuid, UuidString, VariantAccessorFunction, VectorCosineSimilarity, VectorInnerProduct, VectorL1Distance, VectorL2Distance, VectorNormalize, VectorTrunc, WeekFn, WeekIso, WeekOfYear, XmlGet, YearFn, YearOfWeek, YearOfWeekIso

public abstract class BuiltInFunction extends Object
  • Constructor Details

    • BuiltInFunction

      protected BuiltInFunction(String name, DataType returnType)
  • Method Details

    • getName

      public String getName()
    • getReturnType

      public DataType getReturnType()
    • evaluate

      public abstract Object evaluate(List<Object> args)
      Computes the function's result over its already-evaluated argument values. A SQL NULL argument arrives as Java null, and returning null makes the SQL result NULL.
      Parameters:
      args - the argument values, in call order
      Returns:
      the function's value for these arguments, or null for SQL NULL
    • evaluate

      public Object evaluate(List<Object> args, CollationSpec collation)
      The same, for a call whose arguments settled on a collation. A function that COMPARES text — CONTAINS, REPLACE, NULLIF and their kin — looks for what the collation calls equal rather than what matches byte for byte; every other function answers as it always did.
      Parameters:
      args - the argument values, in call order
      collation - the collation the call settled on, or null when it carries none
      Returns:
      the function's value for these arguments, or null for SQL NULL
    • getMinArgCount

      public abstract int getMinArgCount()
      The fewest arguments a call to this function may pass; fewer is an argument-count error.
      Returns:
      the minimum accepted argument count
    • getMaxArgCount

      public abstract int getMaxArgCount()
      The most arguments a call to this function may pass; Integer.MAX_VALUE marks a variadic function (see isVariadic()).
      Returns:
      the maximum accepted argument count
    • isVariadic

      public boolean isVariadic()
    • semiStructuredRejection

      public SemiStructuredRejection semiStructuredRejection(int position)
      How argument position refuses a statically OBJECT- or ARRAY-typed value, or SemiStructuredRejection.NONE when it does not. Snowflake never implicitly coerces a semi-structured value to the VARCHAR (or NUMBER) a text or numeric function reads, so such an argument is an argument-type error at COMPILE time rather than a stringification or a fabricated zero: live, UPPER(o) over an OBJECT column is "Invalid argument types for function 'UPPER': (OBJECT)", SUM(o) is the same sentence for 'SUM', and SPLIT_PART(s, o, 1) names the position it was given. VARIANT is never refused, even when it holds an object.

      Declared HERE, on the function, rather than in a name-keyed table beside the rule: the registry is already the authority on a function's types (getReturnType()), a declaration on the instance covers the function's ALIASES for free (SUBSTR and SUBSTRING are one object, and so are VARIANCE_POP and VAR_POP), and a per-position answer is the only shape that fits — ARRAY_TO_STRING(a, ',') takes an ARRAY in position 0 and refuses one in position 1.

      The answer is an ENUM rather than a boolean because Snowflake phrases the refusal three different ways, with three different SQLSTATEs — see SemiStructuredRejection.

      The default is NONE, meaning UNDECLARED rather than "accepts": a function that has not been measured against live Snowflake constrains nothing. Answering for every position is what TextArgumentFunction and NumericArgumentFunction exist for.

      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the refusal this position gives a semi-structured value, or NONE when undeclared
    • structuredRejection

      public SemiStructuredRejection structuredRejection(int position)
      The EXTRA refusal argument position reserves for a STRUCTURED value — OBJECT(x VARCHAR), ARRAY(INT), MAP(VARCHAR, INT) — where the plain semi-structured OBJECT or ARRAY is ACCEPTED. Consulted only when semiStructuredRejection(int) declares nothing for the position, so a function that refuses every semi-structured value keeps saying so in one place.

      The two are separate because Snowflake genuinely treats OBJECT and OBJECT(x VARCHAR) as different types, and they DIVERGE — measured over populated columns of both: ARRAY_AGG(o) returns the array while ARRAY_AGG(so) is an argument-type error, TO_JSON(o) returns the JSON text while TO_JSON(so) is refused, and TYPEOF, IS_OBJECT, AS_VARCHAR, ARRAY_TO_STRING and the constructors all split the same way. A single rule keyed on "is this semi-structured?" gets both cases wrong in opposite directions, which is why the answer is asked twice.

      What a structured type does NOT get is a rejection anywhere the plain types are accepted as KEYS: live, GROUP BY so, ORDER BY so, SELECT DISTINCT so, PARTITION BY so, the set operators, JOIN … ON so = so and COUNT(DISTINCT so) all work over each of the three structured kinds — that was measured rather than inferred from the plain behaviour.

      The default is NONE for the same reason as above: undeclared means unconstrained.

      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the extra refusal this position gives a structured value, or NONE when undeclared
    • fileRejection

      public SemiStructuredRejection fileRejection(int position)
      How argument position refuses a statically FILE-typed value. A FILE IS an object of file metadata, and Frostlake used to let it stringify to that descriptor — so LENGTH(f) counted the JSON, UPPER(f) upper-cased its KEYS and SUM(f) answered a number — but Snowflake refuses it at COMPILE time exactly as it refuses an OBJECT: live, UPPER(f) is "Invalid argument types for function 'UPPER': (FILE)" and SUM(f) is the same sentence for 'SUM'.

      The DEFAULT is semiStructuredRejection(int), because that is what the account says: over a populated FILE column, every one of the 52 text functions, the 42 numeric functions and the numeric / moment / percentile aggregates refuses a FILE with the SAME shape and the SAME sentence it gives an OBJECT, down to the SQLSTATE — MEDIAN(f) is "incompatible types: [FILE] and [NUMBER(9,0)]" (42846) where SUM(f) is the argument-type list (42P13), and STDDEV(f) reports its internal "'*': (FILE, FILE)" just as STDDEV(o) does.

      It is nevertheless a THIRD question rather than a reuse of the first, because FILE and the semi-structured types genuinely DIVERGE in both directions, and a shared answer would be wrong each way. ARRAY_AGG and ARRAY_UNIQUE_AGG refuse a structured value and ACCEPT a FILE; OBJECT_AGG's VALUE position takes a plain OBJECT and REFUSES a FILE; and OBJECT_CONSTRUCT accepts a FILE as a value while refusing it as a KEY. Those three override this method; everything else is answered by the default.

      What a FILE does NOT get is a rejection where it is used as a VALUE rather than read: live, f = f, SELECT DISTINCT f, COUNT(f), COUNT(DISTINCT f), ANY_VALUE, ARRAY_AGG, HASH, HASH_AGG, MAX_BY / MIN_BY, APPROX_COUNT_DISTINCT, the conditionals, JOIN … ON a.f = b.f and the set operators all take a FILE. Only MAX / MIN / MODE refuse it among the aggregates that ORDER, and they say so with their own sentence.

      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the refusal this position gives a FILE value; by default, the semi-structured answer
    • geoRejection

      public SemiStructuredRejection geoRejection(int position)
      How argument position refuses a statically GEOGRAPHY- or GEOMETRY-typed value. A geo value is a DOMAIN type that coerces to nothing: not to the VARCHAR or NUMBER a text or numeric function reads, and not to the VARIANT the semi-structured surface reads — so live refuses it in both families at COMPILE time. Measured over a populated GEOGRAPHY column and a GEOMETRY column in the same table: UPPER(g) is "Invalid argument types for function 'UPPER': (GEOGRAPHY)", SUM(g) names 'SUM', MEDIAN(g) is "incompatible types: [GEOGRAPHY] and [NUMBER(9,0)]", STDDEV(g) reports its internal "'*': (GEOGRAPHY, GEOGRAPHY)", ARRAY_CONSTRUCT(g) is "does not support GEOGRAPHY argument type" and TO_VARCHAR(g) is the conversion sentence. Frostlake used to accept every one of them and answer from the GeoJSON text, so UPPER(g) upper-cased the JSON KEYS and SUM(g) returned a number.

      The DEFAULT is the UNION of the two semi-structured answers — semiStructuredRejection(int) when it says anything, structuredRejection(int) otherwise — because that is what the account says: a geo value is refused wherever EITHER a plain OBJECT or a merely STRUCTURED one is refused, with the same sentence and the same SQLSTATE. It reaches the right answer for the text family, the numeric family, SUM / AVG / LISTAGG / MEDIAN / the moment aggregates (through the first), and for TYPEOF, TO_JSON, IS_OBJECT, AS_VARCHAR, ARRAY_AGG, OBJECT_AGG, the constructors and TO_VARCHAR / TO_CHAR (through the second).

      It is nevertheless a FOURTH question rather than a reuse, because geo REFUSES a surface both semi-structured kinds accept, and the overriding classes say so one at a time: live, HASH_AGG(o), MAX_BY(o, n), APPROX_COUNT_DISTINCT(o), GET(o, 'k'), OBJECT_KEYS(o), ARRAY_SIZE(o), OBJECT_INSERT(o, 'a', 1), PARSE_JSON, GREATEST(o, o), LEAST(o, o) and EQUAL_NULL(o, o) all return a value over an OBJECT and are argument-type errors over a GEOGRAPHY.

      What a geo value does NOT get is a rejection where it is carried rather than read: live, SELECT DISTINCT g, COUNT(g), COUNT(DISTINCT g), ANY_VALUE(g), HASH(g), FIRST_VALUE / LAST_VALUE, IFF / COALESCE / NVL / IFNULL / NVL2 / DECODE / CASE, the set operators and TO_GEOGRAPHY / TO_GEOMETRY all take one.

      The default is NONE for an unmeasured function, for the same reason as the other three: undeclared means unconstrained.

      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the refusal this position gives a GEOGRAPHY or GEOMETRY value; by default, the union of the two semi-structured answers
    • binaryRejection

      public SemiStructuredRejection binaryRejection(int position)
      The refusal a position gives a statically BINARY-typed value.

      A fifth question rather than a reuse of any of the four above, because BINARY sits on the opposite side of them: it is a scalar a text function is happy to be handed almost everywhere — live answers LENGTH(bn), SUBSTR(bn, 1, 1), CONCAT(bn, bn) — where an OBJECT is refused. Only the functions that read their argument AS TEXT and would have to decode it refuse one, and they say so themselves: VALIDATE_UTF8(bn) and TRY_VALIDATE_UTF8(bn) are "Invalid argument types for function 'TRY_VALIDATE_UTF8': (BINARY(5))" while the same call over a VARCHAR, and even over a NUMBER, returns a value.

      The default is NONE: undeclared means unconstrained, as for the other four.

      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the refusal this position gives a BINARY value; by default none
    • vectorRejection

      public SemiStructuredRejection vectorRejection(int position)
      The refusal this position gives a VECTOR argument.

      A vector is not semi-structured and is not binary, so it needs its own declaration: the functions that refuse one are the TEXT CONVERSIONS and the concatenations, and they refuse in two different shapes — the conversion sentence quotes the whole call, the concatenation lists argument types and carries a position.

      The default is NONE: undeclared means unconstrained, as for the others.

      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the refusal this position gives a VECTOR value; by default none
    • uuidRejection

      public SemiStructuredRejection uuidRejection(int position)
      The refusal this position gives a declared UUID argument. A UUID is its own type on the account, and the ordering aggregates refuse it — "Function MAX does not support UUID argument type" — while the text functions read it as the text it holds.
      Parameters:
      position - the argument's position, counted from zero
      Returns:
      how it is refused, or SemiStructuredRejection.NONE when it is taken
    • booleanRejection

      public SemiStructuredRejection booleanRejection(int position)
      The refusal this position gives a declared BOOLEAN argument. Membership is declared per function and never assumed for a family: the whole NUMERIC family (NumericArgumentFunction) refuses a SQL BOOLEAN at compile time in every position — "Invalid argument types for function 'ABS': (BOOLEAN)", MOD(1, TRUE) listing "(NUMBER(1,0), BOOLEAN)" — while the SAME value inside a VARIANT converts to 1.0, and the conditionals (NULLIF(b, 0), NULLIFZERO(b)) take it. The rule reads the DECLARED type, like every channel here.
      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the refusal this position gives a BOOLEAN value; by default none
    • temporalRejection

      public SemiStructuredRejection temporalRejection(int position)
      The refusal this position gives a declared DATE / TIME / TIMESTAMP argument. Declared per function: the numeric family refuses every temporal flavour at compile time, each named with its own parameters — (DATE), (TIME(9)), (TIMESTAMP_NTZ(9)) and the LTZ/TZ twins — where the datetime functions read them happily.
      Parameters:
      position - the zero-based argument position being asked about
      Returns:
      the refusal this position gives a temporal value; by default none
    • temporalRejection

      public SemiStructuredRejection temporalRejection(int position, int argumentCount)
      The refusal this position gives a declared temporal argument in a call of argumentCount arguments. One member's answer depends on the call's ARITY: TRUNC over a temporal is DATE_TRUNC with a unit, so a temporal first argument BESIDE a unit is legal while the same argument alone is refused "(DATE)" — live-verified. Every other function answers the arity-blind question, which is what this consults by default.
      Parameters:
      position - the zero-based argument position being asked about
      argumentCount - how many arguments the call carries
      Returns:
      the refusal this position gives a temporal value in a call of that arity
    • temporalRejection

      public SemiStructuredRejection temporalRejection(int position, int argumentCount, DataType temporal)
      The refusal this position gives a declared temporal argument of type temporal. One member's answer depends on WHICH temporal type arrives: the TIME synonym takes a DATE (its midnight) and every timestamp flavour, and refuses only a TIME. Every other function answers without looking, which is what this consults by default.
      Parameters:
      position - the zero-based argument position being asked about
      argumentCount - how many arguments the call carries
      temporal - the argument's declared temporal type
      Returns:
      the refusal this position gives that temporal value
    • refusesMissingArgumentsByType

      public boolean refusesMissingArgumentsByType()
      Whether a call with fewer arguments than getMinArgCount() is refused by its argument types rather than by its count. A function the account resolves among overloads has no single count to report: live, TIME() is "Invalid argument types for function 'TIME': ()" where LOG(10) is "not enough arguments for function [LOG(10)], expected 2, got 1".
      Returns:
      true when the refusal lists the argument types; false by default
    • textRejection

      public SemiStructuredRejection textRejection(int position)
      How the function treats a TEXT argument at position — NONE for the many that take one.
    • approximateRejection

      public SemiStructuredRejection approximateRejection(int position)
      How the function treats an APPROXIMATE numeric argument at position.