/* tslint:disable */ /* eslint-disable */ /** * Additional query rules to apply during type-checking. */ type QueryValidationMode = "standard" | "record_local"; /** * Completion result with an exclusive range matching CodeMirror's convention. * `at` is a half-open range [start, end) where `start..end` covers the text to replace. * An empty range like `5..5` means "insert at position 5, replace nothing." */ interface Completion { at: { start: number; end: number }; filter: boolean | undefined; items: CompletionItem[]; } /** * JSON / TS shape for [`TemplateParameterKind`] in WASM bindings. */ type WasmTemplateParameterKind = { kind: "primitive"; type: TemplateParameterType } | { kind: "identifier_fragment"; values: string[] }; /** * JSON / TS shape for [`TemplateParameterValue`] when substituting template parameters. */ type WasmTemplateParameterValue = { kind: "boolean"; value: boolean } | { kind: "int"; value: number } | { kind: "double"; value: number } | { kind: "string"; value: string } | { kind: "interval"; value: string }; /** * One output column of type `timestamp` with optional `TruncUnit` and `multiplier` from `@` truncation. */ interface OutputTimestampColumn { name: string; unit?: TruncUnit; multiplier?: number; } interface BuildCatalogOutput { catalog: Catalog; errors: BuildCatalogError[]; } interface CatalogResource { name: QualifiedDatasetIdentifier; query: string; isUnion: boolean; } interface Column { name: SimpleIdentifier; type: HamelinType; } interface CombineQueriesForInliningOk { query: string; cte_names: CteNameEntry[]; } interface CompileHamelinQueryResultOk { columns: Column[]; } interface CompletionItem { /** * What to show */ label: string; /** * What to actually put down */ apply_string: string; /** * Small text next to the label. */ detail: string | undefined; /** * Floating shit out to the right. */ description: string | undefined; /** * Icon */ kind: CompletionItemKind; snippet: string | undefined; /** * The group header this item sorts under. Currently only ever a space name. * * Unlike [`Self::boost`] this is not a nudge. Members of a section never interleave * with anything outside it: the editor ranks the sections against each other, by the * best-matching member of each, and every member then moves as a block. An item with * no section takes no group offset at all, which places it above *every* section * however badly it matches -- so leaving something unsectioned is a strong claim, not * a neutral default. * * Most completions do carry no section -- fields, functions, commands, keywords -- * which is only harmless because they never share a completion set with sectioned * ones. Among the `FROM` dataset completions, which do, pipeline definitions are the * only unsectioned item. */ section: string | undefined; /** * Ranking nudge applied by the editor on top of its own match score. * * Only meaningful when the editor is doing the filtering: a completion that * sets `filter(false)` is emitted in order and this is ignored. Keep values * inside ±99, which is what CodeMirror documents. */ boost: number | undefined; } interface Context { interval: { start: number; end: number }; message: string; } interface ContextualTranslationError { error: TranslationError; pretty: string; } interface ContextualTranslationErrors { hamelin: string; errors: ContextualTranslationError[]; } interface CteNameEntry { catalog_key: string; cte_name: string; } interface FunctionDescription { name: string; parameters: string; } interface GetOutputTimestampColumnsResultOk { columns: OutputTimestampColumn[]; } interface QueryDatasetsByCommand { from: string[]; union: string[]; join: string[]; lookup: string[]; } interface SubstituteTemplateParametersOk { query: string; } interface TranslationError { area: LanguageArea | undefined; stage: Stage; level: Level; primary: Context; supporting: Context[] | undefined; source_desc: string | undefined; } interface WasmCteInline { catalog_key: string; query: string; cte_name: string; } type BuildCatalogError = { kind: "catalogInit"; message: string } | { kind: "compilation"; name: string; errors: ContextualTranslationErrors } | { kind: "datasetParse"; name: string; message: string }; type Catalog = Record; type CombineQueriesForInliningResult = { Ok: CombineQueriesForInliningOk } | { Err: ContextualTranslationErrors } | { CombineError: string }; type CompileHamelinQueryResult = { Ok: CompileHamelinQueryResultOk } | { Err: ContextualTranslationErrors }; type CompletionItemKind = "Text" | "Variable" | "Function" | "Command" | "Keyword"; type GetOutputTimestampColumnsResult = { Ok: GetOutputTimestampColumnsResultOk } | { Err: ContextualTranslationErrors }; type HamelinType = "binary" | "boolean" | "interval" | "calendar_interval" | "int" | "double" | "rows" | "string" | "timestamp" | "unknown" | { decimal: { precision: number; scale: number } } | { array: { element_type: HamelinType } } | { map: { key_type: HamelinType; value_type: HamelinType } } | { tuple: { elements: HamelinType[] } } | "variant" | { range: { of: HamelinType } } | { range_inclusive: { of: HamelinType } } | { struct: Column[] }; type IncrementalEligibilityResult = { Eligible: { strategies: string[] } } | { NotEligible: { reasons: string[] } } | { CompilationError: ContextualTranslationErrors }; type LanguageArea = "FunctionCall" | "Operator" | "FieldLookup" | "IndexAccess" | "Parsing"; type Level = "Error" | "Warning" | "Info"; type QueryDatasetsByCommandResult = { Ok: QueryDatasetsByCommand } | { Err: ContextualTranslationErrors }; type QueryDatasetsResult = { Ok: string[] } | { Err: ContextualTranslationErrors }; type Stage = "Translation" | "Parsing" | "SemanticAnalysis" | "Normalization" | "Lowering"; type SubstituteTemplateParametersResult = { Ok: SubstituteTemplateParametersOk } | { Err: ContextualTranslationErrors } | { SubstitutionError: string }; type TruncUnit = "Second" | "Minute" | "Hour" | "Day" | "Week" | "Month" | "Quarter" | "Year"; declare class PreparedCatalog$1 { private constructor(); free(): void; [Symbol.dispose](): void; } type CatalogResourceInput = Omit & { isUnion?: boolean; }; declare const buildCatalog: (startingCatalog: Catalog, resources: Array) => Promise; declare class PreparedCatalog { #private; constructor(handle: PreparedCatalog$1); static wasmHandleOf(catalog: PreparedCatalog): PreparedCatalog$1; free(): void; [Symbol.dispose](): void; } declare const prepareCatalog: (catalog: Catalog) => Promise; declare const checkIncrementalEligibility: (catalog: Catalog | PreparedCatalog, query: string, allowLookups: boolean, defaultSpace?: string | null) => Promise; type CombineQueriesForInliningInput = { mainQuery: string; cteInlines: WasmCteInline[]; defaultSpaceCatalogName?: string | null; }; type CombineQueriesForInliningSuccess = { query: string; cteNames: Record; }; type CombineQueriesForInliningOutput = { kind: "Ok"; value: CombineQueriesForInliningSuccess; } | { kind: "Err"; value: CombineQueriesForInliningResult & { Err: unknown; }; } | { kind: "CombineError"; message: string; }; /** * Merge upstream queries as tabular DEFs for catalog inlining, rewrite catalog table refs, * and attach the main query. */ declare const combineQueriesForInlining: ({ mainQuery, cteInlines, defaultSpaceCatalogName, }: CombineQueriesForInliningInput) => Promise; type QueryValidationOptions = Readonly<{ validationMode?: QueryValidationMode; }>; declare const compileHamelinQuery: (catalog: Catalog | PreparedCatalog, hamelinInput: string, templateParameters?: Record | null, defaultSpace?: string | null, options?: QueryValidationOptions) => Promise; declare function getCompletions(catalog: Catalog | PreparedCatalog, hamelinInput: string, pos: number, templateParameters?: Record | null, defaultSpace?: string | null, options?: QueryValidationOptions): Promise; declare const hamelinGrammar = "grammar Hamelin;\n\nidentifierEOF\n : identifier EOF\n ;\n\nqueryEOF\n : query EOF\n ;\n\ncommandEOF\n : command EOF\n ;\n\nexpressionEOF\n : expression EOF\n ;\n\npipelineEOF\n : pipeline EOF\n ;\n\nsimpleIdentifierEOF\n : simpleIdentifier EOF\n ;\n\ndefRhs\n : pipeline #defRhsPipeline\n | expression #defRhsExpression\n ;\n\ndefStatement\n : DEF simpleIdentifier ASSIGN defRhs SEMICOLON\n ;\n\nqueryMain\n : pipeline #pipelineQueryMain\n | expression #expressionQueryMain\n ;\n\nquery\n : defStatement+ queryMain? SEMICOLON? #queryWithDefs\n | queryMain SEMICOLON? #queryWithoutDefs\n ;\n\npipeline\n : command ( PIPE command )* #pipelineAlt\n ;\n\ncommand\n : SET_COMMAND assignment (COMMA assignment)* COMMA? #setCommand\n | WHERE_COMMAND expression #whereCommand\n | SELECT_COMMAND assignmentClause (COMMA assignmentClause)* COMMA? #selectCommand\n | DROP_COMMAND selection (COMMA selection)* COMMA? #dropCommand\n | FROM_COMMAND fromClause (COMMA fromClause)* COMMA? #fromCommand\n | UNION_COMMAND fromClause (COMMA fromClause)* COMMA? #unionCommand\n | LIMIT_COMMAND expression #limitCommand\n | TRIMSTRINGS_COMMAND expression #trimstringsCommand\n | PARSE_COMMAND src=expression? string\n AS? identifier (COMMA identifier)* COMMA? NODROP? #parseCommand\n | WITHIN_COMMAND expression #withinCommand\n | AGG_COMMAND assignmentClause (COMMA assignmentClause)* COMMA?\n (BY groupClause (COMMA groupClause)*)? COMMA?\n (SORT sortExpression (COMMA sortExpression)*)? COMMA? #aggCommand\n | SORT sortExpression (COMMA sortExpression)* COMMA? #sortCommand\n | WINDOW_COMMAND assignmentClause (COMMA assignmentClause)* COMMA?\n (BY groupClause (COMMA groupClause)*)? COMMA?\n (SORT sortExpression (COMMA sortExpression)*)? COMMA?\n (WITHIN_COMMAND within=expression)? #windowCommand\n | APPEND_COMMAND tableReference (DISTINCT_COMMAND selection (COMMA selection)*)? COMMA? #appendCommand\n | DISTINCT_COMMAND groupClause (COMMA groupClause)* COMMA? #distinctCommand\n | SUPPRESS_COMMAND expression (BY groupClause (COMMA groupClause)*)? COMMA? #suppressCommand\n | (JOIN_COMMAND | LOOKUP_COMMAND) fromClause ON on=expression #joinCommand\n | EXPLODE_COMMAND assignmentClause #explodeCommand\n | (UNNEST_COMMAND | ROWS_COMMAND) expression #unnestCommand\n | NEST_COMMAND identifier #nestCommand\n | MATCH_COMMAND pattern+\n (AGG_COMMAND assignmentClause (COMMA assignmentClause)*)? COMMA?\n (BY groupClause (COMMA groupClause)*)? COMMA?\n (SORT sortExpression (COMMA sortExpression)*)? COMMA?\n (WITHIN_COMMAND within=expression)? COMMA? #matchCommand\n ;\n\nassignmentClause: assignment | expression;\ngroupClause: assignmentClause;\nassignment: identifier ASSIGN expression;\nselection: identifier;\nsortExpression: expression (ASC | DESC)?;\ntableAlias: simpleIdentifier ASSIGN tableReference;\nfromClause: tableAlias | tableReference;\n\nexpression\n // Keep this list in precedence order (important!)\n : operator=(MINUS | PLUS) expression #unaryPrefixOperator\n | expression '@' TEMPLATE_OPEN simpleIdentifier RCURLY #templatedTsTrunc\n | expression (SECOND_TRUNC | MINUTE_TRUNC | HOUR_TRUNC | DAY_TRUNC | WEEK_TRUNC |\n MONTH_TRUNC | QUARTER_TRUNC | YEAR_TRUNC) #tsTrunc\n | left=expression operator=DOT right=simpleIdentifier #fieldLookup\n | value=expression LBRACKET index=expression RBRACKET #indexAccess\n | left=expression operator=(ASTERISK | SLASH | PERCENT) right=expression #binaryOperator\n | left=expression operator=(PLUS | MINUS) right=expression #binaryOperator\n | operator=RANGE_INCLUSIVE expression #unaryPrefixOperator\n | operator=RANGE expression #unaryPrefixOperator\n | expression operator=RANGE #unaryPostfixOperator\n | left=expression operator=RANGE_INCLUSIVE right=expression #binaryOperator\n | left=expression operator=RANGE right=expression #binaryOperator\n | left=expression operator=AS right=hamelintype #cast\n | left=expression\n operator=(EQ | NEQ | LT | LTE | GT | GTE | IS | ISNOT | IN | NOTIN)\n right=expression #binaryOperator\n | operator=NOT expression #unaryPrefixOperator\n | left=expression operator=AND right=expression #binaryOperator\n | left=expression operator=OR right=expression #binaryOperator\n\n // Complex Literals\n | left=expression operator=COLON right=expression #pairLiteral\n\n // Lambda\n | lambdaParams ARROW expression #lambdaExpression\n | LCURLY simpleIdentifier COLON expression\n (COMMA simpleIdentifier COLON expression)* COMMA? RCURLY #structLiteral\n | LPARENS ((expression COMMA) |\n (expression COMMA expression (COMMA expression)* COMMA?)) RPARENS #tupleLiteral\n | LBRACKET (expression (COMMA expression)* COMMA?)? RBRACKET #arrayLiteral\n\n // Function Calls\n | functionName=simpleIdentifier\n LPARENS (namedArgument (COMMA namedArgument)* COMMA?)? RPARENS #functionCall\n | functionName=simpleIdentifier LPARENS\n positionalArgument (COMMA positionalArgument)*\n (COMMA namedArgument)* COMMA? RPARENS #functionCall\n\n // Primitive Literals\n | NULL #nullLiteral\n | number #numericLiteral\n | TRUE #booleanLiteral\n | FALSE #booleanLiteral\n | string #stringLiteral\n | BINARY_LITERAL #binaryLiteral\n | RANGE #unboundRangeLiteral\n | (MILLISECOND_INTERVAL |\n SECOND_INTERVAL | MINUTE_INTERVAL | HOUR_INTERVAL | DAY_INTERVAL |\n WEEK_INTERVAL | MONTH_INTERVAL | QUARTER_INTERVAL | YEAR_INTERVAL) #intervalLiteral\n | ROWS_LITERAL #rowsLiteral\n | (SECOND_TRUNC | MINUTE_TRUNC | HOUR_TRUNC | DAY_TRUNC | WEEK_TRUNC |\n MONTH_TRUNC | QUARTER_TRUNC | YEAR_TRUNC) #tsTruncTimestampLiteral\n\n // Environment references\n | fieldReference #fieldReferenceAlt\n | TEMPLATE_OPEN simpleIdentifier RCURLY #templateParameterExpr\n\n // Keep this at the bottom to use it the mechanism that query authors have to specify precedence.\n | LPARENS expression RPARENS #parenthesizedExpression\n ;\n\nhamelintype\n : simpleIdentifier LPARENS hamelintype (COMMA hamelintype)* COMMA? RPARENS #parameterizedType\n | simpleIdentifier LPARENS INTEGER_VALUE (COMMA INTEGER_VALUE)* COMMA? RPARENS #typeWithArguments\n | LCURLY simpleIdentifier COLON hamelintype\n (COMMA simpleIdentifier COLON hamelintype)* COMMA? RCURLY #structType\n | LPARENS hamelintype (COMMA hamelintype )* COMMA? RPARENS #tupleType\n | ROWS_COMMAND #rowsType\n | simpleIdentifier #simpleType\n ;\n\npattern\n : fromClause quantifier? #quantified\n | LPARENS pattern+ RPARENS quantifier #nested\n ;\n\nquantifier\n : ASTERISK #AnyNumber\n | PLUS #AtLeastOne\n | QUESTIONMARK #ZeroOrOne\n | LCURLY INTEGER_VALUE RCURLY #Exactly\n ;\n\nfieldReference\n : simpleIdentifier\n ;\n\ntableReference\n : tablePath\n ;\n\ntablePath\n : tablePathSegment COLON innerTablePath\n | innerTablePath\n ;\n\ninnerTablePath\n : tablePathSegment (DOT tablePathSegment)*\n ;\n\ntablePathSegment\n : ( IDENTIFIER | BACKQUOTED_IDENTIFIER ) templatePair*\n | templatePair+\n ;\n\n// One `${name}` hole with an optional literal suffix (for example `${tenant}_events`).\ntemplatePair\n : TEMPLATE_OPEN simpleIdentifier RCURLY ( IDENTIFIER | BACKQUOTED_IDENTIFIER )?\n ;\n\nidentifier\n : simpleIdentifier\n | simpleIdentifier (DOT simpleIdentifier)+\n ;\n\nsimpleIdentifier\n : IDENTIFIER #unquotedIdentifier\n | BACKQUOTED_IDENTIFIER #backQuotedIdentifier\n ;\n\nstring\n : SINGLE_QUOTED_STRING #basicSingleQuotedStringLiteral\n | DOUBLE_QUOTED_STRING #basicDoubleQuotedStringLiteral\n | value=SINGLE_QUOTED_UNICODE_STRING (UESCAPE uesc=SINGLE_QUOTED_STRING)? #unicodeSingleQuotedStringLiteral\n | value=DOUBLE_QUOTED_UNICODE_STRING (UESCAPE uesc=DOUBLE_QUOTED_STRING)? #unicodeDoubleQuotedStringLiteral\n ;\n\nnumber\n : value=DECIMAL_VALUE #decimalLiteral\n | value=SCIENTIFIC_VALUE #scientificLiteral\n | value=DOUBLE_VALUE #doubleLiteral\n | value=INTEGER_VALUE #integerLiteral\n ;\n\npositionalArgument\n : expression\n ;\n\nnamedArgument\n : simpleIdentifier ASSIGN expression\n ;\n\nlambdaParams\n : simpleIdentifier\n | LPARENS simpleIdentifier (COMMA simpleIdentifier)* COMMA? RPARENS\n ;\n\n//\n// COMMANDS\n//\n\nSET_COMMAND: 'SET' | 'set';\nDEF: 'DEF' | 'def';\nWHERE_COMMAND: 'WHERE' | 'where';\nSELECT_COMMAND: 'SELECT' | 'select';\nDROP_COMMAND: 'DROP' | 'drop';\nFROM_COMMAND: 'FROM' | 'from';\nUNION_COMMAND: 'UNION' | 'union';\nLIMIT_COMMAND: 'LIMIT' | 'limit';\nTRIMSTRINGS_COMMAND: 'TRIMSTRINGS' | 'trimstrings';\nPARSE_COMMAND: 'PARSE' | 'parse';\nWITHIN_COMMAND: 'WITHIN' | 'within';\nAGG_COMMAND: 'AGG' | 'agg';\nWINDOW_COMMAND: 'WINDOW' | 'window';\nAPPEND_COMMAND: 'APPEND' | 'append';\nJOIN_COMMAND: 'JOIN' | 'join';\nLOOKUP_COMMAND: 'LOOKUP' | 'lookup';\nEXPLODE_COMMAND: 'EXPLODE' | 'explode';\nUNNEST_COMMAND: 'UNNEST' | 'unnest';\nNEST_COMMAND: 'NEST' | 'nest';\nROWS_COMMAND: 'ROWS' | 'rows';\nMATCH_COMMAND: 'MATCH' | 'match';\n\nAS: 'AS' | 'as';\nNODROP: 'NODROP' | 'nodrop';\n\n//\n// Operators\n//\n\nARROW: '->';\nPLUS: '+';\nMINUS: '-';\nASTERISK: '*';\nSLASH: '/';\nPERCENT: '%';\nTEMPLATE_OPEN: '${';\nLCURLY: '{';\nRCURLY: '}';\nCOLON: ':';\nQUESTIONMARK: '?';\n\nEQ: '==';\nNEQ: '!=';\nLT: '<';\nLTE: '<=';\nGT: '>';\nGTE: '>=';\nRANGE_INCLUSIVE: '..=';\nRANGE: '..';\n\nASSIGN: '=';\n\n//\n// Keywords\n//\n\nAND: 'AND' | 'and';\nFALSE: 'FALSE' | 'false';\nIS: 'IS' | 'is';\nNOT: 'NOT' | 'not';\nISNOT: 'IS NOT' | 'is not';\nIN: 'IN' | 'in';\nNOTIN: 'NOT IN' | 'not in';\nNULL: 'NULL' | 'null';\nOR: 'OR' | 'or';\nTRUE: 'TRUE' | 'true';\nUESCAPE: 'UESCAPE' | 'uescape';\nBY: 'BY' | 'by';\nSORT: 'SORT' | 'sort';\nASC: 'ASC' | 'asc';\nDESC: 'DESC' | 'desc';\nDISTINCT_COMMAND: 'DISTINCT' | 'distinct';\nSUPPRESS_COMMAND: 'SUPPRESS' | 'suppress';\nON: 'ON' | 'on';\nWHEN: 'WHEN' | 'when';\n\n//\n// Symbols\n//\n\nCOMMA: ',';\nSEMICOLON: ';';\nPIPE: '|';\nLPARENS: '(';\nRPARENS: ')';\nDOT: '.';\nLBRACKET: '[';\nRBRACKET: ']';\n\n//\n// Literals\n//\n\nSINGLE_QUOTED_STRING\n : '\\'' ( ~['\\\\] | '\\\\' . )* '\\''\n ;\nDOUBLE_QUOTED_STRING\n : '\"' ( ~[\"\\\\] | '\\\\' . )* '\"'\n ;\n\nSINGLE_QUOTED_UNICODE_STRING\n : 'U&\\'' ( ~['\\\\] | '\\\\' . )* '\\'' // Unicode string with default escape character: U&'Hello winter \\2603 !'\n ;\n\nDOUBLE_QUOTED_UNICODE_STRING\n : 'U&\"' ( ~[\"\\\\] | '\\\\' . )* '\"' // Unicode string with custom escape character: U&'Hello winter #2603 !' UESCAPE '#'\n ;\n\n// Note: we allow any character inside the binary literal and validate\n// its a correct literal when the AST is being constructed. This\n// allows us to provide more meaningful error messages to the user\nBINARY_LITERAL\n : 'x\\'' (~'\\'')* '\\''\n ;\n\nMILLISECOND_INTERVAL\n : DECIMAL_INTEGER 'ms'\n ;\n\nSECOND_INTERVAL\n : DECIMAL_INTEGER ('s' | 'sec' | 'secs' | 'second' | 'seconds')\n ;\n\nMINUTE_INTERVAL\n : DECIMAL_INTEGER ('m' | 'min' | 'mins' | 'minute' | 'minutes')\n ;\n\nHOUR_INTERVAL\n : DECIMAL_INTEGER ('h' | 'hr' | 'hrs' | 'hour' | 'hours')\n ;\n\nDAY_INTERVAL\n : DECIMAL_INTEGER ('d' | 'day' | 'days')\n ;\n\nWEEK_INTERVAL\n : DECIMAL_INTEGER ('w' | 'week' | 'weeks')\n ;\n\nMONTH_INTERVAL\n : DECIMAL_INTEGER ('mon' | 'month' | 'months')\n ;\n\nQUARTER_INTERVAL\n : DECIMAL_INTEGER ('q' | 'qtr' | 'qtrs' | 'quarter' | 'quarters')\n ;\n\nYEAR_INTERVAL\n : DECIMAL_INTEGER ('y' | 'yr' | 'yrs' | 'year' | 'years')\n ;\n\nROWS_LITERAL\n : DECIMAL_INTEGER ('r' | 'row' | 'rows')\n ;\n\nSECOND_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('s' | 'sec' | 'secs' | 'second' | 'seconds')\n ;\n\nMINUTE_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('m' | 'min' | 'mins' | 'minute' | 'minutes')\n ;\n\nHOUR_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('h' | 'hr' | 'hrs' | 'hour' | 'hours')\n ;\n\nDAY_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('d' | 'day' | 'days')\n ;\n\nWEEK_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('w' | 'week' | 'weeks')\n ;\n\nMONTH_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('mon' | 'month' | 'months')\n ;\n\nQUARTER_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('q' | 'qtr' | 'qtrs' | 'quarter' | 'quarters')\n ;\n\nYEAR_TRUNC\n : '@' [ \\r\\n\\t]* DECIMAL_INTEGER? ('y' | 'yr' | 'yrs' | 'year' | 'years')\n ;\n\nINTEGER_VALUE\n : DECIMAL_INTEGER\n | HEXADECIMAL_INTEGER\n | OCTAL_INTEGER\n | BINARY_INTEGER\n ;\n\nDECIMAL_VALUE\n : DECIMAL_INTEGER '.' DECIMAL_INTEGER 'm'\n | '.' DECIMAL_INTEGER 'm'\n ;\n\nSCIENTIFIC_VALUE\n : DECIMAL_INTEGER ('.' DECIMAL_INTEGER)? EXPONENT\n | '.' DECIMAL_INTEGER EXPONENT\n ;\n\nDOUBLE_VALUE\n : DECIMAL_INTEGER '.' DECIMAL_INTEGER\n | '.' DECIMAL_INTEGER\n ;\n\nIDENTIFIER\n : [a-zA-Z_][a-zA-Z_0-9]*\n ;\n\nBACKQUOTED_IDENTIFIER\n : '`' ( ~'`' | '``' )* '`'\n ;\n\nfragment DECIMAL_INTEGER\n : DIGIT ('_'? DIGIT)*\n ;\n\nfragment HEXADECIMAL_INTEGER\n : '0x' ('_'? (DIGIT | [A-F]))+\n ;\n\nfragment OCTAL_INTEGER\n : '0o' ('_'? [0-7])+\n ;\n\nfragment BINARY_INTEGER\n : '0b' ('_'? [01])+\n ;\n\nfragment EXPONENT\n : 'e' [+-]? DECIMAL_INTEGER\n ;\n\nfragment DIGIT\n : [0-9]\n ;\n\n//\n// Comments and whitespace\n//\n\nSIMPLE_COMMENT\n : '//' ~[\\r\\n]* '\\r'? '\\n'? -> channel(HIDDEN)\n ;\n\nBRACKETED_COMMENT\n : '/*' .*? '*/' -> channel(HIDDEN)\n ;\n\nWS\n : [ \\r\\n\\t]+ -> skip\n ;\n"; declare const hamelinPrompt = "## Hamelin guide\n\nHamelin is a typed pipeline query language. Each command consumes the previous\ncommand's output. This guide covers the foundations for writing queries.\n\n### Discover the data first\n\nUse the supplied dataset list and schema tools, such as `list-dataset-names` and\n`get-dataset-columns`, when available. Check exact field names and types before\nfiltering. If schema tools are unavailable, a small sample query returns column\ntypes as well as rows. Empty results do not prove a field or dataset is absent.\nA missing-field compiler error is a schema problem, not evidence of no events.\nInspect the schema instead of retrying guessed field names.\n\nDataset references use `space:namespace.table`. An unqualified name requires the\nquery's default space. Copy the catalog's spelling. Do not put backticks around\nan entire qualified path, because that makes it a single literal name.\n\nThe examples below assume a fictional dataset `acme:security.events` with\n`timestamp: timestamp`, `action: string`, `status: int`, `message: string`,\n`user: {name: string, email: string}`, `labels: map(string, string)`,\n`tags: array(string)`, and `resources: array({id: string, kind: string})`.\nReplace these names with fields you have verified in the real schema.\n\n```hamelin\nFROM acme:security.events\n| LIMIT 5\n```\n\nThis is an unordered sample, not the latest five events. Supply the relevant\ninvestigation window through the query tool's separate `timeRange` parameter.\n\n### Reserved keywords\n\nThe following words are reserved in Hamelin and cannot be used as unquoted identifiers:\n\n- Commands: `SET`, `WHERE`, `SELECT`, `DROP`, `FROM`, `UNION`, `LIMIT`, `TRIMSTRINGS`, `PARSE`, `WITHIN`, `AGG`, `WINDOW`, `APPEND`, `DISTINCT`, `SUPPRESS`, `JOIN`, `LOOKUP`, `EXPLODE`, `UNNEST`, `NEST`, `ROWS`, `MATCH`\n- Operators/Keywords: `AS`, `AND`, `OR`, `NOT`, `IN`, `IS`, `BY`, `ON`, `SORT`, `ASC`, `DESC`, `DEF`, `TRUE`, `FALSE`, `NULL`, `NODROP`, `WHEN`, `UESCAPE`\n\n### Build and filter a pipeline\n\nSeparate commands with `|`. `FROM` reads a dataset, `WHERE` keeps rows whose\ncondition is true, `SET` adds or replaces fields, `SELECT` keeps only its listed\nfields, and `DROP` removes fields. Commands can repeat. After `SELECT`, dropped\nfields cannot be referenced downstream. `FROM a, b` combines rows from both\nsources like SQL UNION ALL; it does not join matching rows. `SELECT` is optional;\nwithout it, the pipeline keeps its current fields. For a calculation without a\ndataset, start with `SET`, for example `SET result = 8 * 2`.\n\n```hamelin\nFROM acme:security.events\n| WHERE action IN ['login', 'login_failed']\n| WHERE user.name == 'alice' AND status >= 400\n| SET normalized_email = lower(user.email)\n| SELECT timestamp, action, user.name, normalized_email, status\n| SORT timestamp DESC\n| LIMIT 50\n```\n\nUse `==`, `!=`, `<`, `<=`, `>`, `>=` for comparisons; `=` assigns a field name.\nCombine scalar conditions with `AND`, `OR`, and `NOT`. Parenthesize mixed\nconditions to make their grouping explicit. Use `IS NULL` or `IS NOT NULL` for\nnull checks. `WHERE` discards false and null conditions, so `field != 'x'` does\nnot keep nulls. Add `OR field IS NULL` if nulls should remain.\n\nStrings can use single or double quotes. Escape backslashes and quotes with a\nbackslash. Integers, `true`, `false`, and `null` are unquoted. `1.5` is a double;\n`1.5m` is an exact decimal. Backticks quote identifiers, never strings. Quote\nindividual field segments with spaces, punctuation, or reserved names, such as\n``source.`as`.organization`` or ``user.`display.name` ``.\n\nFor strings, `contains(message, 'needle')` tests a substring;\n`starts_with(message, 'prefix')` tests a prefix. Use `lower()` when you explicitly\nwant case-insensitive matching. `+` concatenates strings. Use an explicit cast\nfor other types, for example `'status=' + (status AS string)`. SQL `LIKE`, `ILIKE`,\nand invented function names are not substitutes for these functions.\nRegular expressions have their own functions and escaping rules.\n\n```hamelin\nFROM acme:security.events\n| WHERE message IS NOT NULL AND contains(lower(message), 'denied')\n| SELECT timestamp, summary = 'status=' + (status AS string), message\n| SORT timestamp DESC\n| LIMIT 20\n```\n\nUse `SORT field DESC` for descending order; ascending is the default. Sort before\n`LIMIT` when selecting the newest or largest rows. A limit before aggregation\nchanges the population being counted. A limited result or tool preview is not a\ncomplete event set. Use server-side aggregation for counts, and keep enough\nidentifiers and timestamps in evidence queries to trace the results.\n\n### Aggregate rows and group results\n\n`AGG` produces only its aggregate fields and grouping keys. `BY` is optional;\nwithout it, the aggregate covers the whole input. Filter input rows before\n`AGG`; filter aggregate results with a later `WHERE`. Name calculated fields\nexplicitly so subsequent commands can reference them easily. `AGG` requires at\nleast one aggregate expression; use `DISTINCT` for grouping keys alone.\nWithout an alias, expressions can produce field names containing punctuation:\nreference an output named `count()` as `` `count()` ``, not a new function call.\n\n```hamelin\nFROM acme:security.events\n| WHERE action IN ['login', 'login_failed']\n| AGG attempts = count(), failures = count_if(status >= 400),\n first_seen = min(timestamp), last_seen = max(timestamp)\n BY actor = user.name\n| WHERE failures > 0\n| SORT failures DESC, actor ASC\n| LIMIT 20\n```\n\n`count()` counts rows. `count(field)` counts non-null values, and\n`count_distinct(field)` counts distinct non-null values. Other common aggregates\nare `sum(field)`, `avg(field)`, `min(field)`, and `max(field)`. Use `DISTINCT` for\nunique combinations without an aggregate. `SELECT` does not deduplicate.\n\n```hamelin\nFROM acme:security.events\n| AGG events = count(), actors = count_distinct(user.name)\n BY hour = timestamp@hr\n| SORT hour ASC\n```\n\n```hamelin\nFROM acme:security.events\n| DISTINCT action, status\n```\n\n### Time windows and timestamps\n\nFor `execute-hamelin-query`, provide `timeRange` separately. Do not also add a\nstandalone `WITHIN` command for that same window. Follow the tool's time-range\ncontract: its earliest bound is inclusive and latest bound is exclusive.\nExamples are `-1hr..now()` and\n`ts('2026-10-13T14:00:00Z')..ts('2026-10-13T15:00:00Z')`.\n`-1hr..` has no upper bound and can include future events. Either endpoint may\nbe omitted: `..-1hr` ends an hour ago; `-2hr..-1hr` bounds both ends.\n\nSimba resolves relative expressions and `today()`, `yesterday()`, and `tomorrow()`\nin the organization's time zone. Check the returned resolved time range when\nreporting results. Use explicit `Z` or numeric offsets in absolute timestamps;\ndo not assume an unzoned timestamp literal means the organization's local time.\nA fixed duration such as `24hr` and a local calendar day can differ across a\ndaylight-saving transition.\n\nInside queries, `ts('...')` creates a timestamp, `now()` returns the current time,\nand durations include `30sec`, `5min`, `1hr`, and `7d`. `timestamp@hr` truncates to\nan hour boundary for grouping. Do not infer local-day boundaries from a bucket\nlabel; time-zone conversion and calendar bucketing need explicit handling.\nQuery expression `x IN low..high` includes both endpoints, unlike the\nexecution tool's half-open time window. Range endpoints must match the value's\nsortable scalar type. Quoted strings do not define IP or CIDR ranges; use\n`cidr_contains(cidr, ip)` for network membership. For adjacent windows on a secondary\ntimestamp field, use explicit `>=` and `<` conditions:\n\n```hamelin\nFROM acme:security.events\n| WHERE timestamp >= ts('2026-10-13T14:00:00Z')\n AND timestamp < ts('2026-10-13T15:00:00Z')\n| SELECT timestamp, action\n```\n\nThis illustrates field-level comparisons. Use the separate tool parameter for\nthe primary investigation window. An additional field filter intersects that\nwindow; it does not override it.\n\n### Structs, maps, JSON, and arrays\n\nFollow the schema, even when two values look alike in a JSON preview:\n\n- A struct has named, typed fields. Read `user.name`, not `user['name']`.\n Compare `user.name` to a string, not the whole `user` struct.\n- A map has typed keys and values. Read `labels['environment']`, not\n `labels.environment`. Missing keys can yield null.\n- An array has typed elements and zero-based indexing, such as `tags[0]`.\n A struct field projected through an array, such as `resources.id`, is an array.\n- `parse_json(message)` produces a variant. Cast it to the expected schema\n before filtering its fields. Unknown-typed fields also need a cast before\n field access or indexing. Use `AS array(string)` and `AS map(string, string)`\n for those composite types. Cast behavior can depend on the source type and\n backend; inspect errors and null results rather than assuming conversion\n succeeded.\n\n```hamelin\nFROM acme:security.events\n| WHERE user.name == 'alice' AND labels['environment'] == 'production'\n| SELECT timestamp, user.name, environment = labels['environment']\n```\n\n```hamelin\nFROM acme:security.events\n| SET parsed = parse_json(message) AS {actor: string, code: int}\n| WHERE parsed.actor == 'alice' AND parsed.code >= 400\n| SELECT timestamp, parsed.actor, parsed.code\n```\n\nComparisons and many functions broadcast over arrays. `resources.kind == 'host'`\nand `contains(tags, 'prod')` yield arrays of booleans, not one boolean for the\nrow. Reduce them with `any()` or `all()` before `WHERE`, `AND`, or `OR`.\n\n```hamelin\nFROM acme:security.events\n| WHERE any(resources.kind == 'host') OR any(tags == 'production')\n| SELECT timestamp, resources.id, tags\n```\n\n`any(array)` tests whether any element is true; `all(array)` tests whether all\nare true. For an empty array, `any` is false and `all` is true. Nulls require\ncare; neither proves the array contains evidence. These scalar reductions are\ndifferent from aggregate `any(boolean)` and `all(boolean)` across rows.\nWhen several conditions must match the same array element, use `filter()` with\na lambda so separate elements cannot satisfy separate conditions:\n\n```hamelin\nFROM acme:security.events\n| WHERE len(filter(resources, r -> r.kind == 'host' AND r.id == 'host-123')) > 0\n| SELECT timestamp, resources\n```\n\n`EXPLODE` creates a row per array element. `UNNEST` lifts struct fields and can\nalso expand arrays of structs. Both can affect downstream counts. Construct\nnested structs with nested braces, such as `{actor: {name: user.name}}`, not a dotted literal key.\n\n### SQL translation and other commands\n\nUse `FROM ... | WHERE ... | SELECT ...`, not SQL clause order. Rename with\n`name = expression`, not SQL `expression AS name`; Hamelin `AS` casts types.\nUse `AGG n = count() BY key`, not `COUNT(*)` or a separate `GROUP BY`.\nUse `WHERE` after `AGG` instead of `HAVING`, and `SORT` instead of `ORDER BY`.\nAll referenced fields must still exist at that point in the pipeline.\n\nThe language also supports commands beyond the examples. Every command must start with one of these names: FROM, SELECT, WHERE, DROP, SET, DEF, WINDOW, MATCH,\nSORT, LIMIT, AGG, UNNEST, NEST, EXPLODE, UNION, TRIMSTRINGS, DISTINCT, JOIN, LOOKUP,\nPARSE, SUPPRESS, APPEND, WITHIN, ROWS.\n\n### Command syntax at a glance\n\nThese one-line examples use `events` as a dataset name; substitute a catalog\nreference. Prefix pipeline fragments with `FROM events |`. `DEF` precedes the\nmain pipeline; `FROM`, `UNION`, `MATCH`, and `ROWS` can start it.\n\n| Command | Syntax example | Effect |\n| --- | --- | --- |\n| FROM | `FROM events` | Read rows; comma-separated sources stack rows. |\n| WHERE | `WHERE status >= 400` | Keep rows satisfying a scalar boolean. |\n| SET | `SET actor = user.name` | Add or replace fields. |\n| SELECT | `SELECT timestamp, actor = user.name` | Replace the output field set. |\n| DROP | `DROP message` | Remove fields. |\n| DEF | `DEF failures = FROM events \\| WHERE status >= 400; FROM failures` | Name a reusable pipeline. |\n| AGG | `AGG n = count() BY action` | Collapse rows into groups. |\n| WINDOW | `WINDOW n = count() BY user.name SORT timestamp WITHIN -5min` | Add a sliding calculation to each row. |\n| MATCH | `MATCH a=events b=events? BY user.name WITHIN 5min` | Find ordered event sequences. |\n| SORT | `SORT timestamp DESC, action ASC` | Order rows. |\n| LIMIT | `LIMIT 20` | Keep at most this many rows. |\n| DISTINCT | `DISTINCT action, status` | Keep distinct key combinations; drop other fields. |\n| JOIN | `JOIN other = events ON user.name == other.user.name` | Inner join; unmatched left rows disappear. |\n| LOOKUP | `LOOKUP other = events ON user.name == other.user.name` | Left join; unmatched right fields are null. |\n| PARSE | `PARSE message 'user=* action=*' AS actor, operation NODROP` | Capture `*` spans; unmatched rows are dropped unless NODROP is present. |\n| SUPPRESS | `SUPPRESS 5min BY user.name` | Keep one original row per aligned bucket and key. |\n| UNNEST | `UNNEST user` | Lift struct fields; arrays of structs also expand rows. |\n| NEST | `NEST detail` | Wrap all current fields in a struct. |\n| EXPLODE | `EXPLODE resource = resources` | Produce one row per array element. |\n| ROWS | `ROWS [{name: 'alice'}, {name: 'bob'}]` | Start a pipeline from an expression, lifting fields like UNNEST. |\n| UNION | `UNION events, events` | Stack sources without source aliases. |\n| TRIMSTRINGS | `TRIMSTRINGS 1024` | Recursively cap strings at a UTF-8 byte boundary. |\n| WITHIN | `WITHIN -1hr` | Filter the configured timestamp; avoid duplicating the tool timeRange. |\n| APPEND | `APPEND events` | Write output to a table; not a read operation. |\n\n### Named pipelines and joins\n\n`DEF name = pipeline;` defines a named relation for later `FROM`, `JOIN`, or\n`MATCH`. It is not a scalar variable. End each definition with `;`, then write\none terminal pipeline. A semicolon does not start a second independent query.\nSubqueries inside expressions, such as `x IN (FROM ...)`, are unsupported.\n\n```hamelin\nDEF failures = FROM acme:security.events | WHERE status >= 400;\nFROM failures\n| AGG n = count() BY user.name\n```\n\nJoin aliases expose right-side fields as `alias.field`. A `WHERE` before a join\nfilters only its left input. Filter the right side in a `DEF` when needed.\nMultiple right-side matches can multiply left rows and downstream counts.\n\n```hamelin\nDEF actors = FROM acme:security.events | DISTINCT actor = user.name;\nFROM acme:security.events\n| LOOKUP known = actors ON user.name == known.actor\n| SELECT timestamp, user.name, known.actor\n```\n\n`FROM a=dataset_a, b=dataset_b` stacks rows and provides source structs `a` and\n`b` alongside aligned fields. Fields absent from a source become null; aliases\ndo not turn this into a join. `UNION` must start a pipeline and cannot alias\nsources.\n\n### Windows, correlation, and reshaping\n\n- `WINDOW` retains rows and adds fields. `BY` partitions, `SORT` orders each\n partition, and `WITHIN` defines the frame relative to each output row, not\n wall-clock now. `WITHIN -5min` looks backward from that row. All expressions\n in the command share the frame. Time frames require a timestamp\n sort expression, or the configured timestamp field when SORT is omitted.\n A string containing a date does not satisfy that requirement. Row frames use\n `r`, `row`, or `rows`, such as `WITHIN -5r`. `AGG` cannot take a WITHIN clause.\n- `MATCH` patterns are space-separated, not comma-separated. Quantifiers are\n `?`, `*`, `+`, and `{n}`; `{n,m}` and `{n,}` are unsupported. At least one\n element must be required. Use `+` and a count filter for a variable minimum.\n `BY` partitions sequences. Ordering defaults to timestamp. WITHIN constrains\n the span on one sort field; its type must match that field, and a literal\n bound cannot be negative. Time-based matches need timestamp fields preserved\n in their inputs. Refer to aliased matches through their aliases.\n- `UNNEST` of a struct leaves row count unchanged; of an array of structs it\n expands rows. A simple source-column reference is consumed. `NEST` collects\n every current field, so SELECT first when only some belong in the struct.\n Dotted names nest deeper. NEST cannot rebuild an exploded array; use AGG with\n array_agg. EXPLODE keeps other fields and replaces its source unless an\n assignment names a separate output field.\n- `SUPPRESS` uses aligned buckets, not sliding windows, and retains the earliest\n timestamp per key/bucket. It needs a positive interval literal of at least\n one second. Timestamp ties use event.id when available; an earlier SORT does\n not choose the survivor. `TRIMSTRINGS` needs a non-negative integer constant,\n recurses through structs and arrays, and preserves nulls.\n\n```hamelin\nDEF failed = FROM acme:security.events | WHERE status >= 400;\nDEF succeeded = FROM acme:security.events | WHERE status < 400;\nMATCH f=failed+ s=succeeded\n AGG attempts = count(), first_seen = first(timestamp), last_seen = last(timestamp)\n BY user.name WITHIN 10min\n```\n\n### Additional type and expression rules\n\n- Tuples use `(1, 'a')` or `(42,)`; fields are `f0`, `f1`, etc. Arrays use\n `[1, 2]`; array elements share a type, as do map keys and map values within\n their respective collections. Array equality is unsupported. `+` concatenates arrays or strings;\n arithmetic supports `+`, `-`, `*`, `/`, `%`. Lambda parameters use `x -> expr`\n or `(a, b) -> expr` when the function accepts multiple parameters.\n- Struct literal keys cannot be dotted paths. Nested assignment is allowed\n (`SET user.name = 'alice'`), but do not assign a whole struct and its nested\n fields in the same command. A variant is not a typed struct: construct a new\n typed struct from cast fields instead of incrementally assigning into a raw\n variant. Variant object access uses dots; string-key brackets are for maps.\n- Persisted table, view, and detection outputs cannot contain variants or\n intervals. Cast variants to typed structures; convert intervals with\n to_nanos or to_millis. Unknown fields require a cast before access.\n- Do not assume strings, numbers, and variants convert implicitly when compared\n or combined; cast to the intended type. All fields can be null. Replacing null\n with a default can hide missing evidence, so use coalesce only deliberately.\n- Use `AS array(string)`, not `AS string[]`; `AS map(string, int)`, not a struct\n type with a string key. Decimal types use `decimal(precision, scale)`.\n- Aggregate expressions belong before BY, never inside grouping keys. After\n AGG or SELECT, removed fields are unavailable. Trailing commas are allowed.\n- Durations such as `1hr` differ from calendar intervals such as `1mon` or\n `1yr`. Truncation accepts multipliers: `timestamp@15min`, `timestamp@2hr`.\n Fixed-unit buckets such as `@7hr` run continuously across calendar boundaries;\n they do not restart at midnight. Whitespace around `@` is optional; keep\n multipliers next to their units, as in `timestamp @ 15min`.\n\nFor a raw JSON object, build a separate typed output rather than assigning\nnested fields back into the variant:\n\n```hamelin\nSET raw = parse_json('{\"Id\":\"finding-1\",\"Severity\":{\"Label\":\"high\"}}')\n| SET finding = {id: raw.Id AS string, severity: {label: raw.Severity.Label AS string}}\n| DROP raw\n```\n\n### Function signatures\n\n`[...]` below marks optional arguments; `...` marks repeated arguments. Functions\nare scalar unless a section restricts their context. Array overloads reduce\none array within a row; aggregate overloads combine rows. Do not use aggregate\nfunctions in ordinary `SET`, `SELECT`, `WHERE`, or grouping-key expressions.\n\n#### Strings and regex\n\n- `len(string)` counts characters; `lower(string)`, `upper(string)` change case.\n- `contains(string, substring)`, `starts_with(string, prefix)`, `ends_with(string, suffix)` test literal text.\n- `replace(string, needle[, replacement])` replaces literal matches; omitted replacement removes them.\n- `substr(string, start[, end])` uses zero-based indices and an exclusive end; negative indices count from the end.\n- `split(string, delimiter)` returns an array of strings.\n- `url_encode(string)`, `url_decode(string)` use form encoding: spaces encode as `+`.\n- `uuid()` generates a random UUID v4; `uuid5(name)` generates a deterministic UUID v5.\n- `if_blank(value, fallback)` returns the string fallback when value is null, empty, or contains only ASCII whitespace; otherwise it returns value unchanged.\n- `regexp_like(string, pattern)` tests for a regex match; `regexp_count(string, pattern)` counts matches.\n- `regexp_extract(string, pattern[, group])` returns the first match or capture group.\n- `regexp_extract_all(string, pattern[, group])` returns all matches or capture groups.\n- `regexp_position(string, pattern[, start[, occurrence]])` returns a match position.\n- `regexp_replace(string, pattern[, replacement])` replaces matches; omitted replacement removes them.\n- `regexp_split(string, pattern)` splits on regex matches.\n\nRegex patterns pass through the string lexer and then the regex engine. Unknown\nstring escapes such as `\\d` pass through unchanged. Matching one literal\nbackslash needs `'\\\\'` in a literal needle but `'\\\\\\\\'` in a regex pattern.\nAn under-escaped pattern may silently match the wrong text or fail with\n\"unopened group\" or \"incomplete escape\". Regex `.` excludes newlines unless\n`(?s)` enables dotall.\n\n```hamelin\nSET account = 'CORP\\\\alice'\n| SELECT name = regexp_extract(account, '^.+\\\\\\\\(.+)$', 1)\n```\n\n#### Conditions, JSON, and maps\n\n- `if(condition, then[, else])` returns the selected branch, or null when false and else is omitted; branches must have the same type.\n- `case(condition: value, ...)` returns the first matching value; use `true: fallback` last for a default. Values must have the same type. SQL `CASE WHEN` is unsupported.\n- `coalesce(value, ...)` returns the first non-null value; arguments must have compatible types. Cast variants before combining them with typed defaults.\n- `parse_json(string)`, `parse_json(variant)` return a variant; cast before comparing its fields.\n- `to_json_string(variant)` serializes JSON; cast other inputs with `AS variant` first.\n- `schema_of_variant(value)` returns Hamelin type syntax for a variant value; `typeof(value)` returns its static type.\n- `map()`, `map(key: value, ...)`, `map(keys, values)`, `map(pairs)` construct maps; `pairs` is an array of key/value tuples.\n- `map_keys(map)`, `map_values(map)` return arrays of keys or values.\n- `transform_values(map, value -> expression)` transforms values while retaining keys.\n- `get(array, index)`, `get(map, key)` are the function forms of bracket access.\n\n#### Arrays\n\n- `len(array)`, `len(map)` count elements or entries.\n- `array_distinct(array)` removes duplicates; output order is not guaranteed.\n- `filter_null(array)` removes null elements.\n- `slice(array, start, end)` uses an exclusive end and allows negative indices.\n- `flatten(array_of_arrays)` removes one nesting level.\n- `sequence(start, stop[, step])` produces integers including the stop when reached.\n- `zip(left, right)` returns tuples, padding the shorter array with nulls; tuple fields are `f0`, `f1`.\n- `transform(array, x -> expression)` maps elements; `filter(array, x -> condition)` retains matching elements.\n- `array_join(array, separator[, null_replacement])` joins strings, skipping nulls unless a replacement is supplied.\n- `any(boolean_array)`, `all(boolean_array)` reduce booleans within a row.\n- `sum(array)`, `avg(array)`, `min(array)`, `max(array)` reduce values within a row.\n- `histogram_percentile(bucket_counts, explicit_bounds, percentile)` estimates a percentile from non-cumulative histogram counts; counts need one more element than bounds. It returns a bucket bound, not an interpolated value.\n\n#### Math\n\n- `abs(x)`, `cbrt(x)`, `ceil(x)`, `floor(x)`, `sqrt(x)`, `sign(x)`.\n- `round(x[, digits])` rounds; `truncate(x)` removes the fractional part.\n- `pow(x, exponent)`, `exp(x)`, `ln(x)`, `log(base, x)`, `log10(x)`, `log2(x)`.\n- `degrees(radians)`, `radians(degrees)`, `e()`, `pi()`.\n- `width_bucket(x, lower, upper, count)`, `width_bucket(x, bounds)` return a histogram bucket number.\n\n#### Time\n\n- `now()` returns the current timestamp; `today()`, `yesterday()`, `tomorrow()` return calendar-day boundaries.\n- `ts(string)` parses a timestamp; prefer explicit offsets for absolute instants.\n- `at_timezone(timestamp, timezone)` expresses a timestamp in a named time zone.\n- `year(timestamp)`, `month(timestamp)`, `day(timestamp)`, `hour(timestamp)`, `minute(timestamp)`, `second(timestamp)` extract components.\n- `day_of_week(timestamp)` returns 1 for Monday through 7 for Sunday.\n- `from_unixtime_seconds(value)`, `from_unixtime_millis(value)`, `from_unixtime_micros(value)`, `from_unixtime_nanos(value)` convert Unix-epoch values to timestamps.\n- `to_unixtime(timestamp)` returns double seconds since the Unix epoch.\n- `from_millis(value)`, `from_nanos(value)` produce intervals; `to_millis(interval)`, `to_nanos(interval)` convert intervals to numbers.\n\n#### Network\n\n- `cidr_contains(cidr, ip)` tests membership; invalid input returns null, differing address families return false.\n- `is_ipv4(ip)`, `is_ipv6(ip)` validate address strings.\n- `ip_prefix(ip, prefix_length)` returns a canonical CIDR with host bits cleared.\n- `cidr_cover(cidr, prefix_length)` returns overlapping prefixes of the requested length; more than 65,536 prefixes per row raises an error.\n- `cidr_range(cidr)` returns inclusive address strings in `{first, last}`.\n- `ip_to_binary(ip)` returns 4-byte IPv4 or 16-byte IPv6 network-order bytes. Binary ordering is lexicographic, not address-family-aware.\n\n#### Aggregates in AGG, WINDOW, and MATCH AGG\n\n- `count()`, `count(value)` count rows or non-null values, respectively.\n- `count_distinct(value)` counts distinct non-null values.\n- `sum(value)`, `avg(value)`, `min(value)`, `max(value)` aggregate values.\n- `array_agg(value)` collects values into an array.\n\n#### Additional aggregates in AGG and WINDOW only\n\n- `count_if(condition)` counts true rows; `any(boolean)`, `all(boolean)` reduce across rows.\n- `any_value(value)` selects an arbitrary value, not the first or last.\n- `approx_distinct(value)` estimates distinct count.\n- `approx_percentile(value, percentile)` estimates a percentile.\n- `approx_top_k(value[, k[, max_items_tracked]])` estimates frequent values and counts.\n- `stddev(value)` computes sample standard deviation.\n- `set_agg(value)` collects distinct values, including at most one null.\n- `map_agg(key, value)` builds a map; `multimap_agg(key, value)` collects an array of values for each key.\n- `schema_of_variant_agg(value)` merges variant schemas into one Hamelin type string.\n\n#### WINDOW-only functions\n\n- `row_number()` assigns sequential numbers; `rank()` leaves gaps for ties; `dense_rank()` does not.\n- `lag(expression, offset[, ignore_nulls=true])`, `lead(expression, offset[, ignore_nulls=true])` read preceding or following values.\n- `first_value(expression[, ignore_nulls=true])`, `last_value(expression[, ignore_nulls=true])` read frame endpoints.\n- `nth_value(expression, n[, ignore_nulls=true])` reads the nth value in the frame.\n- `cume_dist()` returns cumulative distribution; `percent_rank()` returns relative rank.\n\n#### MATCH AGG-only functions\n\n- `first(expression)`, `last(expression)` read the first or last matched value.\n\n`MATCH AGG` aggregates only rows participating in the match, not every row in\nits time span. It supports the shared aggregate list above, but not `count_if`,\n`any_value`, or the WINDOW-only functions. Reference calculated output fields\nin later commands instead of calling aggregate functions again.\n"; type QuerySort = { field: string; direction: "asc" | "desc" | null; }; /** * Returns the top level sorting information from the provided Hamelin query. */ declare const getSorts: (hamelinQuery: string) => QuerySort[]; type QueryAggregation = { fields: string[]; by: string[]; sort: QuerySort[]; /** Index of this command in the main pipeline (`command` list, 0-based). */ pipelineStageIndex: number; }; declare const getAggregations: (query: string) => QueryAggregation[]; declare function getDatasetsByCommandFromQuery(hamelinInput: string, templateParameters?: Record | null, defaultSpace?: string | null): Promise; declare function getDatasetsFromQuery(hamelinInput: string, templateParameters?: Record | null, defaultSpace?: string | null): Promise; declare function getFunctionDescriptions(): Promise; /** * Returns the top level limit information from the provided Hamelin query. */ declare const getLimits: (hamelinQuery: string) => number[]; /** * Inclusive-exclusive character indices into the original query string for the `queryMain` * rule (the pipeline or expression after any leading `DEF … ;` blocks). `end` is suitable * for `String.prototype.slice` as the exclusive bound. */ declare function getMainPipelineSourceRange(hamelinQuery: string): { start: number; end: number; } | null; /** Text of the main query body only (excludes DEF definitions and optional trailing `;`). */ declare function getMainPipelineText(hamelinQuery: string): string; declare const getOutputTimestampColumns: (catalog: Catalog | PreparedCatalog, hamelinInput: string, defaultSpace?: string | null) => Promise; /** * How the main pipeline defines one logical output row for identity purposes. * * When multiple `AGG` (with `BY`) and/or `SUPPRESS` commands appear, the **last** * such command in the main pipeline wins — it defines the final row shape. */ type RowCollapsingIdentity = { kind: "none"; } | { kind: "aggregated"; by: string[]; } | { kind: "suppressed"; interval: string; by: string[]; }; /** * Returns which row-collapsing command defines output-row identity for the query. * * - `none` — no `AGG` with `BY` and no `SUPPRESS`; callers typically use per-event identity. * - `aggregated` — last `AGG` with non-empty `BY` wins over any earlier `SUPPRESS`. * - `suppressed` — last `SUPPRESS` wins over any earlier `AGG` with `BY`. */ declare const getRowCollapsingIdentity: (query: string) => RowCollapsingIdentity; type FieldNames = string[] | null; declare const getSelectedFields: (query: string) => FieldNames; type QuerySuppress = { /** Interval literal text (e.g. `15m`, `1h`). */ interval: string; /** Output field names for each BY clause (aliases inferred like AGG). */ by: string[]; /** Index of this command in the main pipeline (`command` list, 0-based). */ pipelineStageIndex: number; }; /** * Returns each `SUPPRESS` command in the main query pipeline, in pipeline order. */ declare const getSuppress: (query: string) => QuerySuppress[]; declare const hasSuppress: (query: string) => boolean; /** * Inserts `sortInsertion` immediately before the `|` that precedes the last `LIMIT` stage * in the **main** query pipeline (not inside `DEF` bodies). `sortInsertion` should include * the pipe and a trailing newline when appropriate, e.g. `| SORT timestamp DESC\n`. * * Returns the original string if there is no such LIMIT, LIMIT is the first pipeline stage, * or the main body is not a pipeline query. */ declare function insertImplicitSortBeforeLastMainLimit(hamelinQuery: string, sortInsertion: string): string; declare function parseTokenValueClass(stream: { string: string; pos: number; match: (text: string) => boolean | unknown[] | null; }, functions: FunctionDescription[]): string | null; declare const sampleCatalog: Catalog; declare const sampleMultiSpaceCatalog: Catalog; declare const sampleLargeCatalog: Catalog; /** The spaces above, for a playground control. */ declare const sampleLargeCatalogSpaces: string[]; /** * Replace `${name}` template holes in a Hamelin query with concrete values. Expression holes use * each value's tagged shape; table path holes require string values. * * When `templateParameters` is provided, values are validated against the declared spec before * substitution. */ declare const substituteTemplateParameters: (hamelinInput: string, templateValues: Record, templateParameters?: Record) => Promise; export { type BuildCatalogError, type BuildCatalogOutput, type Catalog, type Column, type CombineQueriesForInliningOk, type CombineQueriesForInliningResult, type CompileHamelinQueryResult, type CompileHamelinQueryResultOk, type Completion, type CompletionItem, type ContextualTranslationError, type ContextualTranslationErrors, type FunctionDescription, type GetOutputTimestampColumnsResult, type GetOutputTimestampColumnsResultOk, type HamelinType, type IncrementalEligibilityResult, type OutputTimestampColumn, PreparedCatalog, type QueryAggregation, type QueryDatasetsByCommand, type QueryDatasetsByCommandResult, type QuerySort, type QuerySuppress, type QueryValidationMode, type QueryValidationOptions, type RowCollapsingIdentity, type SubstituteTemplateParametersOk, type SubstituteTemplateParametersResult, type TranslationError, type TruncUnit, type WasmCteInline, type WasmTemplateParameterKind, type WasmTemplateParameterValue, buildCatalog, checkIncrementalEligibility, combineQueriesForInlining, compileHamelinQuery, getAggregations, getCompletions, getDatasetsByCommandFromQuery, getDatasetsFromQuery, getFunctionDescriptions, getLimits, getMainPipelineSourceRange, getMainPipelineText, getOutputTimestampColumns, getRowCollapsingIdentity, getSelectedFields, getSorts, getSuppress, hamelinGrammar, hamelinPrompt, hasSuppress, insertImplicitSortBeforeLastMainLimit, parseTokenValueClass, prepareCatalog, sampleCatalog, sampleLargeCatalog, sampleLargeCatalogSpaces, sampleMultiSpaceCatalog, substituteTemplateParameters };