feat: add DatabaseSchemaEndpointTable to SQL Editor (#40648)

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Jovan Sakovic
2025-11-05 15:43:39 +00:00
committed by GitHub
parent 7830a9aa35
commit f6905ed313
16 changed files with 3213 additions and 1789 deletions

View File

@@ -95,7 +95,10 @@ export const TreeNodeDisplayIcon = ({
let iconElement: React.ReactNode = item.icon || defaultNodeIcon || <div />
// use provided icon as the default icon for source folder nodes
if (isFolder && !['sources', 'source-folder', 'table', 'view', 'managed-view'].includes(item.record?.type)) {
if (
isFolder &&
!['sources', 'source-folder', 'table', 'view', 'managed-view', 'endpoint'].includes(item.record?.type)
) {
iconElement = defaultFolderIcon ? defaultFolderIcon : isOpen ? <IconFolderOpenFilled /> : <IconFolder />
}

View File

@@ -9870,6 +9870,38 @@
"required": ["fields", "format", "id", "name", "type", "url_pattern"],
"type": "object"
},
"DatabaseSchemaEndpointTable": {
"additionalProperties": false,
"properties": {
"fields": {
"additionalProperties": {
"$ref": "#/definitions/DatabaseSchemaField"
},
"type": "object"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"query": {
"$ref": "#/definitions/HogQLQuery"
},
"row_count": {
"type": "number"
},
"status": {
"type": "string"
},
"type": {
"const": "endpoint",
"type": "string"
}
},
"required": ["fields", "id", "name", "query", "type"],
"type": "object"
},
"DatabaseSchemaField": {
"additionalProperties": false,
"properties": {
@@ -10159,6 +10191,9 @@
},
{
"$ref": "#/definitions/DatabaseSchemaMaterializedViewTable"
},
{
"$ref": "#/definitions/DatabaseSchemaEndpointTable"
}
]
},
@@ -10195,7 +10230,8 @@
"view",
"batch_export",
"materialized_view",
"managed_view"
"managed_view",
"endpoint"
],
"type": "string"
},

View File

@@ -3186,6 +3186,7 @@ export type DatabaseSchemaTableType =
| 'batch_export'
| 'materialized_view'
| 'managed_view'
| 'endpoint'
export interface DatabaseSchemaTableCommon {
type: DatabaseSchemaTableType
@@ -3215,6 +3216,12 @@ export interface DatabaseSchemaManagedViewTable extends DatabaseSchemaTableCommo
source_id?: string
}
export interface DatabaseSchemaEndpointTable extends DatabaseSchemaTableCommon {
query: HogQLQuery
type: 'endpoint'
status?: string
}
export interface DatabaseSchemaMaterializedViewTable extends DatabaseSchemaTableCommon {
type: 'materialized_view'
query: HogQLQuery
@@ -3250,6 +3257,7 @@ export type DatabaseSchemaTable =
| DatabaseSchemaManagedViewTable
| DatabaseSchemaBatchExportTable
| DatabaseSchemaMaterializedViewTable
| DatabaseSchemaEndpointTable
export interface DatabaseSchemaQueryResponse {
tables: Record<string, DatabaseSchemaTable>

View File

@@ -6,6 +6,7 @@ import { objectsEqual } from 'lib/utils'
import { performQuery } from '~/queries/query'
import {
DatabaseSchemaDataWarehouseTable,
DatabaseSchemaEndpointTable,
DatabaseSchemaManagedViewTable,
DatabaseSchemaQuery,
DatabaseSchemaQueryResponse,
@@ -141,22 +142,31 @@ export const databaseTableListLogic = kea<databaseTableListLogicType>([
},
{ resultEqualityCheck: objectsEqual },
],
endpointTables: [
(s) => [s.allTables],
(allTables: DatabaseSchemaTable[]): DatabaseSchemaEndpointTable[] => {
return allTables.filter((n): n is DatabaseSchemaEndpointTable => n.type === 'endpoint')
},
{ resultEqualityCheck: objectsEqual },
],
viewsMap: [
(s) => [s.views, s.managedViews],
(s) => [s.views, s.managedViews, s.endpointTables],
(
views: DatabaseSchemaViewTable[],
managedViews: DatabaseSchemaManagedViewTable[]
): Record<string, DatabaseSchemaViewTable | DatabaseSchemaManagedViewTable> =>
toMapByName([...views, ...managedViews]),
managedViews: DatabaseSchemaManagedViewTable[],
endpointTables: DatabaseSchemaEndpointTable[]
): Record<string, DatabaseSchemaViewTable | DatabaseSchemaManagedViewTable | DatabaseSchemaEndpointTable> =>
toMapByName([...views, ...managedViews, ...endpointTables]),
{ resultEqualityCheck: objectsEqual },
],
viewsMapById: [
(s) => [s.views, s.managedViews],
(s) => [s.views, s.managedViews, s.endpointTables],
(
views: DatabaseSchemaViewTable[],
managedViews: DatabaseSchemaManagedViewTable[]
): Record<string, DatabaseSchemaViewTable | DatabaseSchemaManagedViewTable> =>
toMapById([...views, ...managedViews]),
managedViews: DatabaseSchemaManagedViewTable[],
endpointTables: DatabaseSchemaEndpointTable[]
): Record<string, DatabaseSchemaViewTable | DatabaseSchemaManagedViewTable | DatabaseSchemaEndpointTable> =>
toMapById([...views, ...managedViews, ...endpointTables]),
{ resultEqualityCheck: objectsEqual },
],
}),

View File

@@ -20,6 +20,7 @@ import { SearchHighlightMultiple } from '~/layout/navigation-3000/components/Sea
import { dataWarehouseViewsLogic } from '../../saved_queries/dataWarehouseViewsLogic'
import { draftsLogic } from '../draftsLogic'
import { renderTableCount } from '../editorSceneLogic'
import { OutputTab } from '../outputPaneLogic'
import { isJoined, queryDatabaseLogic } from './queryDatabaseLogic'
export const QueryDatabase = (): JSX.Element => {
@@ -103,9 +104,14 @@ export const QueryDatabase = (): JSX.Element => {
<div className="flex flex-row gap-1 justify-between">
<span
className={cn(
['managed-views', 'views', 'sources', 'drafts', 'unsaved-folder'].includes(
item.record?.type
) && 'font-bold',
[
'managed-views',
'views',
'sources',
'drafts',
'unsaved-folder',
'endpoints',
].includes(item.record?.type) && 'font-bold',
item.record?.type === 'column' && 'font-mono text-xs',
'truncate'
)}
@@ -349,7 +355,41 @@ export const QueryDatabase = (): JSX.Element => {
)
}
if (item.record?.type === 'sources') {
// Show menu for endpoints
if (item.record?.type === 'endpoint') {
return (
<DropdownMenuGroup>
<DropdownMenuItem
asChild
onClick={(e) => {
e.stopPropagation()
sceneLogic.actions.newTab(urls.endpoint(item.name))
}}
>
<ButtonPrimitive menuItem>View endpoint</ButtonPrimitive>
</DropdownMenuItem>
<DropdownMenuItem
asChild
onClick={(e) => {
e.stopPropagation()
sceneLogic.actions.newTab(
urls.sqlEditor(
item.record?.endpoint?.query.query,
undefined,
undefined,
undefined,
OutputTab.Endpoint
)
)
}}
>
<ButtonPrimitive menuItem>Edit endpoint query</ButtonPrimitive>
</DropdownMenuItem>
</DropdownMenuGroup>
)
}
if (['sources', 'endpoints'].includes(item.record?.type)) {
// used to override default icon behavior
return null
}
@@ -373,6 +413,25 @@ export const QueryDatabase = (): JSX.Element => {
</ButtonPrimitive>
)
}
if (item.record?.type === 'endpoints') {
return (
<ButtonPrimitive
iconOnly
isSideActionRight
className="z-2"
onClick={(e) => {
e.stopPropagation()
sceneLogic.actions.newTab(
urls.sqlEditor(undefined, undefined, undefined, undefined, OutputTab.Endpoint)
)
}}
data-attr="sql-editor-add-endpoint"
>
<IconPlusSmall className="text-tertiary" />
</ButtonPrimitive>
)
}
}}
renderItemIcon={(item) => {
if (item.record?.type === 'column') {

View File

@@ -3,7 +3,7 @@ import { actions, connect, events, kea, listeners, path, reducers, selectors } f
import { loaders } from 'kea-loaders'
import { subscriptions } from 'kea-subscriptions'
import { IconBolt, IconDatabase, IconDocument, IconPlug, IconPlus } from '@posthog/icons'
import { IconBolt, IconCode2, IconDatabase, IconDocument, IconPlug, IconPlus } from '@posthog/icons'
import { LemonMenuItem } from '@posthog/lemon-ui'
import { Spinner } from '@posthog/lemon-ui'
@@ -24,6 +24,7 @@ import { FuseSearchMatch } from '~/layout/navigation-3000/sidebars/utils'
import { iconForType } from '~/layout/panel-layout/ProjectTree/defaultTree'
import {
DatabaseSchemaDataWarehouseTable,
DatabaseSchemaEndpointTable,
DatabaseSchemaField,
DatabaseSchemaManagedViewTable,
DatabaseSchemaTable,
@@ -74,6 +75,12 @@ const isManagedViewTable = (
return 'type' in table && table.type === 'managed_view'
}
const isEndpointTable = (
table: DatabaseSchemaDataWarehouseTable | DatabaseSchemaTable | DataWarehouseSavedQuery
): table is DatabaseSchemaEndpointTable => {
return 'type' in table && table.type === 'endpoint'
}
export const isJoined = (field: DatabaseSchemaField): boolean => {
return field.type === 'view' || field.type === 'lazy_table'
}
@@ -90,6 +97,7 @@ const systemTablesFuse = new Fuse<DatabaseSchemaTable>([], FUSE_OPTIONS)
const dataWarehouseTablesFuse = new Fuse<DatabaseSchemaDataWarehouseTable>([], FUSE_OPTIONS)
const savedQueriesFuse = new Fuse<DataWarehouseSavedQuery>([], FUSE_OPTIONS)
const managedViewsFuse = new Fuse<DatabaseSchemaManagedViewTable>([], FUSE_OPTIONS)
const endpointTablesFuse = new Fuse<DatabaseSchemaEndpointTable>([], FUSE_OPTIONS)
const draftsFuse = new Fuse<DataWarehouseSavedQueryDraft>([], FUSE_OPTIONS)
// Factory functions for creating tree nodes
const createColumnNode = (tableName: string, field: DatabaseSchemaField, isSearch = false): TreeDataItem => ({
@@ -218,6 +226,33 @@ const createManagedViewNode = (
}
}
const createEndpointNode = (
endpoint: DatabaseSchemaEndpointTable,
matches: FuseSearchMatch[] | null = null,
isSearch = false
): TreeDataItem => {
const endpointChildren: TreeDataItem[] = []
Object.values(endpoint.fields).forEach((field: DatabaseSchemaField) => {
endpointChildren.push(createColumnNode(endpoint.name, field, isSearch))
})
const endpointId = `${isSearch ? 'search-' : ''}endpoint-${endpoint.id}`
return {
id: endpointId,
name: endpoint.name,
type: 'node',
icon: <IconCode2 />,
record: {
type: 'endpoint',
endpoint: endpoint,
...(matches && { searchMatches: matches }),
},
children: endpointChildren,
}
}
const createSourceFolderNode = (
sourceType: string,
tables: (DatabaseSchemaTable | DatabaseSchemaDataWarehouseTable)[],
@@ -268,7 +303,7 @@ const createSourceFolderNode = (
}
const createTopLevelFolderNode = (
type: 'sources' | 'views' | 'managed-views' | 'drafts',
type: 'sources' | 'views' | 'managed-views' | 'endpoints' | 'drafts',
children: TreeDataItem[],
isSearch = false,
icon?: JSX.Element
@@ -315,6 +350,19 @@ const createTopLevelFolderNode = (
]
}
if (type === 'endpoints' && children.length === 0) {
finalChildren = [
{
id: `${isSearch ? 'search-' : ''}endpoints-folder-empty/`,
name: 'Empty folder',
type: 'empty-folder',
record: {
type: 'empty-folder',
},
},
]
}
return {
id: isSearch ? `search-${type}` : type,
name:
@@ -324,7 +372,9 @@ const createTopLevelFolderNode = (
? 'Views'
: type === 'drafts'
? 'Drafts'
: 'Managed Views',
: type === 'endpoints'
? 'Endpoints'
: 'Managed Views',
type: 'node',
icon: icon,
record: {
@@ -364,6 +414,7 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
'dataWarehouseTablesMap',
'viewsMapById',
'managedViews',
'endpointTables',
'databaseLoading',
'systemTables',
'systemTablesMap',
@@ -400,7 +451,7 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
},
],
expandedFolders: [
['sources', 'views', 'managed-views'] as string[], // Default expanded folders
['sources', 'views', 'managed-views', 'endpoints'] as string[], // Default expanded folders
{
setExpandedFolders: (_, { folderIds }) => folderIds,
},
@@ -410,11 +461,13 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
'sources',
'views',
'managed-views',
'endpoints',
'search-posthog',
'search-system',
'search-datawarehouse',
'search-views',
'search-managed-views',
'search-endpoints',
] as string[],
{
setExpandedSearchFolders: (_, { folderIds }) => folderIds,
@@ -563,6 +616,20 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
return managedViews.map((view) => [view, null])
},
],
relevantEndpointTables: [
(s) => [s.endpointTables, s.searchTerm],
(
endpointTables: DatabaseSchemaEndpointTable[],
searchTerm: string
): [DatabaseSchemaEndpointTable, FuseSearchMatch[] | null][] => {
if (searchTerm) {
return endpointTablesFuse
.search(searchTerm)
.map((result) => [result.item, result.matches as FuseSearchMatch[]])
}
return endpointTables.map((table) => [table, null])
},
],
relevantDrafts: [
(s) => [s.drafts, s.searchTerm],
(
@@ -584,6 +651,7 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
s.relevantDataWarehouseTables,
s.relevantSavedQueries,
s.relevantManagedViews,
s.relevantEndpointTables,
s.relevantDrafts,
s.searchTerm,
s.featureFlags,
@@ -594,6 +662,7 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
relevantDataWarehouseTables: [DatabaseSchemaDataWarehouseTable, FuseSearchMatch[] | null][],
relevantSavedQueries: [DataWarehouseSavedQuery, FuseSearchMatch[] | null][],
relevantManagedViews: [DatabaseSchemaManagedViewTable, FuseSearchMatch[] | null][],
relevantEndpointTables: [DatabaseSchemaEndpointTable, FuseSearchMatch[] | null][],
relevantDrafts: [DataWarehouseSavedQueryDraft, FuseSearchMatch[] | null][],
searchTerm: string,
featureFlags: FeatureFlagsSet
@@ -641,6 +710,7 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
// Create views children
const viewsChildren: TreeDataItem[] = []
const managedViewsChildren: TreeDataItem[] = []
const endpointChildren: TreeDataItem[] = []
const draftsChildren: TreeDataItem[] = []
// Add saved queries
@@ -653,6 +723,13 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
managedViewsChildren.push(createManagedViewNode(view, matches, true))
})
// Add endpoints
if (featureFlags[FEATURE_FLAGS.ENDPOINTS]) {
relevantEndpointTables.forEach(([endpoint, matches]) => {
endpointChildren.push(createEndpointNode(endpoint, matches, true))
})
}
// Add drafts
if (featureFlags[FEATURE_FLAGS.EDITOR_DRAFTS]) {
relevantDrafts.forEach(([draft, matches]) => {
@@ -677,6 +754,11 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
searchResults.push(createTopLevelFolderNode('managed-views', managedViewsChildren, true))
}
if (endpointChildren.length > 0) {
expandedIds.push('search-endpoints')
searchResults.push(createTopLevelFolderNode('endpoints', endpointChildren, true))
}
// TODO: this needs to moved to the backend
if (draftsChildren.length > 0) {
expandedIds.push('search-drafts')
@@ -698,6 +780,7 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
s.dataWarehouseTables,
s.dataWarehouseSavedQueries,
s.managedViews,
s.endpointTables,
s.databaseLoading,
s.dataWarehouseSavedQueriesLoading,
s.drafts,
@@ -712,6 +795,7 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
dataWarehouseTables: DatabaseSchemaDataWarehouseTable[],
dataWarehouseSavedQueries: DataWarehouseSavedQuery[],
managedViews: DatabaseSchemaManagedViewTable[],
endpointTables: DatabaseSchemaEndpointTable[],
databaseLoading: boolean,
dataWarehouseSavedQueriesLoading: boolean,
drafts: DataWarehouseSavedQueryDraft[],
@@ -766,12 +850,14 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
// Create views children
const viewsChildren: TreeDataItem[] = []
const managedViewsChildren: TreeDataItem[] = []
const endpointChildren: TreeDataItem[] = []
// Add loading indicator for views if still loading
if (
dataWarehouseSavedQueriesLoading &&
dataWarehouseSavedQueries.length === 0 &&
managedViews.length === 0
managedViews.length === 0 &&
endpointTables.length === 0
) {
viewsChildren.push({
id: 'views-loading/',
@@ -790,6 +876,16 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
disableSelect: true,
type: 'loading-indicator',
})
if (featureFlags[FEATURE_FLAGS.ENDPOINTS]) {
endpointChildren.push({
id: 'endpoints-loading/',
name: 'Loading...',
displayName: <>Loading...</>,
icon: <Spinner />,
disableSelect: true,
type: 'loading-indicator',
})
}
} else {
// Add saved queries
dataWarehouseSavedQueries.forEach((view) => {
@@ -800,10 +896,18 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
managedViews.forEach((view) => {
managedViewsChildren.push(createManagedViewNode(view))
})
// Add endpoints
if (featureFlags[FEATURE_FLAGS.ENDPOINTS]) {
endpointTables.forEach((endpoint) => {
endpointChildren.push(createEndpointNode(endpoint))
})
}
}
viewsChildren.sort((a, b) => a.name.localeCompare(b.name))
managedViewsChildren.sort((a, b) => a.name.localeCompare(b.name))
endpointChildren.sort((a, b) => a.name.localeCompare(b.name))
const states = queryTabState?.state?.editorModelsStateKey
const unsavedChildren: TreeDataItem[] = []
@@ -901,6 +1005,9 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
...(featureFlags[FEATURE_FLAGS.MANAGED_VIEWSETS]
? []
: [createTopLevelFolderNode('managed-views', managedViewsChildren)]),
...(featureFlags[FEATURE_FLAGS.ENDPOINTS]
? [createTopLevelFolderNode('endpoints', endpointChildren)]
: []),
]
},
],
@@ -954,6 +1061,10 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
table = dataWarehouseSavedQueryMapById[selectedSchema.id]
}
if (isEndpointTable(selectedSchema)) {
table = viewsMapById[selectedSchema.id]
}
if (table == null) {
return []
}
@@ -1040,6 +1151,9 @@ export const queryDatabaseLogic = kea<queryDatabaseLogicType>([
managedViews: (managedViews: DatabaseSchemaManagedViewTable[]) => {
managedViewsFuse.setCollection(managedViews)
},
endpointTables: (endpointTables: DatabaseSchemaEndpointTable[]) => {
endpointTablesFuse.setCollection(endpointTables)
},
drafts: (drafts: DataWarehouseSavedQueryDraft[]) => {
draftsFuse.setCollection(drafts)
},

View File

@@ -568,7 +568,6 @@ posthog/helpers/full_text_search.py:0: error: Incompatible return value type (go
posthog/hogql/ast.py:0: error: Incompatible types in assignment (expression has type "type[AST]", target has type "AST") [assignment]
posthog/hogql/database/database.py:0: error: Argument "week_start_day" to "Database" has incompatible type "int | None"; expected "WeekStartDay | None" [arg-type]
posthog/hogql/database/database.py:0: error: Item "None" of "Any | None" has no attribute "get" [union-attr]
posthog/hogql/database/database.py:0: error: Value of type "Any | None" is not indexable [index]
posthog/hogql/filters.py:0: error: Incompatible default for argument "team" (default has type "None", argument has type "Team") [assignment]
posthog/hogql/parser.py:0: error: Argument "body" to "WhileStatement" has incompatible type "Any | None"; expected "Statement" [arg-type]
posthog/hogql/parser.py:0: error: Argument "expr" to "ThrowStatement" has incompatible type "Any | None"; expected "Expr" [arg-type]

View File

@@ -12,6 +12,7 @@ from pydantic import BaseModel, ConfigDict
from posthog.schema import (
DatabaseSchemaDataWarehouseTable,
DatabaseSchemaEndpointTable,
DatabaseSchemaField,
DatabaseSchemaManagedViewTable,
DatabaseSchemaPostHogTable,
@@ -147,6 +148,7 @@ type DatabaseSchemaTable = (
| DatabaseSchemaDataWarehouseTable
| DatabaseSchemaViewTable
| DatabaseSchemaManagedViewTable
| DatabaseSchemaEndpointTable
)
logger = structlog.get_logger(__name__)
@@ -507,6 +509,7 @@ class Database(BaseModel):
continue
saved_query = views_dict.get(view_name)
if not saved_query:
continue
@@ -514,11 +517,22 @@ class Database(BaseModel):
if saved_query.table:
row_count = saved_query.table.row_count
if saved_query and saved_query.origin == DataWarehouseSavedQuery.Origin.ENDPOINT:
tables[view_name] = DatabaseSchemaEndpointTable(
fields=fields_dict,
id=str(saved_query.pk),
name=view_name,
query=HogQLQuery(query=saved_query.query["query"]), # type: ignore[index]
row_count=row_count,
status=saved_query.status,
)
continue
tables[view_name] = DatabaseSchemaViewTable(
fields=fields_dict,
id=str(saved_query.pk),
name=view_name,
query=HogQLQuery(query=saved_query.query["query"]),
query=HogQLQuery(query=saved_query.query["query"]), # type: ignore[index]
row_count=row_count,
)
@@ -714,6 +728,26 @@ class Database(BaseModel):
table_conflict_mode="ignore",
)
with timings.measure("endpoint_saved_query"):
endpoint_saved_queries = []
try:
endpoint_saved_queries = list(
DataWarehouseSavedQuery.objects.filter(team_id=team.pk)
.filter(origin=DataWarehouseSavedQuery.Origin.ENDPOINT)
.exclude(deleted=True)
.select_related("table", "table__credential")
)
for endpoint_saved_query in endpoint_saved_queries:
with timings.measure(f"endpoint_saved_query_{endpoint_saved_query.name}"):
views.add_child(
TableNode(
name=endpoint_saved_query.name, table=endpoint_saved_query.hogql_definition(modifiers)
),
table_conflict_mode="ignore",
)
except Exception as e:
capture_exception(e)
with timings.measure("revenue_analytics_views"):
revenue_views: list[RevenueAnalyticsBaseView] = []
try:

View File

@@ -62,6 +62,88 @@
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.10
'''
SELECT "posthog_datawarehousesavedquery"."created_by_id",
"posthog_datawarehousesavedquery"."created_at",
"posthog_datawarehousesavedquery"."deleted",
"posthog_datawarehousesavedquery"."deleted_at",
"posthog_datawarehousesavedquery"."id",
"posthog_datawarehousesavedquery"."name",
"posthog_datawarehousesavedquery"."team_id",
"posthog_datawarehousesavedquery"."latest_error",
"posthog_datawarehousesavedquery"."columns",
"posthog_datawarehousesavedquery"."external_tables",
"posthog_datawarehousesavedquery"."query",
"posthog_datawarehousesavedquery"."status",
"posthog_datawarehousesavedquery"."last_run_at",
"posthog_datawarehousesavedquery"."sync_frequency_interval",
"posthog_datawarehousesavedquery"."table_id",
"posthog_datawarehousesavedquery"."is_materialized",
"posthog_datawarehousesavedquery"."deleted_name",
"posthog_datawarehousesavedquery"."managed_viewset_id",
"posthog_datawarehousesavedquery"."origin",
"posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
"posthog_datawarehousetable"."updated_at",
"posthog_datawarehousetable"."deleted",
"posthog_datawarehousetable"."deleted_at",
"posthog_datawarehousetable"."id",
"posthog_datawarehousetable"."name",
"posthog_datawarehousetable"."format",
"posthog_datawarehousetable"."team_id",
"posthog_datawarehousetable"."url_pattern",
"posthog_datawarehousetable"."queryable_folder",
"posthog_datawarehousetable"."credential_id",
"posthog_datawarehousetable"."external_data_source_id",
"posthog_datawarehousetable"."columns",
"posthog_datawarehousetable"."row_count",
"posthog_datawarehousetable"."size_in_s3_mib",
"posthog_datawarehousecredential"."created_by_id",
"posthog_datawarehousecredential"."created_at",
"posthog_datawarehousecredential"."id",
"posthog_datawarehousecredential"."access_key",
"posthog_datawarehousecredential"."access_secret",
"posthog_datawarehousecredential"."team_id"
FROM "posthog_datawarehousesavedquery"
LEFT OUTER JOIN "posthog_datawarehousetable" ON ("posthog_datawarehousesavedquery"."table_id" = "posthog_datawarehousetable"."id")
LEFT OUTER JOIN "posthog_datawarehousecredential" ON ("posthog_datawarehousetable"."credential_id" = "posthog_datawarehousecredential"."id")
WHERE ("posthog_datawarehousesavedquery"."team_id" = 99999
AND "posthog_datawarehousesavedquery"."origin" = 'endpoint'
AND NOT ("posthog_datawarehousesavedquery"."deleted"
AND "posthog_datawarehousesavedquery"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.11
'''
SELECT "posthog_externaldatasource"."created_by_id",
"posthog_externaldatasource"."created_at",
"posthog_externaldatasource"."updated_at",
"posthog_externaldatasource"."deleted",
"posthog_externaldatasource"."deleted_at",
"posthog_externaldatasource"."id",
"posthog_externaldatasource"."source_id",
"posthog_externaldatasource"."connection_id",
"posthog_externaldatasource"."destination_id",
"posthog_externaldatasource"."team_id",
"posthog_externaldatasource"."sync_frequency",
"posthog_externaldatasource"."status",
"posthog_externaldatasource"."source_type",
"posthog_externaldatasource"."job_inputs",
"posthog_externaldatasource"."are_tables_created",
"posthog_externaldatasource"."prefix",
"posthog_externaldatasource"."revenue_analytics_enabled",
"posthog_externaldatasourcerevenueanalyticsconfig"."external_data_source_id",
"posthog_externaldatasourcerevenueanalyticsconfig"."enabled",
"posthog_externaldatasourcerevenueanalyticsconfig"."include_invoiceless_charges"
FROM "posthog_externaldatasource"
LEFT OUTER JOIN "posthog_externaldatasourcerevenueanalyticsconfig" ON ("posthog_externaldatasource"."id" = "posthog_externaldatasourcerevenueanalyticsconfig"."external_data_source_id")
WHERE ("posthog_externaldatasource"."source_type" IN ('Stripe')
AND "posthog_externaldatasource"."team_id" = 99999
AND NOT ("posthog_externaldatasource"."deleted"
AND "posthog_externaldatasource"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.12
'''
SELECT "posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
@@ -110,7 +192,7 @@
AND "posthog_datawarehousetable"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.11
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.13
'''
SELECT "posthog_datawarehousejoin"."created_by_id",
"posthog_datawarehousejoin"."created_at",
@@ -190,6 +272,58 @@
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.3
'''
SELECT "posthog_datawarehousesavedquery"."created_by_id",
"posthog_datawarehousesavedquery"."created_at",
"posthog_datawarehousesavedquery"."deleted",
"posthog_datawarehousesavedquery"."deleted_at",
"posthog_datawarehousesavedquery"."id",
"posthog_datawarehousesavedquery"."name",
"posthog_datawarehousesavedquery"."team_id",
"posthog_datawarehousesavedquery"."latest_error",
"posthog_datawarehousesavedquery"."columns",
"posthog_datawarehousesavedquery"."external_tables",
"posthog_datawarehousesavedquery"."query",
"posthog_datawarehousesavedquery"."status",
"posthog_datawarehousesavedquery"."last_run_at",
"posthog_datawarehousesavedquery"."sync_frequency_interval",
"posthog_datawarehousesavedquery"."table_id",
"posthog_datawarehousesavedquery"."is_materialized",
"posthog_datawarehousesavedquery"."deleted_name",
"posthog_datawarehousesavedquery"."managed_viewset_id",
"posthog_datawarehousesavedquery"."origin",
"posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
"posthog_datawarehousetable"."updated_at",
"posthog_datawarehousetable"."deleted",
"posthog_datawarehousetable"."deleted_at",
"posthog_datawarehousetable"."id",
"posthog_datawarehousetable"."name",
"posthog_datawarehousetable"."format",
"posthog_datawarehousetable"."team_id",
"posthog_datawarehousetable"."url_pattern",
"posthog_datawarehousetable"."queryable_folder",
"posthog_datawarehousetable"."credential_id",
"posthog_datawarehousetable"."external_data_source_id",
"posthog_datawarehousetable"."columns",
"posthog_datawarehousetable"."row_count",
"posthog_datawarehousetable"."size_in_s3_mib",
"posthog_datawarehousecredential"."created_by_id",
"posthog_datawarehousecredential"."created_at",
"posthog_datawarehousecredential"."id",
"posthog_datawarehousecredential"."access_key",
"posthog_datawarehousecredential"."access_secret",
"posthog_datawarehousecredential"."team_id"
FROM "posthog_datawarehousesavedquery"
LEFT OUTER JOIN "posthog_datawarehousetable" ON ("posthog_datawarehousesavedquery"."table_id" = "posthog_datawarehousetable"."id")
LEFT OUTER JOIN "posthog_datawarehousecredential" ON ("posthog_datawarehousetable"."credential_id" = "posthog_datawarehousecredential"."id")
WHERE ("posthog_datawarehousesavedquery"."team_id" = 99999
AND "posthog_datawarehousesavedquery"."origin" = 'endpoint'
AND NOT ("posthog_datawarehousesavedquery"."deleted"
AND "posthog_datawarehousesavedquery"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.4
'''
SELECT "posthog_externaldatasource"."created_by_id",
"posthog_externaldatasource"."created_at",
@@ -219,7 +353,7 @@
AND "posthog_externaldatasource"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.4
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.5
'''
SELECT "posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
@@ -268,7 +402,7 @@
AND "posthog_datawarehousetable"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.5
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.6
'''
SELECT "posthog_datawarehousejoin"."created_by_id",
"posthog_datawarehousejoin"."created_at",
@@ -288,7 +422,7 @@
AND "posthog_datawarehousejoin"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.6
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.7
'''
SELECT "posthog_grouptypemapping"."id",
"posthog_grouptypemapping"."team_id",
@@ -304,7 +438,7 @@
WHERE "posthog_grouptypemapping"."team_id" = 99999
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.7
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.8
'''
SELECT "posthog_grouptypemapping"."id",
"posthog_grouptypemapping"."team_id",
@@ -320,7 +454,7 @@
WHERE "posthog_grouptypemapping"."project_id" = 99999
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.8
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.9
'''
SELECT "posthog_datawarehousesavedquery"."created_by_id",
"posthog_datawarehousesavedquery"."created_at",
@@ -379,36 +513,6 @@
AND "posthog_datawarehousesavedquery"."managed_viewset_id" IS NULL)
'''
# ---
# name: TestDatabase.test_database_with_warehouse_tables_and_saved_queries_n_plus_1.9
'''
SELECT "posthog_externaldatasource"."created_by_id",
"posthog_externaldatasource"."created_at",
"posthog_externaldatasource"."updated_at",
"posthog_externaldatasource"."deleted",
"posthog_externaldatasource"."deleted_at",
"posthog_externaldatasource"."id",
"posthog_externaldatasource"."source_id",
"posthog_externaldatasource"."connection_id",
"posthog_externaldatasource"."destination_id",
"posthog_externaldatasource"."team_id",
"posthog_externaldatasource"."sync_frequency",
"posthog_externaldatasource"."status",
"posthog_externaldatasource"."source_type",
"posthog_externaldatasource"."job_inputs",
"posthog_externaldatasource"."are_tables_created",
"posthog_externaldatasource"."prefix",
"posthog_externaldatasource"."revenue_analytics_enabled",
"posthog_externaldatasourcerevenueanalyticsconfig"."external_data_source_id",
"posthog_externaldatasourcerevenueanalyticsconfig"."enabled",
"posthog_externaldatasourcerevenueanalyticsconfig"."include_invoiceless_charges"
FROM "posthog_externaldatasource"
LEFT OUTER JOIN "posthog_externaldatasourcerevenueanalyticsconfig" ON ("posthog_externaldatasource"."id" = "posthog_externaldatasourcerevenueanalyticsconfig"."external_data_source_id")
WHERE ("posthog_externaldatasource"."source_type" IN ('Stripe')
AND "posthog_externaldatasource"."team_id" = 99999
AND NOT ("posthog_externaldatasource"."deleted"
AND "posthog_externaldatasource"."deleted" IS NOT NULL))
'''
# ---
# name: TestDatabase.test_serialize_database_no_person_on_events
'''
{

View File

@@ -433,7 +433,7 @@ class TestDatabase(BaseTest, QueryMatchingTest):
)
# initialization team query doesn't run
with self.assertNumQueries(6):
with self.assertNumQueries(7):
modifiers = create_default_modifiers_for_team(
self.team, modifiers=HogQLQueryModifiers(useMaterializedViews=True)
)

View File

@@ -921,6 +921,7 @@ class DatabaseSchemaTableType(StrEnum):
BATCH_EXPORT = "batch_export"
MATERIALIZED_VIEW = "materialized_view"
MANAGED_VIEW = "managed_view"
ENDPOINT = "endpoint"
class DatabaseSerializedFieldType(StrEnum):
@@ -13433,6 +13434,19 @@ class DataVisualizationNode(BaseModel):
version: Optional[float] = Field(default=None, description="version of the node, used for schema migrations")
class DatabaseSchemaEndpointTable(BaseModel):
model_config = ConfigDict(
extra="forbid",
)
fields: dict[str, DatabaseSchemaField]
id: str
name: str
query: HogQLQuery
row_count: Optional[float] = None
status: Optional[str] = None
type: Literal["endpoint"] = "endpoint"
class DatabaseSchemaManagedViewTable(BaseModel):
model_config = ConfigDict(
extra="forbid",
@@ -14529,6 +14543,7 @@ class QueryResponseAlternative66(BaseModel):
DatabaseSchemaManagedViewTable,
DatabaseSchemaBatchExportTable,
DatabaseSchemaMaterializedViewTable,
DatabaseSchemaEndpointTable,
],
]
@@ -14744,6 +14759,7 @@ class DatabaseSchemaQueryResponse(BaseModel):
DatabaseSchemaManagedViewTable,
DatabaseSchemaBatchExportTable,
DatabaseSchemaMaterializedViewTable,
DatabaseSchemaEndpointTable,
],
]

View File

@@ -1011,6 +1011,58 @@
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.31
'''
SELECT "posthog_datawarehousesavedquery"."created_by_id",
"posthog_datawarehousesavedquery"."created_at",
"posthog_datawarehousesavedquery"."deleted",
"posthog_datawarehousesavedquery"."deleted_at",
"posthog_datawarehousesavedquery"."id",
"posthog_datawarehousesavedquery"."name",
"posthog_datawarehousesavedquery"."team_id",
"posthog_datawarehousesavedquery"."latest_error",
"posthog_datawarehousesavedquery"."columns",
"posthog_datawarehousesavedquery"."external_tables",
"posthog_datawarehousesavedquery"."query",
"posthog_datawarehousesavedquery"."status",
"posthog_datawarehousesavedquery"."last_run_at",
"posthog_datawarehousesavedquery"."sync_frequency_interval",
"posthog_datawarehousesavedquery"."table_id",
"posthog_datawarehousesavedquery"."is_materialized",
"posthog_datawarehousesavedquery"."deleted_name",
"posthog_datawarehousesavedquery"."managed_viewset_id",
"posthog_datawarehousesavedquery"."origin",
"posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
"posthog_datawarehousetable"."updated_at",
"posthog_datawarehousetable"."deleted",
"posthog_datawarehousetable"."deleted_at",
"posthog_datawarehousetable"."id",
"posthog_datawarehousetable"."name",
"posthog_datawarehousetable"."format",
"posthog_datawarehousetable"."team_id",
"posthog_datawarehousetable"."url_pattern",
"posthog_datawarehousetable"."queryable_folder",
"posthog_datawarehousetable"."credential_id",
"posthog_datawarehousetable"."external_data_source_id",
"posthog_datawarehousetable"."columns",
"posthog_datawarehousetable"."row_count",
"posthog_datawarehousetable"."size_in_s3_mib",
"posthog_datawarehousecredential"."created_by_id",
"posthog_datawarehousecredential"."created_at",
"posthog_datawarehousecredential"."id",
"posthog_datawarehousecredential"."access_key",
"posthog_datawarehousecredential"."access_secret",
"posthog_datawarehousecredential"."team_id"
FROM "posthog_datawarehousesavedquery"
LEFT OUTER JOIN "posthog_datawarehousetable" ON ("posthog_datawarehousesavedquery"."table_id" = "posthog_datawarehousetable"."id")
LEFT OUTER JOIN "posthog_datawarehousecredential" ON ("posthog_datawarehousetable"."credential_id" = "posthog_datawarehousecredential"."id")
WHERE ("posthog_datawarehousesavedquery"."team_id" = 99999
AND "posthog_datawarehousesavedquery"."origin" = 'endpoint'
AND NOT ("posthog_datawarehousesavedquery"."deleted"
AND "posthog_datawarehousesavedquery"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.32
'''
SELECT "posthog_externaldatasource"."created_by_id",
"posthog_externaldatasource"."created_at",
@@ -1040,7 +1092,7 @@
AND "posthog_externaldatasource"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.32
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.33
'''
SELECT "posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
@@ -1089,7 +1141,7 @@
AND "posthog_datawarehousetable"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.33
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.34
'''
SELECT "posthog_datawarehousejoin"."created_by_id",
"posthog_datawarehousejoin"."created_at",
@@ -1109,7 +1161,7 @@
AND "posthog_datawarehousejoin"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.34
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.35
'''
SELECT COUNT(*)
FROM
@@ -1118,30 +1170,14 @@
WHERE "ee_single_session_summary"."team_id" = 99999) subquery
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.35
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.36
'''
SELECT "posthog_sessionrecordingplaylistitem"."session_id"
FROM "posthog_sessionrecordingplaylistitem"
WHERE "posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.36
'''
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingplaylistitem"
WHERE ("posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
AND NOT ("posthog_sessionrecordingplaylistitem"."deleted"
AND "posthog_sessionrecordingplaylistitem"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.37
'''
SELECT "posthog_sessionrecordingplaylistitem"."session_id"
FROM "posthog_sessionrecordingplaylistitem"
WHERE "posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.38
'''
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingplaylistitem"
@@ -1150,37 +1186,20 @@
AND "posthog_sessionrecordingplaylistitem"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.38
'''
SELECT "posthog_sessionrecordingplaylistitem"."session_id"
FROM "posthog_sessionrecordingplaylistitem"
WHERE "posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.39
'''
SELECT "posthog_user"."id",
"posthog_user"."password",
"posthog_user"."last_login",
"posthog_user"."first_name",
"posthog_user"."last_name",
"posthog_user"."is_staff",
"posthog_user"."date_joined",
"posthog_user"."uuid",
"posthog_user"."current_organization_id",
"posthog_user"."current_team_id",
"posthog_user"."email",
"posthog_user"."pending_email",
"posthog_user"."temporary_token",
"posthog_user"."distinct_id",
"posthog_user"."is_email_verified",
"posthog_user"."has_seen_product_intro_for",
"posthog_user"."strapi_id",
"posthog_user"."is_active",
"posthog_user"."role_at_organization",
"posthog_user"."theme_mode",
"posthog_user"."partial_notification_settings",
"posthog_user"."anonymize_data",
"posthog_user"."toolbar_mode",
"posthog_user"."hedgehog_config",
"posthog_user"."events_column_config",
"posthog_user"."email_opt_in"
FROM "posthog_user"
WHERE "posthog_user"."id" = 99999
LIMIT 21
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingplaylistitem"
WHERE ("posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
AND NOT ("posthog_sessionrecordingplaylistitem"."deleted"
AND "posthog_sessionrecordingplaylistitem"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.4
@@ -1217,6 +1236,39 @@
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.40
'''
SELECT "posthog_user"."id",
"posthog_user"."password",
"posthog_user"."last_login",
"posthog_user"."first_name",
"posthog_user"."last_name",
"posthog_user"."is_staff",
"posthog_user"."date_joined",
"posthog_user"."uuid",
"posthog_user"."current_organization_id",
"posthog_user"."current_team_id",
"posthog_user"."email",
"posthog_user"."pending_email",
"posthog_user"."temporary_token",
"posthog_user"."distinct_id",
"posthog_user"."is_email_verified",
"posthog_user"."has_seen_product_intro_for",
"posthog_user"."strapi_id",
"posthog_user"."is_active",
"posthog_user"."role_at_organization",
"posthog_user"."theme_mode",
"posthog_user"."partial_notification_settings",
"posthog_user"."anonymize_data",
"posthog_user"."toolbar_mode",
"posthog_user"."hedgehog_config",
"posthog_user"."events_column_config",
"posthog_user"."email_opt_in"
FROM "posthog_user"
WHERE "posthog_user"."id" = 99999
LIMIT 21
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.41
'''
SELECT "posthog_organization"."id",
"posthog_organization"."name",
@@ -1250,7 +1302,7 @@
LIMIT 21
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.41
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.42
'''
SELECT "posthog_team"."id",
"posthog_team"."uuid",
@@ -1335,7 +1387,7 @@
LIMIT 21
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.42
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.43
'''
SELECT "posthog_organizationmembership"."id",
"posthog_organizationmembership"."organization_id",
@@ -1377,7 +1429,7 @@
LIMIT 21
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.43
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.44
'''
SELECT "ee_accesscontrol"."id",
"ee_accesscontrol"."team_id",
@@ -1423,7 +1475,7 @@
AND "ee_accesscontrol"."team_id" = 99999))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.44
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.45
'''
SELECT "posthog_organizationmembership"."id",
"posthog_organizationmembership"."organization_id",
@@ -1463,17 +1515,6 @@
WHERE "posthog_organizationmembership"."user_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.45
'''
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingplaylist"
WHERE (NOT "posthog_sessionrecordingplaylist"."deleted"
AND NOT "posthog_sessionrecordingplaylist"."deleted"
AND "posthog_sessionrecordingplaylist"."team_id" = 99999
AND NOT "posthog_sessionrecordingplaylist"."deleted"
AND NOT "posthog_sessionrecordingplaylist"."deleted")
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.46
'''
SELECT COUNT(*) AS "__count"
@@ -1486,6 +1527,17 @@
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.47
'''
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingplaylist"
WHERE (NOT "posthog_sessionrecordingplaylist"."deleted"
AND NOT "posthog_sessionrecordingplaylist"."deleted"
AND "posthog_sessionrecordingplaylist"."team_id" = 99999
AND NOT "posthog_sessionrecordingplaylist"."deleted"
AND NOT "posthog_sessionrecordingplaylist"."deleted")
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.48
'''
SELECT "posthog_sessionrecordingplaylist"."id",
"posthog_sessionrecordingplaylist"."short_id",
@@ -1655,7 +1707,7 @@
LIMIT 100
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.48
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.49
'''
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingviewed"
@@ -1663,18 +1715,6 @@
AND "posthog_sessionrecordingviewed"."user_id" = 99999)
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.49
'''
SELECT COUNT(*)
FROM
(SELECT DISTINCT "posthog_comment"."item_id" AS "col1"
FROM "posthog_comment"
WHERE (NOT "posthog_comment"."deleted"
AND "posthog_comment"."scope" = 'Replay'
AND "posthog_comment"."team_id" = 99999
AND NOT ("posthog_comment"."item_id" IS NULL))) subquery
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.5
'''
SELECT "posthog_organization"."id",
@@ -1710,6 +1750,18 @@
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.50
'''
SELECT COUNT(*)
FROM
(SELECT DISTINCT "posthog_comment"."item_id" AS "col1"
FROM "posthog_comment"
WHERE (NOT "posthog_comment"."deleted"
AND "posthog_comment"."scope" = 'Replay'
AND "posthog_comment"."team_id" = 99999
AND NOT ("posthog_comment"."item_id" IS NULL))) subquery
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.51
'''
SELECT COUNT(*)
FROM
@@ -1720,7 +1772,7 @@
AND NOT ("posthog_sharingconfiguration"."recording_id" IS NULL))) subquery
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.51
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.52
'''
SELECT COUNT(*)
FROM
@@ -1735,22 +1787,6 @@
AND "posthog_exportedasset"."export_context" IS NOT NULL))) subquery
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.52
'''
SELECT "posthog_grouptypemapping"."id",
"posthog_grouptypemapping"."team_id",
"posthog_grouptypemapping"."project_id",
"posthog_grouptypemapping"."group_type",
"posthog_grouptypemapping"."group_type_index",
"posthog_grouptypemapping"."name_singular",
"posthog_grouptypemapping"."name_plural",
"posthog_grouptypemapping"."default_columns",
"posthog_grouptypemapping"."detail_dashboard_id",
"posthog_grouptypemapping"."created_at"
FROM "posthog_grouptypemapping"
WHERE "posthog_grouptypemapping"."team_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.53
'''
SELECT "posthog_grouptypemapping"."id",
@@ -1764,10 +1800,26 @@
"posthog_grouptypemapping"."detail_dashboard_id",
"posthog_grouptypemapping"."created_at"
FROM "posthog_grouptypemapping"
WHERE "posthog_grouptypemapping"."project_id" = 99999
WHERE "posthog_grouptypemapping"."team_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.54
'''
SELECT "posthog_grouptypemapping"."id",
"posthog_grouptypemapping"."team_id",
"posthog_grouptypemapping"."project_id",
"posthog_grouptypemapping"."group_type",
"posthog_grouptypemapping"."group_type_index",
"posthog_grouptypemapping"."name_singular",
"posthog_grouptypemapping"."name_plural",
"posthog_grouptypemapping"."default_columns",
"posthog_grouptypemapping"."detail_dashboard_id",
"posthog_grouptypemapping"."created_at"
FROM "posthog_grouptypemapping"
WHERE "posthog_grouptypemapping"."project_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.55
'''
SELECT "posthog_datawarehousesavedquery"."created_by_id",
"posthog_datawarehousesavedquery"."created_at",
@@ -1826,7 +1878,59 @@
AND "posthog_datawarehousesavedquery"."managed_viewset_id" IS NULL)
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.55
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.56
'''
SELECT "posthog_datawarehousesavedquery"."created_by_id",
"posthog_datawarehousesavedquery"."created_at",
"posthog_datawarehousesavedquery"."deleted",
"posthog_datawarehousesavedquery"."deleted_at",
"posthog_datawarehousesavedquery"."id",
"posthog_datawarehousesavedquery"."name",
"posthog_datawarehousesavedquery"."team_id",
"posthog_datawarehousesavedquery"."latest_error",
"posthog_datawarehousesavedquery"."columns",
"posthog_datawarehousesavedquery"."external_tables",
"posthog_datawarehousesavedquery"."query",
"posthog_datawarehousesavedquery"."status",
"posthog_datawarehousesavedquery"."last_run_at",
"posthog_datawarehousesavedquery"."sync_frequency_interval",
"posthog_datawarehousesavedquery"."table_id",
"posthog_datawarehousesavedquery"."is_materialized",
"posthog_datawarehousesavedquery"."deleted_name",
"posthog_datawarehousesavedquery"."managed_viewset_id",
"posthog_datawarehousesavedquery"."origin",
"posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
"posthog_datawarehousetable"."updated_at",
"posthog_datawarehousetable"."deleted",
"posthog_datawarehousetable"."deleted_at",
"posthog_datawarehousetable"."id",
"posthog_datawarehousetable"."name",
"posthog_datawarehousetable"."format",
"posthog_datawarehousetable"."team_id",
"posthog_datawarehousetable"."url_pattern",
"posthog_datawarehousetable"."queryable_folder",
"posthog_datawarehousetable"."credential_id",
"posthog_datawarehousetable"."external_data_source_id",
"posthog_datawarehousetable"."columns",
"posthog_datawarehousetable"."row_count",
"posthog_datawarehousetable"."size_in_s3_mib",
"posthog_datawarehousecredential"."created_by_id",
"posthog_datawarehousecredential"."created_at",
"posthog_datawarehousecredential"."id",
"posthog_datawarehousecredential"."access_key",
"posthog_datawarehousecredential"."access_secret",
"posthog_datawarehousecredential"."team_id"
FROM "posthog_datawarehousesavedquery"
LEFT OUTER JOIN "posthog_datawarehousetable" ON ("posthog_datawarehousesavedquery"."table_id" = "posthog_datawarehousetable"."id")
LEFT OUTER JOIN "posthog_datawarehousecredential" ON ("posthog_datawarehousetable"."credential_id" = "posthog_datawarehousecredential"."id")
WHERE ("posthog_datawarehousesavedquery"."team_id" = 99999
AND "posthog_datawarehousesavedquery"."origin" = 'endpoint'
AND NOT ("posthog_datawarehousesavedquery"."deleted"
AND "posthog_datawarehousesavedquery"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.57
'''
SELECT "posthog_externaldatasource"."created_by_id",
"posthog_externaldatasource"."created_at",
@@ -1856,7 +1960,7 @@
AND "posthog_externaldatasource"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.56
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.58
'''
SELECT "posthog_datawarehousetable"."created_by_id",
"posthog_datawarehousetable"."created_at",
@@ -1905,7 +2009,7 @@
AND "posthog_datawarehousetable"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.57
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.59
'''
SELECT "posthog_datawarehousejoin"."created_by_id",
"posthog_datawarehousejoin"."created_at",
@@ -1925,22 +2029,6 @@
AND "posthog_datawarehousejoin"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.58
'''
SELECT COUNT(*)
FROM
(SELECT DISTINCT "ee_single_session_summary"."session_id" AS "col1"
FROM "ee_single_session_summary"
WHERE "ee_single_session_summary"."team_id" = 99999) subquery
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.59
'''
SELECT "posthog_sessionrecordingplaylistitem"."session_id"
FROM "posthog_sessionrecordingplaylistitem"
WHERE "posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.6
'''
SELECT "posthog_team"."id",
@@ -2028,11 +2116,11 @@
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.60
'''
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingplaylistitem"
WHERE ("posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
AND NOT ("posthog_sessionrecordingplaylistitem"."deleted"
AND "posthog_sessionrecordingplaylistitem"."deleted" IS NOT NULL))
SELECT COUNT(*)
FROM
(SELECT DISTINCT "ee_single_session_summary"."session_id" AS "col1"
FROM "ee_single_session_summary"
WHERE "ee_single_session_summary"."team_id" = 99999) subquery
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.61
@@ -2067,6 +2155,22 @@
AND "posthog_sessionrecordingplaylistitem"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.65
'''
SELECT "posthog_sessionrecordingplaylistitem"."session_id"
FROM "posthog_sessionrecordingplaylistitem"
WHERE "posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.66
'''
SELECT COUNT(*) AS "__count"
FROM "posthog_sessionrecordingplaylistitem"
WHERE ("posthog_sessionrecordingplaylistitem"."playlist_id" = 99999
AND NOT ("posthog_sessionrecordingplaylistitem"."deleted"
AND "posthog_sessionrecordingplaylistitem"."deleted" IS NOT NULL))
'''
# ---
# name: TestSessionRecordingPlaylist.test_filters_playlist_by_type.7
'''
SELECT "posthog_organizationmembership"."id",

View File

@@ -513,7 +513,7 @@ class TestExternalDataSource(APIBaseTest):
self._create_external_data_source()
self._create_external_data_source()
with self.assertNumQueries(25):
with self.assertNumQueries(26):
response = self.client.get(f"/api/environments/{self.team.pk}/external_data_sources/")
payload = response.json()

View File

@@ -271,7 +271,7 @@ class TestViewLinkQuery(APIBaseTest):
# Test that listing joins uses efficient querying
with self.assertNumQueries(
FuzzyInt(17, 18)
FuzzyInt(18, 19)
): # depends when team revenue analytisc config cache is hit in a test
response = self.client.get(f"/api/environments/{self.team.id}/warehouse_view_links/")

View File

@@ -154,6 +154,7 @@ CLICKHOUSE_HOGQL_MAPPING = {
"Bool": BooleanDatabaseField,
"Decimal": DecimalDatabaseField,
"FixedString": StringDatabaseField,
"Enum8": StringDatabaseField,
}
STR_TO_HOGQL_MAPPING = {