From 56c8154f045628a00c02a9155bcae8cafbbb9dfa Mon Sep 17 00:00:00 2001 From: Tom Owers Date: Wed, 7 Feb 2024 09:45:40 +0000 Subject: [PATCH] feat(intellisense): Setup the basics of intellisense for the query editor (#20155) * Setup the basic of intellisense for the query editor * Missing node usage * Update query snapshots * Update query snapshots * rename intellisense to autocomplete * Schema fix --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- frontend/src/lib/constants.tsx | 1 + .../nodes/HogQLQuery/HogQLQueryEditor.tsx | 122 +++++++++++++++++- frontend/src/queries/query.ts | 2 +- frontend/src/queries/schema.json | 120 +++++++++++++++++ frontend/src/queries/schema.ts | 78 +++++++++++ .../scenes/saved-insights/SavedInsights.tsx | 6 + posthog/api/services/query.py | 4 + posthog/hogql/autocomplete.py | 32 +++++ posthog/schema.py | 115 +++++++++++++++-- 9 files changed, 466 insertions(+), 14 deletions(-) create mode 100644 posthog/hogql/autocomplete.py diff --git a/frontend/src/lib/constants.tsx b/frontend/src/lib/constants.tsx index cea4efb2bdcec..cdafc82f8a9c5 100644 --- a/frontend/src/lib/constants.tsx +++ b/frontend/src/lib/constants.tsx @@ -176,6 +176,7 @@ export const FEATURE_FLAGS = { HOGQL_INSIGHTS_FUNNELS: 'hogql-insights-funnels', // owner: @thmsobrmlr HOGQL_INSIGHT_LIVE_COMPARE: 'hogql-insight-live-compare', // owner: @mariusandra BI_VIZ: 'bi_viz', // owner: @Gilbert09 + HOGQL_AUTOCOMPLETE: 'hogql-autocomplete', // owner: @Gilbert09 WEBHOOKS_DENYLIST: 'webhooks-denylist', // owner: #team-pipeline SURVEYS_RESULTS_VISUALIZATIONS: 'surveys-results-visualizations', // owner: @jurajmajerik SURVEYS_PAYGATES: 'surveys-paygates', diff --git a/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx b/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx index 0e8b79e633935..20fccfdf535bf 100644 --- a/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx +++ b/frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx @@ -9,14 +9,79 @@ import { IconAutoAwesome, IconInfo } from 'lib/lemon-ui/icons' import { LemonBanner } from 'lib/lemon-ui/LemonBanner' import { LemonButton, LemonButtonWithDropdown } from 'lib/lemon-ui/LemonButton' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' -import type { editor as importedEditor, IDisposable, languages } from 'monaco-editor' +import type { editor as importedEditor, IDisposable } from 'monaco-editor' +import { languages } from 'monaco-editor' import { useEffect, useRef, useState } from 'react' import { urls } from 'scenes/urls' -import { HogQLQuery } from '~/queries/schema' +import { query } from '~/queries/query' +import { AutocompleteCompletionItem, HogQLAutocomplete, HogQLQuery, NodeKind } from '~/queries/schema' import { hogQLQueryEditorLogic } from './hogQLQueryEditorLogic' +const convertCompletionItemKind = (kind: AutocompleteCompletionItem['kind']): languages.CompletionItemKind => { + switch (kind) { + case 'Method': + return languages.CompletionItemKind.Method + case 'Function': + return languages.CompletionItemKind.Function + case 'Constructor': + return languages.CompletionItemKind.Constructor + case 'Field': + return languages.CompletionItemKind.Field + case 'Variable': + return languages.CompletionItemKind.Variable + case 'Class': + return languages.CompletionItemKind.Class + case 'Struct': + return languages.CompletionItemKind.Struct + case 'Interface': + return languages.CompletionItemKind.Interface + case 'Module': + return languages.CompletionItemKind.Module + case 'Property': + return languages.CompletionItemKind.Property + case 'Event': + return languages.CompletionItemKind.Event + case 'Operator': + return languages.CompletionItemKind.Operator + case 'Unit': + return languages.CompletionItemKind.Unit + case 'Value': + return languages.CompletionItemKind.Value + case 'Constant': + return languages.CompletionItemKind.Constant + case 'Enum': + return languages.CompletionItemKind.Enum + case 'EnumMember': + return languages.CompletionItemKind.EnumMember + case 'Keyword': + return languages.CompletionItemKind.Keyword + case 'Text': + return languages.CompletionItemKind.Text + case 'Color': + return languages.CompletionItemKind.Color + case 'File': + return languages.CompletionItemKind.File + case 'Reference': + return languages.CompletionItemKind.Reference + case 'Customcolor': + return languages.CompletionItemKind.Customcolor + case 'Folder': + return languages.CompletionItemKind.Folder + case 'TypeParameter': + return languages.CompletionItemKind.TypeParameter + case 'User': + return languages.CompletionItemKind.User + case 'Issue': + return languages.CompletionItemKind.Issue + case 'Snippet': + return languages.CompletionItemKind.Snippet + default: + throw new Error(`Unknown CompletionItemKind: ${kind}`) + } +} + export interface HogQLQueryEditorProps { query: HogQLQuery setQuery?: (query: HogQLQuery) => void @@ -127,6 +192,59 @@ export function HogQLQueryEditor(props: HogQLQueryEditorProps): JSX.Element { onChange={(v) => setQueryInput(v ?? '')} height="100%" onMount={(editor, monaco) => { + monaco.languages.registerCompletionItemProvider('mysql', { + triggerCharacters: [' ', ',', '.'], + provideCompletionItems: async (model, position) => { + if (!logic.isMounted()) { + return undefined + } + + if (!featureFlags[FEATURE_FLAGS.HOGQL_AUTOCOMPLETE]) { + return undefined + } + + const word = model.getWordUntilPosition(position) + + const startOffset = model.getOffsetAt({ + lineNumber: position.lineNumber, + column: word.startColumn, + }) + const endOffset = model.getOffsetAt({ + lineNumber: position.lineNumber, + column: word.endColumn, + }) + + const response = await query({ + kind: NodeKind.HogQLAutocomplete, + select: logic.values.queryInput, + filters: props.query.filters, + startPosition: startOffset, + endPosition: endOffset, + }) + + const completionItems = response.suggestions + + const suggestions = completionItems.map((item) => { + return { + label: item.label, + documentation: item.documentation, + insertText: item.insertText, + range: { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: word.startColumn, + endColumn: word.endColumn, + }, + kind: convertCompletionItemKind(item.kind), + } + }) + + return { + suggestions, + } + }, + }) + monaco.languages.registerCodeActionProvider('mysql', { provideCodeActions: (model, _range, context) => { if (logic.isMounted()) { diff --git a/frontend/src/queries/query.ts b/frontend/src/queries/query.ts index 5950aa5a01359..8e5427c250acc 100644 --- a/frontend/src/queries/query.ts +++ b/frontend/src/queries/query.ts @@ -103,7 +103,7 @@ async function executeQuery( queryId?: string ): Promise> { const queryAsyncEnabled = Boolean(featureFlagLogic.findMounted()?.values.featureFlags?.[FEATURE_FLAGS.QUERY_ASYNC]) - const excludedKinds = ['HogQLMetadata', 'EventsQuery'] + const excludedKinds = ['HogQLMetadata', 'EventsQuery', 'HogQLAutocomplete'] const queryAsync = queryAsyncEnabled && !excludedKinds.includes(queryNode.kind) const response = await api.query(queryNode, methodOptions, queryId, refresh, queryAsync) diff --git a/frontend/src/queries/schema.json b/frontend/src/queries/schema.json index 4723af09ba034..61209cba2a8b7 100644 --- a/frontend/src/queries/schema.json +++ b/frontend/src/queries/schema.json @@ -210,6 +210,9 @@ { "$ref": "#/definitions/HogQLMetadata" }, + { + "$ref": "#/definitions/HogQLAutocomplete" + }, { "$ref": "#/definitions/WebOverviewQuery" }, @@ -276,6 +279,9 @@ { "$ref": "#/definitions/HogQLMetadataResponse" }, + { + "$ref": "#/definitions/HogQLAutocompleteResponse" + }, { "anyOf": [ { @@ -305,6 +311,59 @@ } ] }, + "AutocompleteCompletionItem": { + "additionalProperties": false, + "properties": { + "documentation": { + "description": "A human-readable string that represents a doc-comment.", + "type": "string" + }, + "insertText": { + "description": "A string or snippet that should be inserted in a document when selecting this completion.", + "type": "string" + }, + "kind": { + "description": "The kind of this completion item. Based on the kind an icon is chosen by the editor.", + "enum": [ + "Method", + "Function", + "Constructor", + "Field", + "Variable", + "Class", + "Struct", + "Interface", + "Module", + "Property", + "Event", + "Operator", + "Unit", + "Value", + "Constant", + "Enum", + "EnumMember", + "Keyword", + "Text", + "Color", + "File", + "Reference", + "Customcolor", + "Folder", + "TypeParameter", + "User", + "Issue", + "Snippet" + ], + "type": "string" + }, + "label": { + "description": "The label of this completion item. By default this is also the text that is inserted when selecting this completion.", + "type": "string" + } + }, + "required": ["label", "insertText", "kind"], + "type": "object" + }, "BaseMathType": { "enum": ["total", "dau", "weekly_active", "monthly_active", "unique_session"], "type": "string" @@ -1841,6 +1900,50 @@ } ] }, + "HogQLAutocomplete": { + "additionalProperties": false, + "properties": { + "endPosition": { + "description": "End position of the editor word", + "type": "integer" + }, + "filters": { + "$ref": "#/definitions/HogQLFilters", + "description": "Table to validate the expression against" + }, + "kind": { + "const": "HogQLAutocomplete", + "type": "string" + }, + "response": { + "$ref": "#/definitions/HogQLAutocompleteResponse", + "description": "Cached query response" + }, + "select": { + "description": "Full select query to validate", + "type": "string" + }, + "startPosition": { + "description": "Start position of the editor word", + "type": "integer" + } + }, + "required": ["endPosition", "kind", "select", "startPosition"], + "type": "object" + }, + "HogQLAutocompleteResponse": { + "additionalProperties": false, + "properties": { + "suggestions": { + "items": { + "$ref": "#/definitions/AutocompleteCompletionItem" + }, + "type": "array" + } + }, + "required": ["suggestions"], + "type": "object" + }, "HogQLExpression": { "type": "string" }, @@ -2614,6 +2717,7 @@ "PersonsNode", "HogQLQuery", "HogQLMetadata", + "HogQLAutocomplete", "ActorsQuery", "SessionsTimelineQuery", "DataTableNode", @@ -3461,6 +3565,19 @@ "required": ["errors", "warnings", "notices"], "type": "object" }, + { + "additionalProperties": false, + "properties": { + "suggestions": { + "items": { + "$ref": "#/definitions/AutocompleteCompletionItem" + }, + "type": "array" + } + }, + "required": ["suggestions"], + "type": "object" + }, { "additionalProperties": false, "properties": { @@ -3757,6 +3874,9 @@ { "$ref": "#/definitions/HogQLMetadata" }, + { + "$ref": "#/definitions/HogQLAutocomplete" + }, { "$ref": "#/definitions/WebOverviewQuery" }, diff --git a/frontend/src/queries/schema.ts b/frontend/src/queries/schema.ts index 609e00b7d09ca..0e1532814c675 100644 --- a/frontend/src/queries/schema.ts +++ b/frontend/src/queries/schema.ts @@ -46,6 +46,7 @@ export enum NodeKind { PersonsNode = 'PersonsNode', HogQLQuery = 'HogQLQuery', HogQLMetadata = 'HogQLMetadata', + HogQLAutocomplete = 'HogQLAutocomplete', ActorsQuery = 'ActorsQuery', SessionsTimelineQuery = 'SessionsTimelineQuery', @@ -92,6 +93,7 @@ export type AnyDataNode = | SessionsTimelineQuery | HogQLQuery | HogQLMetadata + | HogQLAutocomplete | WebOverviewQuery | WebStatsTableQuery | WebTopClicksQuery @@ -112,6 +114,7 @@ export type QuerySchema = | SessionsTimelineQuery | HogQLQuery | HogQLMetadata + | HogQLAutocomplete | WebOverviewQuery | WebStatsTableQuery | WebTopClicksQuery @@ -152,6 +155,7 @@ export type AnyResponseType = | Record | HogQLQueryResponse | HogQLMetadataResponse + | HogQLAutocompleteResponse | EventsNode['response'] | EventsQueryResponse @@ -234,6 +238,61 @@ export interface HogQLMetadataResponse { notices: HogQLNotice[] } +export interface AutocompleteCompletionItem { + /** + * The label of this completion item. By default + * this is also the text that is inserted when selecting + * this completion. + */ + label: string + /** + * A human-readable string that represents a doc-comment. + */ + documentation?: string + /** + * A string or snippet that should be inserted in a document when selecting + * this completion. + */ + insertText: string + /** + * The kind of this completion item. Based on the kind + * an icon is chosen by the editor. + */ + kind: + | 'Method' + | 'Function' + | 'Constructor' + | 'Field' + | 'Variable' + | 'Class' + | 'Struct' + | 'Interface' + | 'Module' + | 'Property' + | 'Event' + | 'Operator' + | 'Unit' + | 'Value' + | 'Constant' + | 'Enum' + | 'EnumMember' + | 'Keyword' + | 'Text' + | 'Color' + | 'File' + | 'Reference' + | 'Customcolor' + | 'Folder' + | 'TypeParameter' + | 'User' + | 'Issue' + | 'Snippet' +} + +export interface HogQLAutocompleteResponse { + suggestions: AutocompleteCompletionItem[] +} + export interface HogQLMetadata extends DataNode { kind: NodeKind.HogQLMetadata /** Full select query to validate (use `select` or `expr`, but not both) */ @@ -251,6 +310,25 @@ export interface HogQLMetadata extends DataNode { response?: HogQLMetadataResponse } +export interface HogQLAutocomplete extends DataNode { + kind: NodeKind.HogQLAutocomplete + /** Full select query to validate */ + select: string + /** Table to validate the expression against */ + filters?: HogQLFilters + /** + * Start position of the editor word + * @asType integer + */ + startPosition: number + /** + * End position of the editor word + * @asType integer + */ + endPosition: number + response?: HogQLAutocompleteResponse +} + export interface EntityNode extends DataNode { name?: string custom_name?: string diff --git a/frontend/src/scenes/saved-insights/SavedInsights.tsx b/frontend/src/scenes/saved-insights/SavedInsights.tsx index 6ff2bd5a06621..11f846bdeb3c3 100644 --- a/frontend/src/scenes/saved-insights/SavedInsights.tsx +++ b/frontend/src/scenes/saved-insights/SavedInsights.tsx @@ -268,6 +268,12 @@ export const QUERY_TYPES_METADATA: Record = { icon: IconHogQL, inMenu: true, }, + [NodeKind.HogQLAutocomplete]: { + name: 'HogQL Autocomplete', + description: 'Autocomplete for the HogQL query editor', + icon: IconHogQL, + inMenu: false, + }, [NodeKind.DatabaseSchemaQuery]: { name: 'Database Schema', description: 'Introspect the PostHog database schema', diff --git a/posthog/api/services/query.py b/posthog/api/services/query.py index c9abbbde65563..3323fbdb8a4b9 100644 --- a/posthog/api/services/query.py +++ b/posthog/api/services/query.py @@ -7,6 +7,7 @@ from posthog.clickhouse.query_tagging import tag_queries from posthog.hogql.constants import LimitContext from posthog.hogql.database.database import create_hogql_database, serialize_database +from posthog.hogql.autocomplete import get_hogql_autocomplete from posthog.hogql.metadata import get_hogql_metadata from posthog.hogql.modifiers import create_default_modifiers_for_team from posthog.hogql_queries.query_runner import get_query_runner @@ -15,6 +16,7 @@ from posthog.queries.time_to_see_data.sessions import get_session_events, get_sessions from posthog.schema import ( FunnelsQuery, + HogQLAutocomplete, HogQLMetadata, HogQLQuery, EventsQuery, @@ -81,6 +83,8 @@ def process_query_model( elif isinstance(query, QUERY_WITH_RUNNER_NO_CACHE): # type: ignore query_runner = get_query_runner(query, team, limit_context=limit_context) result = query_runner.calculate() + elif isinstance(query, HogQLAutocomplete): + result = get_hogql_autocomplete(query=query, team=team) elif isinstance(query, HogQLMetadata): metadata_query = HogQLMetadata.model_validate(query) metadata_response = get_hogql_metadata(query=metadata_query, team=team) diff --git a/posthog/hogql/autocomplete.py b/posthog/hogql/autocomplete.py new file mode 100644 index 0000000000000..d1d835f890fa7 --- /dev/null +++ b/posthog/hogql/autocomplete.py @@ -0,0 +1,32 @@ +from typing import cast +from posthog.hogql.filters import replace_filters +from posthog.hogql.parser import parse_select +from posthog.hogql import ast +from posthog.models.team.team import Team +from posthog.schema import ( + HogQLAutocomplete, + HogQLAutocompleteResponse, + AutocompleteCompletionItem, + Kind, +) + + +def get_hogql_autocomplete(query: HogQLAutocomplete, team: Team) -> HogQLAutocompleteResponse: + response = HogQLAutocompleteResponse(suggestions=[]) + + try: + select_ast = parse_select(query.select) + if query.filters: + select_ast = cast(ast.SelectQuery, replace_filters(select_ast, query.filters, team)) + except Exception: + pass + + response.suggestions.append( + AutocompleteCompletionItem( + insertText="some_field", + label="some_field", + kind=Kind.Field, + ) + ) + + return response diff --git a/posthog/schema.py b/posthog/schema.py index 9109aad06369e..324f601e1142f 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -29,6 +29,56 @@ class AggregationAxisFormat(str, Enum): percentage_scaled = "percentage_scaled" +class Kind(str, Enum): + Method = "Method" + Function = "Function" + Constructor = "Constructor" + Field = "Field" + Variable = "Variable" + Class = "Class" + Struct = "Struct" + Interface = "Interface" + Module = "Module" + Property = "Property" + Event = "Event" + Operator = "Operator" + Unit = "Unit" + Value = "Value" + Constant = "Constant" + Enum = "Enum" + EnumMember = "EnumMember" + Keyword = "Keyword" + Text = "Text" + Color = "Color" + File = "File" + Reference = "Reference" + Customcolor = "Customcolor" + Folder = "Folder" + TypeParameter = "TypeParameter" + User = "User" + Issue = "Issue" + Snippet = "Snippet" + + +class AutocompleteCompletionItem(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + documentation: Optional[str] = Field( + default=None, description="A human-readable string that represents a doc-comment." + ) + insertText: str = Field( + ..., description="A string or snippet that should be inserted in a document when selecting this completion." + ) + kind: Kind = Field( + ..., description="The kind of this completion item. Based on the kind an icon is chosen by the editor." + ) + label: str = Field( + ..., + description="The label of this completion item. By default this is also the text that is inserted when selecting this completion.", + ) + + class BaseMathType(str, Enum): total = "total" dau = "dau" @@ -270,6 +320,13 @@ class GoalLine(BaseModel): value: float +class HogQLAutocompleteResponse(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + suggestions: List[AutocompleteCompletionItem] + + class HogQLNotice(BaseModel): model_config = ConfigDict( extra="forbid", @@ -432,6 +489,7 @@ class NodeKind(str, Enum): PersonsNode = "PersonsNode" HogQLQuery = "HogQLQuery" HogQLMetadata = "HogQLMetadata" + HogQLAutocomplete = "HogQLAutocomplete" ActorsQuery = "ActorsQuery" SessionsTimelineQuery = "SessionsTimelineQuery" DataTableNode = "DataTableNode" @@ -601,6 +659,13 @@ class QueryResponseAlternative8(BaseModel): warnings: List[HogQLNotice] +class QueryResponseAlternative9(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + suggestions: List[AutocompleteCompletionItem] + + class QueryStatus(BaseModel): model_config = ConfigDict( extra="forbid", @@ -637,7 +702,7 @@ class RecordingDurationFilter(BaseModel): value: float -class Kind(str, Enum): +class Kind1(str, Enum): ActionsNode = "ActionsNode" EventsNode = "EventsNode" @@ -648,7 +713,7 @@ class RetentionEntity(BaseModel): ) custom_name: Optional[str] = None id: Optional[Union[str, float]] = None - kind: Optional[Kind] = None + kind: Optional[Kind1] = None name: Optional[str] = None order: Optional[int] = None type: Optional[EntityType] = None @@ -861,7 +926,7 @@ class Sampling(BaseModel): forceSamplingRate: Optional[SamplingRate] = None -class Kind1(str, Enum): +class Kind2(str, Enum): unit = "unit" duration_s = "duration_s" percentage = "percentage" @@ -874,7 +939,7 @@ class WebOverviewItem(BaseModel): changeFromPreviousPct: Optional[float] = None isIncreaseBad: Optional[bool] = None key: str - kind: Kind1 + kind: Kind2 previous: Optional[float] = None value: Optional[float] = None @@ -1281,7 +1346,7 @@ class QueryResponseAlternative7(BaseModel): types: Optional[List] = Field(default=None, description="Types of returned columns") -class QueryResponseAlternative9(BaseModel): +class QueryResponseAlternative10(BaseModel): model_config = ConfigDict( extra="forbid", ) @@ -1294,7 +1359,7 @@ class QueryResponseAlternative9(BaseModel): timings: Optional[List[QueryTiming]] = None -class QueryResponseAlternative10(BaseModel): +class QueryResponseAlternative11(BaseModel): model_config = ConfigDict( extra="forbid", ) @@ -1312,7 +1377,7 @@ class QueryResponseAlternative10(BaseModel): types: Optional[List] = None -class QueryResponseAlternative11(BaseModel): +class QueryResponseAlternative12(BaseModel): model_config = ConfigDict( extra="forbid", ) @@ -1327,7 +1392,7 @@ class QueryResponseAlternative11(BaseModel): types: Optional[List] = None -class QueryResponseAlternative12(BaseModel): +class QueryResponseAlternative13(BaseModel): model_config = ConfigDict( extra="forbid", ) @@ -1505,12 +1570,22 @@ class WebTopClicksQuery(BaseModel): class AnyResponseType( RootModel[ Union[ - Dict[str, Any], HogQLQueryResponse, HogQLMetadataResponse, Union[AnyResponseType1, Any], EventsQueryResponse + Dict[str, Any], + HogQLQueryResponse, + HogQLMetadataResponse, + HogQLAutocompleteResponse, + Union[AnyResponseType1, Any], + EventsQueryResponse, ] ] ): root: Union[ - Dict[str, Any], HogQLQueryResponse, HogQLMetadataResponse, Union[AnyResponseType1, Any], EventsQueryResponse + Dict[str, Any], + HogQLQueryResponse, + HogQLMetadataResponse, + HogQLAutocompleteResponse, + Union[AnyResponseType1, Any], + EventsQueryResponse, ] @@ -1926,7 +2001,7 @@ class PropertyGroupFilterValue(BaseModel): ] -class QueryResponseAlternative13(BaseModel): +class QueryResponseAlternative14(BaseModel): model_config = ConfigDict( extra="forbid", ) @@ -1955,6 +2030,7 @@ class QueryResponseAlternative( QueryResponseAlternative11, QueryResponseAlternative12, QueryResponseAlternative13, + QueryResponseAlternative14, Dict[str, List[DatabaseSchemaQueryResponseField]], ] ] @@ -1974,6 +2050,7 @@ class QueryResponseAlternative( QueryResponseAlternative11, QueryResponseAlternative12, QueryResponseAlternative13, + QueryResponseAlternative14, Dict[str, List[DatabaseSchemaQueryResponseField]], ] @@ -2091,6 +2168,18 @@ class HasPropertiesNode(RootModel[Union[EventsNode, EventsQuery, PersonsNode]]): root: Union[EventsNode, EventsQuery, PersonsNode] +class HogQLAutocomplete(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + endPosition: int = Field(..., description="End position of the editor word") + filters: Optional[HogQLFilters] = Field(default=None, description="Table to validate the expression against") + kind: Literal["HogQLAutocomplete"] = "HogQLAutocomplete" + response: Optional[HogQLAutocompleteResponse] = Field(default=None, description="Cached query response") + select: str = Field(..., description="Full select query to validate") + startPosition: int = Field(..., description="Start position of the editor word") + + class InsightFilter( RootModel[Union[TrendsFilter, FunnelsFilter, RetentionFilter, PathsFilter, StickinessFilter, LifecycleFilter]] ): @@ -2594,6 +2683,7 @@ class HogQLMetadata(BaseModel): SessionsTimelineQuery, HogQLQuery, HogQLMetadata, + HogQLAutocomplete, WebOverviewQuery, WebStatsTableQuery, WebTopClicksQuery, @@ -2633,6 +2723,7 @@ class QueryRequest(BaseModel): SessionsTimelineQuery, HogQLQuery, HogQLMetadata, + HogQLAutocomplete, WebOverviewQuery, WebStatsTableQuery, WebTopClicksQuery, @@ -2669,6 +2760,7 @@ class QuerySchemaRoot( SessionsTimelineQuery, HogQLQuery, HogQLMetadata, + HogQLAutocomplete, WebOverviewQuery, WebStatsTableQuery, WebTopClicksQuery, @@ -2698,6 +2790,7 @@ class QuerySchemaRoot( SessionsTimelineQuery, HogQLQuery, HogQLMetadata, + HogQLAutocomplete, WebOverviewQuery, WebStatsTableQuery, WebTopClicksQuery,