Class SqlCompilationError

java.lang.Object
dev.frostlake.executor.SqlCompilationError

public final class SqlCompilationError extends Object
How Snowflake lays out a compilation-error message.

The detail always begins on a SECOND line — "SQL compilation error:", a newline, then the detail. When the error carries a source position, that clause and only that clause stays on the first line, and the newline comes after it. Measured on a real account, with the newlines shown escaped exactly as the driver returns them:

 SELECT MAX(OBJECT_CONSTRUCT('k',1))  -> SQL compilation error:\nFunction MAX does not support OBJECT …
 SELECT 1::NOSUCHTYPE                 -> SQL compilation error:\nUnsupported data type 'NOSUCHTYPE'.
 SELECT 1::FILE                       -> SQL compilation error:\ninvalid type [CAST(1 AS FILE)] for …
 DROP VIEW nosuchview                 -> SQL compilation error:\nView '…' does not exist or not …
 SELCT 1                              -> SQL compilation error:\nsyntax error line 1 at position 0 …
 SELECT nosuchcolumn FROM …           -> SQL compilation error: error line 1 at position 7\ninvalid …
 SELECT a, b FROM t GROUP BY a        -> SQL compilation error: error line 1 at position 10\n'T.B' in …
 

Note where the two forms differ: a SYNTAX error spells its position inside the detail, on the second line, while a positioned SEMANTIC error spells it on the first. Runtime (non-compilation) failures such as Date 'a' is not recognized carry no prefix at all and do not belong here.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    The prefix, without the separator that follows it.
  • Method Summary

    Modifier and Type
    Method
    Description
    static String
    at(int line, int position, String detail)
     
    static String
    atCapitalised(int line, int position, String detail)
    The positioned form spelled with a CAPITAL E — SQL compilation error: Error line 1 at position 7.
    static String
    The one column phrasing that is NOT "invalid identifier": ALTER TABLE … DROP COLUMN nosuch answers column 'NOSUCH' does not exist — lower-case kind, no position, and no "or not authorized" tail
    static String
    A copy option given twice — first line like the file-format twin, then a trailing newline.
    static String
    A file-format parameter given twice.
    static String
    doesNotExist(String kind, String name)
     
    static String
    A second constraint over the same columns — live names neither constraint.
    static String
    A property given twice in one statement.
    static String
    inline(String detail)
    A compilation error whose detail follows the prefix ON THE SAME LINE, after a space, with no newline anywhere — the layout the date-part slot family keeps: live spells "SQL compilation error: Date/time component [TO_CHAR(1) ]for function TRUNC needs to be an identifier or a string literal." as one line, where the argument-type and conversion sentences break after the prefix.
    static String
    invalidIdentifier(int line, int position, String name)
    An invalid identifier whose source position IS known.
    static String
    A name that resolves to no COLUMN.
    static String
    invalidPropertyFor(String value, String property)
    The THIRD phrasing an enumerated warehouse property uses for a value outside its vocabulary.
    static String
    invalidValueForParameter(String rendered, String parameter)
    The invalid-VALUE refusal for a parameter, brackets around the rendered value.
    static String
    The property-flavored twin, single-quoted — warehouse numerics and the sequence increment.
    static boolean
    Whether a message is one of these — a COMPILE-time refusal rather than a failure that only showed up while rows were being produced.
    static boolean
    Whether a message is the wrong-kind refusal above, which IF EXISTS must not swallow.
    static String
    A column carrying more than one DEFAULT / AUTOINCREMENT / IDENTITY.
    static String
    The sentence live gives when a SHOW cannot reach its scope — for the kinds that do not name what was missing.
    static String
    objectOfOtherType(String found, String specified)
    A DROP that names the wrong kind.
    static String
    of(String detail)
    A compilation error whose detail starts on the second line.
    static String
    A second PRIMARY KEY on one table, inline or table-level.
    static String
    trailing(String detail)
    The ONE sentence family that lays itself out differently: the detail follows the prefix on its OWN line, after a space, and a newline closes the message instead of separating it.
    static String
    The sentence live gives for a kind-less USE of a name with more than two parts, verbatim — the account's own template, with its line and position placeholders left unfilled.
    static String
    The POSITIONED layout with an EMPTY position — the separating space survives where the "error line N at position M" would go, so the message opens "SQL compilation error: " with a trailing space before its newline.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

  • Method Details

    • of

      public static String of(String detail)
      A compilation error whose detail starts on the second line.
    • inline

      public static String inline(String detail)
      A compilation error whose detail follows the prefix ON THE SAME LINE, after a space, with no newline anywhere — the layout the date-part slot family keeps: live spells "SQL compilation error: Date/time component [TO_CHAR(1) ]for function TRUNC needs to be an identifier or a string literal." as one line, where the argument-type and conversion sentences break after the prefix.
      Parameters:
      detail - the sentence
      Returns:
      the message as the driver hands it to a client
    • trailing

      public static String trailing(String detail)
      The ONE sentence family that lays itself out differently: the detail follows the prefix on its OWN line, after a space, and a newline closes the message instead of separating it.
       ALTER TABLE t ALTER COLUMN f SET DATA TYPE NUMBER(10,2)
           SQL compilation error: cannot change column F from type FLOAT to NUMBER(10,2)\n
       

      This is a property of the SENTENCE, not of the statement and not of un-positioned errors in general — which is worth stating plainly, because it looks like both. Twenty-one other un-positioned refusals were measured in one run and every one of them uses of(java.lang.String)'s layout, including three raised by ALTER TABLE itself (column 'I' already exists, column 'X' does not exist, Object 'T.C' already exists.). Only "cannot change column …" reads this way, in all eight retype directions.

      Parameters:
      detail - the sentence, which supplies its own full stop where it has one
      Returns:
      the message as the driver hands it to a client
    • isCompilationError

      public static boolean isCompilationError(String message)
      Whether a message is one of these — a COMPILE-time refusal rather than a failure that only showed up while rows were being produced. The distinction matters wherever Frostlake reaches an answer by executing something Snowflake merely plans.

      One compile-time refusal is worded WITHOUT the prefix: an invalid collation specification (Invalid value 'xx-yy' for COLLATION. Reason: Unknown option: yy), which live raises while the statement compiles all the same — over an empty table, and in a CREATE TABLE. It counts here, so every site that lets a compile-time refusal through lets it through too.

      Parameters:
      message - the exception message, which may be null
      Returns:
      true when the message carries this prefix, or is the collation refusal
    • atCapitalised

      public static String atCapitalised(int line, int position, String detail)
      The positioned form spelled with a CAPITAL E — SQL compilation error: Error line 1 at position 7. Live uses it for the literal READER's refusals and the lower-case at(int, int, java.lang.String) for the identifier and syntax families; the difference is measured, not a typo, and it is one of the few places the word is capitalised at all.
    • withoutPosition

      public static String withoutPosition(String detail)
      The POSITIONED layout with an EMPTY position — the separating space survives where the "error line N at position M" would go, so the message opens "SQL compilation error: " with a trailing space before its newline.

      That trailing space is live's, not a stray character: measured in one run beside the window-inside-an-aggregate refusal, which uses of(java.lang.String) and has no trailing space. The two shapes sit side by side in the same family, so the difference is real.

    • at

      public static String at(int line, int position, String detail)
    • duplicateProperty

      public static String duplicateProperty(String name)
      A property given twice in one statement. The trailing semicolon is a real account's, not a typo, and the name is the property's INTERNAL spelling where the two differ (a sequence's START reports as SEQUENCE_START).
    • conflictingFileFormatParameter

      public static String conflictingFileFormatParameter(String name)
      A file-format parameter given twice. A different shape from duplicateProperty(java.lang.String), and measured: the detail stays on the FIRST line, after a space, with no closing punctuation.
    • conflictingCopyOption

      public static String conflictingCopyOption(String name)
      A copy option given twice — first line like the file-format twin, then a trailing newline.
    • multipleDefaultOrAutoincrement

      public static String multipleDefaultOrAutoincrement(String column)
      A column carrying more than one DEFAULT / AUTOINCREMENT / IDENTITY. Its shape is a third one again — a space AFTER the colon, then the newline, and the sentence ends in a period.
    • primaryKeyAlreadyExists

      public static String primaryKeyAlreadyExists(String table)
      A second PRIMARY KEY on one table, inline or table-level.
    • duplicateConstraintSignature

      public static String duplicateConstraintSignature(String table)
      A second constraint over the same columns — live names neither constraint.
    • invalidValueForParameter

      public static String invalidValueForParameter(String rendered, String parameter)
      The invalid-VALUE refusal for a parameter, brackets around the rendered value. What sits in the brackets follows the surface that raised it: format and copy options echo a quoted string WITH its quotes, session parameters strip them, integers and barewords stay bare.
    • invalidValueForProperty

      public static String invalidValueForProperty(String value, String property)
      The property-flavored twin, single-quoted — warehouse numerics and the sequence increment.
    • invalidPropertyFor

      public static String invalidPropertyFor(String value, String property)
      The THIRD phrasing an enumerated warehouse property uses for a value outside its vocabulary. The three are not interchangeable, and each belongs to one property (live-verified):
         WAREHOUSE_SIZE   invalid type of property 'HUGE' for 'WAREHOUSE_SIZE'
         SCALING_POLICY   invalid value 'NOSUCH' for property 'SCALING_POLICY'      invalidValueForProperty(java.lang.String, java.lang.String)
         WAREHOUSE_TYPE   invalid property 'NOSUCH' for 'WAREHOUSE_TYPE'            this one
       

      Same mistake, three sentences — so the wording is per property and cannot be shared.

    • objectDoesNotExist

      public static String objectDoesNotExist()
      The sentence live gives when a SHOW cannot reach its scope — for the kinds that do not name what was missing. Measured across all three scope forms (IN SCHEMA db.missing, IN SCHEMA missing, IN DATABASE missing): TABLES, VIEWS, STAGES, FILE FORMATS and DYNAMIC TABLES answer exactly this, while PIPES, STREAMS, TASKS, SEQUENCES, TAGS, the two policy kinds, CORTEX SEARCH SERVICES, PROCEDURES, FUNCTIONS and COLUMNS name the missing schema or database instead. Which one a kind uses is a property of the kind, not of the scope form. Every USE that resolves nothing — a database, a schema, a role, a quoted name in the wrong case — answers it too.
    • useNameForm

      public static String useNameForm()
      The sentence live gives for a kind-less USE of a name with more than two parts, verbatim — the account's own template, with its line and position placeholders left unfilled.
    • doesNotExist

      public static String doesNotExist(String kind, String name)
    • invalidIdentifier

      public static String invalidIdentifier(String name)
      A name that resolves to no COLUMN. Snowflake does not phrase this like a missing object at all — measured, a column nobody can resolve is an invalid identifier, in the select list, a WHERE, an ORDER BY, a GROUP BY, an INSERT column list, an UPDATE SET, a view body, an aggregate argument, and every ALTER COLUMN form:
       SELECT nosuchcol FROM t              -> …error line 1 at position 7\ninvalid identifier 'NOSUCHCOL'
       SELECT t.nosuchcol FROM t            -> …position 7\ninvalid identifier 'T.NOSUCHCOL'
       ALTER TABLE t ADD PRIMARY KEY (nsc)  -> …position 31\ninvalid identifier 'NSC'
       

      Live always carries the source position on these. Frostlake resolves columns from an expression AST that does not record one (ColumnReferenceExpression keeps only the names), so the positioned overload is used where a parse context is at hand and this one elsewhere — the wording matches, the position clause is absent. Threading positions through the AST is a separate change.

    • invalidIdentifier

      public static String invalidIdentifier(int line, int position, String name)
      An invalid identifier whose source position IS known.
    • columnDoesNotExist

      public static String columnDoesNotExist(String name)
      The one column phrasing that is NOT "invalid identifier": ALTER TABLE … DROP COLUMN nosuch answers column 'NOSUCH' does not exist — lower-case kind, no position, and no "or not authorized" tail. (RENAME COLUMN is different again and reports an Object; it uses doesNotExist(java.lang.String, java.lang.String).)
    • objectOfOtherType

      public static String objectOfOtherType(String found, String specified)
      A DROP that names the wrong kind. The five relation kinds share one name space, so the object IS found - just not as the statement spells it - and the sentence names both kinds on one line, as Object found is of type 'VIEW', not specified type 'TABLE'. IF EXISTS does not forgive it (live-verified).
      Parameters:
      found - the kind holding the name
      specified - the kind the statement named
      Returns:
      the message as the driver hands it to a client
    • isWrongObjectType

      public static boolean isWrongObjectType(String message)
      Whether a message is the wrong-kind refusal above, which IF EXISTS must not swallow.