diff --git a/.eslintrc.js b/.eslintrc.js index 7aa24b651e2d9..b66539acec105 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -78,6 +78,7 @@ module.exports = { 'error', { ignoreRestSiblings: true, + destructuredArrayIgnorePattern: '^_$', }, ], '@typescript-eslint/prefer-ts-expect-error': 'error', diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000000..e55577185cc30 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,20 @@ +name: Bug report +description: Something not working as expected? Let us look into it. +labels: ['bug'] +body: + - type: textarea + id: bug-description + attributes: + label: Bug Description + value: "## Bug description\n\n*Please describe.*\n*If this affects the front-end, screenshots would be of great help.*\n\n*If you are on PostHog Cloud it would be really valuable if you can share any links where the problem occurs. This speeds up our ability to troubleshoot tremendously.*\n\n## How to reproduce\n\n1. \n2.\n3. \n\n## Additional context\n\n" + + - type: textarea + id: debug-info + attributes: + label: Debug info + value: "- [ ] PostHog Cloud, Debug information: [please copy/paste from https://us.posthog.com/settings/project-details#variables]\n- [ ] PostHog Hobby self-hosted with `docker compose`, version/commit: [please provide]\n- [ ] PostHog self-hosted with Kubernetes (deprecated, see [`Sunsetting Kubernetes support`](https://posthog.com/blog/sunsetting-helm-support-posthog)), version/commit: [please provide]\n" + render: shell + + - type: markdown + attributes: + value: '#### *Thank you* for your bug report – we love squashing them!' diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000000..5bcacc4be27d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,22 @@ +name: Feature request +description: 'Suggest a feature for PostHog' +labels: ['enhancement, feature'] +body: + - type: textarea + id: feature_request + attributes: + label: Feature request + value: + "## Is your feature request related to a problem?\n\n*Please describe.*\n\n## Describe the solution you'd like\n\n\n## Describe alternatives you've considered\n\n\n## Additional context\n\n\n + + " + - type: textarea + id: debug-info + attributes: + label: Debug info + value: "- [ ] PostHog Cloud, Debug information: [please copy/paste from https://us.posthog.com/settings/project-details#variables]\n- [ ] PostHog Hobby self-hosted with `docker compose`, version/commit: [please provide]\n- [ ] PostHog self-hosted with Kubernetes (deprecated, see [`Sunsetting Kubernetes support`](https://posthog.com/blog/sunsetting-helm-support-posthog)), version/commit: [please provide]\n" + render: shell + + - type: markdown + attributes: + value: '#### *Thank you* for your bug report – we love squashing them!' diff --git a/.github/actions/get-pr-labels/action.yml b/.github/actions/get-pr-labels/action.yml index 65b7fd8553ca7..9f1a17130a128 100644 --- a/.github/actions/get-pr-labels/action.yml +++ b/.github/actions/get-pr-labels/action.yml @@ -1,47 +1,47 @@ -name: "Get merged pull request labels" +name: 'Get merged pull request labels' shell: bash -description: "Get the labels of the PR that was merged to create this push event" +description: 'Get the labels of the PR that was merged to create this push event' inputs: - token: - description: "GH token" - required: true + token: + description: 'GH token' + required: true outputs: - labels: - description: "JSON array labels of the PR that was merged (if any)" - value: ${{ steps.labels.outputs.labels }} + labels: + description: 'JSON array labels of the PR that was merged (if any)' + value: ${{ steps.labels.outputs.labels }} runs: - using: "composite" - steps: - - name: Get PR associated with the last commit - id: pr-info - uses: octokit/request-action@v2.x - with: - route: GET /repos/${{ github.repository }}/commits/${{ github.sha }}/pulls - env: - GITHUB_TOKEN: ${{ inputs.token }} + using: 'composite' + steps: + - name: Get PR associated with the last commit + id: pr-info + uses: octokit/request-action@v2.x + with: + route: GET /repos/${{ github.repository }}/commits/${{ github.sha }}/pulls + env: + GITHUB_TOKEN: ${{ inputs.token }} - - name: Extract PR number - shell: bash - if: steps.pr-info.outputs.data - id: extract-pr - run: | - echo "PR_NUMBER=$(cat | jq -r '.[-1].number' <> $GITHUB_OUTPUT + - name: Extract PR number + shell: bash + if: steps.pr-info.outputs.data + id: extract-pr + run: | + echo "PR_NUMBER=$(cat | jq -r '.[-1].number' <> $GITHUB_OUTPUT - - name: Fetch PR Labels - shell: bash - if: steps.extract-pr.outputs.PR_NUMBER - id: labels - run: | - PR_NUMBER=${{ steps.extract-pr.outputs.PR_NUMBER }} - LABELS=$(curl \ - -H "Authorization: Bearer ${{ inputs.token }}" \ - -H "Accept: application/vnd.github.v3+json" \ - https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels | jq -rc '[.[].name]') - echo "Labels of PR #$PR_NUMBER: $LABELS" + - name: Fetch PR Labels + shell: bash + if: steps.extract-pr.outputs.PR_NUMBER + id: labels + run: | + PR_NUMBER=${{ steps.extract-pr.outputs.PR_NUMBER }} + LABELS=$(curl \ + -H "Authorization: Bearer ${{ inputs.token }}" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels | jq -rc '[.[].name]') + echo "Labels of PR #$PR_NUMBER: $LABELS" - echo labels="$LABELS" >> $GITHUB_OUTPUT - env: - GITHUB_TOKEN: ${{ inputs.token }} + echo labels="$LABELS" >> $GITHUB_OUTPUT + env: + GITHUB_TOKEN: ${{ inputs.token }} diff --git a/.github/actions/run-backend-tests/action.yml b/.github/actions/run-backend-tests/action.yml index 2c50c7becfe8a..f78b6eeea75ad 100644 --- a/.github/actions/run-backend-tests/action.yml +++ b/.github/actions/run-backend-tests/action.yml @@ -185,3 +185,8 @@ runs: pytest posthog/api/test/test_decide.py::TestDecideUsesReadReplica \ --durations=100 --durations-min=1.0 \ $PYTEST_ARGS + + - name: Show docker compose logs on failure + if: failure() + shell: bash + run: docker compose -f docker-compose.dev.yml logs diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index 139036664c6bf..20a3dbf314649 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Automerge if: env.IS_POSTHOG_BOT_AVAILABLE == 'true' - uses: pascalgn/automerge-action@v0.15.5 + uses: pascalgn/automerge-action@v0.16.3 env: GITHUB_TOKEN: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }} - run: echo diff --git a/.github/workflows/ci-backend.yml b/.github/workflows/ci-backend.yml index ebc593885c4e0..d8428277f7f80 100644 --- a/.github/workflows/ci-backend.yml +++ b/.github/workflows/ci-backend.yml @@ -197,29 +197,22 @@ jobs: sudo apt-get update sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl - # First running migrations from master, to simulate the real-world scenario + - name: Install python dependencies + run: | + uv pip install --system -r requirements.txt -r requirements-dev.txt - - name: Checkout master - uses: actions/checkout@v3 + - uses: actions/checkout@v3 with: ref: master - - name: Install python dependencies for master - run: | - uv pip install --system -r requirements.txt -r requirements-dev.txt - - name: Run migrations up to master run: | + # We need to ensure we have requirements for the master branch + # now also, so we can run migrations up to master. + uv pip install --system -r requirements.txt -r requirements-dev.txt python manage.py migrate - # Now we can consider this PR's migrations - - - name: Checkout this PR - uses: actions/checkout@v3 - - - name: Install python dependencies for this PR - run: | - uv pip install --system -r requirements.txt -r requirements-dev.txt + - uses: actions/checkout@v3 - name: Check migrations run: | diff --git a/.github/workflows/container-images-cd.yml b/.github/workflows/container-images-cd.yml index b6a1c3f52ae52..96b6ca673aee2 100644 --- a/.github/workflows/container-images-cd.yml +++ b/.github/workflows/container-images-cd.yml @@ -15,8 +15,6 @@ on: - master workflow_dispatch: -concurrency: ${{ github.workflow }} # ensure only one of this runs at a time - jobs: posthog_build: name: Build and push PostHog diff --git a/docker-compose.base.yml b/docker-compose.base.yml index 1254f103c9f1c..a560547c1f79a 100644 --- a/docker-compose.base.yml +++ b/docker-compose.base.yml @@ -168,6 +168,9 @@ services: kompose.volume.type: configMap volumes: - ./docker/temporal/dynamicconfig:/etc/temporal/config/dynamicconfig + depends_on: + - db + - elasticsearch temporal-admin-tools: environment: - TEMPORAL_CLI_ADDRESS=temporal:7233 diff --git a/ee/api/test/__snapshots__/test_organization_resource_access.ambr b/ee/api/test/__snapshots__/test_organization_resource_access.ambr index b70fa6dfcc673..607a86166a10f 100644 --- a/ee/api/test/__snapshots__/test_organization_resource_access.ambr +++ b/ee/api/test/__snapshots__/test_organization_resource_access.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.1 @@ -53,7 +53,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.10 @@ -79,7 +79,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.11 @@ -88,7 +88,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.12 @@ -102,14 +102,14 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 21 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.13 ''' SELECT COUNT(*) AS "__count" FROM "ee_organizationresourceaccess" - WHERE "ee_organizationresourceaccess"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + WHERE "ee_organizationresourceaccess"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.14 @@ -123,7 +123,7 @@ "ee_organizationresourceaccess"."updated_at" FROM "ee_organizationresourceaccess" WHERE "ee_organizationresourceaccess"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 100 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 100 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.2 @@ -149,7 +149,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.3 @@ -158,7 +158,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.4 @@ -172,7 +172,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 21 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.5 @@ -183,14 +183,14 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.6 ''' SELECT COUNT(*) AS "__count" FROM "ee_organizationresourceaccess" - WHERE "ee_organizationresourceaccess"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + WHERE "ee_organizationresourceaccess"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.7 @@ -204,7 +204,7 @@ "ee_organizationresourceaccess"."updated_at" FROM "ee_organizationresourceaccess" WHERE "ee_organizationresourceaccess"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 100 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 100 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.8 @@ -235,7 +235,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestOrganizationResourceAccessAPI.test_list_organization_resource_access_is_not_nplus1.9 @@ -261,6 +261,6 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_resource_access-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/resource_access/%3F%24'*/ + LIMIT 21 ''' # --- diff --git a/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr b/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr index e45231b084eca..11c70ce750537 100644 --- a/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr +++ b/ee/clickhouse/models/test/__snapshots__/test_cohort.ambr @@ -84,7 +84,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 2 year AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_15_level_level_0_level_0_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_15_level_level_0_level_0_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -149,7 +150,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 2 year AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_17_level_level_0_level_0_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_17_level_level_0_level_0_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -238,7 +240,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 2 year AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_19_level_level_0_level_0_level_0_0, + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_19_level_level_0_level_0_level_0_0, minIf(timestamp, event = 'signup') >= now() - INTERVAL 15 day AND minIf(timestamp, event = 'signup') < now() as first_time_condition_19_level_level_0_level_1_level_0_level_0_level_0_0 FROM events e diff --git a/ee/clickhouse/queries/experiments/funnel_experiment_result.py b/ee/clickhouse/queries/experiments/funnel_experiment_result.py index 1cdda06322c0d..ab117b07c69e2 100644 --- a/ee/clickhouse/queries/experiments/funnel_experiment_result.py +++ b/ee/clickhouse/queries/experiments/funnel_experiment_result.py @@ -1,5 +1,6 @@ from dataclasses import asdict, dataclass from datetime import datetime +import json from typing import List, Optional, Tuple, Type from zoneinfo import ZoneInfo @@ -11,7 +12,7 @@ FF_DISTRIBUTION_THRESHOLD, MIN_PROBABILITY_FOR_SIGNIFICANCE, ) -from posthog.constants import ExperimentSignificanceCode +from posthog.constants import ExperimentSignificanceCode, ExperimentNoResultsErrorKeys from posthog.models.feature_flag import FeatureFlag from posthog.models.filters.filter import Filter from posthog.models.team import Team @@ -320,39 +321,42 @@ def calculate_probability_of_winning_for_each(variants: List[Variant]) -> List[P def validate_event_variants(funnel_results, variants): + errors = { + ExperimentNoResultsErrorKeys.NO_EVENTS: True, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: True, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, + } + if not funnel_results or not funnel_results[0]: - raise ValidationError("No experiment events have been ingested yet.", code="no-events") + raise ValidationError(code="no-results", detail=json.dumps(errors)) + + errors[ExperimentNoResultsErrorKeys.NO_EVENTS] = False + # Funnels: the first step must be present for *any* results to show up eventsWithOrderZero = [] for eventArr in funnel_results: for event in eventArr: if event.get("order") == 0: eventsWithOrderZero.append(event) - missing_variants = [] - # Check if "control" is present - control_found = False for event in eventsWithOrderZero: event_variant = event.get("breakdown_value")[0] if event_variant == "control": - control_found = True + errors[ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT] = False + errors[ExperimentNoResultsErrorKeys.NO_FLAG_INFO] = False break - if not control_found: - missing_variants.append("control") # Check if at least one of the test variants is present test_variants = [variant for variant in variants if variant != "control"] - test_variant_found = False for event in eventsWithOrderZero: event_variant = event.get("breakdown_value")[0] if event_variant in test_variants: - test_variant_found = True + errors[ExperimentNoResultsErrorKeys.NO_TEST_VARIANT] = False + errors[ExperimentNoResultsErrorKeys.NO_FLAG_INFO] = False break - if not test_variant_found: - missing_variants.extend(test_variants) - if not len(missing_variants) == 0: - missing_variants_str = ", ".join(missing_variants) - message = f"No experiment events have been ingested yet for the following variants: {missing_variants_str}" - raise ValidationError(message, code=f"missing-flag-variants::{missing_variants_str}") + has_errors = any(errors.values()) + if has_errors: + raise ValidationError(detail=json.dumps(errors)) diff --git a/ee/clickhouse/queries/experiments/trend_experiment_result.py b/ee/clickhouse/queries/experiments/trend_experiment_result.py index 555c6db4470bc..02974d8bd8252 100644 --- a/ee/clickhouse/queries/experiments/trend_experiment_result.py +++ b/ee/clickhouse/queries/experiments/trend_experiment_result.py @@ -1,3 +1,4 @@ +import json from dataclasses import asdict, dataclass from datetime import datetime from functools import lru_cache @@ -20,6 +21,7 @@ TRENDS_LINEAR, UNIQUE_USERS, ExperimentSignificanceCode, + ExperimentNoResultsErrorKeys, ) from posthog.models.feature_flag import FeatureFlag from posthog.models.filters.filter import Filter @@ -93,6 +95,7 @@ def __init__( uses_math_aggregation = uses_math_aggregation_by_user_or_property_value(filter) + # Keep in sync with https://github.com/PostHog/posthog/blob/master/frontend/src/scenes/experiments/ExperimentView/components.tsx#L91 query_filter = filter.shallow_clone( { "display": TRENDS_CUMULATIVE if not uses_math_aggregation else TRENDS_LINEAR, @@ -466,34 +469,36 @@ def calculate_p_value(control_variant: Variant, test_variants: List[Variant]) -> ) -def validate_event_variants(insight_results, variants): - if not insight_results or not insight_results[0]: - raise ValidationError("No experiment events have been ingested yet.", code="no-events") +def validate_event_variants(trend_results, variants): + errors = { + ExperimentNoResultsErrorKeys.NO_EVENTS: True, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: True, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, + } - missing_variants = [] + if not trend_results or not trend_results[0]: + raise ValidationError(code="no-results", detail=json.dumps(errors)) + + errors[ExperimentNoResultsErrorKeys.NO_EVENTS] = False # Check if "control" is present - control_found = False - for event in insight_results: + for event in trend_results: event_variant = event.get("breakdown_value") if event_variant == "control": - control_found = True + errors[ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT] = False + errors[ExperimentNoResultsErrorKeys.NO_FLAG_INFO] = False break - if not control_found: - missing_variants.append("control") # Check if at least one of the test variants is present test_variants = [variant for variant in variants if variant != "control"] - test_variant_found = False - for event in insight_results: + for event in trend_results: event_variant = event.get("breakdown_value") if event_variant in test_variants: - test_variant_found = True + errors[ExperimentNoResultsErrorKeys.NO_TEST_VARIANT] = False + errors[ExperimentNoResultsErrorKeys.NO_FLAG_INFO] = False break - if not test_variant_found: - missing_variants.extend(test_variants) - if not len(missing_variants) == 0: - missing_variants_str = ", ".join(missing_variants) - message = f"No experiment events have been ingested yet for the following variants: {missing_variants_str}" - raise ValidationError(message, code=f"missing-flag-variants::{missing_variants_str}") + has_errors = any(errors.values()) + if has_errors: + raise ValidationError(detail=json.dumps(errors)) diff --git a/ee/clickhouse/queries/funnels/funnel_correlation.py b/ee/clickhouse/queries/funnels/funnel_correlation.py index 4dc2b50a39490..ebe78d3b86826 100644 --- a/ee/clickhouse/queries/funnels/funnel_correlation.py +++ b/ee/clickhouse/queries/funnels/funnel_correlation.py @@ -435,7 +435,7 @@ def get_properties_query(self) -> Tuple[str, Dict[str, Any]]: return query, params def _get_aggregation_target_join_query(self) -> str: - if self._team.person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + if self._team.person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: aggregation_person_join = f""" JOIN funnel_actors as actors ON event.person_id = actors.actor_id diff --git a/ee/clickhouse/queries/test/__snapshots__/test_cohort_query.ambr b/ee/clickhouse/queries/test/__snapshots__/test_cohort_query.ambr index ecb3645f37924..ac6833f1a0a51 100644 --- a/ee/clickhouse/queries/test/__snapshots__/test_cohort_query.ambr +++ b/ee/clickhouse/queries/test/__snapshots__/test_cohort_query.ambr @@ -7,10 +7,12 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 day AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_0_level_0_0, + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_level_0_0, countIf(timestamp > now() - INTERVAL 2 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_0_level_1_0, + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_level_1_0, minIf(timestamp, ((replaceRegexpAll(JSONExtractRaw(properties, '$current_url'), '^"|"$', '') = 'https://posthog.com/feedback/123' AND event = '$autocapture'))) >= now() - INTERVAL 2 week AND minIf(timestamp, ((replaceRegexpAll(JSONExtractRaw(properties, '$current_url'), '^"|"$', '') = 'https://posthog.com/feedback/123' @@ -126,7 +128,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -167,7 +170,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_1_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_1_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -250,7 +254,8 @@ AND event_0_latest_1 <= event_0_latest_0 + INTERVAL 3 day, 2, 1)) = 2 AS steps_0, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$new_view') >= 1 AS performed_event_multiple_condition_None_level_level_0_level_1_0 + AND event = '$new_view' + AND 1=1) >= 1 AS performed_event_multiple_condition_None_level_level_0_level_1_0 FROM (SELECT person_id, event, @@ -297,7 +302,8 @@ AND event_0_latest_1 <= event_0_latest_0 + INTERVAL 3 day, 2, 1)) = 2 AS steps_0, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') >= 1 AS performed_event_multiple_condition_None_level_level_0_level_1_0 + AND event = '$pageview' + AND 1=1) >= 1 AS performed_event_multiple_condition_None_level_level_0_level_1_0 FROM (SELECT person_id, event, @@ -348,6 +354,58 @@ AND (performed_event_multiple_condition_None_level_level_0_level_1_0))) ''' # --- +# name: TestCohortQuery.test_performed_event_with_event_filters + ''' + + SELECT behavior_query.person_id AS id + FROM + (SELECT pdi.person_id AS person_id, + countIf(timestamp > now() - INTERVAL 1 week + AND timestamp < now() + AND event = '$pageview' + AND (has(['something'], replaceRegexpAll(JSONExtractRaw(properties, '$filter_prop'), '^"|"$', '')))) > 0 AS performed_event_condition_None_level_level_0_level_0_0 + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + WHERE team_id = 2 + AND event IN ['$pageview'] + AND timestamp <= now() + AND timestamp >= now() - INTERVAL 1 week + GROUP BY person_id) behavior_query + WHERE 1 = 1 + AND (((performed_event_condition_None_level_level_0_level_0_0))) + ''' +# --- +# name: TestCohortQuery.test_performed_event_with_event_filters_and_explicit_date + ''' + + SELECT behavior_query.person_id AS id + FROM + (SELECT pdi.person_id AS person_id, + countIf(timestamp > '2024-04-02 13:01:01' + AND timestamp < now() + AND event = '$pageview' + AND (has(['something'], replaceRegexpAll(JSONExtractRaw(properties, '$filter_prop'), '^"|"$', '')))) > 0 AS performed_event_condition_None_level_level_0_level_0_0 + FROM events e + INNER JOIN + (SELECT distinct_id, + argMax(person_id, version) as person_id + FROM person_distinct_id2 + WHERE team_id = 2 + GROUP BY distinct_id + HAVING argMax(is_deleted, version) = 0) AS pdi ON e.distinct_id = pdi.distinct_id + WHERE team_id = 2 + AND event IN ['$pageview'] + GROUP BY person_id) behavior_query + WHERE 1 = 1 + AND (((performed_event_condition_None_level_level_0_level_0_0))) + ''' +# --- # name: TestCohortQuery.test_person ''' @@ -356,7 +414,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -393,7 +452,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -430,10 +490,12 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 day AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_0_level_0_0, + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_level_0_0, countIf(timestamp > now() - INTERVAL 2 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_0_level_1_0, + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_level_1_0, minIf(timestamp, ((replaceRegexpAll(JSONExtractRaw(properties, '$current_url'), '^"|"$', '') = 'https://posthog.com/feedback/123' AND event = '$autocapture'))) >= now() - INTERVAL 2 week AND minIf(timestamp, ((replaceRegexpAll(JSONExtractRaw(properties, '$current_url'), '^"|"$', '') = 'https://posthog.com/feedback/123' @@ -579,7 +641,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_1_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_1_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -619,7 +682,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_1_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_1_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -668,10 +732,12 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 7 day AND timestamp < now() - AND event = '$new_view') > 0 AS performed_event_condition_None_level_level_0_level_0_level_0_0, + AND event = '$new_view' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_0_level_0_0, countIf(timestamp > now() - INTERVAL 1 week AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_None_level_level_0_level_1_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_None_level_level_0_level_1_0 FROM events e INNER JOIN (SELECT distinct_id, diff --git a/ee/clickhouse/queries/test/test_cohort_query.py b/ee/clickhouse/queries/test/test_cohort_query.py index 6b9d4cf7ce116..1c385499f68e5 100644 --- a/ee/clickhouse/queries/test/test_cohort_query.py +++ b/ee/clickhouse/queries/test/test_cohort_query.py @@ -1,5 +1,7 @@ from datetime import datetime, timedelta +from freezegun import freeze_time + from ee.clickhouse.queries.enterprise_cohort_query import check_negation_clause from posthog.client import sync_execute from posthog.constants import PropertyOperatorType @@ -216,10 +218,76 @@ def test_performed_event(self): { "key": "$pageview", "event_type": "events", + "explicit_datetime": "-1w", + "value": "performed_event", + "type": "behavioral", + } + ], + } + } + ) + + q, params = CohortQuery(filter=filter, team=self.team).get_query() + res = sync_execute(q, {**params, **filter.hogql_context.values}) + + self.assertEqual([p1.uuid], [r[0] for r in res]) + + @snapshot_clickhouse_queries + @freeze_time("2024-04-05 13:01:01") + def test_performed_event_with_event_filters_and_explicit_date(self): + p1 = _create_person( + team_id=self.team.pk, + distinct_ids=["p1"], + properties={"name": "test", "email": "test@posthog.com"}, + ) + _create_event( + team=self.team, + event="$pageview", + properties={"$filter_prop": "something"}, + distinct_id="p1", + timestamp=datetime.now() - timedelta(days=2), + ) + + _create_person( + team_id=self.team.pk, + distinct_ids=["p2"], + properties={"name": "test", "email": "test@posthog.com"}, + ) + _create_event( + team=self.team, + event="$pageview", + properties={}, + distinct_id="p2", + timestamp=datetime.now() - timedelta(days=2), + ) + _create_event( + team=self.team, + event="$pageview", + properties={"$filter_prop": "something"}, + distinct_id="p2", + # rejected because explicit datetime is set to 3 days ago + timestamp=datetime.now() - timedelta(days=5), + ) + flush_persons_and_events() + + filter = Filter( + data={ + "properties": { + "type": "AND", + "values": [ + { + "key": "$pageview", + "event_type": "events", + "explicit_datetime": str( + datetime.now() - timedelta(days=3) + ), # overrides time_value and time_interval "time_value": 1, "time_interval": "week", "value": "performed_event", "type": "behavioral", + "event_filters": [ + {"key": "$filter_prop", "value": "something", "operator": "exact", "type": "event"} + ], } ], } @@ -292,6 +360,78 @@ def test_performed_event_multiple(self): self.assertEqual([p1.uuid], [r[0] for r in res]) + def test_performed_event_multiple_with_event_filters(self): + p1 = _create_person( + team_id=self.team.pk, + distinct_ids=["p1"], + properties={"name": "test", "email": "test@posthog.com"}, + ) + _create_event( + team=self.team, + event="$pageview", + properties={"$filter_prop": "something"}, + distinct_id="p1", + timestamp=datetime.now() - timedelta(days=2), + ) + + _create_event( + team=self.team, + event="$pageview", + properties={"$filter_prop": "something"}, + distinct_id="p1", + timestamp=datetime.now() - timedelta(days=4), + ) + + _create_person( + team_id=self.team.pk, + distinct_ids=["p2"], + properties={"name": "test", "email": "test@posthog.com"}, + ) + _create_event( + team=self.team, + event="$pageview", + properties={}, + distinct_id="p2", + timestamp=datetime.now() - timedelta(days=2), + ) + _create_event( + team=self.team, + event="$pageview", + properties={}, + distinct_id="p2", + timestamp=datetime.now() - timedelta(days=4), + ) + flush_persons_and_events() + + filter = Filter( + data={ + "properties": { + "type": "AND", + "values": [ + { + "key": "$pageview", + "event_type": "events", + "operator": "gte", + "operator_value": 1, + "time_value": 1, + "time_interval": "week", + "value": "performed_event_multiple", + "type": "behavioral", + "event_filters": [ + {"key": "$filter_prop", "value": "something", "operator": "exact", "type": "event"}, + {"key": "$filter_prop", "value": "some", "operator": "icontains", "type": "event"}, + ], + } + ], + } + } + ) + + q, params = CohortQuery(filter=filter, team=self.team).get_query() + res = sync_execute(q, {**params, **filter.hogql_context.values}) + + self.assertEqual([p1.uuid], [r[0] for r in res]) + def test_performed_event_lte_1_times(self): _create_person( team_id=self.team.pk, diff --git a/ee/clickhouse/queries/test/test_experiments.py b/ee/clickhouse/queries/test/test_experiments.py index 8cdbcd8681ede..95aacc8ca0d60 100644 --- a/ee/clickhouse/queries/test/test_experiments.py +++ b/ee/clickhouse/queries/test/test_experiments.py @@ -1,3 +1,4 @@ +import json import unittest from ee.clickhouse.queries.experiments.funnel_experiment_result import ( validate_event_variants as validate_funnel_event_variants, @@ -7,206 +8,228 @@ ) from rest_framework.exceptions import ValidationError +from posthog.constants import ExperimentNoResultsErrorKeys + class TestFunnelExperiments(unittest.TestCase): def test_validate_event_variants_no_events(self): - expected_code = "no-events" + funnel_results = [] + + expected_errors = json.dumps( + { + ExperimentNoResultsErrorKeys.NO_EVENTS: True, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: True, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, + } + ) + with self.assertRaises(ValidationError) as context: - validate_funnel_event_variants([], ["test", "control"]) + validate_funnel_event_variants(funnel_results, ["test", "control"]) - self.assertEqual(expected_code, context.exception.detail[0].code) + self.assertEqual(context.exception.detail[0], expected_errors) - def test_validate_event_variants_missing_variants(self): + def test_validate_event_variants_no_control(self): funnel_results = [ [ { - "action_id": "step-a-1", - "name": "step-a-1", - "custom_name": None, + "action_id": "funnel-step-1", + "name": "funnel-step-1", "order": 0, - "people": [], - "count": 1, - "type": "events", - "average_conversion_time": None, - "median_conversion_time": None, "breakdown": ["test"], "breakdown_value": ["test"], }, { - "action_id": "step-a-2", - "name": "step-a-2", - "custom_name": None, + "action_id": "funnel-step-2", + "name": "funnel-step-2", "order": 1, - "people": [], - "count": 0, - "type": "events", - "average_conversion_time": None, - "median_conversion_time": None, "breakdown": ["test"], "breakdown_value": ["test"], }, ] ] - expected_code = "missing-flag-variants::control" + expected_errors = json.dumps( + { + ExperimentNoResultsErrorKeys.NO_EVENTS: False, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: False, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: False, + } + ) + with self.assertRaises(ValidationError) as context: validate_funnel_event_variants(funnel_results, ["test", "control"]) - self.assertEqual(expected_code, context.exception.detail[0].code) + self.assertEqual(context.exception.detail[0], expected_errors) - def test_validate_event_variants_missing_control(self): + def test_validate_event_variants_no_test(self): funnel_results = [ [ { - "action_id": "step-a-1", - "name": "step-a-1", - "custom_name": None, + "action_id": "funnel-step-1", + "name": "funnel-step-1", "order": 0, - "people": [], - "count": 1, - "type": "events", - "average_conversion_time": None, - "median_conversion_time": None, - "breakdown": ["test_1"], - "breakdown_value": ["test_1"], + "breakdown": ["control"], + "breakdown_value": ["control"], }, { - "action_id": "step-a-2", - "name": "step-a-2", - "custom_name": None, + "action_id": "funnel-step-2", + "name": "funnel-step-2", "order": 1, - "people": [], - "count": 0, - "type": "events", - "average_conversion_time": None, - "median_conversion_time": None, - "breakdown": ["test_1"], - "breakdown_value": ["test_1"], + "breakdown": ["control"], + "breakdown_value": ["control"], }, ] ] - # Only 1 test variant is required to return results - expected_code = "missing-flag-variants::control" + expected_errors = json.dumps( + { + ExperimentNoResultsErrorKeys.NO_EVENTS: False, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: False, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: False, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, + } + ) + with self.assertRaises(ValidationError) as context: - validate_funnel_event_variants(funnel_results, ["control", "test_1", "test_2"]) + validate_funnel_event_variants(funnel_results, ["test", "control"]) - self.assertEqual(expected_code, context.exception.detail[0].code) + self.assertEqual(context.exception.detail[0], expected_errors) - def test_validate_event_variants_ignore_old_variant(self): + def test_validate_event_variants_no_flag_info(self): funnel_results = [ [ { - "action_id": "step-a-1", - "name": "step-a-1", - "custom_name": None, + "action_id": "funnel-step-1", + "name": "funnel-step-1", "order": 0, - "people": [], - "count": 1, - "type": "events", - "average_conversion_time": None, - "median_conversion_time": None, - "breakdown": ["test"], - "breakdown_value": ["test"], + "breakdown": [""], + "breakdown_value": [""], }, { - "action_id": "step-a-2", - "name": "step-a-2", - "custom_name": None, + "action_id": "funnel-step-2", + "name": "funnel-step-2", "order": 1, - "people": [], - "count": 0, - "type": "events", - "average_conversion_time": None, - "median_conversion_time": None, - "breakdown": ["old-variant"], - "breakdown_value": ["old-variant"], + "breakdown": [""], + "breakdown_value": [""], }, ] ] - expected_code = "missing-flag-variants::control" + expected_errors = json.dumps( + { + ExperimentNoResultsErrorKeys.NO_EVENTS: False, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: True, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, + } + ) + with self.assertRaises(ValidationError) as context: validate_funnel_event_variants(funnel_results, ["test", "control"]) - self.assertEqual(expected_code, context.exception.detail[0].code) + self.assertEqual(context.exception.detail[0], expected_errors) class TestTrendExperiments(unittest.TestCase): def test_validate_event_variants_no_events(self): - expected_code = "no-events" - with self.assertRaises(ValidationError) as context: - validate_trend_event_variants([], ["test", "control"]) - - self.assertEqual(expected_code, context.exception.detail[0].code) + trend_results = [] - def test_validate_event_variants_missing_variants(self): - insight_results = [ + expected_errors = json.dumps( { - "action": { - "id": "step-b-0", - "type": "events", - "order": 0, - "name": "step-b-0", - }, - "label": "test", - "breakdown_value": "test", + ExperimentNoResultsErrorKeys.NO_EVENTS: True, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: True, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, } - ] + ) - expected_code = "missing-flag-variants::control" with self.assertRaises(ValidationError) as context: - validate_trend_event_variants(insight_results, ["test", "control"]) + validate_trend_event_variants(trend_results, ["test", "control"]) - self.assertEqual(expected_code, context.exception.detail[0].code) + self.assertEqual(context.exception.detail[0], expected_errors) - def test_validate_event_variants_missing_control(self): - insight_results = [ + def test_validate_event_variants_no_control(self): + trend_results = [ { "action": { - "id": "step-b-0", + "id": "trend-event", "type": "events", "order": 0, - "name": "step-b-0", + "name": "trend-event", }, "label": "test_1", "breakdown_value": "test_1", } ] - # Only 1 test variant is required to return results - expected_code = "missing-flag-variants::control" + expected_errors = json.dumps( + { + ExperimentNoResultsErrorKeys.NO_EVENTS: False, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: False, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: False, + } + ) + with self.assertRaises(ValidationError) as context: - validate_trend_event_variants(insight_results, ["control", "test_1", "test_2"]) + validate_trend_event_variants(trend_results, ["control", "test_1", "test_2"]) - self.assertEqual(expected_code, context.exception.detail[0].code) + self.assertEqual(context.exception.detail[0], expected_errors) - def test_validate_event_variants_ignore_old_variant(self): - insight_results = [ + def test_validate_event_variants_no_test(self): + trend_results = [ { "action": { - "id": "step-b-0", + "id": "trend-event", "type": "events", "order": 0, - "name": "step-b-0", + "name": "trend-event", }, - "label": "test", - "breakdown_value": "test", - }, + "label": "control", + "breakdown_value": "control", + } + ] + + expected_errors = json.dumps( + { + ExperimentNoResultsErrorKeys.NO_EVENTS: False, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: False, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: False, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, + } + ) + + with self.assertRaises(ValidationError) as context: + validate_trend_event_variants(trend_results, ["control", "test_1", "test_2"]) + + self.assertEqual(context.exception.detail[0], expected_errors) + + def test_validate_event_variants_no_flag_info(self): + trend_results = [ { "action": { - "id": "step-b-0", + "id": "trend-event", "type": "events", "order": 0, - "name": "step-b-0", + "name": "trend-event", }, - "label": "test", - "breakdown_value": "old-variant", - }, + "label": "", + "breakdown_value": "", + } ] - expected_code = "missing-flag-variants::control" + expected_errors = json.dumps( + { + ExperimentNoResultsErrorKeys.NO_EVENTS: False, + ExperimentNoResultsErrorKeys.NO_FLAG_INFO: True, + ExperimentNoResultsErrorKeys.NO_CONTROL_VARIANT: True, + ExperimentNoResultsErrorKeys.NO_TEST_VARIANT: True, + } + ) + with self.assertRaises(ValidationError) as context: - validate_trend_event_variants(insight_results, ["test", "control"]) + validate_trend_event_variants(trend_results, ["control", "test_1", "test_2"]) - self.assertEqual(expected_code, context.exception.detail[0].code) + self.assertEqual(context.exception.detail[0], expected_errors) diff --git a/ee/clickhouse/views/experiments.py b/ee/clickhouse/views/experiments.py index ff27ede958c66..c30ba6ee58092 100644 --- a/ee/clickhouse/views/experiments.py +++ b/ee/clickhouse/views/experiments.py @@ -28,7 +28,7 @@ from posthog.models.filters.filter import Filter from posthog.utils import generate_cache_key, get_safe_cache -EXPERIMENT_RESULTS_CACHE_DEFAULT_TTL = 60 * 30 # 30 minutes +EXPERIMENT_RESULTS_CACHE_DEFAULT_TTL = 60 * 60 # 1 hour def _calculate_experiment_results(experiment: Experiment, refresh: bool = False): diff --git a/ee/clickhouse/views/test/__snapshots__/test_clickhouse_experiment_secondary_results.ambr b/ee/clickhouse/views/test/__snapshots__/test_clickhouse_experiment_secondary_results.ambr index 3c6b8ef78c385..b365da44bb9d6 100644 --- a/ee/clickhouse/views/test/__snapshots__/test_clickhouse_experiment_secondary_results.ambr +++ b/ee/clickhouse/views/test/__snapshots__/test_clickhouse_experiment_secondary_results.ambr @@ -1,7 +1,7 @@ # serializer version: 1 # name: ClickhouseTestExperimentSecondaryResults.test_basic_secondary_metric_results ''' - /* user_id:107 celery:posthog.tasks.tasks.sync_insight_caching_state */ + /* user_id:109 celery:posthog.tasks.tasks.sync_insight_caching_state */ SELECT team_id, date_diff('second', max(timestamp), now()) AS age FROM events diff --git a/ee/session_recordings/queries/test/__snapshots__/test_session_recording_list_from_session_replay.ambr b/ee/session_recordings/queries/test/__snapshots__/test_session_recording_list_from_session_replay.ambr index a6582b0d45cde..de90558ae7ee8 100644 --- a/ee/session_recordings/queries/test/__snapshots__/test_session_recording_list_from_session_replay.ambr +++ b/ee/session_recordings/queries/test/__snapshots__/test_session_recording_list_from_session_replay.ambr @@ -1,7 +1,7 @@ # serializer version: 1 # name: TestClickhouseSessionRecordingsListFromSessionReplay.test_effect_of_poe_settings_on_query_generated_0_test_poe_v1_still_falls_back_to_person_subquery ''' - -- running in PoE Mode: v1_enabled + -- running in PoE Mode: person_id_no_override_properties_on_events SELECT s.session_id, any(s.team_id), @@ -115,7 +115,7 @@ # --- # name: TestClickhouseSessionRecordingsListFromSessionReplay.test_effect_of_poe_settings_on_query_generated_2_test_allow_denormalised_props_fix_does_not_stop_all_poe_processing ''' - -- running in PoE Mode: v2_enabled + -- running in PoE Mode: person_id_override_properties_on_events SELECT s.session_id, any(s.team_id), @@ -145,7 +145,7 @@ AND s.session_id in (select `$session_id` as session_id from - (-- running in PoE Mode: v2_enabled + (-- running in PoE Mode: person_id_override_properties_on_events SELECT `$session_id` FROM events e -- sometimes we have to join on persons so we can access e.g. person_props in filters PREWHERE team_id = %(team_id)s -- regardless of what other filters are applied @@ -171,7 +171,7 @@ # --- # name: TestClickhouseSessionRecordingsListFromSessionReplay.test_effect_of_poe_settings_on_query_generated_3_test_poe_v2_available_person_properties_are_used_in_replay_listing ''' - -- running in PoE Mode: v2_enabled + -- running in PoE Mode: person_id_override_properties_on_events SELECT s.session_id, any(s.team_id), @@ -201,7 +201,7 @@ AND s.session_id in (select `$session_id` as session_id from - (-- running in PoE Mode: v2_enabled + (-- running in PoE Mode: person_id_override_properties_on_events SELECT `$session_id` FROM events e -- sometimes we have to join on persons so we can access e.g. person_props in filters PREWHERE team_id = %(team_id)s -- regardless of what other filters are applied diff --git a/ee/session_recordings/queries/test/test_session_recording_list_from_session_replay.py b/ee/session_recordings/queries/test/test_session_recording_list_from_session_replay.py index a6fe85ebf9702..33fdd6c3e0236 100644 --- a/ee/session_recordings/queries/test/test_session_recording_list_from_session_replay.py +++ b/ee/session_recordings/queries/test/test_session_recording_list_from_session_replay.py @@ -63,7 +63,7 @@ def create_event( True, False, False, - PersonOnEventsMode.V1_ENABLED, + PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS, { "kperson_filter_pre__0": "rgInternal", "kpersonquery_person_filter_fin__0": "rgInternal", @@ -95,7 +95,7 @@ def create_event( False, True, False, - PersonOnEventsMode.V2_ENABLED, + PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS, { "event_names": [], "event_start_time": mock.ANY, @@ -111,7 +111,7 @@ def create_event( False, True, True, - PersonOnEventsMode.V2_ENABLED, + PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS, { "event_end_time": mock.ANY, "event_names": [], diff --git a/frontend/__snapshots__/exporter-exporter--user-paths-insight--dark.png b/frontend/__snapshots__/exporter-exporter--user-paths-insight--dark.png index fbad3d686cef0..feb1b1b35f9c9 100644 Binary files a/frontend/__snapshots__/exporter-exporter--user-paths-insight--dark.png and b/frontend/__snapshots__/exporter-exporter--user-paths-insight--dark.png differ diff --git a/frontend/__snapshots__/exporter-exporter--user-paths-insight--light.png b/frontend/__snapshots__/exporter-exporter--user-paths-insight--light.png index e014ffbf6d5f4..6dfb50641913e 100644 Binary files a/frontend/__snapshots__/exporter-exporter--user-paths-insight--light.png and b/frontend/__snapshots__/exporter-exporter--user-paths-insight--light.png differ diff --git a/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--dark.png b/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--dark.png index 2cf719cc12960..88b8b5fe7b092 100644 Binary files a/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--dark.png and b/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--dark.png differ diff --git a/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--light.png b/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--light.png index f12d2fdcc90a2..35a49f1af3f6e 100644 Binary files a/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--light.png and b/frontend/__snapshots__/filters-cohort-filters-row-builder--cohort-criteria-row-builder--light.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--actions--dark.png b/frontend/__snapshots__/filters-taxonomic-filter--actions--dark.png index eabd45e3527ce..5b1043ad3c2e7 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--actions--dark.png and b/frontend/__snapshots__/filters-taxonomic-filter--actions--dark.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--actions--light.png b/frontend/__snapshots__/filters-taxonomic-filter--actions--light.png index 07d30d806320a..317d880e78147 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--actions--light.png and b/frontend/__snapshots__/filters-taxonomic-filter--actions--light.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--events-free--dark.png b/frontend/__snapshots__/filters-taxonomic-filter--events-free--dark.png index 88adc56aa426f..31a97d2d8fa55 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--events-free--dark.png and b/frontend/__snapshots__/filters-taxonomic-filter--events-free--dark.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--events-free--light.png b/frontend/__snapshots__/filters-taxonomic-filter--events-free--light.png index d1c2165e100c6..a06c1ed0a7866 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--events-free--light.png and b/frontend/__snapshots__/filters-taxonomic-filter--events-free--light.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--events-premium--dark.png b/frontend/__snapshots__/filters-taxonomic-filter--events-premium--dark.png index 4f4e3680d57ae..4ee39f3b1e205 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--events-premium--dark.png and b/frontend/__snapshots__/filters-taxonomic-filter--events-premium--dark.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--events-premium--light.png b/frontend/__snapshots__/filters-taxonomic-filter--events-premium--light.png index ddf7a2bfeea36..9b4933071bb53 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--events-premium--light.png and b/frontend/__snapshots__/filters-taxonomic-filter--events-premium--light.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--properties--dark.png b/frontend/__snapshots__/filters-taxonomic-filter--properties--dark.png index a2118f93763f0..039df05c6c9c4 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--properties--dark.png and b/frontend/__snapshots__/filters-taxonomic-filter--properties--dark.png differ diff --git a/frontend/__snapshots__/filters-taxonomic-filter--properties--light.png b/frontend/__snapshots__/filters-taxonomic-filter--properties--light.png index 5f1e05c71984e..7d05e29392a65 100644 Binary files a/frontend/__snapshots__/filters-taxonomic-filter--properties--light.png and b/frontend/__snapshots__/filters-taxonomic-filter--properties--light.png differ diff --git a/frontend/__snapshots__/lemon-ui-icons--shelf-s--dark.png b/frontend/__snapshots__/lemon-ui-icons--shelf-s--dark.png index d43ce10c56e88..c4542b66869a0 100644 Binary files a/frontend/__snapshots__/lemon-ui-icons--shelf-s--dark.png and b/frontend/__snapshots__/lemon-ui-icons--shelf-s--dark.png differ diff --git a/frontend/__snapshots__/lemon-ui-icons--shelf-s--light.png b/frontend/__snapshots__/lemon-ui-icons--shelf-s--light.png index bcffa294a37ea..da823d4180f5d 100644 Binary files a/frontend/__snapshots__/lemon-ui-icons--shelf-s--light.png and b/frontend/__snapshots__/lemon-ui-icons--shelf-s--light.png differ diff --git a/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--dark.png b/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--dark.png index c94024858f014..6b0c540a049d5 100644 Binary files a/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--dark.png and b/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--light.png b/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--light.png index 27fe79337869e..6a9b78b7fe442 100644 Binary files a/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--light.png and b/frontend/__snapshots__/scenes-app-experiments--complete-funnel-experiment--light.png differ diff --git a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--dark.png b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--dark.png index 3ccaf6534617b..fccd58d1ec935 100644 Binary files a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--dark.png and b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--light.png b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--light.png index 2dde9775c8b79..b6f7e96e063cc 100644 Binary files a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--light.png and b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment--light.png differ diff --git a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--dark.png b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--dark.png index 324f7458bf668..3f3e0548ae300 100644 Binary files a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--dark.png and b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--light.png b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--light.png index 2b4b60d1c76a1..2d3ffa24f1b27 100644 Binary files a/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--light.png and b/frontend/__snapshots__/scenes-app-experiments--running-trend-experiment-many-variants--light.png differ diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown--dark.png b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown--dark.png index 6fd194e19ee1c..729faab2b5537 100644 Binary files a/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown--dark.png and b/frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-insights--trends-line-multi-edit--dark--webkit.png b/frontend/__snapshots__/scenes-app-insights--trends-line-multi-edit--dark--webkit.png index f9c6eb3ff268c..e61ea67b3f7ac 100644 Binary files a/frontend/__snapshots__/scenes-app-insights--trends-line-multi-edit--dark--webkit.png and b/frontend/__snapshots__/scenes-app-insights--trends-line-multi-edit--dark--webkit.png differ diff --git a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--dark.png b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--dark.png index 22acdc7a712f5..156cdab4898cf 100644 Binary files a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--dark.png and b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--light.png b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--light.png index 87d251ab3abf4..aef4bc0789d92 100644 Binary files a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--light.png and b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks--light.png differ diff --git a/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--dark.png b/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--dark.png index a255eebe5dc2b..74bec0444f508 100644 Binary files a/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--dark.png and b/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--light.png b/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--light.png index 5a4145934c0a9..3c14a17b2b472 100644 Binary files a/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--light.png and b/frontend/__snapshots__/scenes-app-pipeline--pipeline-landing-page--light.png differ diff --git a/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--dark.png b/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--dark.png index a255eebe5dc2b..74bec0444f508 100644 Binary files a/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--dark.png and b/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--light.png b/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--light.png index 5a4145934c0a9..3c14a17b2b472 100644 Binary files a/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--light.png and b/frontend/__snapshots__/scenes-app-pipeline--pipeline-overview-page--light.png differ diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--dark.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--dark.png index f27db9a60fffe..c71b2dc4d4605 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--dark.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--dark.png differ diff --git a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--light.png b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--light.png index 8d53a5e89d14e..9610ba41a8de1 100644 Binary files a/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--light.png and b/frontend/__snapshots__/scenes-app-sidepanels--side-panel-support-with-email--light.png differ diff --git a/frontend/__snapshots__/scenes-other-billing-v2--billing-v-2--dark.png b/frontend/__snapshots__/scenes-other-billing-v2--billing-v-2--dark.png index b760d16fd5592..142d5b7816f45 100644 Binary files a/frontend/__snapshots__/scenes-other-billing-v2--billing-v-2--dark.png and b/frontend/__snapshots__/scenes-other-billing-v2--billing-v-2--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-invitesignup--cloud--dark.png b/frontend/__snapshots__/scenes-other-invitesignup--cloud--dark.png index 4946aedfeb38a..8846a78356f78 100644 Binary files a/frontend/__snapshots__/scenes-other-invitesignup--cloud--dark.png and b/frontend/__snapshots__/scenes-other-invitesignup--cloud--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-invitesignup--cloud--light.png b/frontend/__snapshots__/scenes-other-invitesignup--cloud--light.png index b7eef2e8b826c..33b1613add0a1 100644 Binary files a/frontend/__snapshots__/scenes-other-invitesignup--cloud--light.png and b/frontend/__snapshots__/scenes-other-invitesignup--cloud--light.png differ diff --git a/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--dark.png b/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--dark.png index 6767462f173e0..338fe5981e951 100644 Binary files a/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--dark.png and b/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--light.png b/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--light.png index 18f965fbc6bf6..ee73e04bc73ac 100644 Binary files a/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--light.png and b/frontend/__snapshots__/scenes-other-invitesignup--cloud-eu--light.png differ diff --git a/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--dark.png b/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--dark.png index 1aa1af55b6ba0..8c172c2feaa45 100644 Binary files a/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--dark.png and b/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--light.png b/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--light.png index e11aec2c721fe..96fbac8e5175b 100644 Binary files a/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--light.png and b/frontend/__snapshots__/scenes-other-invitesignup--self-hosted--light.png differ diff --git a/frontend/__snapshots__/scenes-other-settings--settings-project--dark.png b/frontend/__snapshots__/scenes-other-settings--settings-project--dark.png index cb28d08f5b090..7e50137a13381 100644 Binary files a/frontend/__snapshots__/scenes-other-settings--settings-project--dark.png and b/frontend/__snapshots__/scenes-other-settings--settings-project--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-settings--settings-project--light.png b/frontend/__snapshots__/scenes-other-settings--settings-project--light.png index 31dbd5b34cfcf..fca36f690b5b4 100644 Binary files a/frontend/__snapshots__/scenes-other-settings--settings-project--light.png and b/frontend/__snapshots__/scenes-other-settings--settings-project--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--actions--light.png b/frontend/__snapshots__/scenes-other-toolbar--actions--light.png index 1fb68e53203d4..07e36a5f5a118 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--actions--light.png and b/frontend/__snapshots__/scenes-other-toolbar--actions--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--actions-dark--dark.png b/frontend/__snapshots__/scenes-other-toolbar--actions-dark--dark.png index 2f90e951dc806..52d9e853064bd 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--actions-dark--dark.png and b/frontend/__snapshots__/scenes-other-toolbar--actions-dark--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--default--dark.png b/frontend/__snapshots__/scenes-other-toolbar--default--dark.png index cb0b19df4b817..edf4bd017591f 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--default--dark.png and b/frontend/__snapshots__/scenes-other-toolbar--default--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--default--light.png b/frontend/__snapshots__/scenes-other-toolbar--default--light.png index f06bdae7892eb..f38e1335c11dc 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--default--light.png and b/frontend/__snapshots__/scenes-other-toolbar--default--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--default-dark--dark.png b/frontend/__snapshots__/scenes-other-toolbar--default-dark--dark.png index 1dec86e1971c6..4accebb9adc2d 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--default-dark--dark.png and b/frontend/__snapshots__/scenes-other-toolbar--default-dark--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--default-dark--light.png b/frontend/__snapshots__/scenes-other-toolbar--default-dark--light.png index 6c9a1bcd739a3..4875a816823c1 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--default-dark--light.png and b/frontend/__snapshots__/scenes-other-toolbar--default-dark--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger--dark.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger--dark.png new file mode 100644 index 0000000000000..1c1ff9986edcd Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger--light.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger--light.png new file mode 100644 index 0000000000000..20c57dda22fb3 Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger-dark--dark.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-dark--dark.png new file mode 100644 index 0000000000000..6ce4e1d634f05 Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-dark--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger-dark--light.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-dark--light.png new file mode 100644 index 0000000000000..d145281228a70 Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-dark--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty--dark.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty--dark.png new file mode 100644 index 0000000000000..1c1ff9986edcd Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty--light.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty--light.png new file mode 100644 index 0000000000000..20c57dda22fb3 Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty-dark--dark.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty-dark--dark.png new file mode 100644 index 0000000000000..6ce4e1d634f05 Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty-dark--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty-dark--light.png b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty-dark--light.png new file mode 100644 index 0000000000000..d145281228a70 Binary files /dev/null and b/frontend/__snapshots__/scenes-other-toolbar--events-debugger-empty-dark--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--feature-flags--light.png b/frontend/__snapshots__/scenes-other-toolbar--feature-flags--light.png index 0d6d153d2ecb9..a993d1895a5c0 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--feature-flags--light.png and b/frontend/__snapshots__/scenes-other-toolbar--feature-flags--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--feature-flags-dark--dark.png b/frontend/__snapshots__/scenes-other-toolbar--feature-flags-dark--dark.png index 54d4b5df28c69..27f03e5866262 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--feature-flags-dark--dark.png and b/frontend/__snapshots__/scenes-other-toolbar--feature-flags-dark--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--heatmap--light.png b/frontend/__snapshots__/scenes-other-toolbar--heatmap--light.png index f19ddfa738b17..72c8963740f72 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--heatmap--light.png and b/frontend/__snapshots__/scenes-other-toolbar--heatmap--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--inspect--dark.png b/frontend/__snapshots__/scenes-other-toolbar--inspect--dark.png index 13bc32974827e..2e1383a200aaa 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--inspect--dark.png and b/frontend/__snapshots__/scenes-other-toolbar--inspect--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--inspect--light.png b/frontend/__snapshots__/scenes-other-toolbar--inspect--light.png index 7b99c1b5e3b4d..8e24c0684604f 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--inspect--light.png and b/frontend/__snapshots__/scenes-other-toolbar--inspect--light.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--dark.png b/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--dark.png index 4ae22abd74895..55a9405f083b2 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--dark.png and b/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--dark.png differ diff --git a/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--light.png b/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--light.png index 34d247319f1c9..f94857d34f2a3 100644 Binary files a/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--light.png and b/frontend/__snapshots__/scenes-other-toolbar--inspect-dark--light.png differ diff --git a/frontend/scripts/print_property_name_aliases.ts b/frontend/scripts/print_property_name_aliases.ts deleted file mode 100644 index b709504a19ca8..0000000000000 --- a/frontend/scripts/print_property_name_aliases.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { CORE_FILTER_DEFINITIONS_BY_GROUP } from 'lib/taxonomy' - -// Creates PROPERTY_NAME_ALIASES in posthog/api/property_definition.py -// eslint-disable-next-line no-console -console.log( - JSON.stringify( - Object.fromEntries( - Array.from(Object.entries(CORE_FILTER_DEFINITIONS_BY_GROUP.event_properties)) - .map(([key, value]) => [key, value.label]) - .filter(([key, label]) => { - if (!key) { - return false - } - if (!label || label.includes('deprecated')) { - return false - } - - const keyLower = key.toLowerCase() - const labelLower = label.toLowerCase() - - if (keyLower.includes(labelLower)) { - return false - } - - const keyLowerNoSpecial = keyLower.replace(/[$_]+/g, ' ') - const labelWords = labelLower.split(/\s+/) - - return !labelWords.every((word) => keyLowerNoSpecial.includes(word)) - }) - .sort() - ), - null, - 4 - ) -) diff --git a/frontend/src/exporter/Exporter.scss b/frontend/src/exporter/Exporter.scss index e2f731fe2ffb5..edf6a23560730 100644 --- a/frontend/src/exporter/Exporter.scss +++ b/frontend/src/exporter/Exporter.scss @@ -21,11 +21,6 @@ body.ExporterBody { overflow: auto; } - &--insight { - max-height: 100vh; - overflow: auto; - } - .SharedDashboard-header { .SharedDashboard-header-team { display: none; diff --git a/frontend/src/layout/navigation-3000/sidepanel/panels/SidePanelSupport.tsx b/frontend/src/layout/navigation-3000/sidepanel/panels/SidePanelSupport.tsx index d4755e27e91fa..1868dc2132871 100644 --- a/frontend/src/layout/navigation-3000/sidepanel/panels/SidePanelSupport.tsx +++ b/frontend/src/layout/navigation-3000/sidepanel/panels/SidePanelSupport.tsx @@ -14,9 +14,10 @@ import { import { LemonButton, Link } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { SupportForm } from 'lib/components/Support/SupportForm' -import { supportLogic } from 'lib/components/Support/supportLogic' +import { getPublicSupportSnippet, supportLogic } from 'lib/components/Support/supportLogic' import React from 'react' import { billingLogic } from 'scenes/billing/billingLogic' +import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' import { urls } from 'scenes/urls' import { userLogic } from 'scenes/userLogic' @@ -145,6 +146,9 @@ export const SidePanelSupport = (): JSX.Element => { const { hasAvailableFeature } = useValues(userLogic) const { openEmailForm, closeEmailForm } = useActions(supportLogic) const { isEmailFormOpen } = useValues(supportLogic) + const { preflight } = useValues(preflightLogic) + const { user } = useValues(userLogic) + const region = preflight?.region const theLogic = supportLogic({ onClose: () => closeSidePanel(SidePanelTab.Support) }) const { title } = useValues(theLogic) @@ -182,7 +186,7 @@ export const SidePanelSupport = (): JSX.Element => { - {hasAvailableFeature(AvailableFeature.PRIORITY_SUPPORT) ? ( + {hasAvailableFeature(AvailableFeature.EMAIL_SUPPORT) ? ( <>

Can't find what you need in the docs?

@@ -231,7 +235,9 @@ export const SidePanelSupport = (): JSX.Element => { } targetBlank > @@ -264,7 +270,9 @@ export const SidePanelSupport = (): JSX.Element => { } targetBlank > @@ -274,18 +282,7 @@ export const SidePanelSupport = (): JSX.Element => {
- {hasAvailableFeature(AvailableFeature.EMAIL_SUPPORT) ? ( -
- {isEmailFormOpen ? ( - closeEmailForm()} /> - ) : ( -

- Can't find what you need in the docs?{' '} - openEmailForm()}>Open a ticket -

- )} -
- ) : ( + {!hasAvailableFeature(AvailableFeature.EMAIL_SUPPORT) ? (

Due to our large userbase, we're unable to offer email support to organizations on the @@ -329,7 +326,7 @@ export const SidePanelSupport = (): JSX.Element => {

- )} + ) : null} diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 26d85a01bed74..3254d06765ec2 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -914,9 +914,6 @@ const api = { async list(params?: string): Promise> { return await new ApiRequest().actions().withQueryString(params).get() }, - async getCount(actionId: ActionType['id']): Promise { - return (await new ApiRequest().actionsDetail(actionId).withAction('count').get()).count - }, determineDeleteEndpoint(): string { return new ApiRequest().actions().assembleEndpointUrl() }, diff --git a/frontend/src/lib/components/AnimatedCollapsible.tsx b/frontend/src/lib/components/AnimatedCollapsible.tsx index 108f265b3107b..e4d182c7e4c57 100644 --- a/frontend/src/lib/components/AnimatedCollapsible.tsx +++ b/frontend/src/lib/components/AnimatedCollapsible.tsx @@ -9,7 +9,7 @@ export function AnimatedCollapsible({ }): JSX.Element { const collapsibleSectionRef = useRef(null) - const [height, setHeight] = useState() + const [height, setHeight] = useState(collapsed ? 0 : undefined) useEffect(() => { if (!collapsed) { diff --git a/frontend/src/lib/components/DateFilter/DateFilter.tsx b/frontend/src/lib/components/DateFilter/DateFilter.tsx index 8bb267b8b5486..808462941e01a 100644 --- a/frontend/src/lib/components/DateFilter/DateFilter.tsx +++ b/frontend/src/lib/components/DateFilter/DateFilter.tsx @@ -22,6 +22,7 @@ import { DateMappingOption, PropertyOperator } from '~/types' import { PropertyFilterDatePicker } from '../PropertyFilters/components/PropertyFilterDatePicker' import { dateFilterLogic } from './dateFilterLogic' import { RollingDateRangeFilter } from './RollingDateRangeFilter' +import { DateOption } from './rollingDateRangeFilterLogic' export interface DateFilterProps { showCustom?: boolean @@ -41,6 +42,7 @@ interface RawDateFilterProps extends DateFilterProps { dateFrom?: string | null | dayjs.Dayjs dateTo?: string | null | dayjs.Dayjs max?: number | null + allowedRollingDateOptions?: DateOption[] } export function DateFilter({ @@ -58,6 +60,7 @@ export function DateFilter({ dropdownPlacement = 'bottom-start', max, isFixedDateMode = false, + allowedRollingDateOptions, }: RawDateFilterProps): JSX.Element { const key = useRef(uuid()).current const logicProps: DateFilterLogicProps = { @@ -183,7 +186,11 @@ export function DateFilter({ ref: rollingDateRangeRef, }} max={max} - allowedDateOptions={isFixedDateMode ? ['hours', 'days', 'weeks', 'months', 'years'] : undefined} + allowedDateOptions={ + isFixedDateMode && !allowedRollingDateOptions + ? ['hours', 'days', 'weeks', 'months', 'years'] + : allowedRollingDateOptions + } fullWidth /> )} diff --git a/frontend/src/lib/components/DefinitionPopover/DefinitionPopoverContents.tsx b/frontend/src/lib/components/DefinitionPopover/DefinitionPopoverContents.tsx index 0a2d183a71806..d6419882b3327 100644 --- a/frontend/src/lib/components/DefinitionPopover/DefinitionPopoverContents.tsx +++ b/frontend/src/lib/components/DefinitionPopover/DefinitionPopoverContents.tsx @@ -1,5 +1,5 @@ import { hide } from '@floating-ui/react' -import { IconInfo, IconLock } from '@posthog/icons' +import { IconInfo } from '@posthog/icons' import { LemonButton, LemonDivider, LemonSelect, LemonSwitch } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { ActionPopoverInfo } from 'lib/components/DefinitionPopover/ActionPopoverInfo' @@ -16,7 +16,6 @@ import { } from 'lib/components/TaxonomicFilter/types' import { IconOpenInNew } from 'lib/lemon-ui/icons' import { LemonTextArea } from 'lib/lemon-ui/LemonTextArea/LemonTextArea' -import { Link } from 'lib/lemon-ui/Link' import { Popover } from 'lib/lemon-ui/Popover' import { Tooltip } from 'lib/lemon-ui/Tooltip' import { CORE_FILTER_DEFINITIONS_BY_GROUP, isCoreFilter } from 'lib/taxonomy' @@ -28,35 +27,6 @@ import { ActionType, CohortType, EventDefinition, PropertyDefinition } from '~/t import { taxonomicFilterLogic } from '../TaxonomicFilter/taxonomicFilterLogic' import { TZLabel } from '../TZLabel' -function TaxonomyIntroductionSection(): JSX.Element { - const Lock = (): JSX.Element => ( -
- - - -
- ) - - return ( - <> - - } /> - } /> - - - - Learn more about Data Management - - - - ) -} - export function VerifiedDefinitionCheckbox({ verified, isProperty, @@ -161,20 +131,17 @@ function DefinitionView({ group }: { group: TaxonomicFilterGroup }): JSX.Element return ( <> {sharedComponents} - {hasTaxonomyFeatures ? ( - - } - /> - } - /> - - ) : ( - - )} + + } + /> + } + /> + + { + hideUpgradeModal() + posthog.capture('pay gate CTA clicked', { + product_key: productWithFeature?.type, + feature: feature, + gate_variant: gateVariant, + }) + } + if (billingLoading) { return null } @@ -69,85 +79,65 @@ export function PayGateMini({ return null // Don't show anything if paid features are explicitly disabled } - return featureFlags[FEATURE_FLAGS.SUBSCRIBE_FROM_PAYGATE] === 'test' && - // we don't support plan comparisons for addons yet, so we'll use the variant that just sends them to the billing page - !isAddonProduct ? ( - gateVariant && productWithFeature && featureInfo && !overrideShouldShowGate ? ( -
-
- {getProductIcon(productWithFeature.name, featureInfo.icon_key)} -
-

{featureInfo.name}

- {featureAvailableOnOrg?.limit && gateVariant !== 'move-to-cloud' ? ( -
-

- You've reached your usage limit for{' '} - - - {featureInfo.name} - - - - . -

-

- Your current plan limit:{' '} - - {featureAvailableOnOrg.limit} {featureAvailableOnOrg.unit} - -

-

- Please upgrade your {productWithFeature.name} plan to create more {featureInfo.name} -

-
+ {/* we don't support plan comparisons for addons yet, so we'll use the variant that just sends them to the billing page */} + {featureFlags[FEATURE_FLAGS.SUBSCRIBE_FROM_PAYGATE] === 'test' && !isAddonProduct ? ( + ) : ( - <> -

{featureInfo.description}

-

- {gateVariant === 'move-to-cloud' ? ( - <>This feature is only available on PostHog Cloud. - ) : isAddonProduct ? ( - <> - Subscribe to the {productWithFeature?.name} addon to use this feature. - - ) : ( - <> - Upgrade your {productWithFeature?.name} plan to use this feature. - - )} -

- + )} - {isGrandfathered && ( -
- -

- Your plan does not include this feature, but previously set settings may remain. Please - upgrade your plan to regain access. -

-
- )} - {featureInfo.docsUrl && ( -
- <> - - Learn more in PostHog Docs. - - -
- )} - -
- ) : ( -
{children}
+ ) - ) : gateVariant && productWithFeature && featureInfo && !overrideShouldShowGate ? ( + } + + return
{children}
+} + +interface PayGateContentProps { + className?: string + background: boolean + featureInfo: BillingV2FeatureType + featureAvailableOnOrg?: BillingV2FeatureType | null + gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null + productWithFeature: BillingProductV2AddonType | BillingProductV2Type + isGrandfathered?: boolean + isAddonProduct?: boolean + children: React.ReactNode +} + +function PayGateContent({ + className, + background, + featureInfo, + featureAvailableOnOrg, + gateVariant, + productWithFeature, + isGrandfathered, + isAddonProduct, + children, +}: PayGateContentProps): JSX.Element { + return (

{featureInfo.name}

- {featureAvailableOnOrg?.limit && gateVariant !== 'move-to-cloud' ? ( -
-

- You've reached your usage limit for{' '} - - - {featureInfo.name} - - - - . -

-

- Your current plan limit:{' '} + {renderUsageLimitMessage( + featureAvailableOnOrg, + gateVariant, + featureInfo, + productWithFeature, + isAddonProduct + )} + {isGrandfathered && } + {featureInfo.docsUrl && } + {children} +

+ ) +} + +const renderUsageLimitMessage = ( + featureAvailableOnOrg: BillingV2FeatureType | null | undefined, + gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null, + featureInfo: BillingV2FeatureType, + productWithFeature: BillingProductV2AddonType | BillingProductV2Type, + isAddonProduct?: boolean +): JSX.Element => { + if (featureAvailableOnOrg?.limit && gateVariant !== 'move-to-cloud') { + return ( +
+

+ You've reached your usage limit for{' '} + - {featureAvailableOnOrg.limit} {featureAvailableOnOrg.unit} + {featureInfo.name} + -

-

- Please upgrade your {productWithFeature.name} plan to create more {featureInfo.name} -

-
- ) : ( - <> -

{featureInfo.description}

-

- {gateVariant === 'move-to-cloud' ? ( - <>This feature is only available on PostHog Cloud. - ) : isAddonProduct ? ( - <> - Subscribe to the {productWithFeature?.name} addon to use this feature. - - ) : ( - <> - Upgrade your {productWithFeature?.name} plan to use this feature. - - )} -

- - )} - {isGrandfathered && ( -
- -

- Your plan does not include this feature, but previously set settings may remain. Please upgrade - your plan to regain access. -

-
- )} - {featureInfo.docsUrl && ( -
- <> - - Learn more in PostHog Docs. - - -
- )} - { - hideUpgradeModal() - posthog.capture('pay gate CTA clicked', { - product_key: productWithFeature?.type, - feature: feature, - gate_variant: gateVariant, - }) - }} - > - {gateVariant === 'add-card' - ? billing?.has_active_subscription - ? `Upgrade ${productWithFeature?.name}` - : 'Subscribe now' - : gateVariant === 'contact-sales' - ? 'Contact sales' - : 'Move to PostHog Cloud'} - + + . +

+

+ Your current plan limit:{' '} + + {featureAvailableOnOrg.limit} {featureAvailableOnOrg.unit} + +

+

+ Please upgrade your {productWithFeature.name} plan to create more {featureInfo.name} +

+
+ ) + } else { + return ( + <> +

{featureInfo.description}

+

{renderGateVariantMessage(gateVariant, productWithFeature, isAddonProduct)}

+ + ) + } +} + +const renderGateVariantMessage = ( + gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null, + productWithFeature: BillingProductV2AddonType | BillingProductV2Type, + isAddonProduct?: boolean +): JSX.Element => { + if (gateVariant === 'move-to-cloud') { + return <>This feature is only available on PostHog Cloud. + } else if (isAddonProduct) { + return ( + <> + Subscribe to the {productWithFeature?.name} addon to use this feature. + + ) + } else { + return ( + <> + Upgrade your {productWithFeature?.name} plan to use this feature. + + ) + } +} + +const GrandfatheredMessage = (): JSX.Element => { + return ( +
+ +

+ Your plan does not include this feature, but previously set settings may remain. Please upgrade your + plan to regain access. +

+
+ ) +} + +const DocsLink = ({ url }: { url: string }): JSX.Element => { + return ( +
+ + Learn more in PostHog Docs. +
- ) : ( -
{children}
) } diff --git a/frontend/src/lib/components/PayGateMini/PayGateMiniButtonVariant.tsx b/frontend/src/lib/components/PayGateMini/PayGateMiniButtonVariant.tsx new file mode 100644 index 0000000000000..1693bf791b20f --- /dev/null +++ b/frontend/src/lib/components/PayGateMini/PayGateMiniButtonVariant.tsx @@ -0,0 +1,59 @@ +import { LemonButton } from '@posthog/lemon-ui' + +import { BillingProductV2AddonType, BillingProductV2Type, BillingV2FeatureType, BillingV2Type } from '~/types' + +interface PayGateMiniButtonVariantProps { + gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null + productWithFeature: BillingProductV2AddonType | BillingProductV2Type + featureInfo: BillingV2FeatureType + onCtaClick: () => void + billing: BillingV2Type | null +} + +export const PayGateMiniButtonVariant = ({ + gateVariant, + productWithFeature, + featureInfo, + onCtaClick, + billing, +}: PayGateMiniButtonVariantProps): JSX.Element => { + return ( + + {getCtaLabel(gateVariant, productWithFeature, billing)} + + ) +} + +const getCtaLink = ( + gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null, + productWithFeature: BillingProductV2AddonType | BillingProductV2Type, + featureInfo: BillingV2FeatureType +): string | undefined => { + if (gateVariant === 'add-card') { + return `/organization/billing?products=${productWithFeature.type}` + } else if (gateVariant === 'contact-sales') { + return `mailto:sales@posthog.com?subject=Inquiring about ${featureInfo.name}` + } else if (gateVariant === 'move-to-cloud') { + return 'https://us.posthog.com/signup?utm_medium=in-product&utm_campaign=move-to-cloud' + } + return undefined +} + +const getCtaLabel = ( + gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null, + productWithFeature: BillingProductV2AddonType | BillingProductV2Type, + billing: BillingV2Type | null +): string => { + if (gateVariant === 'add-card') { + return billing?.has_active_subscription ? `Upgrade ${productWithFeature?.name}` : 'Subscribe now' + } else if (gateVariant === 'contact-sales') { + return 'Contact sales' + } else { + return 'Move to PostHog Cloud' + } +} diff --git a/frontend/src/lib/components/PropertyFilters/utils.ts b/frontend/src/lib/components/PropertyFilters/utils.ts index 255c8428ba8ba..ad135c0525b0e 100644 --- a/frontend/src/lib/components/PropertyFilters/utils.ts +++ b/frontend/src/lib/components/PropertyFilters/utils.ts @@ -341,3 +341,11 @@ export function taxonomicFilterTypeToPropertyFilterType( | PropertyFilterType | undefined } + +export function isEmptyProperty(property: AnyPropertyFilter): boolean { + return ( + property.value === null || + property.value === undefined || + (Array.isArray(property.value) && property.value.length === 0) + ) +} diff --git a/frontend/src/lib/components/Support/SupportForm.tsx b/frontend/src/lib/components/Support/SupportForm.tsx index a7ff431855397..32d6f72ff5675 100644 --- a/frontend/src/lib/components/Support/SupportForm.tsx +++ b/frontend/src/lib/components/Support/SupportForm.tsx @@ -1,6 +1,5 @@ import { IconBug, IconInfo, IconQuestion } from '@posthog/icons' import { - LemonBanner, LemonInput, LemonSegmentedButton, LemonSegmentedButtonOption, @@ -59,7 +58,6 @@ export function SupportForm(): JSX.Element | null { // the support model can be shown when logged out, file upload is not offered to anonymous users const { user } = useValues(userLogic) // only allow authentication issues for logged out users - const blockNonAuthIssues = ![null, 'login'].includes(supportLogic.values.sendSupportRequest.target_area) && !user const dropRef = useRef(null) @@ -127,7 +125,15 @@ export function SupportForm(): JSX.Element | null { - + {(props) => (
- {blockNonAuthIssues ? ( - - Please login to your account before opeing a ticket unrelated to authentication issues. - - ) : null} void }): JSX.Eleme const { closeSupportForm } = useActions(supportLogic) const { isCloudOrDev } = useValues(preflightLogic) const { sidePanelAvailable } = useValues(sidePanelStateLogic) - const { user } = useValues(userLogic) - // only allow authentication issues for logged out users - const blockNonAuthIssues = ![null, 'login'].includes(supportLogic.values.sendSupportRequest.target_area) && !user useEffect(() => { if (!isCloudOrDev) { @@ -40,17 +36,7 @@ function SupportModal({ onAfterClose }: { onAfterClose: () => void }): JSX.Eleme Cancel - + Submit
diff --git a/frontend/src/lib/components/Support/supportLogic.ts b/frontend/src/lib/components/Support/supportLogic.ts index 3201e31fc5289..7679f614c868e 100644 --- a/frontend/src/lib/components/Support/supportLogic.ts +++ b/frontend/src/lib/components/Support/supportLogic.ts @@ -16,6 +16,20 @@ import { Region, SidePanelTab, TeamType, UserType } from '~/types' import type { supportLogicType } from './supportLogicType' import { openSupportModal } from './SupportModal' +export function getPublicSupportSnippet(region: Region | null | undefined, user: UserType | null): string { + if (!user || !region) { + return '' + } + + return `Session: ${posthog + .get_session_replay_url({ withTimestamp: true, timestampLookBack: 30 }) + .replace(window.location.origin + '/replay/', 'http://go/session/')} ${ + !window.location.href.includes('settings/project') ? `(at ${window.location.href})` : '' + }\n${`Admin: ${`http://go/adminOrg${region}/${user.organization?.id}`} (Project: ${ + teamLogic.values.currentTeamId + })`}\nSentry: ${`http://go/sentry${region}/${user.team?.id}`}` +} + function getSessionReplayLink(): string { const link = posthog .get_session_replay_url({ withTimestamp: true, timestampLookBack: 30 }) @@ -324,7 +338,10 @@ export const supportLogic = kea([ } }, openSupportForm: async ({ name, email, kind, target_area, severity_level, message }) => { - const area = target_area ?? getURLPathToTargetArea(window.location.pathname) + let area = target_area ?? getURLPathToTargetArea(window.location.pathname) + if (!userLogic.values.user) { + area = 'login' + } kind = kind ?? 'support' actions.resetSendSupportRequest({ name: name ?? '', diff --git a/frontend/src/lib/lemon-ui/LemonInputSelect/LemonInputSelect.tsx b/frontend/src/lib/lemon-ui/LemonInputSelect/LemonInputSelect.tsx index 9ef2439343a0e..6bb8ef2e6fc71 100644 --- a/frontend/src/lib/lemon-ui/LemonInputSelect/LemonInputSelect.tsx +++ b/frontend/src/lib/lemon-ui/LemonInputSelect/LemonInputSelect.tsx @@ -35,6 +35,7 @@ export type LemonInputSelectProps = Pick< onBlur?: () => void onInputChange?: (newValue: string) => void 'data-attr'?: string + popoverClassName?: string } export function LemonInputSelect({ @@ -50,6 +51,7 @@ export function LemonInputSelect({ disableFiltering = false, allowCustomValues = false, autoFocus = false, + popoverClassName, ...props }: LemonInputSelectProps): JSX.Element { const [showPopover, setShowPopover] = useState(false) @@ -269,6 +271,7 @@ export function LemonInputSelect({ popoverFocusRef.current = true e.stopPropagation() }} + className={popoverClassName} overlay={
{visibleOptions.length ? ( diff --git a/frontend/src/lib/lemon-ui/Link/Link.tsx b/frontend/src/lib/lemon-ui/Link/Link.tsx index 32824126f5a8e..a805cad16b2dd 100644 --- a/frontend/src/lib/lemon-ui/Link/Link.tsx +++ b/frontend/src/lib/lemon-ui/Link/Link.tsx @@ -61,10 +61,12 @@ const isDirectLink = (url: string): boolean => { return /^(mailto:|https?:\/\/|:\/\/)/.test(url) } -const isPostHogComDocs = (url: string): boolean => { +const isPostHogComDocs = (url: string): url is PostHogComDocsURL => { return /^https:\/\/(www\.)?posthog\.com\/docs/.test(url) } +export type PostHogComDocsURL = `https://${'www.' | ''}posthog.com/docs/${string}` + /** * Link * diff --git a/frontend/src/lib/lemon-ui/icons/icons.tsx b/frontend/src/lib/lemon-ui/icons/icons.tsx index 45451163f8326..df94a69db4232 100644 --- a/frontend/src/lib/lemon-ui/icons/icons.tsx +++ b/frontend/src/lib/lemon-ui/icons/icons.tsx @@ -1360,3 +1360,16 @@ export function IconAdsClick(props: LemonIconProps): JSX.Element { ) } + +export function IconSquare(props: LemonIconProps): JSX.Element { + return ( + + + + ) +} diff --git a/frontend/src/models/cohortsModel.ts b/frontend/src/models/cohortsModel.ts index 2d2c106e4d728..295d3cd4b1fad 100644 --- a/frontend/src/models/cohortsModel.ts +++ b/frontend/src/models/cohortsModel.ts @@ -5,6 +5,7 @@ import api from 'lib/api' import { exportsLogic } from 'lib/components/ExportButton/exportsLogic' import { deleteWithUndo } from 'lib/utils/deleteWithUndo' import { permanentlyMount } from 'lib/utils/kea-logic-builders' +import { COHORT_EVENT_TYPES_WITH_EXPLICIT_DATETIME } from 'scenes/cohorts/CohortFilters/constants' import { BehavioralFilterKey } from 'scenes/cohorts/CohortFilters/types' import { personsLogic } from 'scenes/persons/personsLogic' import { isAuthenticatedTeam, teamLogic } from 'scenes/teamLogic' @@ -36,18 +37,7 @@ export function processCohort(cohort: CohortType): CohortType { ? { ...group, values: (group.values as AnyCohortCriteriaType[]).map((c) => - c.type && - [BehavioralFilterKey.Cohort, BehavioralFilterKey.Person].includes(c.type) && - !('value_property' in c) - ? { - ...c, - value_property: c.value, - value: - c.type === BehavioralFilterKey.Cohort - ? BehavioralCohortType.InCohort - : BehavioralEventType.HaveProperty, - } - : c + processCohortCriteria(c) ), } : group @@ -58,6 +48,45 @@ export function processCohort(cohort: CohortType): CohortType { } } +function convertTimeValueToRelativeTime(criteria: AnyCohortCriteriaType): string | undefined { + const timeValue = criteria?.time_value + const timeInterval = criteria?.time_interval + + if (timeValue && timeInterval) { + return `-${timeValue}${timeInterval[0]}` + } +} + +function processCohortCriteria(criteria: AnyCohortCriteriaType): AnyCohortCriteriaType { + if (!criteria.type) { + return criteria + } + + const processedCriteria = { ...criteria } + + if ( + [BehavioralFilterKey.Cohort, BehavioralFilterKey.Person].includes(criteria.type) && + !('value_property' in criteria) + ) { + processedCriteria.value_property = criteria.value + processedCriteria.value = + criteria.type === BehavioralFilterKey.Cohort + ? BehavioralCohortType.InCohort + : BehavioralEventType.HaveProperty + } + + if ( + [BehavioralFilterKey.Behavioral].includes(criteria.type) && + !('explicit_datetime' in criteria) && + criteria.value && + COHORT_EVENT_TYPES_WITH_EXPLICIT_DATETIME.includes(criteria.value) + ) { + processedCriteria.explicit_datetime = convertTimeValueToRelativeTime(criteria) + } + + return processedCriteria +} + export const cohortsModel = kea([ path(['models', 'cohortsModel']), connect({ diff --git a/frontend/src/queries/nodes/WebOverview/WebOverview.tsx b/frontend/src/queries/nodes/WebOverview/WebOverview.tsx index cad6ef36867ce..7fecec4864542 100644 --- a/frontend/src/queries/nodes/WebOverview/WebOverview.tsx +++ b/frontend/src/queries/nodes/WebOverview/WebOverview.tsx @@ -166,13 +166,13 @@ const labelFromKey = (key: string): string => { case 'visitors': return 'Visitors' case 'views': - return 'Views' + return 'Page views' case 'sessions': return 'Sessions' case 'session duration': - return 'Session Duration' + return 'Session duration' case 'bounce rate': - return 'Bounce Rate' + return 'Bounce rate' default: return key .split(' ') diff --git a/frontend/src/queries/schema.json b/frontend/src/queries/schema.json index 21f02f13100f4..7be6c6a2483ef 100644 --- a/frontend/src/queries/schema.json +++ b/frontend/src/queries/schema.json @@ -2620,7 +2620,12 @@ "type": "string" }, "personsOnEventsMode": { - "enum": ["disabled", "v1_enabled", "v1_mixed", "v2_enabled", "v3_enabled"], + "enum": [ + "disabled", + "person_id_no_override_properties_on_events", + "person_id_override_properties_on_events", + "person_id_override_properties_joined" + ], "type": "string" } }, @@ -4926,7 +4931,6 @@ "additionalProperties": false, "properties": { "key": { - "const": "$session_duration", "type": "string" }, "label": { diff --git a/frontend/src/queries/schema.ts b/frontend/src/queries/schema.ts index 831c39241ed83..72941d8436e74 100644 --- a/frontend/src/queries/schema.ts +++ b/frontend/src/queries/schema.ts @@ -179,7 +179,11 @@ export interface DataNode extends Node { /** HogQL Query Options are automatically set per team. However, they can be overriden in the query. */ export interface HogQLQueryModifiers { - personsOnEventsMode?: 'disabled' | 'v1_enabled' | 'v1_mixed' | 'v2_enabled' | 'v3_enabled' + personsOnEventsMode?: + | 'disabled' + | 'person_id_no_override_properties_on_events' + | 'person_id_override_properties_on_events' + | 'person_id_override_properties_joined' personsArgMaxVersion?: 'auto' | 'v1' | 'v2' inCohortVia?: 'auto' | 'leftjoin' | 'subquery' | 'leftjoin_conjoined' materializationMode?: 'auto' | 'legacy_null_as_string' | 'legacy_null_as_null' | 'disabled' diff --git a/frontend/src/scenes/actions/ActionEdit.tsx b/frontend/src/scenes/actions/ActionEdit.tsx index c8d86aca18dcb..f105e7e3bd6e3 100644 --- a/frontend/src/scenes/actions/ActionEdit.tsx +++ b/frontend/src/scenes/actions/ActionEdit.tsx @@ -11,8 +11,7 @@ import { LemonButton } from 'lib/lemon-ui/LemonButton' import { LemonField } from 'lib/lemon-ui/LemonField' import { LemonLabel } from 'lib/lemon-ui/LemonLabel/LemonLabel' import { Link } from 'lib/lemon-ui/Link' -import { Spinner } from 'lib/lemon-ui/Spinner/Spinner' -import { compactNumber, uuid } from 'lib/utils' +import { uuid } from 'lib/utils' import { teamLogic } from 'scenes/teamLogic' import { urls } from 'scenes/urls' @@ -28,7 +27,7 @@ export function ActionEdit({ action: loadedAction, id }: ActionEditLogicProps): action: loadedAction, } const logic = actionEditLogic(logicProps) - const { action, actionLoading, actionCount, actionCountLoading } = useValues(logic) + const { action, actionLoading } = useValues(logic) const { submitAction, deleteAction } = useActions(logic) const { currentTeam } = useValues(teamLogic) const { tags } = useValues(tagsModel) @@ -149,21 +148,6 @@ export function ActionEdit({ action: loadedAction, id }: ActionEditLogicProps): } /> - {id && ( -
-
- - {actionCount !== null && actionCount > -1 && ( - - This action matches {compactNumber(actionCount)} events in the last 3 - months - - )} - {actionCountLoading && } - -
-
- )}

Match groups

diff --git a/frontend/src/scenes/actions/actionEditLogic.tsx b/frontend/src/scenes/actions/actionEditLogic.tsx index 63e16bba17919..00a34ab5e02cc 100644 --- a/frontend/src/scenes/actions/actionEditLogic.tsx +++ b/frontend/src/scenes/actions/actionEditLogic.tsx @@ -81,11 +81,6 @@ export const actionEditLogic = kea([ })), loaders(({ props, values, actions }) => ({ - actionCount: { - loadActionCount: async () => { - return props.id ? await api.actions.getCount(props.id) : 0 - }, - }, action: [ { ...props.action } as ActionEditType, { @@ -130,7 +125,6 @@ export const actionEditLogic = kea([ // reload actions so they are immediately available throughout the app actions.loadEventDefinitions() actions.loadActions() - actions.loadActionCount() actions.loadTags() // reload tags in case new tags are being saved return action }, @@ -152,9 +146,7 @@ export const actionEditLogic = kea([ })), afterMount(({ actions, props }) => { - if (props.id) { - actions.loadActionCount() - } else { + if (!props.id) { actions.setAction({ name: '', steps: [{ isNew: uuid() }] }, { merge: false }) } }), diff --git a/frontend/src/scenes/appScenes.ts b/frontend/src/scenes/appScenes.ts index a5cdf17ca7f4b..d59f284e09c96 100644 --- a/frontend/src/scenes/appScenes.ts +++ b/frontend/src/scenes/appScenes.ts @@ -22,6 +22,7 @@ export const appScenes: Record any> = { [Scene.Replay]: () => import('./session-recordings/SessionRecordings'), [Scene.ReplaySingle]: () => import('./session-recordings/detail/SessionRecordingDetail'), [Scene.ReplayPlaylist]: () => import('./session-recordings/playlist/SessionRecordingsPlaylistScene'), + [Scene.ReplayFilePlayback]: () => import('./session-recordings/file-playback/SessionRecordingFilePlaybackScene'), [Scene.PersonsManagement]: () => import('./persons-management/PersonsManagementScene'), [Scene.Person]: () => import('./persons/PersonScene'), [Scene.Pipeline]: () => import('./pipeline/Pipeline'), diff --git a/frontend/src/scenes/authentication/InviteSignup.tsx b/frontend/src/scenes/authentication/InviteSignup.tsx index d36fb9df47efa..7b129de26229f 100644 --- a/frontend/src/scenes/authentication/InviteSignup.tsx +++ b/frontend/src/scenes/authentication/InviteSignup.tsx @@ -1,4 +1,4 @@ -import { LemonButton, LemonCheckbox, LemonDivider, LemonInput } from '@posthog/lemon-ui' +import { LemonButton, LemonDivider, LemonInput } from '@posthog/lemon-ui' import clsx from 'clsx' import { useActions, useValues } from 'kea' import { Form } from 'kea-forms' @@ -255,19 +255,6 @@ function UnauthenticatedAcceptInvite({ invite }: { invite: PrevalidatedInvite }) - - {({ value, onChange }) => { - return ( - - ) - }} - - setCriteria(newCriteria, groupIndex, index), + groupIndex, + index, } as CohortFieldProps)}
) @@ -120,7 +122,7 @@ export function CohortCriteriaRowBuilder({
-
+
{rowShape.fields.map((field, i) => { return ( !field.hide && diff --git a/frontend/src/scenes/cohorts/CohortFilters/CohortField.tsx b/frontend/src/scenes/cohorts/CohortFilters/CohortField.tsx index eb30b33f72298..e0301d158606e 100644 --- a/frontend/src/scenes/cohorts/CohortFilters/CohortField.tsx +++ b/frontend/src/scenes/cohorts/CohortFilters/CohortField.tsx @@ -2,24 +2,30 @@ import './CohortField.scss' import clsx from 'clsx' import { useActions, useValues } from 'kea' +import { DateFilter } from 'lib/components/DateFilter/DateFilter' import { PropertyValue } from 'lib/components/PropertyFilters/components/PropertyValue' +import { PropertyFilters } from 'lib/components/PropertyFilters/PropertyFilters' import { TaxonomicFilterGroupType, TaxonomicFilterValue } from 'lib/components/TaxonomicFilter/types' import { TaxonomicPopover } from 'lib/components/TaxonomicPopover/TaxonomicPopover' +import { dayjs } from 'lib/dayjs' import { LemonButton, LemonButtonWithDropdown } from 'lib/lemon-ui/LemonButton' import { LemonDivider } from 'lib/lemon-ui/LemonDivider' import { LemonInput } from 'lib/lemon-ui/LemonInput/LemonInput' -import { useMemo } from 'react' +import { formatDate } from 'lib/utils' +import { useEffect, useMemo, useRef } from 'react' import { cohortFieldLogic } from 'scenes/cohorts/CohortFilters/cohortFieldLogic' import { + CohortEventFiltersFieldProps, CohortFieldBaseProps, CohortNumberFieldProps, CohortPersonPropertiesValuesFieldProps, + CohortRelativeAndExactTimeFieldProps, CohortSelectorFieldProps, CohortTaxonomicFieldProps, CohortTextFieldProps, } from 'scenes/cohorts/CohortFilters/types' -import { PropertyFilterType, PropertyFilterValue, PropertyOperator } from '~/types' +import { AnyPropertyFilter, PropertyFilterType, PropertyFilterValue, PropertyOperator } from '~/types' let uniqueMemoizedIndex = 0 @@ -167,6 +173,118 @@ export function CohortPersonPropertiesValuesField({ ) } +export function CohortEventFiltersField({ + fieldKey, + criteria, + cohortFilterLogicKey, + onChange: _onChange, + groupIndex, + index, +}: CohortEventFiltersFieldProps): JSX.Element { + const { logic } = useCohortFieldLogic({ + fieldKey, + criteria, + cohortFilterLogicKey, + onChange: _onChange, + }) + const { value } = useValues(logic) + const { onChange } = useActions(logic) + const componentRef = useRef(null) + + const valueExists = ((value as AnyPropertyFilter[]) || []).length > 0 + + useEffect(() => { + // :TRICKY: We check paremt has CohortCriteriaRow__Criteria__Field class and add basis-full class if value exists + // We need to do this because of how this list is generated, and we need to add a line-break programatically + // when the PropertyFilters take up too much space. + // Since the list of children is declared in the parent component, we can't add a class to the parent directly, without + // adding a lot of annoying complexity to the parent component. + // This is a hacky solution, but it works 🙈. + + // find parent with className CohortCriteriaRow__Criteria__Field and add basis-full class if value exists + const parent = componentRef.current?.closest('.CohortCriteriaRow__Criteria__Field') + if (parent) { + if (valueExists) { + parent.classList.add('basis-full') + } else { + parent.classList.remove('basis-full') + } + } + }, [componentRef, value]) + + return ( +
+ { + onChange({ [fieldKey]: newValue }) + }} + pageKey={`${fieldKey}-${groupIndex}-${index}`} + eventNames={criteria?.key ? [criteria?.key] : []} + disablePopover + hasRowOperator={valueExists ? true : false} + sendAllKeyUpdates + /> +
+ ) +} + +export function CohortRelativeAndExactTimeField({ + fieldKey, + criteria, + cohortFilterLogicKey, + onChange: _onChange, +}: CohortRelativeAndExactTimeFieldProps): JSX.Element { + const { logic } = useCohortFieldLogic({ + fieldKey, + criteria, + cohortFilterLogicKey, + onChange: _onChange, + }) + // This replaces the old TimeUnit and TimeInterval filters + // and combines them with a relative+exact time option. + // This is more inline with rest of analytics filters and make things much nicer here. + const { value } = useValues(logic) + const { onChange } = useActions(logic) + + return ( + { + onChange({ [fieldKey]: fromDate }) + }} + max={1000} + isFixedDateMode + allowedRollingDateOptions={['days', 'weeks', 'months', 'years']} + showCustom + dateOptions={[ + { + key: 'Last 7 days', + values: ['-7d'], + getFormattedDate: (date: dayjs.Dayjs): string => formatDate(date.subtract(7, 'd')), + defaultInterval: 'day', + }, + { + key: 'Last 30 days', + values: ['-30d'], + getFormattedDate: (date: dayjs.Dayjs): string => formatDate(date.subtract(14, 'd')), + defaultInterval: 'day', + }, + ]} + size="medium" + makeLabel={(_, startOfRange) => ( + Matches all values after {startOfRange} if evaluated today. + )} + /> + ) +} + export function CohortTextField({ value }: CohortTextFieldProps): JSX.Element { return {value} } diff --git a/frontend/src/scenes/cohorts/CohortFilters/CohortTaxonomicField.stories.tsx b/frontend/src/scenes/cohorts/CohortFilters/CohortTaxonomicField.stories.tsx index 69e9421c43aa1..8efe734e1b8b9 100644 --- a/frontend/src/scenes/cohorts/CohortFilters/CohortTaxonomicField.stories.tsx +++ b/frontend/src/scenes/cohorts/CohortFilters/CohortTaxonomicField.stories.tsx @@ -27,7 +27,7 @@ const Template: StoryFn = (props: CohortTaxonomicFi props.taxonomicGroupTypes[0] === TaxonomicFilterGroupType.Events && props.taxonomicGroupTypes[1] === TaxonomicFilterGroupType.Actions ? FilterType.EventsAndActions - : FilterType.EventProperties + : FilterType.PersonProperties return renderField[type]({ ...props, criteria: { diff --git a/frontend/src/scenes/cohorts/CohortFilters/constants.tsx b/frontend/src/scenes/cohorts/CohortFilters/constants.tsx index dc17d1b7883ea..e1f5c7b53bfbd 100644 --- a/frontend/src/scenes/cohorts/CohortFilters/constants.tsx +++ b/frontend/src/scenes/cohorts/CohortFilters/constants.tsx @@ -2,8 +2,10 @@ import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types' import { CohortTypeEnum, PROPERTY_MATCH_TYPE } from 'lib/constants' import { LemonSelectOptions } from 'lib/lemon-ui/LemonSelect' import { + CohortEventFiltersField, CohortNumberField, CohortPersonPropertiesValuesField, + CohortRelativeAndExactTimeField, CohortSelectorField, CohortTaxonomicField, CohortTextField, @@ -12,9 +14,11 @@ import { BehavioralFilterKey, BehavioralFilterType, CohortClientErrors, + CohortEventFiltersFieldProps, CohortFieldProps, CohortNumberFieldProps, CohortPersonPropertiesValuesFieldProps, + CohortRelativeAndExactTimeFieldProps, CohortTaxonomicFieldProps, CohortTextFieldProps, FieldOptionsType, @@ -342,18 +346,17 @@ export const ROWS: Record = { hide: true, }, { - type: FilterType.Text, - defaultValue: 'in the last', + fieldKey: 'event_filters', + type: FilterType.EventFilters, }, { - fieldKey: 'time_value', - type: FilterType.Number, - defaultValue: '30', + type: FilterType.Text, + defaultValue: 'after', }, { - fieldKey: 'time_interval', - type: FilterType.TimeUnit, - defaultValue: TimeUnitType.Day, + fieldKey: 'explicit_datetime', + type: FilterType.RelativeAndExactTime, + defaultValue: '-30d', }, ], }, @@ -374,18 +377,17 @@ export const ROWS: Record = { hide: true, }, { - type: FilterType.Text, - defaultValue: 'in the last', + fieldKey: 'event_filters', + type: FilterType.EventFilters, }, { - fieldKey: 'time_value', - type: FilterType.Number, - defaultValue: '30', + type: FilterType.Text, + defaultValue: 'after', }, { - fieldKey: 'time_interval', - type: FilterType.TimeUnit, - defaultValue: TimeUnitType.Day, + fieldKey: 'explicit_datetime', + type: FilterType.RelativeAndExactTime, + defaultValue: '-30d', }, ], }, @@ -405,6 +407,10 @@ export const ROWS: Record = { defaultValue: TaxonomicFilterGroupType.Events, hide: true, }, + { + fieldKey: 'event_filters', + type: FilterType.EventFilters, + }, { fieldKey: 'operator', type: FilterType.EventsAndActionsMathOperator, @@ -417,17 +423,12 @@ export const ROWS: Record = { }, { type: FilterType.Text, - defaultValue: 'times in the last', + defaultValue: 'times after', }, { - fieldKey: 'time_value', - type: FilterType.Number, - defaultValue: '30', - }, - { - fieldKey: 'time_interval', - type: FilterType.TimeUnit, - defaultValue: TimeUnitType.Day, + fieldKey: 'explicit_datetime', + type: FilterType.RelativeAndExactTime, + defaultValue: '-30d', }, ], }, @@ -568,7 +569,7 @@ export const ROWS: Record = { fields: [ { fieldKey: 'key', - type: FilterType.EventProperties, + type: FilterType.PersonProperties, }, { fieldKey: 'operator', @@ -588,7 +589,7 @@ export const ROWS: Record = { fields: [ { fieldKey: 'key', - type: FilterType.EventProperties, + type: FilterType.PersonProperties, }, { fieldKey: 'operator', @@ -823,6 +824,10 @@ export const ROWS: Record = { }, } +export const COHORT_EVENT_TYPES_WITH_EXPLICIT_DATETIME = Object.entries(ROWS) + .filter(([_, row]) => row.fields.some((field) => field.type === FilterType.RelativeAndExactTime)) + .map(([eventType, _]) => eventType) + // Building blocks of a row export const renderField: Record JSX.Element> = { [FilterType.Behavioral]: function _renderField(p) { @@ -877,7 +882,7 @@ export const renderField: Record JSX.El /> ) }, - [FilterType.EventProperties]: function _renderField(p) { + [FilterType.PersonProperties]: function _renderField(p) { return ( JSX.El /> ) }, + [FilterType.EventFilters]: function _renderField(p) { + return + }, [FilterType.PersonPropertyValues]: function _renderField(p) { return p.criteria['operator'] && [PropertyOperator.IsSet, PropertyOperator.IsNotSet].includes(p.criteria['operator']) ? ( @@ -913,6 +921,9 @@ export const renderField: Record JSX.El /> ) }, + [FilterType.RelativeAndExactTime]: function _renderField(p) { + return + }, [FilterType.EventType]: function _renderField() { return <> }, @@ -926,7 +937,8 @@ export const CRITERIA_VALIDATIONS: Record< (d: string | number | null | undefined) => CohortClientErrors | undefined > = { [FilterType.EventsAndActions]: () => CohortClientErrors.EmptyEventsAndActions, - [FilterType.EventProperties]: () => CohortClientErrors.EmptyEventProperties, + [FilterType.EventFilters]: () => CohortClientErrors.EmptyEventFilters, + [FilterType.PersonProperties]: () => CohortClientErrors.EmptyPersonProperties, [FilterType.PersonPropertyValues]: () => CohortClientErrors.EmptyPersonPropertyValues, [FilterType.EventType]: () => CohortClientErrors.EmptyEventType, [FilterType.Number]: (d) => (Number(d) > 1 ? undefined : CohortClientErrors.EmptyNumber), @@ -934,6 +946,7 @@ export const CRITERIA_VALIDATIONS: Record< [FilterType.TimeUnit]: () => CohortClientErrors.EmptyTimeUnit, [FilterType.MathOperator]: () => CohortClientErrors.EmptyMathOperator, [FilterType.EventsAndActionsMathOperator]: () => CohortClientErrors.EmptyMathOperator, + [FilterType.RelativeAndExactTime]: () => CohortClientErrors.EmptyRelativeAndExactTime, [FilterType.CohortId]: () => CohortClientErrors.EmptyCohortId, [FilterType.CohortValues]: () => CohortClientErrors.EmptyCohortValues, [FilterType.Value]: () => CohortClientErrors.EmptyValue, @@ -952,8 +965,7 @@ export const NEW_CRITERIA = { type: BehavioralFilterKey.Behavioral, value: BehavioralEventType.PerformEvent, event_type: TaxonomicFilterGroupType.Events, - time_value: '30', - time_interval: TimeUnitType.Day, + explicit_datetime: '-30d', } export const NEW_CRITERIA_GROUP: CohortCriteriaGroupFilter = { diff --git a/frontend/src/scenes/cohorts/CohortFilters/types.ts b/frontend/src/scenes/cohorts/CohortFilters/types.ts index f66717385bd6b..2b9f753b15558 100644 --- a/frontend/src/scenes/cohorts/CohortFilters/types.ts +++ b/frontend/src/scenes/cohorts/CohortFilters/types.ts @@ -21,7 +21,9 @@ export enum FilterType { Value = 'value', Text = 'text', EventsAndActions = 'eventsAndActions', - EventProperties = 'eventProperties', + RelativeAndExactTime = 'relativeAndExactTime', + EventFilters = 'eventFilters', + PersonProperties = 'personProperties', PersonPropertyValues = 'personPropertyValues', EventType = 'eventType', Number = 'number', @@ -86,6 +88,8 @@ export interface Row { export interface CohortFieldBaseProps extends Omit { cohortFilterLogicKey?: string + groupIndex?: number + index?: number } export interface CohortSelectorFieldProps extends CohortFieldBaseProps { @@ -105,6 +109,14 @@ export interface CohortPersonPropertiesValuesFieldProps extends Omit { + fieldOptionGroupTypes: never +} + +export interface CohortRelativeAndExactTimeFieldProps extends Omit { + fieldOptionGroupTypes: never +} + export interface CohortTextFieldProps extends CohortFieldBaseProps { value: string } @@ -119,6 +131,8 @@ export type CohortFieldProps = | CohortTaxonomicFieldProps | CohortTextFieldProps | CohortPersonPropertiesValuesFieldProps + | CohortEventFiltersFieldProps + | CohortRelativeAndExactTimeFieldProps export enum CohortClientErrors { NegationCriteriaMissingOther = 'Negation criteria can only be used when matching all criteria (AND), and must be accompanied by at least one positive matching criteria.', @@ -126,12 +140,14 @@ export enum CohortClientErrors { PeriodTimeMismatch = 'The lower bound period value must not be greater than the upper bound value.', SequentialTimeMismatch = 'The lower bound period sequential time value must not be greater than the upper bound time value.', EmptyEventsAndActions = 'Event or action cannot be empty.', - EmptyEventProperties = 'Event property cannot be empty.', + EmptyEventFilters = 'Event filters cannot be empty.', + EmptyPersonProperties = 'Person property name cannot be empty.', EmptyPersonPropertyValues = 'Person property value cannot be empty', EmptyEventType = 'Event type cannot be empty.', EmptyNumber = 'Period values must be at least 1 day and cannot be empty.', EmptyNumberTicker = 'Number cannot be empty.', EmptyTimeUnit = 'Time interval cannot be empty.', + EmptyRelativeAndExactTime = 'Time value cannot be empty.', EmptyMathOperator = 'Math operator cannot be empty.', EmptyCohortId = 'Cohort id cannot be empty.', EmptyCohortValues = 'Cohort value cannot be empty.', diff --git a/frontend/src/scenes/cohorts/cohortEditLogic.test.ts b/frontend/src/scenes/cohorts/cohortEditLogic.test.ts index 94f6910e1b99b..ec215fbb33bd5 100644 --- a/frontend/src/scenes/cohorts/cohortEditLogic.test.ts +++ b/frontend/src/scenes/cohorts/cohortEditLogic.test.ts @@ -17,6 +17,7 @@ import { BehavioralLifecycleType, CohortCriteriaGroupFilter, FilterLogicalOperator, + PropertyFilterType, PropertyOperator, TimeUnitType, } from '~/types' @@ -83,9 +84,6 @@ describe('cohortEditLogic', () => { }) .toFinishAllListeners() .toDispatchActions(['setCohort', 'deleteCohort', router.actionCreators.push(urls.cohorts())]) - .toMatchValues({ - cohort: mockCohort, - }) expect(api.update).toBeCalledTimes(1) }) @@ -431,6 +429,86 @@ describe('cohortEditLogic', () => { expect(api.update).toBeCalledTimes(0) }) + it('do not save on partial event filters', async () => { + await initCohortLogic({ id: 1 }) + await expectLogic(logic, async () => { + logic.actions.setCohort({ + ...mockCohort, + filters: { + properties: { + id: '39777', + type: FilterLogicalOperator.Or, + values: [ + { + id: '70427', + type: FilterLogicalOperator.And, + values: [ + { + type: BehavioralFilterKey.Behavioral, + value: BehavioralEventType.PerformEvent, + event_type: TaxonomicFilterGroupType.Events, + explicit_datetime: '-14d', + key: 'dashboard date range changed', + event_filters: [ + { + key: '$browser', + value: null, + type: PropertyFilterType.Event, + operator: PropertyOperator.Exact, + }, + ], + }, + { + type: BehavioralFilterKey.Behavioral, + value: BehavioralEventType.PerformEvent, + event_type: TaxonomicFilterGroupType.Events, + time_value: '1', + time_interval: TimeUnitType.Day, + key: '$rageclick', + negation: true, + event_filters: [ + { + key: '$browser', + value: null, + type: PropertyFilterType.Event, + operator: PropertyOperator.Exact, + }, + ], + }, + ], + }, + ], + }, + }, + }) + logic.actions.submitCohort() + }) + .toDispatchActions(['setCohort', 'submitCohort', 'submitCohortFailure']) + .toMatchValues({ + cohortErrors: partial({ + filters: { + properties: { + values: [ + { + values: [ + { + event_filters: 'Event filters cannot be empty.', + id: 'Event filters cannot be empty.', + }, + { + event_filters: 'Event filters cannot be empty.', + id: 'Event filters cannot be empty.', + }, + ], + }, + ], + }, + }, + }), + }) + expect(api.update).toBeCalledTimes(0) + }) + describe('empty input errors', () => { Object.entries(ROWS).forEach(([key, row]) => { it(`${key} row missing all required fields`, async () => { @@ -475,7 +553,10 @@ describe('cohortEditLogic', () => { partial( Object.fromEntries( row.fields - .filter(({ fieldKey }) => !!fieldKey) + .filter( + ({ fieldKey }) => + !!fieldKey && fieldKey !== 'event_filters' + ) // event_filters are optional .map(({ fieldKey, type }) => [ fieldKey, CRITERIA_VALIDATIONS[type](undefined), @@ -530,6 +611,16 @@ describe('cohortEditLogic', () => { }) it('duplicate group', async () => { + const expectedGroupValue = partial({ + ...mockCohort.filters.properties.values[0], + values: [ + { + ...(mockCohort.filters.properties.values[0] as CohortCriteriaGroupFilter).values[0], + explicit_datetime: '-30d', + }, + ], + }) // Backwards compatible processing adds explicit_datetime + await expectLogic(logic, () => { logic.actions.duplicateFilter(0) }) @@ -538,10 +629,7 @@ describe('cohortEditLogic', () => { cohort: partial({ filters: { properties: partial({ - values: [ - partial(mockCohort.filters.properties.values[0]), - partial(mockCohort.filters.properties.values[0]), - ], + values: [expectedGroupValue, expectedGroupValue], }), }, }), @@ -574,7 +662,17 @@ describe('cohortEditLogic', () => { filters: { properties: partial({ values: [ - partial(mockCohort.filters.properties.values[0]), + partial({ + ...mockCohort.filters.properties.values[0], + values: [ + { + ...( + mockCohort.filters.properties.values[0] as CohortCriteriaGroupFilter + ).values[0], + explicit_datetime: '-30d', + }, + ], + }), // Backwards compatible processing adds explicit_datetime partial({ type: FilterLogicalOperator.Or, values: [NEW_CRITERIA], diff --git a/frontend/src/scenes/cohorts/cohortUtils.tsx b/frontend/src/scenes/cohorts/cohortUtils.tsx index d8d701daeb13a..5d1efee633852 100644 --- a/frontend/src/scenes/cohorts/cohortUtils.tsx +++ b/frontend/src/scenes/cohorts/cohortUtils.tsx @@ -1,5 +1,6 @@ import equal from 'fast-deep-equal' import { DeepPartialMap, ValidationErrorType } from 'kea-forms' +import { isEmptyProperty } from 'lib/components/PropertyFilters/utils' import { ENTITY_MATCH_TYPE, PROPERTY_MATCH_TYPE } from 'lib/constants' import { areObjectValuesEmpty, calculateDays, isNumeric } from 'lib/utils' import { BEHAVIORAL_TYPE_TO_LABEL, CRITERIA_VALIDATIONS, ROWS } from 'scenes/cohorts/CohortFilters/constants' @@ -15,6 +16,7 @@ import { ActionType, AnyCohortCriteriaType, AnyCohortGroupType, + AnyPropertyFilter, BehavioralCohortType, BehavioralEventType, BehavioralLifecycleType, @@ -22,6 +24,7 @@ import { CohortCriteriaType, CohortType, FilterLogicalOperator, + PropertyFilterType, PropertyOperator, TimeUnitType, } from '~/types' @@ -272,6 +275,15 @@ export function validateGroup( requiredFields = requiredFields.filter((f) => f.fieldKey !== 'value_property') } + // Handle EventFilters separately, since these are optional + requiredFields = requiredFields.filter((f) => f.fieldKey !== 'event_filters') + const eventFilterError = + c?.event_filters && + c.event_filters.length > 0 && + c.event_filters.some((prop) => prop?.type !== PropertyFilterType.HogQL && isEmptyProperty(prop)) + ? CohortClientErrors.EmptyEventFilters + : undefined + const criteriaErrors = Object.fromEntries( requiredFields.map(({ fieldKey, type }) => [ fieldKey, @@ -284,13 +296,15 @@ export function validateGroup( : CRITERIA_VALIDATIONS?.[type](c[fieldKey]), ]) ) - const consolidatedErrors = Object.values(criteriaErrors) + + const allErrors = { ...criteriaErrors, event_filters: eventFilterError } + const consolidatedErrors = Object.values(allErrors) .filter((e) => !!e) .join(' ') return { - ...(areObjectValuesEmpty(criteriaErrors) ? {} : { id: consolidatedErrors }), - ...criteriaErrors, + ...(areObjectValuesEmpty(allErrors) ? {} : { id: consolidatedErrors }), + ...allErrors, } }), } @@ -361,7 +375,7 @@ export function determineFilterType( export function resolveCohortFieldValue( criteria: AnyCohortCriteriaType, fieldKey: string -): string | number | boolean | null | undefined { +): string | number | boolean | null | undefined | AnyPropertyFilter[] { // Resolve correct behavioral filter type if (fieldKey === 'value') { return criteriaToBehavioralFilterType(criteria) @@ -452,6 +466,7 @@ export function criteriaToHumanSentence( } data.fields.forEach(({ type, fieldKey, defaultValue, hide }) => { + // TODO: This needs to be much nicer for all cohort criteria options if (!hide) { if (type === FilterType.Text) { words.push(defaultValue) @@ -461,6 +476,8 @@ export function criteriaToHumanSentence( words.push(
{cohortsById?.[value]?.name ?? `Cohort ${value}`}
) } else if (type === FilterType.EventsAndActions && typeof value === 'number') { words.push(
{actionsById?.[value]?.name ?? `Action ${value}`}
) + } else if (type === FilterType.EventFilters && (criteria.event_filters?.length || 0) > 0) { + words.push(
with filters
) } else { words.push(
{value}
) } diff --git a/frontend/src/scenes/data-management/properties/propertyDefinitionsTableLogic.ts b/frontend/src/scenes/data-management/properties/propertyDefinitionsTableLogic.ts index a9a1541df21f8..fad143572f570 100644 --- a/frontend/src/scenes/data-management/properties/propertyDefinitionsTableLogic.ts +++ b/frontend/src/scenes/data-management/properties/propertyDefinitionsTableLogic.ts @@ -155,11 +155,13 @@ export const propertyDefinitionsTableLogic = kea ({ - setFilters: () => { + setFilters: async (_, breakpoint) => { + await breakpoint(500) actions.loadPropertyDefinitions( normalizePropertyDefinitionEndpointUrl( values.propertyDefinitions.current, { + offset: 0, search: values.filters.property, type: values.filters.type, group_type_index: values.filters.group_type_index, @@ -200,9 +202,12 @@ export const propertyDefinitionsTableLogic = kea ({ [urls.propertyDefinitions()]: (_, searchParams) => { + if (values.propertyDefinitionsLoading) { + return + } if (!objectsEqual(cleanFilters(values.filters), cleanFilters(router.values.searchParams))) { actions.setFilters(searchParams as Filters) - } else if (!values.propertyDefinitions.results.length && !values.propertyDefinitionsLoading) { + } else if (!values.propertyDefinitions.results.length) { actions.loadPropertyDefinitions() } }, diff --git a/frontend/src/scenes/data-warehouse/external/forms/SourceForm.tsx b/frontend/src/scenes/data-warehouse/external/forms/SourceForm.tsx index 345b3ff5ef0d0..cd97c5e5a56b1 100644 --- a/frontend/src/scenes/data-warehouse/external/forms/SourceForm.tsx +++ b/frontend/src/scenes/data-warehouse/external/forms/SourceForm.tsx @@ -4,8 +4,7 @@ import { LemonField } from 'lib/lemon-ui/LemonField' import { SourceConfig } from '~/types' -import { SOURCE_DETAILS } from '../../new/sourceWizardLogic' -import { sourceFormLogic } from './sourceFormLogic' +import { SOURCE_DETAILS, sourceWizardLogic } from '../../new/sourceWizardLogic' interface SourceFormProps { sourceConfig: SourceConfig @@ -13,13 +12,7 @@ interface SourceFormProps { export default function SourceForm({ sourceConfig }: SourceFormProps): JSX.Element { return ( -
+ {SOURCE_DETAILS[sourceConfig.name].fields.map((field) => ( diff --git a/frontend/src/scenes/data-warehouse/external/forms/sourceFormLogic.ts b/frontend/src/scenes/data-warehouse/external/forms/sourceFormLogic.ts deleted file mode 100644 index 4bc162ab034d6..0000000000000 --- a/frontend/src/scenes/data-warehouse/external/forms/sourceFormLogic.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { lemonToast } from '@posthog/lemon-ui' -import { actions, connect, kea, key, listeners, path, props } from 'kea' -import { forms } from 'kea-forms' -import { urlToAction } from 'kea-router' -import api from 'lib/api' - -import { ExternalDataSourceCreatePayload, SourceConfig, SourceFieldConfig } from '~/types' - -import { getHubspotRedirectUri, sourceWizardLogic } from '../../new/sourceWizardLogic' -import type { sourceFormLogicType } from './sourceFormLogicType' - -export interface SourceFormProps { - sourceConfig: SourceConfig -} - -const getErrorsForFields = ( - fields: SourceFieldConfig[] -): ((args: { prefix: string; payload: Record }) => Record) => { - return ({ prefix, payload }) => { - const errors: Record = { - payload: {}, - } - - // Prefix errors - if (!/^[a-zA-Z0-9_-]*$/.test(prefix)) { - errors['prefix'] = "Please enter a valid prefix (only letters, numbers, and '_' or '-')." - } - - // Payload errors - for (const field of fields) { - const fieldValue = payload[field.name] - if (field.required && !fieldValue) { - errors['payload'][field.name] = `Please enter a ${field.label.toLowerCase()}` - } - } - - return errors - } -} - -export const sourceFormLogic = kea([ - path(['scenes', 'data-warehouse', 'external', 'sourceFormLogic']), - key((props) => props.sourceConfig.name), - props({} as SourceFormProps), - connect({ - actions: [ - sourceWizardLogic, - [ - 'setDatabaseSchemas', - 'onBack', - 'onNext', - 'selectConnector', - 'loadSources', - 'updateSource', - 'clearSource', - 'setIsLoading', - ], - ], - values: [sourceWizardLogic, ['source']], - }), - actions({ - onCancel: true, - handleRedirect: (kind: string, searchParams: any) => ({ kind, searchParams }), - getDatabaseSchemas: true, - }), - listeners(({ actions, values, props }) => ({ - onCancel: () => { - actions.clearSource() - actions.onBack() - actions.selectConnector(null) - }, - submitSourceConnectionDetailsSuccess: () => { - actions.getDatabaseSchemas() - }, - handleRedirect: async ({ kind, searchParams }) => { - switch (kind) { - case 'hubspot': { - actions.updateSource({ - source_type: 'Hubspot', - payload: { - code: searchParams.code, - redirect_uri: getHubspotRedirectUri(), - }, - }) - return - } - default: - lemonToast.error(`Something went wrong.`) - } - }, - getDatabaseSchemas: async () => { - const schemas = await api.externalDataSources.database_schema( - props.sourceConfig.name, - values.source.payload ?? {} - ) - actions.setDatabaseSchemas(schemas) - actions.onNext() - }, - })), - urlToAction(({ actions }) => ({ - '/data-warehouse/:kind/redirect': ({ kind = '' }, searchParams) => { - actions.handleRedirect(kind, searchParams) - }, - })), - forms(({ props, actions, values }) => ({ - sourceConnectionDetails: { - defaults: { - prefix: values.source?.prefix ?? '', - source_type: props.sourceConfig.name, - payload: values.source?.payload ?? {}, - } as ExternalDataSourceCreatePayload, - errors: getErrorsForFields(props.sourceConfig.fields), - submit: async (sourceValues) => { - actions.setIsLoading(true) - - try { - await api.externalDataSources.source_prefix(sourceValues.source_type, sourceValues.prefix) - actions.updateSource(sourceValues) - } catch (e: any) { - if (e?.data?.message) { - actions.setSourceConnectionDetailsManualErrors({ prefix: e.data.message }) - } - actions.setIsLoading(false) - - throw e - } - }, - }, - })), -]) diff --git a/frontend/src/scenes/data-warehouse/new/NewSourceWizard.tsx b/frontend/src/scenes/data-warehouse/new/NewSourceWizard.tsx index 5fff9b0abf5b5..48085faa831ef 100644 --- a/frontend/src/scenes/data-warehouse/new/NewSourceWizard.tsx +++ b/frontend/src/scenes/data-warehouse/new/NewSourceWizard.tsx @@ -1,5 +1,6 @@ import { LemonButton } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' +import { router } from 'kea-router' import { PageHeader } from 'lib/components/PageHeader' import { FEATURE_FLAGS } from 'lib/constants' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' @@ -25,7 +26,7 @@ export const scene: SceneExport = { } export function NewSourceWizard(): JSX.Element { const { modalTitle, modalCaption } = useValues(sourceWizardLogic) - const { onBack, onSubmit, closeWizard } = useActions(sourceWizardLogic) + const { onBack, onSubmit, closeWizard, cancelWizard } = useActions(sourceWizardLogic) const { currentStep, isLoading, canGoBack, canGoNext, nextButtonText, showSkipButton } = useValues(sourceWizardLogic) @@ -64,17 +65,17 @@ export function NewSourceWizard(): JSX.Element { ) }, [currentStep, isLoading, canGoNext, canGoBack, nextButtonText, showSkipButton]) + const onCancel = (): void => { + cancelWizard() + router.actions.push(urls.dataWarehouse()) + } + return ( <> - + Cancel diff --git a/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx b/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx index 6c5316e84b285..7aa8813f57450 100644 --- a/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx +++ b/frontend/src/scenes/data-warehouse/new/sourceWizardLogic.tsx @@ -1,14 +1,20 @@ import { lemonToast, Link } from '@posthog/lemon-ui' import { actions, connect, kea, listeners, path, reducers, selectors } from 'kea' -import { router } from 'kea-router' +import { forms } from 'kea-forms' +import { router, urlToAction } from 'kea-router' import api from 'lib/api' import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' import { Scene } from 'scenes/sceneTypes' import { urls } from 'scenes/urls' -import { Breadcrumb, ExternalDataSourceCreatePayload, ExternalDataSourceSyncSchema, SourceConfig } from '~/types' +import { + Breadcrumb, + ExternalDataSourceCreatePayload, + ExternalDataSourceSyncSchema, + SourceConfig, + SourceFieldConfig, +} from '~/types' -import { sourceFormLogic } from '../external/forms/sourceFormLogic' import { dataWarehouseSettingsLogic } from '../settings/dataWarehouseSettingsLogic' import { dataWarehouseTableLogic } from './dataWarehouseTableLogic' import type { sourceWizardLogicType } from './sourceWizardLogicType' @@ -160,6 +166,9 @@ export const sourceWizardLogic = kea([ setIsLoading: (isLoading: boolean) => ({ isLoading }), setSourceId: (id: string) => ({ sourceId: id }), closeWizard: true, + cancelWizard: true, + setStep: (step: number) => ({ step }), + getDatabaseSchemas: true, }), connect({ values: [ @@ -191,6 +200,7 @@ export const sourceWizardLogic = kea([ onNext: (state) => state + 1, onBack: (state) => state - 1, onClear: () => 1, + setStep: (_, { step }) => step, }, ], databaseSchema: [ @@ -369,6 +379,11 @@ export const sourceWizardLogic = kea([ ], }), listeners(({ actions, values }) => ({ + onBack: () => { + if (values.currentStep <= 2) { + actions.selectConnector(null) + } + }, onClear: () => { actions.selectConnector(null) actions.clearSource() @@ -385,8 +400,7 @@ export const sourceWizardLogic = kea([ if (values.currentStep === 2) { if (values.selectedConnector?.name) { - const logic = sourceFormLogic({ sourceConfig: values.selectedConnector }) - logic.actions.submitSourceConnectionDetails() + actions.submitSourceConnectionDetails() } else { // Used for manual S3 file links dataWarehouseTableLogic.actions.submitTable() @@ -414,6 +428,11 @@ export const sourceWizardLogic = kea([ actions.loadSources(null) router.actions.push(urls.dataWarehouseSettings()) }, + cancelWizard: () => { + actions.onClear() + actions.setStep(1) + actions.loadSources(null) + }, createSource: async () => { if (values.selectedConnector === null) { // This should never happen @@ -433,5 +452,110 @@ export const sourceWizardLogic = kea([ actions.setIsLoading(false) } }, + handleRedirect: async ({ kind, searchParams }) => { + switch (kind) { + case 'hubspot': { + actions.updateSource({ + source_type: 'Hubspot', + payload: { + code: searchParams.code, + redirect_uri: getHubspotRedirectUri(), + }, + }) + return + } + default: + lemonToast.error(`Something went wrong.`) + } + }, + submitSourceConnectionDetailsSuccess: () => { + actions.getDatabaseSchemas() + }, + getDatabaseSchemas: async () => { + if (values.selectedConnector) { + const schemas = await api.externalDataSources.database_schema( + values.selectedConnector.name, + values.source.payload ?? {} + ) + actions.setDatabaseSchemas(schemas) + actions.onNext() + } + }, + })), + urlToAction(({ actions }) => ({ + '/data-warehouse/:kind/redirect': ({ kind = '' }, searchParams) => { + if (kind === 'hubspot') { + router.actions.push(urls.dataWarehouseTable(), { kind, code: searchParams.code }) + } + }, + '/data-warehouse/new': (_, searchParams) => { + if (searchParams.kind == 'hubspot' && searchParams.code) { + actions.selectConnector(SOURCE_DETAILS['Hubspot']) + actions.handleRedirect(searchParams.kind, { + code: searchParams.code, + }) + actions.setStep(2) + } + }, + })), + forms(({ actions, values }) => ({ + sourceConnectionDetails: { + defaults: { + prefix: '', + payload: {}, + } as { + prefix: string + payload: Record + }, + errors: (sourceValues) => { + return getErrorsForFields(values.selectedConnector?.fields ?? [], sourceValues) + }, + submit: async (sourceValues) => { + if (values.selectedConnector) { + const payload = { + ...sourceValues, + source_type: values.selectedConnector.name, + } + actions.setIsLoading(true) + + try { + await api.externalDataSources.source_prefix(payload.source_type, payload.prefix) + actions.updateSource(payload) + actions.setIsLoading(false) + } catch (e: any) { + if (e?.data?.message) { + actions.setSourceConnectionDetailsManualErrors({ prefix: e.data.message }) + } + actions.setIsLoading(false) + + throw e + } + } + }, + }, })), ]) + +const getErrorsForFields = ( + fields: SourceFieldConfig[], + { prefix, payload }: { prefix: string; payload: Record } +): Record => { + const errors: Record = { + payload: {}, + } + + // Prefix errors + if (!/^[a-zA-Z0-9_-]*$/.test(prefix ?? '')) { + errors['prefix'] = "Please enter a valid prefix (only letters, numbers, and '_' or '-')." + } + + // Payload errors + for (const field of fields) { + const fieldValue = payload[field.name] + if (field.required && !fieldValue) { + errors['payload'][field.name] = `Please enter a ${field.label.toLowerCase()}` + } + } + + return errors +} diff --git a/frontend/src/scenes/data-warehouse/redirect/DataWarehouseRedirectScene.tsx b/frontend/src/scenes/data-warehouse/redirect/DataWarehouseRedirectScene.tsx index 0d7b433cbc7cb..4b343b7ae1604 100644 --- a/frontend/src/scenes/data-warehouse/redirect/DataWarehouseRedirectScene.tsx +++ b/frontend/src/scenes/data-warehouse/redirect/DataWarehouseRedirectScene.tsx @@ -1,32 +1,17 @@ -import { LemonButton, LemonInput } from '@posthog/lemon-ui' -import { Form } from 'kea-forms' -import { LemonField } from 'lib/lemon-ui/LemonField' -import { sourceFormLogic } from 'scenes/data-warehouse/external/forms/sourceFormLogic' +import { Spinner } from '@posthog/lemon-ui' import { SceneExport } from 'scenes/sceneTypes' +import { sourceWizardLogic } from '../new/sourceWizardLogic' + export const scene: SceneExport = { component: DataWarehouseRedirectScene, - logic: sourceFormLogic, + logic: sourceWizardLogic, } export function DataWarehouseRedirectScene(): JSX.Element { return (
-

Configure

-

Add a prefix to your tables to avoid conflicts with other data sources

- - - - - - Submit - - +
) } diff --git a/frontend/src/scenes/debug/HogQLDebug.tsx b/frontend/src/scenes/debug/HogQLDebug.tsx index e2c4a08341d13..3322638e0eda6 100644 --- a/frontend/src/scenes/debug/HogQLDebug.tsx +++ b/frontend/src/scenes/debug/HogQLDebug.tsx @@ -68,10 +68,18 @@ export function HogQLDebug({ query, setQuery, queryKey }: HogQLDebugProps): JSX. setQuery({ diff --git a/frontend/src/scenes/experiments/Experiment.tsx b/frontend/src/scenes/experiments/Experiment.tsx index 4a01bcb120b33..8bed661f07b59 100644 --- a/frontend/src/scenes/experiments/Experiment.tsx +++ b/frontend/src/scenes/experiments/Experiment.tsx @@ -829,7 +829,7 @@ export function Experiment(): JSX.Element {
)}
-

Experiment result

+

Experiment results

diff --git a/frontend/src/scenes/experiments/ExperimentNext.tsx b/frontend/src/scenes/experiments/ExperimentNext.tsx index 664a6a53e3c77..f77625045a335 100644 --- a/frontend/src/scenes/experiments/ExperimentNext.tsx +++ b/frontend/src/scenes/experiments/ExperimentNext.tsx @@ -2,15 +2,17 @@ import './Experiment.scss' import { LemonDivider } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' +import { NotFound } from 'lib/components/NotFound' +import { LoadingState } from './Experiment' import { ExperimentForm } from './ExperimentForm' import { ExperimentImplementationDetails } from './ExperimentImplementationDetails' import { experimentLogic } from './experimentLogic' import { - ExperimentLoader, ExperimentLoadingAnimation, NoResultsEmptyState, PageHeaderCustom, + ResultsHeader, } from './ExperimentView/components' import { DistributionTable } from './ExperimentView/DistributionTable' import { ExperimentExposureModal, ExperimentGoalModal, Goal } from './ExperimentView/Goal' @@ -32,7 +34,7 @@ export function ExperimentView(): JSX.Element {
{experimentLoading ? ( - + ) : ( <> @@ -59,7 +61,12 @@ export function ExperimentView(): JSX.Element { <> - {experiment.start_date && } + {experiment.start_date && ( +
+ + +
+ )} )} @@ -80,7 +87,11 @@ export function ExperimentView(): JSX.Element { } export function ExperimentNext(): JSX.Element { - const { experimentId, editingExistingExperiment } = useValues(experimentLogic) + const { experimentId, editingExistingExperiment, experimentMissing } = useValues(experimentLogic) + + if (experimentMissing) { + return + } return experimentId === 'new' || editingExistingExperiment ? : } diff --git a/frontend/src/scenes/experiments/ExperimentResult.tsx b/frontend/src/scenes/experiments/ExperimentResult.tsx index c978a5cd8c767..bf312c8a98b05 100644 --- a/frontend/src/scenes/experiments/ExperimentResult.tsx +++ b/frontend/src/scenes/experiments/ExperimentResult.tsx @@ -2,6 +2,7 @@ import './Experiment.scss' import { IconInfo } from '@posthog/icons' import { LemonTable, Tooltip } from '@posthog/lemon-ui' +import { Empty } from 'antd' import { useValues } from 'kea' import { EntityFilterInfo } from 'lib/components/EntityFilterInfo' import { FunnelLayout } from 'lib/constants' @@ -15,6 +16,7 @@ import { ChartDisplayType, FilterType, FunnelVizType, InsightShortId, InsightTyp import { LoadingState } from './Experiment' import { experimentLogic } from './experimentLogic' +import { NoResultsEmptyState } from './ExperimentView/components' import { getExperimentInsightColour } from './utils' interface ExperimentResultProps { @@ -32,7 +34,6 @@ export function ExperimentResult({ secondaryMetricId }: ExperimentResultProps): conversionRateForVariant, getIndexForVariant, areTrendResultsConfusing, - experimentResultCalculationError, sortedExperimentResultVariants, experimentMathAggregationForTrends, } = useValues(experimentLogic) @@ -240,27 +241,21 @@ export function ExperimentResult({ secondaryMetricId }: ExperimentResultProps): />
) : ( - experiment.start_date && ( + experiment.start_date && + !targetResultsLoading && ( <> -
- {!targetResultsLoading && ( -
-
- - There are no results for this{' '} - {isSecondaryMetric ? 'secondary metric' : 'experiment'} yet. - -
- {!!experimentResultCalculationError && ( -
{experimentResultCalculationError}
- )} -
- Wait a bit longer for your users to be exposed to the experiment. Double check - your feature flag implementation if you're still not seeing results. -
+ {isSecondaryMetric ? ( +
+
+ +

+ There are no results for this metric yet +

- )} -
+
+ ) : ( + + )} ) )} diff --git a/frontend/src/scenes/experiments/ExperimentView/Info.tsx b/frontend/src/scenes/experiments/ExperimentView/Info.tsx index dcd6234bcc497..fa0a2e5cf9503 100644 --- a/frontend/src/scenes/experiments/ExperimentView/Info.tsx +++ b/frontend/src/scenes/experiments/ExperimentView/Info.tsx @@ -14,7 +14,7 @@ import { ProgressStatus } from '~/types' import { StatusTag } from '../Experiment' import { experimentLogic } from '../experimentLogic' import { getExperimentStatus } from '../experimentsLogic' -import { ResultsTag } from './components' +import { ActionBanner, ResultsTag } from './components' export function Info(): JSX.Element { const { experiment } = useValues(experimentLogic) @@ -102,6 +102,7 @@ export function Info(): JSX.Element { compactButtons />
+ ) } diff --git a/frontend/src/scenes/experiments/ExperimentView/ProgressBar.tsx b/frontend/src/scenes/experiments/ExperimentView/ProgressBar.tsx index 229003ead99ac..568c37b254758 100644 --- a/frontend/src/scenes/experiments/ExperimentView/ProgressBar.tsx +++ b/frontend/src/scenes/experiments/ExperimentView/ProgressBar.tsx @@ -1,32 +1,28 @@ import '../Experiment.scss' import { useValues } from 'kea' -import { dayjs } from 'lib/dayjs' import { LemonProgress } from 'lib/lemon-ui/LemonProgress' import { humanFriendlyNumber } from 'lib/utils' -import { FunnelStep, InsightType } from '~/types' +import { InsightType } from '~/types' import { experimentLogic } from '../experimentLogic' +import { formatUnitByQuantity } from '../utils' export function ProgressBar(): JSX.Element { - const { experiment, experimentResults, experimentInsightType } = useValues(experimentLogic) - - // Parameters for experiment results - // don't use creation variables in results - const funnelResultsPersonsTotal = - experimentInsightType === InsightType.FUNNELS && experimentResults?.insight - ? (experimentResults.insight as FunnelStep[][]).reduce( - (sum: number, variantResult: FunnelStep[]) => variantResult[0]?.count + sum, - 0 - ) - : 0 + const { + experiment, + experimentInsightType, + funnelResultsPersonsTotal, + recommendedSampleSize, + actualRunningTime, + recommendedRunningTime, + } = useValues(experimentLogic) const experimentProgressPercent = experimentInsightType === InsightType.FUNNELS - ? ((funnelResultsPersonsTotal || 0) / (experiment?.parameters?.recommended_sample_size || 1)) * 100 - : (dayjs().diff(experiment?.start_date, 'day') / (experiment?.parameters?.recommended_running_time || 1)) * - 100 + ? (funnelResultsPersonsTotal / recommendedSampleSize) * 100 + : (actualRunningTime / recommendedRunningTime) * 100 return (
@@ -48,15 +44,15 @@ export function ProgressBar(): JSX.Element {
{experiment.end_date ? (
- Ran for {dayjs(experiment.end_date).diff(experiment.start_date, 'day')} days + Ran for {actualRunningTime} {formatUnitByQuantity(actualRunningTime, 'day')}
) : (
- {dayjs().diff(experiment.start_date, 'day')} days running + {actualRunningTime} {formatUnitByQuantity(actualRunningTime, 'day')} running
)}
- Goal: {experiment?.parameters?.recommended_running_time ?? 'Unknown'} days + Goal: {recommendedRunningTime} {formatUnitByQuantity(recommendedRunningTime, 'day')}
)} @@ -64,16 +60,18 @@ export function ProgressBar(): JSX.Element {
{experiment.end_date ? (
- Saw {humanFriendlyNumber(funnelResultsPersonsTotal)} participants + Saw {humanFriendlyNumber(funnelResultsPersonsTotal)}{' '} + {formatUnitByQuantity(funnelResultsPersonsTotal, 'participant')}
) : (
- {humanFriendlyNumber(funnelResultsPersonsTotal)} participants seen + {humanFriendlyNumber(funnelResultsPersonsTotal)}{' '} + {formatUnitByQuantity(funnelResultsPersonsTotal, 'participant')} seen
)}
- Goal: {humanFriendlyNumber(experiment?.parameters?.recommended_sample_size || 0)}{' '} - participants + Goal: {humanFriendlyNumber(recommendedSampleSize)}{' '} + {formatUnitByQuantity(recommendedSampleSize, 'participant')}
)} diff --git a/frontend/src/scenes/experiments/ExperimentView/Results.tsx b/frontend/src/scenes/experiments/ExperimentView/Results.tsx index f330c19868096..0afe6482ae6bb 100644 --- a/frontend/src/scenes/experiments/ExperimentView/Results.tsx +++ b/frontend/src/scenes/experiments/ExperimentView/Results.tsx @@ -3,7 +3,7 @@ import '../Experiment.scss' import { useValues } from 'kea' import { experimentLogic } from '../experimentLogic' -import { ResultsQuery, ResultsTag } from './components' +import { ResultsHeader, ResultsQuery } from './components' import { SummaryTable } from './SummaryTable' export function Results(): JSX.Element { @@ -11,10 +11,7 @@ export function Results(): JSX.Element { return (
-
-

Results

- -
+
diff --git a/frontend/src/scenes/experiments/ExperimentView/SecondaryMetricsTable.tsx b/frontend/src/scenes/experiments/ExperimentView/SecondaryMetricsTable.tsx index 5361a5b744710..26f1b1bdc6a28 100644 --- a/frontend/src/scenes/experiments/ExperimentView/SecondaryMetricsTable.tsx +++ b/frontend/src/scenes/experiments/ExperimentView/SecondaryMetricsTable.tsx @@ -2,6 +2,7 @@ import '../Experiment.scss' import { IconPencil, IconPlus } from '@posthog/icons' import { LemonButton, LemonInput, LemonModal, LemonTable, LemonTableColumns } from '@posthog/lemon-ui' +import { Empty } from 'antd' import { useActions, useValues } from 'kea' import { Form } from 'kea-forms' import { EntityFilterInfo } from 'lib/components/EntityFilterInfo' @@ -85,9 +86,20 @@ export function SecondaryMetricsModal({ ) } > - {showResults && targetResults ? ( + {showResults ? (
- + {targetResults && targetResults.insight ? ( + + ) : ( +
+
+ +

+ There are no results for this metric yet +

+
+
+ )}
) : (
- {metrics && metrics.length > 0 && metrics.length < 3 && isExperimentRunning && ( + {metrics && metrics.length > 0 && metrics.length < 3 && (
- ) -} - export function ResultsQuery({ targetResults, showTable, @@ -100,27 +87,141 @@ export function ResultsQuery({ ) } +export function ExploreButton({ icon = }: { icon?: JSX.Element }): JSX.Element { + const { experimentResults, experiment } = useValues(experimentLogic) + + // keep in sync with https://github.com/PostHog/posthog/blob/master/ee/clickhouse/queries/experiments/funnel_experiment_result.py#L71 + // :TRICKY: In the case of no results, we still want users to explore the query, so they can debug further. + // This generates a close enough query that the backend would use to compute results. + const filtersFromExperiment: Partial = { + ...experiment.filters, + date_from: experiment.start_date, + date_to: experiment.end_date, + explicit_date: true, + breakdown: `$feature/${experiment.feature_flag_key ?? experiment.feature_flag?.key}`, + breakdown_type: 'event', + properties: [], + } + + return ( + + Explore results + + ) +} + +export function ResultsHeader(): JSX.Element { + return ( +
+
+
+

Results

+ +
+
+ +
+
+ +
+
+
+ ) +} + export function NoResultsEmptyState(): JSX.Element { const { experimentResultsLoading, experimentResultCalculationError } = useValues(experimentLogic) + function ChecklistItem({ failureReason, checked }: { failureReason: string; checked: boolean }): JSX.Element { + const failureReasonToText = { + 'no-events': 'Events have been received', + 'no-flag-info': 'Feature flag information is present on the events', + 'no-control-variant': 'Events with the control variant received', + 'no-test-variant': 'Events with at least one test variant received', + } + + return ( +
+ {checked ? ( + + ) : ( + + )} + {failureReasonToText[failureReason]} +
+ ) + } + if (experimentResultsLoading) { return <> } + // Validation errors return 400 and are rendered as a checklist + if (experimentResultCalculationError?.statusCode === 400) { + const checklistItems = [] + for (const [failureReason, value] of Object.entries(JSON.parse(experimentResultCalculationError.detail))) { + checklistItems.push() + } + + return ( +
+
+
+
+
+
+ Experiment results not yet available +
+
+
+ Results will be calculated once we've received the necessary minimum events. The + checklist on the right shows what's still needed. +
+
+ +
+
{checklistItems}
+
+
+
+
+ ) + } + + // Non-400 errors are rendered as plain text return (
-

Results

-
-
+
+

There are no experiment results yet

{!!experimentResultCalculationError && ( -
{experimentResultCalculationError}
+
+ {experimentResultCalculationError.detail} +
)} -
- Wait a bit longer for your users to be exposed to the experiment. Double check your feature flag - implementation if you're still not seeing results. -
@@ -232,3 +333,159 @@ export function PageHeaderCustom(): JSX.Element { /> ) } + +export function ActionBanner(): JSX.Element { + const { + experiment, + experimentInsightType, + experimentResults, + experimentLoading, + experimentResultsLoading, + isExperimentRunning, + areResultsSignificant, + isExperimentStopped, + funnelResultsPersonsTotal, + recommendedSampleSize, + actualRunningTime, + recommendedRunningTime, + getHighestProbabilityVariant, + } = useValues(experimentLogic) + + const { archiveExperiment } = useActions(experimentLogic) + + if (!experiment || experimentLoading || experimentResultsLoading) { + return <> + } + + // Draft + if (!isExperimentRunning) { + return ( + + Your experiment is in draft mode. You can edit your variants, adjust release conditions, and{' '} + + test your feature flag + + . Once everything works as expected, you can launch your experiment. From that point, any new experiment + events will be counted towards the results. + + ) + } + + // Running, results present, not significant + if (isExperimentRunning && experimentResults && !isExperimentStopped && !areResultsSignificant) { + // Results insignificant, but a large enough sample/running time has been achieved + // Further collection unlikely to change the result -> recommmend cutting the losses + if ( + experimentInsightType === InsightType.FUNNELS && + funnelResultsPersonsTotal > Math.max(recommendedSampleSize, 500) && + dayjs().diff(experiment.start_date, 'day') > 2 // at least 2 days running + ) { + return ( + + You've reached a robust sample size for your experiment, but the results are still inconclusive. + Continuing the experiment is unlikely to yield significant findings. It may be time to stop this + experiment. + + ) + } + if (experimentInsightType === InsightType.TRENDS && actualRunningTime > Math.max(recommendedRunningTime, 7)) { + return ( + + Your experiment has been running long enough, but the results are still inconclusive. Continuing the + experiment is unlikely to yield significant findings. It may be time to stop this experiment. + + ) + } + + return ( + + Your experiment is live and is collecting data, but hasn't yet reached the statistical significance + needed to make reliable decisions. It's important to wait for more data to avoid premature conclusions. + + ) + } + + // Running, results significant + if (isExperimentRunning && !isExperimentStopped && areResultsSignificant && experimentResults) { + const { probability } = experimentResults + const winningVariant = getHighestProbabilityVariant(experimentResults) + if (!winningVariant) { + return <> + } + + const winProbability = probability[winningVariant] + + // Win probability only slightly over 0.9 and the recommended sample/time just met -> proceed with caution + if ( + experimentInsightType === InsightType.FUNNELS && + funnelResultsPersonsTotal > recommendedSampleSize + 50 && + winProbability < 0.93 + ) { + return ( + + You've achieved significant results, however, the sample size just meets the minimum requirements, + and the win probability is only marginally above 90%. To ensure more reliable outcomes, consider + running the experiment a bit longer. + + ) + } + + if ( + experimentInsightType === InsightType.TRENDS && + actualRunningTime > recommendedRunningTime + 2 && + winProbability < 0.93 + ) { + return ( + + You've achieved significant results, however, the running time just meets the minimum requirements, + and the win probability is only marginally above 90%. To ensure more reliable outcomes, consider + running the experiment a bit longer. + + ) + } + + return ( + + Good news! Your experiment has gathered enough data to reach statistical significance, providing + reliable results for decision making. Before taking any action, review relevant secondary metrics for + any unintended side effects. Once you're done, you can stop the experiment. + + ) + } + + // Stopped, results significant + if (isExperimentStopped && areResultsSignificant) { + return ( + + You have stopped this experiment, and it is no longer collecting data. With significant results in hand, + you can now roll out the winning variant to all your users by adjusting the{' '} + + {experiment.feature_flag?.key} + {' '} + feature flag. + + ) + } + + // Stopped, results not significant + if (isExperimentStopped && experimentResults && !areResultsSignificant) { + return ( + + You have stopped this experiment, and it is no longer collecting data. Because your results are not + significant, we don't recommend drawing any conclusions from them. You can reset the experiment + (deleting the data collected so far) and restart the experiment at any point again. If this experiment + is no longer relevant, you can{' '} + archiveExperiment()}> + archive it + + . + + ) + } + + return <> +} diff --git a/frontend/src/scenes/experiments/SecondaryMetricsTable.tsx b/frontend/src/scenes/experiments/SecondaryMetricsTable.tsx index c15b4f8293a3a..c15dd08ca88e0 100644 --- a/frontend/src/scenes/experiments/SecondaryMetricsTable.tsx +++ b/frontend/src/scenes/experiments/SecondaryMetricsTable.tsx @@ -254,7 +254,7 @@ export function SecondaryMetricsTable({ ) : ( <> )} - {metrics && !(metrics.length > 2) && isExperimentRunning && ( + {metrics && !(metrics.length > 2) && (
Add metric diff --git a/frontend/src/scenes/experiments/experimentLogic.tsx b/frontend/src/scenes/experiments/experimentLogic.tsx index 7f0946a9220d8..31de23b9d696f 100644 --- a/frontend/src/scenes/experiments/experimentLogic.tsx +++ b/frontend/src/scenes/experiments/experimentLogic.tsx @@ -80,6 +80,11 @@ export interface TabularSecondaryMetricResults { results?: SecondaryMetricResult[] } +export interface ExperimentResultCalculationError { + detail: string + statusCode: number +} + export const experimentLogic = kea([ props({} as ExperimentLogicProps), key((props) => props.experimentId || 'new'), @@ -127,7 +132,7 @@ export const experimentLogic = kea([ setExperimentExposureInsight: (filters?: Partial) => ({ filters }), removeExperimentGroup: (idx: number) => ({ idx }), setEditExperiment: (editing: boolean) => ({ editing }), - setExperimentResultCalculationError: (error: string) => ({ error }), + setExperimentResultCalculationError: (error: ExperimentResultCalculationError) => ({ error }), setFlagImplementationWarning: (warning: boolean) => ({ warning }), setExposureAndSampleSize: (exposure: number, sampleSize: number) => ({ exposure, sampleSize }), updateExperimentGoal: (filters: Partial) => ({ filters }), @@ -241,7 +246,7 @@ export const experimentLogic = kea([ }, ], experimentResultCalculationError: [ - null as string | null, + null as ExperimentResultCalculationError | null, { setExperimentResultCalculationError: (_, { error }) => error, }, @@ -630,7 +635,7 @@ export const experimentLogic = kea([ last_refresh: response.last_refresh, } } catch (error: any) { - actions.setExperimentResultCalculationError(error.detail) + actions.setExperimentResultCalculationError({ detail: error.detail, statusCode: error.status }) return null } }, @@ -1102,6 +1107,44 @@ export const experimentLogic = kea([ }) }, ], + recommendedSampleSize: [ + (s) => [s.experiment], + (experiment: Experiment): number => experiment?.parameters?.recommended_sample_size || 100, + ], + funnelResultsPersonsTotal: [ + (s) => [s.experimentResults, s.experimentInsightType], + (experimentResults: ExperimentResults['result'], experimentInsightType: InsightType): number => { + if (experimentInsightType !== InsightType.FUNNELS || !experimentResults?.insight) { + return 0 + } + + let sum = 0 + experimentResults.insight.forEach((variantResult) => { + if (variantResult[0]?.count) { + sum += variantResult[0].count + } + }) + return sum + }, + ], + actualRunningTime: [ + (s) => [s.experiment], + (experiment: Experiment): number => { + if (!experiment.start_date) { + return 0 + } + + if (experiment.end_date) { + return dayjs(experiment.end_date).diff(experiment.start_date, 'day') + } + + return dayjs().diff(experiment.start_date, 'day') + }, + ], + recommendedRunningTime: [ + (s) => [s.experiment], + (experiment: Experiment): number => experiment?.parameters?.recommended_running_time || 1, + ], }), forms(({ actions, values }) => ({ experiment: { diff --git a/frontend/src/scenes/experiments/utils.ts b/frontend/src/scenes/experiments/utils.ts index 90d7b2c64f44b..6f71d6c1829b2 100644 --- a/frontend/src/scenes/experiments/utils.ts +++ b/frontend/src/scenes/experiments/utils.ts @@ -17,3 +17,7 @@ export const transformResultFilters = (filters: Partial): Partial([ }) .filter(Boolean) as AnyPropertyFilter[] } else { - // eslint-disable-next-line @typescript-eslint/no-unused-vars const [_, propertyName, propertyValue] = correlation.event.event.split('::') properties = [ diff --git a/frontend/src/scenes/insights/filters/AggregationSelect.tsx b/frontend/src/scenes/insights/filters/AggregationSelect.tsx index 5d4d3ea6acc3c..89bd5c6f7688d 100644 --- a/frontend/src/scenes/insights/filters/AggregationSelect.tsx +++ b/frontend/src/scenes/insights/filters/AggregationSelect.tsx @@ -132,7 +132,7 @@ export function AggregationSelect({ return ( { if (newValue !== null) { diff --git a/frontend/src/scenes/pipeline/Destinations.tsx b/frontend/src/scenes/pipeline/Destinations.tsx index 58d43539499ed..a96716246a70a 100644 --- a/frontend/src/scenes/pipeline/Destinations.tsx +++ b/frontend/src/scenes/pipeline/Destinations.tsx @@ -49,13 +49,15 @@ export function Destinations(): JSX.Element { ) } -function DestinationsTable(): JSX.Element { +export function DestinationsTable({ inOverview = false }: { inOverview?: boolean }): JSX.Element { const { loading, destinations } = useValues(pipelineDestinationsLogic) + const data = inOverview ? destinations.filter((destination) => destination.enabled) : destinations + return ( <> } /> + return ( + + } + /> + ) }, }, ]} @@ -143,40 +151,42 @@ export const DestinationMoreOverlay = ({ return ( toggleEnabled(destination, !destination.enabled), + disabledReason: !canConfigurePlugins + ? 'You do not have permission to enable/disable destinations.' + : !canEnableNewDestinations && !destination.enabled + ? 'Data pipelines add-on is required for enabling new destinations' + : undefined, + }, + ...pipelineNodeMenuCommonItems(destination), ...(!inOverview ? [ { - label: destination.enabled ? 'Pause destination' : 'Unpause destination', - onClick: () => toggleEnabled(destination, !destination.enabled), - disabledReason: !canConfigurePlugins - ? 'You do not have permission to enable/disable destinations.' - : !canEnableNewDestinations && !destination.enabled - ? 'Data pipelines add-on is required for enabling new destinations' - : undefined, + label: 'Delete destination', + onClick: () => { + if (destination.backend === PipelineBackend.Plugin) { + void deleteWithUndo({ + endpoint: `plugin_config`, // TODO: Batch exports too + object: { + id: destination.id, + name: destination.name, + }, + callback: loadPluginConfigs, + }) + } else { + lemonToast.warning( + 'Deleting batch export destinations is not yet supported here.' + ) + } + }, + disabledReason: canConfigurePlugins + ? undefined + : 'You do not have permission to delete destinations.', }, ] : []), - ...pipelineNodeMenuCommonItems(destination), - { - label: 'Delete destination', - onClick: () => { - if (destination.backend === PipelineBackend.Plugin) { - void deleteWithUndo({ - endpoint: `plugin_config`, // TODO: Batch exports too - object: { - id: destination.id, - name: destination.name, - }, - callback: loadPluginConfigs, - }) - } else { - lemonToast.warning('Deleting batch export destinations is not yet supported here.') - } - }, - disabledReason: canConfigurePlugins - ? undefined - : 'You do not have permission to delete destinations.', - }, ]} /> ) diff --git a/frontend/src/scenes/pipeline/Overview.tsx b/frontend/src/scenes/pipeline/Overview.tsx index f96fd93f07bf1..5fc01f89767c7 100644 --- a/frontend/src/scenes/pipeline/Overview.tsx +++ b/frontend/src/scenes/pipeline/Overview.tsx @@ -1,161 +1,24 @@ -import { LemonCard, LemonSkeleton, LemonTag, Link } from '@posthog/lemon-ui' -import clsx from 'clsx' -import { useValues } from 'kea' -import { SeriesGlyph } from 'lib/components/SeriesGlyph' -import { More } from 'lib/lemon-ui/LemonButton/More' -import { LemonMarkdown } from 'lib/lemon-ui/LemonMarkdown' -import { PluginImage } from 'scenes/plugins/plugin/PluginImage' +import { Link } from '@posthog/lemon-ui' import { urls } from 'scenes/urls' -import { PipelineNodeTab, PipelineStage, PluginType } from '~/types' +import { PipelineTab } from '~/types' -import { AppMetricSparkLine } from './AppMetricSparkLine' -import { DestinationMoreOverlay } from './Destinations' -import { pipelineOverviewLogic } from './overviewLogic' -import { TransformationsMoreOverlay } from './Transformations' -import { pipelineTransformationsLogic } from './transformationsLogic' -import { Destination, PipelineBackend, Transformation } from './types' -import { humanFriendlyFrequencyName } from './utils' - -type PipelineStepProps = { - order?: number - name: string - to: string - description?: string - headerInfo: JSX.Element - additionalInfo?: JSX.Element - plugin?: PluginType | null -} - -const PipelineStep = ({ - order, - name, - to, - description, - headerInfo, - additionalInfo, - plugin, -}: PipelineStepProps): JSX.Element => ( - - {order !== undefined && ( -
- - {order} - -
- )} - -
-
- {plugin && } -

- - {name} - -

-
- -
{headerInfo}
-
- {description ? ( - - {description} - - ) : ( - No description. - )} - {additionalInfo &&
{additionalInfo}
} -
-) - -const PipelineStepSkeleton = (): JSX.Element => ( - - - - - -) - -const PipelineStepTransformation = ({ transformation }: { transformation: Transformation }): JSX.Element => { - const { sortedEnabledTransformations } = useValues(pipelineTransformationsLogic) - - return ( - pc.id === transformation.id) + 1} - name={transformation.name} - to={urls.pipelineNode(PipelineStage.Transformation, transformation.id, PipelineNodeTab.Configuration)} - description={transformation.description} - headerInfo={ - <> -
- -
- } /> - - } - plugin={transformation.plugin} - /> - ) -} - -const PipelineStepDestination = ({ destination }: { destination: Destination }): JSX.Element => { - return ( - -
- -
- } /> - - } - additionalInfo={ -
- {humanFriendlyFrequencyName(destination.interval)} -
- } - plugin={destination.backend === PipelineBackend.Plugin ? destination.plugin : undefined} - /> - ) -} +import { DestinationsTable } from './Destinations' +import { TransformationsTable } from './Transformations' export function Overview(): JSX.Element { - const { transformations, destinations, transformationsLoading, destinationsLoading } = - useValues(pipelineOverviewLogic) - return (

Transformations

-
- {transformationsLoading ? ( - - ) : ( - transformations && - transformations - .filter((t) => t.enabled) - .map((t) => ) - )} -
- + Showing only enabled, go to + Transformations tab + {' '} + to see all. +

Destinations

-
- {destinationsLoading ? ( - - ) : ( - destinations && - destinations - .filter((d) => d.enabled) - .map((d) => ) - )} -
+ Showing only active, go to Destinations tab to see + all. +
) } diff --git a/frontend/src/scenes/pipeline/Transformations.tsx b/frontend/src/scenes/pipeline/Transformations.tsx index 5049a41d43187..9f934cb6c3371 100644 --- a/frontend/src/scenes/pipeline/Transformations.tsx +++ b/frontend/src/scenes/pipeline/Transformations.tsx @@ -25,13 +25,8 @@ export function Transformations(): JSX.Element { if (!featureFlags[FEATURE_FLAGS.PIPELINE_UI]) { return

Pipeline 3000 not available yet

} - const { - loading, - sortedTransformations, - sortedEnabledTransformations, - canConfigurePlugins, - shouldShowProductIntroduction, - } = useValues(pipelineTransformationsLogic) + const { sortedEnabledTransformations, canConfigurePlugins, shouldShowProductIntroduction } = + useValues(pipelineTransformationsLogic) const { openReorderModal } = useActions(pipelineTransformationsLogic) const shouldShowEmptyState = sortedEnabledTransformations.length === 0 @@ -49,64 +44,73 @@ export function Transformations(): JSX.Element { isEmpty={true} /> )} - {!shouldShowEmptyState && ( + {sortedEnabledTransformations.length > 1 && ( // Only show rearranging if there's more then 1 sortable app <> - {sortedEnabledTransformations.length > 1 && ( // Only show rearranging if there's more then 1 sortable app - <> - -
- Processed sequentially. - - Change order - -
- - )} - t.id === transformation.id) + 1 - }, - }, - nameColumn() as LemonTableColumn, - appColumn() as LemonTableColumn, - updatedAtColumn() as LemonTableColumn, - statusColumn() as LemonTableColumn, - { - width: 0, - render: function Render(_, transformation) { - return ( - } - /> - ) - }, - }, - ]} - /> + +
+ Processed sequentially. + + Change order + +
)} + + + ) +} + +export function TransformationsTable({ inOverview = false }: { inOverview?: boolean }): JSX.Element { + const { loading, sortedTransformations, sortedEnabledTransformations } = useValues(pipelineTransformationsLogic) + + return ( + <> + t.id === transformation.id) + 1 + }, + }, + nameColumn() as LemonTableColumn, + appColumn() as LemonTableColumn, + updatedAtColumn() as LemonTableColumn, + statusColumn() as LemonTableColumn, + { + width: 0, + render: function Render(_, transformation) { + return ( + + } + /> + ) + }, + }, + ]} + /> ) } diff --git a/frontend/src/scenes/pipeline/utils.tsx b/frontend/src/scenes/pipeline/utils.tsx index f64415f8d420f..c5fc67b80e234 100644 --- a/frontend/src/scenes/pipeline/utils.tsx +++ b/frontend/src/scenes/pipeline/utils.tsx @@ -320,21 +320,15 @@ export function pipelinePluginBackedNodeMenuCommonItems( const { canConfigurePlugins } = useValues(pipelineTransformationsLogic) return [ - ...(!inOverview - ? [ - { - label: node.enabled ? 'Disable app' : 'Enable app', - onClick: () => - toggleEnabled({ - enabled: !node.enabled, - id: node.id, - }), - disabledReason: canConfigurePlugins - ? undefined - : 'You do not have permission to enable/disable apps.', - }, - ] - : []), + { + label: node.enabled ? 'Disable app' : 'Enable app', + onClick: () => + toggleEnabled({ + enabled: !node.enabled, + id: node.id, + }), + disabledReason: canConfigurePlugins ? undefined : 'You do not have permission to enable/disable apps.', + }, ...pipelineNodeMenuCommonItems(node), ...(!inOverview ? [ diff --git a/frontend/src/scenes/sceneTypes.ts b/frontend/src/scenes/sceneTypes.ts index 0da4b8a1825cd..cf6c7a80fa2ec 100644 --- a/frontend/src/scenes/sceneTypes.ts +++ b/frontend/src/scenes/sceneTypes.ts @@ -23,6 +23,7 @@ export enum Scene { Replay = 'Replay', ReplaySingle = 'ReplaySingle', ReplayPlaylist = 'ReplayPlaylist', + ReplayFilePlayback = 'ReplayFilePlayback', PersonsManagement = 'PersonsManagement', Person = 'Person', Pipeline = 'Pipeline', diff --git a/frontend/src/scenes/scenes.ts b/frontend/src/scenes/scenes.ts index b6d7424861089..44e1d8f7efd59 100644 --- a/frontend/src/scenes/scenes.ts +++ b/frontend/src/scenes/scenes.ts @@ -136,6 +136,12 @@ export const sceneConfigurations: Record = { activityScope: ActivityScope.REPLAY, defaultDocsPath: '/docs/session-replay', }, + [Scene.ReplayFilePlayback]: { + projectBased: true, + name: 'File playback', + activityScope: ActivityScope.REPLAY, + defaultDocsPath: '/docs/session-replay', + }, [Scene.Person]: { projectBased: true, name: 'Person', @@ -436,6 +442,7 @@ export const redirects: Record< '/annotations/:id': ({ id }) => urls.annotation(id), '/recordings/:id': ({ id }) => urls.replaySingle(id), '/recordings/playlists/:id': ({ id }) => urls.replayPlaylist(id), + '/recordings/file-playback': () => urls.replayFilePlayback(), '/recordings': (_params, _searchParams, hashParams) => { if (hashParams.sessionRecordingId) { // Previous URLs for an individual recording were like: /recordings/#sessionRecordingId=foobar @@ -494,6 +501,7 @@ export const routes: Record = { acc[urls.replay(tab)] = Scene.Replay return acc }, {} as Record), + [urls.replayFilePlayback()]: Scene.ReplayFilePlayback, [urls.replaySingle(':id')]: Scene.ReplaySingle, [urls.replayPlaylist(':id')]: Scene.ReplayPlaylist, [urls.personByDistinctId('*', false)]: Scene.Person, diff --git a/frontend/src/scenes/session-recordings/SessionRecordings.tsx b/frontend/src/scenes/session-recordings/SessionRecordings.tsx index 383a0f27a5073..7084e9649b48e 100644 --- a/frontend/src/scenes/session-recordings/SessionRecordings.tsx +++ b/frontend/src/scenes/session-recordings/SessionRecordings.tsx @@ -1,5 +1,5 @@ -import { IconGear } from '@posthog/icons' -import { LemonButton } from '@posthog/lemon-ui' +import { IconEllipsis, IconGear } from '@posthog/icons' +import { LemonButton, LemonMenu } from '@posthog/lemon-ui' import { useActions, useValues } from 'kea' import { router } from 'kea-router' import { authorizedUrlListLogic, AuthorizedUrlListType } from 'lib/components/AuthorizedUrlList/authorizedUrlListLogic' @@ -22,7 +22,6 @@ import { sidePanelSettingsLogic } from '~/layout/navigation-3000/sidepanel/panel import { AvailableFeature, NotebookNodeType, ReplayTabs } from '~/types' import { SessionRecordingErrors } from './errors/SessionRecordingErrors' -import { SessionRecordingFilePlayback } from './file-playback/SessionRecordingFilePlayback' import { createPlaylist } from './playlist/playlistUtils' import { SessionRecordingsPlaylist } from './playlist/SessionRecordingsPlaylist' import { SavedSessionRecordingPlaylists } from './saved-playlists/SavedSessionRecordingPlaylists' @@ -66,6 +65,16 @@ export function SessionsRecordings(): JSX.Element { <> {tab === ReplayTabs.Recent && !recordingsDisabled && ( <> + + } /> + ) : tab === ReplayTabs.Playlists ? ( - ) : tab === ReplayTabs.FilePlayback ? ( - ) : tab === ReplayTabs.Errors ? ( ) : null} diff --git a/frontend/src/scenes/session-recordings/__mocks__/recording_snapshots.ts b/frontend/src/scenes/session-recordings/__mocks__/recording_snapshots.ts index 9cc60a88fb8e4..1e73cc1c8d4c3 100644 --- a/frontend/src/scenes/session-recordings/__mocks__/recording_snapshots.ts +++ b/frontend/src/scenes/session-recordings/__mocks__/recording_snapshots.ts @@ -27,7 +27,7 @@ export const convertSnapshotsResponse = ( snapshotsByWindowId: { [key: string]: eventWithTime[] }, existingSnapshots?: RecordingSnapshot[] ): RecordingSnapshot[] => { - return deduplicateSnapshots(convertSnapshotsByWindowId(snapshotsByWindowId), existingSnapshots) + return deduplicateSnapshots([...convertSnapshotsByWindowId(snapshotsByWindowId), ...(existingSnapshots ?? [])]) } export const sortedRecordingSnapshots = (): { snapshot_data_by_window_id: Record } => { diff --git a/frontend/src/scenes/session-recordings/file-playback/SessionRecordingFilePlayback.tsx b/frontend/src/scenes/session-recordings/file-playback/SessionRecordingFilePlaybackScene.tsx similarity index 87% rename from frontend/src/scenes/session-recordings/file-playback/SessionRecordingFilePlayback.tsx rename to frontend/src/scenes/session-recordings/file-playback/SessionRecordingFilePlaybackScene.tsx index c5ed669625a11..5a67f49d9aae0 100644 --- a/frontend/src/scenes/session-recordings/file-playback/SessionRecordingFilePlayback.tsx +++ b/frontend/src/scenes/session-recordings/file-playback/SessionRecordingFilePlaybackScene.tsx @@ -5,16 +5,22 @@ import { LemonBanner } from 'lib/lemon-ui/LemonBanner' import { LemonFileInput } from 'lib/lemon-ui/LemonFileInput' import { SpinnerOverlay } from 'lib/lemon-ui/Spinner/Spinner' import { useRef } from 'react' +import { SceneExport } from 'scenes/sceneTypes' import { userLogic } from 'scenes/userLogic' import { AvailableFeature } from '~/types' import { SessionRecordingPlayer } from '../player/SessionRecordingPlayer' -import { sessionRecordingFilePlaybackLogic } from './sessionRecordingFilePlaybackLogic' +import { sessionRecordingFilePlaybackSceneLogic } from './sessionRecordingFilePlaybackSceneLogic' -export function SessionRecordingFilePlayback(): JSX.Element { - const { loadFromFile, resetSessionRecording } = useActions(sessionRecordingFilePlaybackLogic) - const { sessionRecording, sessionRecordingLoading, playerKey } = useValues(sessionRecordingFilePlaybackLogic) +export const scene: SceneExport = { + component: SessionRecordingFilePlaybackScene, + logic: sessionRecordingFilePlaybackSceneLogic, +} + +export function SessionRecordingFilePlaybackScene(): JSX.Element { + const { loadFromFile, resetSessionRecording } = useActions(sessionRecordingFilePlaybackSceneLogic) + const { sessionRecording, sessionRecordingLoading, playerKey } = useValues(sessionRecordingFilePlaybackSceneLogic) const { hasAvailableFeature } = useValues(userLogic) const filePlaybackEnabled = hasAvailableFeature(AvailableFeature.RECORDINGS_FILE_EXPORT) diff --git a/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.test.ts b/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackSceneLogic.test.ts similarity index 76% rename from frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.test.ts rename to frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackSceneLogic.test.ts index 05b3265f43757..7c27f8cd7dd12 100644 --- a/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.test.ts +++ b/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackSceneLogic.test.ts @@ -2,10 +2,10 @@ import { expectLogic } from 'kea-test-utils' import { initKeaTests } from '~/test/init' -import { sessionRecordingFilePlaybackLogic } from './sessionRecordingFilePlaybackLogic' +import { sessionRecordingFilePlaybackSceneLogic } from './sessionRecordingFilePlaybackSceneLogic' describe('sessionRecordingFilePlaybackLogic', () => { - let logic: ReturnType + let logic: ReturnType beforeEach(() => { initKeaTests() @@ -13,7 +13,7 @@ describe('sessionRecordingFilePlaybackLogic', () => { describe('file-playback logic', () => { beforeEach(() => { - logic = sessionRecordingFilePlaybackLogic() + logic = sessionRecordingFilePlaybackSceneLogic() logic.mount() }) diff --git a/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.ts b/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackSceneLogic.ts similarity index 84% rename from frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.ts rename to frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackSceneLogic.ts index 2c3ab70fab516..30109a3936a2a 100644 --- a/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.ts +++ b/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackSceneLogic.ts @@ -9,7 +9,7 @@ import { eventUsageLogic } from 'lib/utils/eventUsageLogic' import { Scene } from 'scenes/sceneTypes' import { urls } from 'scenes/urls' -import { Breadcrumb, ReplayTabs } from '~/types' +import { Breadcrumb } from '~/types' import { deduplicateSnapshots, @@ -17,28 +17,9 @@ import { sessionRecordingDataLogic, } from '../player/sessionRecordingDataLogic' import type { sessionRecordingDataLogicType } from '../player/sessionRecordingDataLogicType' -import type { sessionRecordingFilePlaybackLogicType } from './sessionRecordingFilePlaybackLogicType' +import type { sessionRecordingFilePlaybackSceneLogicType } from './sessionRecordingFilePlaybackSceneLogicType' import { ExportedSessionRecordingFileV1, ExportedSessionRecordingFileV2 } from './types' -export const createExportedSessionRecording = ( - logic: BuiltLogic, - // DEBUG signal only, to be removed before release - exportUntransformedMobileSnapshotData: boolean -): ExportedSessionRecordingFileV2 => { - const { sessionPlayerMetaData, sessionPlayerSnapshotData } = logic.values - - return { - version: '2023-04-28', - data: { - id: sessionPlayerMetaData?.id ?? '', - person: sessionPlayerMetaData?.person, - snapshots: exportUntransformedMobileSnapshotData - ? sessionPlayerSnapshotData?.untransformed_snapshots || [] - : sessionPlayerSnapshotData?.snapshots || [], - }, - } -} - export const parseExportedSessionRecording = (fileData: string): ExportedSessionRecordingFileV2 => { const data = JSON.parse(fileData) as ExportedSessionRecordingFileV1 | ExportedSessionRecordingFileV2 @@ -103,8 +84,8 @@ const waitForDataLogic = async (playerKey: string): Promise([ - path(['scenes', 'session-recordings', 'detail', 'sessionRecordingFilePlaybackLogic']), +export const sessionRecordingFilePlaybackSceneLogic = kea([ + path(['scenes', 'session-recordings', 'detail', 'sessionRecordingFilePlaybackSceneLogic']), connect({ actions: [eventUsageLogic, ['reportRecordingLoadedFromFile']], values: [featureFlagLogic, ['featureFlags']], @@ -163,9 +144,13 @@ export const sessionRecordingFilePlaybackLogic = kea [ { key: Scene.Replay, - name: 'Session replay', + name: 'Replay', path: urls.replay(), }, { - key: ReplayTabs.FilePlayback, - name: 'Import', + key: Scene.ReplayFilePlayback, + name: 'File playback', + path: urls.replayFilePlayback(), }, ], ], diff --git a/frontend/src/scenes/session-recordings/player/inspector/playerInspectorLogic.ts b/frontend/src/scenes/session-recordings/player/inspector/playerInspectorLogic.ts index 09ebe7988bc3e..91bdd827c65b6 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/playerInspectorLogic.ts +++ b/frontend/src/scenes/session-recordings/player/inspector/playerInspectorLogic.ts @@ -172,7 +172,7 @@ export const playerInspectorLogic = kea([ [ 'sessionPlayerData', 'sessionPlayerMetaDataLoading', - 'sessionPlayerSnapshotDataLoading', + 'snapshotsLoading', 'sessionEventsData', 'sessionEventsDataLoading', 'windowIds', @@ -856,7 +856,7 @@ export const playerInspectorLogic = kea([ (s) => [ s.sessionEventsDataLoading, s.sessionPlayerMetaDataLoading, - s.sessionPlayerSnapshotDataLoading, + s.snapshotsLoading, s.sessionEventsData, s.consoleLogs, s.allPerformanceEvents, @@ -865,7 +865,7 @@ export const playerInspectorLogic = kea([ ( sessionEventsDataLoading, sessionPlayerMetaDataLoading, - sessionPlayerSnapshotDataLoading, + snapshotsLoading, events, logs, performanceEvents, @@ -873,19 +873,19 @@ export const playerInspectorLogic = kea([ ): Record => { const tabEventsState = sessionEventsDataLoading ? 'loading' : events?.length ? 'ready' : 'empty' const tabConsoleState = - sessionPlayerMetaDataLoading || sessionPlayerSnapshotDataLoading || !logs + sessionPlayerMetaDataLoading || snapshotsLoading || !logs ? 'loading' : logs.length ? 'ready' : 'empty' const tabNetworkState = - sessionPlayerMetaDataLoading || sessionPlayerSnapshotDataLoading || !performanceEvents + sessionPlayerMetaDataLoading || snapshotsLoading || !performanceEvents ? 'loading' : performanceEvents.length ? 'ready' : 'empty' const tabDoctorState = - sessionPlayerMetaDataLoading || sessionPlayerSnapshotDataLoading || !performanceEvents + sessionPlayerMetaDataLoading || snapshotsLoading || !performanceEvents ? 'loading' : doctorEvents.length ? 'ready' diff --git a/frontend/src/scenes/session-recordings/player/modal/sessionPlayerModalLogic.ts b/frontend/src/scenes/session-recordings/player/modal/sessionPlayerModalLogic.ts index 6b70ccbd939d3..09bf3758b10fd 100644 --- a/frontend/src/scenes/session-recordings/player/modal/sessionPlayerModalLogic.ts +++ b/frontend/src/scenes/session-recordings/player/modal/sessionPlayerModalLogic.ts @@ -42,9 +42,7 @@ export const sessionPlayerModalLogic = kea([ ], }), actionToUrl(({ values }) => { - const buildURL = ( - replace: boolean - ): [ + const buildURL = (): [ string, Record, Record, @@ -71,12 +69,12 @@ export const sessionPlayerModalLogic = kea([ searchParams.timestamp = values.initialTimestamp } - return [router.values.location.pathname, searchParams, hashParams, { replace }] + return [router.values.location.pathname, searchParams, hashParams, { replace: true }] } return { - openSessionPlayer: () => buildURL(false), - closeSessionPlayer: () => buildURL(false), + openSessionPlayer: () => buildURL(), + closeSessionPlayer: () => buildURL(), } }), urlToAction(({ actions, values }) => { diff --git a/frontend/src/scenes/session-recordings/player/rrweb/canvas/canvas-plugin.ts b/frontend/src/scenes/session-recordings/player/rrweb/canvas/canvas-plugin.ts index e2d608d8ad701..1325e071eeba2 100644 --- a/frontend/src/scenes/session-recordings/player/rrweb/canvas/canvas-plugin.ts +++ b/frontend/src/scenes/session-recordings/player/rrweb/canvas/canvas-plugin.ts @@ -74,8 +74,8 @@ export const CanvasReplayerPlugin = (events: eventWithTime[]): ReplayPlugin => { return } - target.width = source.width - target.height = source.height + target.width = source.clientWidth + target.height = source.clientHeight await canvasMutation({ event: e, diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts index 9262eb2f4d956..f0b310bf748f2 100644 --- a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts +++ b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts @@ -30,14 +30,12 @@ const BLOB_SOURCE: SessionRecordingSnapshotSource = { start_timestamp: '2023-08-11T12:03:36.097000Z', end_timestamp: '2023-08-11T12:04:52.268000Z', blob_key: '1691755416097-1691755492268', - loaded: false, } const REALTIME_SOURCE: SessionRecordingSnapshotSource = { source: 'realtime', start_timestamp: '2024-01-28T21:19:49.217000Z', end_timestamp: undefined, blob_key: undefined, - loaded: false, } describe('sessionRecordingDataLogic', () => { @@ -115,11 +113,14 @@ describe('sessionRecordingDataLogic', () => { it('loads all data', async () => { await expectLogic(logic, () => { logic.actions.loadRecordingMeta() - logic.actions.loadRecordingSnapshots() + logic.actions.loadSnapshots() }) .toDispatchActions([ + 'loadSnapshots', + 'loadSnapshotSources', 'loadRecordingMetaSuccess', - 'loadRecordingSnapshotsSuccess', + 'loadSnapshotSourcesSuccess', + 'loadSnapshotsForSourceSuccess', 'reportUsageIfFullyLoaded', ]) .toFinishAllListeners() @@ -174,9 +175,9 @@ describe('sessionRecordingDataLogic', () => { }) logic.mount() logic.actions.loadRecordingMeta() - logic.actions.loadRecordingSnapshots() + logic.actions.loadSnapshots() - await expectLogic(logic).toDispatchActions(['loadRecordingMetaSuccess', 'loadRecordingSnapshotsFailure']) + await expectLogic(logic).toDispatchActions(['loadRecordingMetaSuccess', 'loadSnapshotSourcesFailure']) expect(logic.values.sessionPlayerData).toMatchObject({ person: recordingMetaJson.person, durationMs: 11868, @@ -219,7 +220,7 @@ describe('sessionRecordingDataLogic', () => { }) await expectLogic(logic, () => { - logic.actions.loadRecordingSnapshots() + logic.actions.loadSnapshots() }).toDispatchActions(['loadEvents', 'loadEventsSuccess']) expect(api.create).toHaveBeenCalledWith( @@ -255,11 +256,11 @@ describe('sessionRecordingDataLogic', () => { describe('report usage', () => { it('sends `recording loaded` event only when entire recording has loaded', async () => { await expectLogic(logic, () => { - logic.actions.loadRecordingSnapshots() + logic.actions.loadSnapshots() }) .toDispatchActionsInAnyOrder([ - 'loadRecordingSnapshots', - 'loadRecordingSnapshotsSuccess', + 'loadSnapshots', + 'loadSnapshotsForSourceSuccess', 'loadEvents', 'loadEventsSuccess', ]) @@ -267,9 +268,9 @@ describe('sessionRecordingDataLogic', () => { }) it('sends `recording viewed` and `recording analyzed` event on first contentful paint', async () => { await expectLogic(logic, () => { - logic.actions.loadRecordingSnapshots() + logic.actions.loadSnapshots() }) - .toDispatchActions(['loadRecordingSnapshotsSuccess']) + .toDispatchActions(['loadSnapshotsForSourceSuccess']) .toDispatchActionsInAnyOrder([ eventUsageLogic.actionTypes.reportRecording, // loaded eventUsageLogic.actionTypes.reportRecording, // viewed @@ -278,7 +279,7 @@ describe('sessionRecordingDataLogic', () => { }) it('clears the cache after unmounting', async () => { await expectLogic(logic, () => { - logic.actions.loadRecordingSnapshots() + logic.actions.loadSnapshots() }) expect(Object.keys(logic.cache)).toEqual( expect.arrayContaining(['metaStartTime', 'snapshotsStartTime', 'eventsStartTime']) @@ -326,7 +327,9 @@ describe('sessionRecordingDataLogic', () => { }, ] // we call this multiple times and pass existing data in, so we need to make sure it doesn't change - expect(deduplicateSnapshots(verySimilarSnapshots, verySimilarSnapshots)).toEqual(verySimilarSnapshots) + expect(deduplicateSnapshots([...verySimilarSnapshots, ...verySimilarSnapshots])).toEqual( + verySimilarSnapshots + ) }) it('should match snapshot', () => { @@ -351,66 +354,68 @@ describe('sessionRecordingDataLogic', () => { it('loads each source, and on success reports recording viewed', async () => { await expectLogic(logic, () => { - logic.actions.loadRecordingSnapshots() - // loading the snapshots will trigger a loadRecordingSnapshotsSuccess + logic.actions.loadSnapshots() + // loading the snapshots will trigger a loadSnapshotsForSourceSuccess // that will have the blob source - // that triggers loadRecordingSnapshots + // that triggers loadNextSnapshotSource }).toDispatchActions([ // the action we triggered - logic.actionCreators.loadRecordingSnapshots(), - 'loadRecordingSnapshotsSuccess', + 'loadSnapshots', // the response to that triggers loading of the first item which is the blob source (action) => - action.type === logic.actionTypes.loadRecordingSnapshots && + action.type === logic.actionTypes.loadSnapshotsForSource && action.payload.source?.source === 'blob', - 'loadRecordingSnapshotsSuccess', + 'loadSnapshotsForSourceSuccess', // and then we report having viewed the recording 'reportViewed', // the response to the success action triggers loading of the second item which is the realtime source (action) => - action.type === logic.actionTypes.loadRecordingSnapshots && + action.type === logic.actionTypes.loadSnapshotsForSource && action.payload.source?.source === 'realtime', - 'loadRecordingSnapshotsSuccess', + 'loadSnapshotsForSourceSuccess', // having loaded any real time data we start polling to check for more - 'startRealTimePolling', + 'pollRealtimeSnapshots', + // which in turn triggers another load + (action) => + action.type === logic.actionTypes.loadSnapshotsForSource && + action.payload.source?.source === 'realtime', + 'loadSnapshotsForSourceSuccess', ]) }) - it('can start polling for snapshots', async () => { + it('polls up to a max threshold', async () => { await expectLogic(logic, () => { - logic.actions.startRealTimePolling() + logic.actions.loadSnapshots() }) .toDispatchActions([ - // the action we triggered - 'startRealTimePolling', - 'pollRecordingSnapshots', // 0 - 'pollRecordingSnapshotsSuccess', + 'loadSnapshotsForSource', // blob + 'loadSnapshotsForSourceSuccess', // the returned data isn't changing from our mock, // so we'll not keep polling indefinitely - 'pollRecordingSnapshots', // 1 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 2 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 3 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 4 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 5 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 6 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 7 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 8 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 9 - 'pollRecordingSnapshotsSuccess', - 'pollRecordingSnapshots', // 10 - 'pollRecordingSnapshotsSuccess', + 'loadSnapshotsForSource', // 1 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 2 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 3 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 4 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 5 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 6 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 7 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 8 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 9 + 'loadSnapshotsForSourceSuccess', + 'loadSnapshotsForSource', // 10 + 'loadSnapshotsForSourceSuccess', ]) .toNotHaveDispatchedActions([ // this isn't called again - 'pollRecordingSnapshots', + 'loadSnapshotsForSource', ]) await waitForExpect(() => { @@ -433,12 +438,14 @@ describe('sessionRecordingDataLogic', () => { it('should start polling even though realtime is empty', async () => { await expectLogic(logic, () => { - logic.actions.loadRecordingSnapshots() + logic.actions.loadSnapshots() }).toDispatchActions([ - 'loadRecordingSnapshotsSuccess', - 'startRealTimePolling', - 'pollRecordingSnapshots', - 'pollRecordingSnapshotsSuccess', + 'loadSnapshots', + 'loadSnapshotSourcesSuccess', + 'loadNextSnapshotSource', + 'pollRealtimeSnapshots', + 'loadSnapshotsForSource', + 'loadSnapshotsForSourceSuccess', ]) }) }) diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts index d71d860d5a568..f986818ecf485 100644 --- a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts +++ b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts @@ -5,7 +5,6 @@ import { actions, afterMount, beforeUnmount, - BreakPointFunction, connect, defaults, kea, @@ -38,15 +37,16 @@ import { RecordingSegment, RecordingSnapshot, SessionPlayerData, - SessionPlayerSnapshotData, SessionRecordingId, SessionRecordingSnapshotSource, + SessionRecordingSnapshotSourceResponse, SessionRecordingType, SessionRecordingUsageType, SnapshotSourceType, } from '~/types' import { PostHogEE } from '../../../../@posthog/ee/types' +import { ExportedSessionRecordingFileV2 } from '../file-playback/types' import type { sessionRecordingDataLogicType } from './sessionRecordingDataLogicType' import { createSegments, mapSnapshotsToWindowId } from './utils/segmenter' @@ -143,14 +143,10 @@ const cyrb53 = function (str: string, seed = 0): number { return 4294967296 * (2097151 & h2) + (h1 >>> 0) } -export const deduplicateSnapshots = ( - newSnapshots?: RecordingSnapshot[], - existingSnapshots?: RecordingSnapshot[] -): RecordingSnapshot[] => { +export const deduplicateSnapshots = (snapshots: RecordingSnapshot[] | null): RecordingSnapshot[] => { const seenHashes: Set = new Set() - return (newSnapshots || []) - .concat(existingSnapshots ? existingSnapshots ?? [] : []) + return (snapshots ?? []) .filter((snapshot) => { // For a multitude of reasons, there can be duplicate snapshots in the same recording. // we have to stringify the snapshot to compare it to other snapshots. @@ -230,30 +226,27 @@ function makeEventsQuery( async function processEncodedResponse( encodedResponse: (EncodedRecordingSnapshot | string)[], props: SessionRecordingDataLogicProps, - existingData: SessionPlayerSnapshotData | null, featureFlags: FeatureFlagsSet ): Promise<{ transformed: RecordingSnapshot[]; untransformed: RecordingSnapshot[] | null }> { let untransformed: RecordingSnapshot[] | null = null - const transformed = deduplicateSnapshots( - await parseEncodedSnapshots(encodedResponse, props.sessionRecordingId), - existingData?.snapshots ?? [] - ) + const transformed = await parseEncodedSnapshots(encodedResponse, props.sessionRecordingId) if (featureFlags[FEATURE_FLAGS.SESSION_REPLAY_EXPORT_MOBILE_DATA]) { - untransformed = deduplicateSnapshots( - await parseEncodedSnapshots( - encodedResponse, - props.sessionRecordingId, - false // don't transform mobile data - ), - existingData?.untransformed_snapshots ?? [] + untransformed = await parseEncodedSnapshots( + encodedResponse, + props.sessionRecordingId, + false // don't transform mobile data ) } return { transformed, untransformed } } +const getSourceKey = (source: SessionRecordingSnapshotSource): string => { + return `${source.source}-${source.blob_key}` +} + export const sessionRecordingDataLogic = kea([ path((key) => ['scenes', 'session-recordings', 'sessionRecordingDataLogic', key]), props({} as SessionRecordingDataLogicProps), @@ -269,24 +262,19 @@ export const sessionRecordingDataLogic = kea([ setFilters: (filters: Partial) => ({ filters }), loadRecordingMeta: true, maybeLoadRecordingMeta: true, - loadRecordingSnapshots: (source?: SessionRecordingSnapshotSource) => ({ source }), + loadSnapshots: true, + loadSnapshotSources: true, + loadNextSnapshotSource: true, + loadSnapshotsForSource: (source: Pick) => ({ source }), loadEvents: true, loadFullEventData: (event: RecordingEventType) => ({ event }), reportViewed: true, reportUsageIfFullyLoaded: true, persistRecording: true, maybePersistRecording: true, - startRealTimePolling: true, - pollRecordingSnapshots: true, - pollingLoadedNoNewData: true, + pollRealtimeSnapshots: true, }), reducers(() => ({ - unnecessaryPollingCount: [ - 0, - { - pollingLoadedNoNewData: (state) => state + 1, - }, - ], filters: [ {} as Partial, { @@ -301,143 +289,21 @@ export const sessionRecordingDataLogic = kea([ loadRecordingMetaFailure: () => true, }, ], - snapshotsLoaded: [ - false as boolean, + snapshotsBySource: [ + null as Record | null, { - loadRecordingSnapshotsSuccess: () => true, - loadRecordingSnapshotsFailure: () => true, - }, - ], - })), - listeners(({ values, actions, cache, props }) => ({ - pollRecordingSnapshotsSuccess: () => { - // always make sure we've cleared up the last timeout - clearTimeout(cache.realTimePollingTimeoutID) - cache.realTimePollingTimeoutID = null - - // ten is an arbitrary limit to try to avoid sending requests to our backend unnecessarily - // we could change this or add to it e.g. only poll if browser is visible to user - if (values.unnecessaryPollingCount <= 10) { - cache.realTimePollingTimeoutID = setTimeout(() => { - actions.pollRecordingSnapshots() - }, props.realTimePollingIntervalMilliseconds || DEFAULT_REALTIME_POLLING_MILLIS) - } - }, - startRealTimePolling: () => { - if (cache.realTimePollingTimeoutID) { - clearTimeout(cache.realTimePollingTimeoutID) - } - - cache.realTimePollingTimeoutID = setTimeout(() => { - actions.pollRecordingSnapshots() - }, props.realTimePollingIntervalMilliseconds || DEFAULT_REALTIME_POLLING_MILLIS) - }, - maybeLoadRecordingMeta: () => { - if (!values.sessionPlayerMetaDataLoading) { - actions.loadRecordingMeta() - } - }, - loadRecordingSnapshots: () => { - actions.loadEvents() - }, - loadRecordingMetaSuccess: () => { - cache.metadataLoadDuration = Math.round(performance.now() - cache.metaStartTime) - actions.reportUsageIfFullyLoaded() - }, - loadRecordingMetaFailure: () => { - cache.metadataLoadDuration = Math.round(performance.now() - cache.metaStartTime) - }, - loadRecordingSnapshotsSuccess: () => { - const { snapshots, sources } = values.sessionPlayerSnapshotData ?? {} - if (snapshots) { - if (!snapshots.length && sources?.length === 1) { - // We got only a single source to load, loaded it successfully, but it had no snapshots. - posthog.capture('recording_snapshots_v2_empty_response', { - source: sources[0], - }) + loadSnapshotsForSourceSuccess: (state, { snapshotsForSource }) => { + const sourceKey = getSourceKey(snapshotsForSource.source) - // If we only have a realtime source and its empty, start polling it anyway - if (sources[0].source === SnapshotSourceType.realtime) { - actions.startRealTimePolling() + return { + ...state, + [sourceKey]: snapshotsForSource, } - - return - } - - if (!cache.firstPaintDuration) { - cache.firstPaintDuration = Math.round(performance.now() - cache.snapshotsStartTime) - actions.reportViewed() - } - } - - const nextSourceToLoad = sources?.find((s) => !s.loaded) - - if (nextSourceToLoad) { - actions.loadRecordingSnapshots(nextSourceToLoad) - } else { - cache.snapshotsLoadDuration = Math.round(performance.now() - cache.snapshotsStartTime) - actions.reportUsageIfFullyLoaded() - - // If we have a realtime source, start polling it - const realTimeSource = sources?.find((s) => s.source === SnapshotSourceType.realtime) - if (realTimeSource) { - actions.startRealTimePolling() - } - } - }, - loadRecordingSnapshotsFailure: () => { - cache.snapshotsLoadDuration = Math.round(performance.now() - cache.snapshotsStartTime) - }, - loadEventsSuccess: () => { - cache.eventsLoadDuration = Math.round(performance.now() - cache.eventsStartTime) - actions.reportUsageIfFullyLoaded() - }, - loadEventsFailure: () => { - cache.eventsLoadDuration = Math.round(performance.now() - cache.eventsStartTime) - }, - reportUsageIfFullyLoaded: (_, breakpoint) => { - breakpoint() - if (values.fullyLoaded) { - eventUsageLogic.actions.reportRecording( - values.sessionPlayerData, - generateRecordingReportDurations(cache), - SessionRecordingUsageType.LOADED, - 0 - ) - // Reset cache now that final usage report has been sent - resetTimingsCache(cache) - } - }, - reportViewed: async (_, breakpoint) => { - const durations = generateRecordingReportDurations(cache) - breakpoint() - // Triggered on first paint - eventUsageLogic.actions.reportRecording( - values.sessionPlayerData, - durations, - SessionRecordingUsageType.VIEWED, - 0 - ) - await breakpoint(IS_TEST_MODE ? 1 : 10000) - eventUsageLogic.actions.reportRecording( - values.sessionPlayerData, - durations, - SessionRecordingUsageType.ANALYZED, - 10 - ) - }, - - maybePersistRecording: () => { - if (values.sessionPlayerMetaDataLoading) { - return - } - - if (values.sessionPlayerMetaData?.storage === 'object_storage') { - actions.persistRecording() - } - }, + }, + }, + ], })), - loaders(({ values, props, cache, actions }) => ({ + loaders(({ values, props, cache }) => ({ sessionPlayerMetaData: { loadRecordingMeta: async (_, breakpoint) => { if (!props.sessionRecordingId) { @@ -467,42 +333,27 @@ export const sessionRecordingDataLogic = kea([ } }, }, - sessionPlayerSnapshotData: [ - null as SessionPlayerSnapshotData | null, + snapshotSources: [ + null as SessionRecordingSnapshotSource[] | null, { - pollRecordingSnapshots: async (_, breakpoint: BreakPointFunction) => { + loadSnapshotSources: async () => { const params = { version: values.featureFlags[FEATURE_FLAGS.SESSION_REPLAY_V3_INGESTION_PLAYBACK] ? '3' : '2', - source: SnapshotSourceType.realtime, } - await breakpoint(1) // debounce const response = await api.recordings.listSnapshots(props.sessionRecordingId, params) - breakpoint() // handle out of order - - if (response.snapshots) { - const { transformed, untransformed } = await processEncodedResponse( - response.snapshots, - props, - values.sessionPlayerSnapshotData, - values.featureFlags - ) - - if (transformed.length === (values.sessionPlayerSnapshotData?.snapshots || []).length) { - actions.pollingLoadedNoNewData() - } - - return { - ...(values.sessionPlayerSnapshotData || {}), - snapshots: transformed, - untransformed_snapshots: untransformed ?? undefined, - } - } - return values.sessionPlayerSnapshotData + return response.sources ?? [] }, - loadRecordingSnapshots: async ({ source }, breakpoint): Promise => { - if (!props.sessionRecordingId) { - return values.sessionPlayerSnapshotData + }, + ], + snapshotsForSource: [ + null as SessionRecordingSnapshotSourceResponse | null, + { + loadSnapshotsForSource: async ({ source }, breakpoint) => { + const params = { + source: source.source, + blob_key: source.blob_key, + version: values.featureFlags[FEATURE_FLAGS.SESSION_REPLAY_V3_INGESTION_PLAYBACK] ? '3' : '2', } const snapshotLoadingStartTime = performance.now() @@ -511,73 +362,31 @@ export const sessionRecordingDataLogic = kea([ cache.snapshotsStartTime = snapshotLoadingStartTime } - const data: SessionPlayerSnapshotData = { - ...(values.sessionPlayerSnapshotData || {}), - } - await breakpoint(1) - if (source?.source === SnapshotSourceType.blob) { - const params = { - source: source.source, - blob_key: source.blob_key, - version: '2', - } - - if (values.featureFlags[FEATURE_FLAGS.SESSION_REPLAY_V3_INGESTION_PLAYBACK]) { - params.version = '3' - } - - if (!source.blob_key) { - throw new Error('Missing key') - } - const encodedResponse = await api.recordings.getBlobSnapshots(props.sessionRecordingId, params) - - const { transformed, untransformed } = await processEncodedResponse( - encodedResponse, - props, - values.sessionPlayerSnapshotData, - values.featureFlags - ) - data.snapshots = transformed - data.untransformed_snapshots = untransformed ?? undefined - } else { - const params = { - source: source?.source, - version: '2', - } - - if (values.featureFlags[FEATURE_FLAGS.SESSION_REPLAY_V3_INGESTION_PLAYBACK]) { - params.version = '3' - } - - const response = await api.recordings.listSnapshots(props.sessionRecordingId, params) - if (response.snapshots) { - const { transformed, untransformed } = await processEncodedResponse( - response.snapshots, - props, - values.sessionPlayerSnapshotData, - values.featureFlags - ) - data.snapshots = transformed - data.untransformed_snapshots = untransformed ?? undefined - } - - if (response.sources) { - data.sources = response.sources - } + if (source.source === SnapshotSourceType.blob && !source.blob_key) { + throw new Error('Missing key') } - if (source) { - source.loaded = true - - posthog.capture('recording_snapshot_loaded', { - source: source.source, - duration: Math.round(performance.now() - snapshotLoadingStartTime), - }) - } + const blobResponseType = source.source === SnapshotSourceType.blob || params.version === '3' + + const response = blobResponseType + ? await api.recordings.getBlobSnapshots(props.sessionRecordingId, params).catch((e) => { + if (source.source === 'realtime' && e.status === 404) { + // Realtime source is not always available so a 404 is expected + return [] + } + throw e + }) + : (await api.recordings.listSnapshots(props.sessionRecordingId, params)).snapshots ?? [] + + const { transformed, untransformed } = await processEncodedResponse( + response, + props, + values.featureFlags + ) - return data + return { snapshots: transformed, untransformed_snapshots: untransformed ?? undefined, source } }, }, ], @@ -703,6 +512,147 @@ export const sessionRecordingDataLogic = kea([ }, ], })), + listeners(({ values, actions, cache, props }) => ({ + loadSnapshots: () => { + // This kicks off the loading chain + if (!values.snapshotSourcesLoading) { + actions.loadSnapshotSources() + } + }, + maybeLoadRecordingMeta: () => { + if (!values.sessionPlayerMetaDataLoading) { + actions.loadRecordingMeta() + } + }, + loadSnapshotSources: () => { + // We only load events once we actually start loading the recording + actions.loadEvents() + }, + loadRecordingMetaSuccess: () => { + cache.metadataLoadDuration = Math.round(performance.now() - cache.metaStartTime) + actions.reportUsageIfFullyLoaded() + }, + loadRecordingMetaFailure: () => { + cache.metadataLoadDuration = Math.round(performance.now() - cache.metaStartTime) + }, + + loadSnapshotSourcesSuccess: () => { + // When we receive the list of sources we can kick off the loading chain + actions.loadNextSnapshotSource() + }, + + loadSnapshotsForSourceSuccess: ({ snapshotsForSource }) => { + const sources = values.snapshotSources + const snapshots = snapshotsForSource.snapshots + + // Cache the last response count to detect if we're getting the same data over and over + const newSnapshotsCount = snapshots.length + + if ((cache.lastSnapshotsCount ?? newSnapshotsCount) === newSnapshotsCount) { + cache.lastSnapshotsUnchangedCount = (cache.lastSnapshotsUnchangedCount ?? 0) + 1 + } else { + cache.lastSnapshotsUnchangedCount = 0 + } + cache.lastSnapshotsCount = newSnapshotsCount + + if (!snapshots.length && sources?.length === 1) { + // We got only a single source to load, loaded it successfully, but it had no snapshots. + posthog.capture('recording_snapshots_v2_empty_response', { + source: sources[0], + }) + } else if (!cache.firstPaintDuration) { + cache.firstPaintDuration = Math.round(performance.now() - cache.snapshotsStartTime) + actions.reportViewed() + } + + actions.loadNextSnapshotSource() + }, + + loadNextSnapshotSource: () => { + const nextSourceToLoad = values.snapshotSources?.find((s) => { + const sourceKey = getSourceKey(s) + return !values.snapshotsBySource?.[sourceKey] + }) + + if (nextSourceToLoad) { + return actions.loadSnapshotsForSource(nextSourceToLoad) + } + + // TODO: Move this to a one time check - only report once per recording + cache.snapshotsLoadDuration = Math.round(performance.now() - cache.snapshotsStartTime) + actions.reportUsageIfFullyLoaded() + + // If we have a realtime source, start polling it + const realTimeSource = values.snapshotSources?.find((s) => s.source === SnapshotSourceType.realtime) + if (realTimeSource) { + actions.pollRealtimeSnapshots() + } + }, + loadSnapshotsForSourceFailure: () => { + cache.snapshotsLoadDuration = Math.round(performance.now() - cache.snapshotsStartTime) + }, + pollRealtimeSnapshots: () => { + // always make sure we've cleared up the last timeout + clearTimeout(cache.realTimePollingTimeoutID) + cache.realTimePollingTimeoutID = null + + // ten is an arbitrary limit to try to avoid sending requests to our backend unnecessarily + // we could change this or add to it e.g. only poll if browser is visible to user + if ((cache.lastSnapshotsUnchangedCount ?? 0) <= 10) { + cache.realTimePollingTimeoutID = setTimeout(() => { + actions.loadSnapshotsForSource({ source: SnapshotSourceType.realtime }) + }, props.realTimePollingIntervalMilliseconds || DEFAULT_REALTIME_POLLING_MILLIS) + } + }, + loadEventsSuccess: () => { + cache.eventsLoadDuration = Math.round(performance.now() - cache.eventsStartTime) + actions.reportUsageIfFullyLoaded() + }, + loadEventsFailure: () => { + cache.eventsLoadDuration = Math.round(performance.now() - cache.eventsStartTime) + }, + reportUsageIfFullyLoaded: (_, breakpoint) => { + breakpoint() + if (values.fullyLoaded) { + eventUsageLogic.actions.reportRecording( + values.sessionPlayerData, + generateRecordingReportDurations(cache), + SessionRecordingUsageType.LOADED, + 0 + ) + // Reset cache now that final usage report has been sent + resetTimingsCache(cache) + } + }, + reportViewed: async (_, breakpoint) => { + const durations = generateRecordingReportDurations(cache) + breakpoint() + // Triggered on first paint + eventUsageLogic.actions.reportRecording( + values.sessionPlayerData, + durations, + SessionRecordingUsageType.VIEWED, + 0 + ) + await breakpoint(IS_TEST_MODE ? 1 : 10000) + eventUsageLogic.actions.reportRecording( + values.sessionPlayerData, + durations, + SessionRecordingUsageType.ANALYZED, + 10 + ) + }, + + maybePersistRecording: () => { + if (values.sessionPlayerMetaDataLoading) { + return + } + + if (values.sessionPlayerMetaData?.storage === 'object_storage') { + actions.persistRecording() + } + }, + })), selectors({ sessionPlayerData: [ (s, p) => [ @@ -739,23 +689,22 @@ export const sessionRecordingDataLogic = kea([ }), ], + snapshotsLoading: [ + (s) => [s.snapshotSourcesLoading, s.snapshotsForSourceLoading], + (snapshotSourcesLoading, snapshotsForSourceLoading): boolean => { + return snapshotSourcesLoading || snapshotsForSourceLoading + }, + ], + snapshotsLoaded: [(s) => [s.snapshotSources], (snapshotSources): boolean => !!snapshotSources], + fullyLoaded: [ - (s) => [ - s.sessionPlayerSnapshotData, - s.sessionPlayerMetaDataLoading, - s.sessionPlayerSnapshotDataLoading, - s.sessionEventsDataLoading, - ], - ( - sessionPlayerSnapshotData, - sessionPlayerMetaDataLoading, - sessionPlayerSnapshotDataLoading, - sessionEventsDataLoading - ): boolean => { + (s) => [s.snapshots, s.sessionPlayerMetaDataLoading, s.snapshotsLoading, s.sessionEventsDataLoading], + (snapshots, sessionPlayerMetaDataLoading, snapshotsLoading, sessionEventsDataLoading): boolean => { + // TODO: Do a proper check for all sources having been loaded return ( - !!sessionPlayerSnapshotData?.snapshots?.length && + !!snapshots.length && !sessionPlayerMetaDataLoading && - !sessionPlayerSnapshotDataLoading && + !snapshotsLoading && !sessionEventsDataLoading ) }, @@ -769,12 +718,12 @@ export const sessionRecordingDataLogic = kea([ ], end: [ - (s) => [s.sessionPlayerMetaData, s.sessionPlayerSnapshotData], - (meta, sessionPlayerSnapshotData): Dayjs | undefined => { + (s) => [s.sessionPlayerMetaData, s.snapshots], + (meta, snapshots): Dayjs | undefined => { // NOTE: We might end up with more snapshots than we knew about when we started the recording so we // either use the metadata end point or the last snapshot, whichever is later. const end = meta?.end_time ? dayjs(meta.end_time) : undefined - const lastEvent = sessionPlayerSnapshotData?.snapshots?.slice(-1)[0] + const lastEvent = snapshots?.slice(-1)[0] return lastEvent?.timestamp && lastEvent.timestamp > +(end ?? 0) ? dayjs(lastEvent.timestamp) : end }, @@ -788,18 +737,18 @@ export const sessionRecordingDataLogic = kea([ ], segments: [ - (s) => [s.sessionPlayerSnapshotData, s.start, s.end], - (sessionPlayerSnapshotData, start, end): RecordingSegment[] => { - return createSegments(sessionPlayerSnapshotData?.snapshots || [], start, end) + (s) => [s.snapshots, s.start, s.end], + (snapshots, start, end): RecordingSegment[] => { + return createSegments(snapshots || [], start, end) }, ], urls: [ - (s) => [s.sessionPlayerSnapshotData], - (sessionPlayerSnapshotData): { url: string; timestamp: number }[] => { + (s) => [s.snapshots], + (snapshots): { url: string; timestamp: number }[] => { return ( - sessionPlayerSnapshotData?.snapshots - ?.filter((snapshot) => getHrefFromSnapshot(snapshot)) + snapshots + .filter((snapshot) => getHrefFromSnapshot(snapshot)) .map((snapshot) => { return { url: getHrefFromSnapshot(snapshot) as string, @@ -810,10 +759,35 @@ export const sessionRecordingDataLogic = kea([ }, ], + snapshots: [ + (s) => [s.snapshotSources, s.snapshotsBySource], + (sources, snapshotsBySource): RecordingSnapshot[] => { + const allSnapshots = + sources?.flatMap((source) => { + const sourceKey = getSourceKey(source) + return snapshotsBySource?.[sourceKey]?.snapshots || [] + }) ?? [] + + return deduplicateSnapshots(allSnapshots) + }, + ], + untransformedSnapshots: [ + (s) => [s.snapshotSources, s.snapshotsBySource], + (sources, snapshotsBySource): RecordingSnapshot[] => { + const allSnapshots = + sources?.flatMap((source) => { + const sourceKey = getSourceKey(source) + return snapshotsBySource?.[sourceKey]?.untransformed_snapshots || [] + }) ?? [] + + return deduplicateSnapshots(allSnapshots) + }, + ], + snapshotsByWindowId: [ - (s) => [s.sessionPlayerSnapshotData], - (sessionPlayerSnapshotData): Record => { - return mapSnapshotsToWindowId(sessionPlayerSnapshotData?.snapshots || []) + (s) => [s.snapshots], + (snapshots): Record => { + return mapSnapshotsToWindowId(snapshots || []) }, ], @@ -877,6 +851,24 @@ export const sessionRecordingDataLogic = kea([ return Object.keys(snapshotsByWindowId) }, ], + + createExportJSON: [ + (s) => [s.sessionPlayerMetaData, s.snapshots, s.untransformedSnapshots], + ( + sessionPlayerMetaData, + snapshots, + untransformedSnapshots + ): ((exportUntransformedMobileSnapshotData: boolean) => ExportedSessionRecordingFileV2) => { + return (exportUntransformedMobileSnapshotData: boolean) => ({ + version: '2023-04-28', + data: { + id: sessionPlayerMetaData?.id ?? '', + person: sessionPlayerMetaData?.person, + snapshots: exportUntransformedMobileSnapshotData ? untransformedSnapshots : snapshots, + }, + }) + }, + ], }), afterMount(({ cache }) => { resetTimingsCache(cache) diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts index bd985c6da05d5..b10664a21bd46 100644 --- a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts +++ b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts @@ -83,8 +83,8 @@ describe('sessionRecordingPlayerLogic', () => { expect(logic.values.sessionPlayerData).toMatchSnapshot() await expectLogic(logic).toNotHaveDispatchedActions([ - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshots, - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshotsSuccess, + sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadSnapshotSources, + sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadSnapshotSourcesSuccess, ]) }) @@ -104,10 +104,10 @@ describe('sessionRecordingPlayerLogic', () => { await expectLogic(logic).toDispatchActions([ // once to gather sources - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshots, + sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadSnapshotSources, // once to load source from that - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshots, - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshotsSuccess, + sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadSnapshotsForSource, + sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadSnapshotsForSourceSuccess, ]) expect(logic.values.sessionPlayerData).toMatchSnapshot() @@ -136,15 +136,11 @@ describe('sessionRecordingPlayerLogic', () => { logic.actions.seekToTime(50) // greater than null buffered time }) .toDispatchActions([ - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingMeta, - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingMetaSuccess, 'seekToTimestamp', + sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadSnapshotSourcesFailure, ]) .toFinishAllListeners() - .toDispatchActions([ - sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshots, - 'setErrorPlayerState', - ]) + .toDispatchActions(['setErrorPlayerState']) expect(logic.values).toMatchObject({ sessionPlayerData: { @@ -161,7 +157,10 @@ describe('sessionRecordingPlayerLogic', () => { logic = sessionRecordingPlayerLogic({ sessionRecordingId: '2', playerKey: 'test' }) logic.mount() - await expectLogic(logic).toDispatchActions(['initializePlayerFromStart']) + await expectLogic(logic).toDispatchActions([ + sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingMetaSuccess, + 'initializePlayerFromStart', + ]) expect(logic.cache.hasInitialized).toBeTruthy() logic.unmount() diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts index 0d2b82c9dea88..d1bbf94be6fa6 100644 --- a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts +++ b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts @@ -15,6 +15,7 @@ import { selectors, } from 'kea' import { router } from 'kea-router' +import { subscriptions } from 'kea-subscriptions' import { delay } from 'kea-test-utils' import { now } from 'lib/dayjs' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' @@ -37,7 +38,6 @@ import { userLogic } from 'scenes/userLogic' import { AvailableFeature, RecordingSegment, SessionPlayerData, SessionPlayerState } from '~/types' -import { createExportedSessionRecording } from '../file-playback/sessionRecordingFilePlaybackLogic' import type { sessionRecordingsPlaylistLogicType } from '../playlist/sessionRecordingsPlaylistLogicType' import { playerSettingsLogic } from './playerSettingsLogic' import { COMMON_REPLAYER_CONFIG, CorsPlugin } from './rrweb' @@ -102,10 +102,11 @@ export const sessionRecordingPlayerLogic = kea( sessionRecordingDataLogic(props), [ 'snapshotsLoaded', + 'snapshotsLoading', 'sessionPlayerData', 'sessionPlayerMetaData', - 'sessionPlayerSnapshotDataLoading', 'sessionPlayerMetaDataLoading', + 'createExportJSON', ], playerSettingsLogic, ['speed', 'skipInactivitySetting'], @@ -120,9 +121,9 @@ export const sessionRecordingPlayerLogic = kea( sessionRecordingDataLogic(props), [ 'maybeLoadRecordingMeta', - 'loadRecordingSnapshots', - 'loadRecordingSnapshotsSuccess', - 'loadRecordingSnapshotsFailure', + 'loadSnapshots', + 'loadSnapshotsForSourceFailure', + 'loadSnapshotSourcesFailure', 'loadRecordingMetaSuccess', 'maybePersistRecording', ], @@ -168,7 +169,7 @@ export const sessionRecordingPlayerLogic = kea( initializePlayerFromStart: true, incrementErrorCount: true, incrementWarningCount: (count: number = 1) => ({ count }), - updateFromMetadata: true, + syncSnapshotsWithPlayer: true, exportRecordingToFile: (exportUntransformedMobileData?: boolean) => ({ exportUntransformedMobileData }), deleteRecording: true, openExplorer: true, @@ -359,7 +360,7 @@ export const sessionRecordingPlayerLogic = kea( s.isScrubbing, s.isSkippingInactivity, s.snapshotsLoaded, - s.sessionPlayerSnapshotDataLoading, + s.snapshotsLoading, ], ( playingState, @@ -620,13 +621,15 @@ export const sessionRecordingPlayerLogic = kea( actions.setCurrentSegment(initialSegment) } }, - updateFromMetadata: async (_, breakpoint) => { + syncSnapshotsWithPlayer: async (_, breakpoint) => { // On loading more of the recording, trigger some state changes const currentEvents = values.player?.replayer?.service.state.context.events ?? [] const eventsToAdd = [] if (values.currentSegment?.windowId !== undefined) { // TODO: Probably need to check for de-dupes here.... + // TODO: We do some sorting and rearranging in the data logic... We may need to handle that here, replacing the + // whole events stream.... eventsToAdd.push( ...(values.sessionPlayerData.snapshotsByWindowId[values.currentSegment?.windowId] ?? []).slice( currentEvents.length @@ -649,27 +652,28 @@ export const sessionRecordingPlayerLogic = kea( }, loadRecordingMetaSuccess: () => { // As the connected data logic may be preloaded we call a shared function here and on mount - actions.updateFromMetadata() + actions.syncSnapshotsWithPlayer() if (props.autoPlay) { // Autoplay assumes we are playing immediately so lets go ahead and load more data actions.setPlay() } }, - loadRecordingSnapshotsSuccess: () => { - // As the connected data logic may be preloaded we call a shared function here and on mount - actions.updateFromMetadata() + loadSnapshotsForSourceFailure: () => { + if (Object.keys(values.sessionPlayerData.snapshotsByWindowId).length === 0) { + console.error('PostHog Recording Playback Error: No snapshots loaded') + actions.setErrorPlayerState(true) + } }, - - loadRecordingSnapshotsFailure: () => { + loadSnapshotSourcesFailure: () => { if (Object.keys(values.sessionPlayerData.snapshotsByWindowId).length === 0) { console.error('PostHog Recording Playback Error: No snapshots loaded') actions.setErrorPlayerState(true) } }, setPlay: () => { - if (!values.snapshotsLoaded && !values.sessionPlayerSnapshotDataLoading) { - actions.loadRecordingSnapshots() + if (!values.snapshotsLoaded) { + actions.loadSnapshots() } actions.stopAnimation() actions.restartIframePlayback() @@ -736,7 +740,7 @@ export const sessionRecordingPlayerLogic = kea( if (!values.snapshotsLoaded) { // We haven't started properly loading yet so nothing to do - } else if (!values.sessionPlayerSnapshotDataLoading && segment?.kind === 'buffer') { + } else if (!values.snapshotsLoading && segment?.kind === 'buffer') { // If not currently loading anything and part of the recording hasn't loaded, set error state values.player?.replayer?.pause() actions.endBuffer() @@ -937,10 +941,7 @@ export const sessionRecordingPlayerLogic = kea( await delay(delayTime) } - const payload = createExportedSessionRecording( - sessionRecordingDataLogic(props), - !!exportUntransformedMobileData - ) + const payload = values.createExportJSON(!!exportUntransformedMobileData) const recordingFile = new File( [JSON.stringify(payload, null, 2)], @@ -1002,6 +1003,18 @@ export const sessionRecordingPlayerLogic = kea( }, })), + subscriptions(({ actions }) => ({ + sessionPlayerData: (next, prev) => { + const hasSnapshotChanges = next?.snapshotsByWindowId !== prev?.snapshotsByWindowId + + // TODO: Detect if the order of the current window has changed (this would require re-initializing the player) + + if (hasSnapshotChanges) { + actions.syncSnapshotsWithPlayer() + } + }, + })), + beforeUnmount(({ values, actions, cache, props }) => { if (props.mode === SessionRecordingPlayerMode.Preview) { values.player?.replayer?.destroy() diff --git a/frontend/src/scenes/session-recordings/playlist/SessionRecordingPreview.tsx b/frontend/src/scenes/session-recordings/playlist/SessionRecordingPreview.tsx index 0ce2a9213ebe8..10e31ca899d00 100644 --- a/frontend/src/scenes/session-recordings/playlist/SessionRecordingPreview.tsx +++ b/frontend/src/scenes/session-recordings/playlist/SessionRecordingPreview.tsx @@ -12,6 +12,7 @@ import { Spinner } from 'lib/lemon-ui/Spinner' import { Tooltip } from 'lib/lemon-ui/Tooltip' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { colonDelimitedDuration } from 'lib/utils' +import posthog from 'posthog-js' import { Fragment, useState } from 'react' import { DraggableToNotebook } from 'scenes/notebooks/AddToNotebook/DraggableToNotebook' import { asDisplay } from 'scenes/persons/person-utils' @@ -153,6 +154,7 @@ export function PropertyIcons({ onClick={(e) => { if (e.altKey) { e.stopPropagation() + posthog.capture('alt click property filter added', { property }) onPropertyClick?.(property, value) } }} diff --git a/frontend/src/scenes/session-recordings/sessionRecordingsLogic.ts b/frontend/src/scenes/session-recordings/sessionRecordingsLogic.ts index 2a03fd471af36..31c9015b9fbc1 100644 --- a/frontend/src/scenes/session-recordings/sessionRecordingsLogic.ts +++ b/frontend/src/scenes/session-recordings/sessionRecordingsLogic.ts @@ -16,8 +16,6 @@ export const humanFriendlyTabName = (tab: ReplayTabs): string => { return 'Recent recordings' case ReplayTabs.Playlists: return 'Playlists' - case ReplayTabs.FilePlayback: - return 'Playback from file' default: return capitalizeFirstLetter(tab) } diff --git a/frontend/src/scenes/settings/SettingsMap.tsx b/frontend/src/scenes/settings/SettingsMap.tsx index 3530ad15fe407..571f10320ccb6 100644 --- a/frontend/src/scenes/settings/SettingsMap.tsx +++ b/frontend/src/scenes/settings/SettingsMap.tsx @@ -31,7 +31,6 @@ import { ReplayCostControl, ReplayGeneral, } from './project/SessionRecordingSettings' -import { SettingPersonsOnEvents } from './project/SettingPersonsOnEvents' import { SlackIntegration } from './project/SlackIntegration' import { SurveySettings } from './project/SurveySettings' import { ProjectAccountFiltersSetting } from './project/TestAccountFiltersConfig' @@ -139,11 +138,6 @@ export const SettingsMap: SettingSection[] = [ title: 'Group analytics', component: , }, - { - id: 'persons-on-events', - title: 'Persons on events (beta)', - component: , - }, ], }, diff --git a/frontend/src/scenes/settings/project/ProjectSettings.tsx b/frontend/src/scenes/settings/project/ProjectSettings.tsx index 99a71270d299f..013e66f4417d4 100644 --- a/frontend/src/scenes/settings/project/ProjectSettings.tsx +++ b/frontend/src/scenes/settings/project/ProjectSettings.tsx @@ -6,11 +6,13 @@ import { AuthorizedUrlListType } from 'lib/components/AuthorizedUrlList/authoriz import { CodeSnippet } from 'lib/components/CodeSnippet' import { JSBookmarklet } from 'lib/components/JSBookmarklet' import { JSSnippet } from 'lib/components/JSSnippet' +import { getPublicSupportSnippet } from 'lib/components/Support/supportLogic' import { IconRefresh } from 'lib/lemon-ui/icons' import { Link } from 'lib/lemon-ui/Link' import { useState } from 'react' import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' import { isAuthenticatedTeam, teamLogic } from 'scenes/teamLogic' +import { userLogic } from 'scenes/userLogic' import { TimezoneConfig } from './TimezoneConfig' import { WeekStartConfig } from './WeekStartConfig' @@ -90,6 +92,7 @@ export function ProjectVariables(): JSX.Element { const { currentTeam, isTeamTokenResetAvailable } = useValues(teamLogic) const { resetToken } = useActions(teamLogic) const { preflight } = useValues(preflightLogic) + const { user } = useValues(userLogic) const region = preflight?.region const openDialog = (): void => { @@ -152,6 +155,17 @@ export function ProjectVariables(): JSX.Element { {`${region} Cloud`}
) : null} + {region && user ? ( +
+

+ Debug information +

+

Include this snippet when opening a Feature request or Bug report on GitHub.

+ + {getPublicSupportSnippet(region, user)} + +
+ ) : null}
) } diff --git a/frontend/src/scenes/settings/project/SettingPersonsOnEvents.tsx b/frontend/src/scenes/settings/project/SettingPersonsOnEvents.tsx deleted file mode 100644 index 8f17a1b88c6f8..0000000000000 --- a/frontend/src/scenes/settings/project/SettingPersonsOnEvents.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { LemonSwitch, Link } from '@posthog/lemon-ui' -import { useActions, useValues } from 'kea' -import { teamLogic } from 'scenes/teamLogic' - -export function SettingPersonsOnEvents(): JSX.Element { - const { updateCurrentTeam } = useActions(teamLogic) - const { currentTeam } = useValues(teamLogic) - - return ( - <> -

- We have updated our data model to store person properties directly on events, making queries - significantly faster. This means that person properties will no longer be "timeless", but rather - point-in-time i.e. on filters we'll consider a person's properties at the time of the event, rather than - at present time. This may cause data to change on some of your insights, but will be the default way we - handle person properties going forward. For now, you can control whether you want this on or not, and - should feel free to let us know of any concerns you might have. If you do enable this, you should see - speed improvements of around 3-5x on average on most of your insights. -

-

- Please note, you might need to change the way you send us events after enabling this - feature. Read more here. -

- - { - updateCurrentTeam({ - extra_settings: { ...currentTeam?.extra_settings, ['poe_v2_enabled']: checked }, - }) - }} - label="Enable Person on Events (Beta)" - checked={!!currentTeam?.extra_settings?.['poe_v2_enabled']} - bordered - /> - - ) -} diff --git a/frontend/src/scenes/settings/project/TimezoneConfig.tsx b/frontend/src/scenes/settings/project/TimezoneConfig.tsx index c02caa0ee0a03..230372ff58eec 100644 --- a/frontend/src/scenes/settings/project/TimezoneConfig.tsx +++ b/frontend/src/scenes/settings/project/TimezoneConfig.tsx @@ -31,6 +31,7 @@ export function TimezoneConfig(): JSX.Element { loading={currentTeamLoading} disabled={currentTeamLoading} value={[currentTeam.timezone]} + popoverClassName="z-[1000]" onChange={([newTimezone]): void => { // This is a string for a single-mode select, but typing is poor if (!preflight?.available_timezones) { diff --git a/frontend/src/scenes/urls.ts b/frontend/src/scenes/urls.ts index 3f4affdb4417c..38cf07aa323d6 100644 --- a/frontend/src/scenes/urls.ts +++ b/frontend/src/scenes/urls.ts @@ -110,6 +110,7 @@ export const urls = { combineUrl(`/replay/playlists/${id}`, filters ? { filters } : {}).url, replaySingle: (id: string, filters?: Partial): string => combineUrl(`/replay/${id}`, filters ? { filters } : {}).url, + replayFilePlayback: (): string => combineUrl('/replay/file-playback').url, personByDistinctId: (id: string, encode: boolean = true): string => encode ? `/person/${encodeURIComponent(id)}` : `/person/${id}`, personByUUID: (uuid: string, encode: boolean = true): string => diff --git a/frontend/src/scenes/web-analytics/WebDashboard.tsx b/frontend/src/scenes/web-analytics/WebDashboard.tsx index 71b438546ebc4..90b94111afbbb 100644 --- a/frontend/src/scenes/web-analytics/WebDashboard.tsx +++ b/frontend/src/scenes/web-analytics/WebDashboard.tsx @@ -1,4 +1,4 @@ -import { IconExpand45 } from '@posthog/icons' +import { IconExpand45, IconInfo, IconOpenSidebar, IconX } from '@posthog/icons' import clsx from 'clsx' import { BindLogic, useActions, useValues } from 'kea' import { DateFilter } from 'lib/components/DateFilter/DateFilter' @@ -6,8 +6,10 @@ import { IconOpenInNew } from 'lib/lemon-ui/icons' import { LemonButton } from 'lib/lemon-ui/LemonButton' import { LemonSegmentedButton } from 'lib/lemon-ui/LemonSegmentedButton' import { LemonSelect } from 'lib/lemon-ui/LemonSelect' +import { PostHogComDocsURL } from 'lib/lemon-ui/Link/Link' +import { Popover } from 'lib/lemon-ui/Popover' import { isNotNil } from 'lib/utils' -import React from 'react' +import React, { useState } from 'react' import { WebAnalyticsHealthCheck } from 'scenes/web-analytics/WebAnalyticsHealthCheck' import { QueryTile, @@ -75,7 +77,7 @@ const Tiles = (): JSX.Element => { } const QueryTileItem = ({ tile }: { tile: QueryTile }): JSX.Element => { - const { query, title, layout, insightProps, showPathCleaningControls, showIntervalSelect } = tile + const { query, title, layout, insightProps, showPathCleaningControls, showIntervalSelect, docs } = tile const { openModal } = useActions(webAnalyticsLogic) const { getNewInsightUrl } = useValues(webAnalyticsLogic) @@ -116,6 +118,7 @@ const QueryTileItem = ({ tile }: { tile: QueryTile }): JSX.Element => { )} > {title &&

{title}

} + {docs && } { canOpenModal: !!tab.canOpenModal, canOpenInsight: !!tab.canOpenInsight, query: tab.query, + docs: tab.docs, }))} tileId={tile.tileId} openModal={openModal} @@ -187,6 +191,13 @@ export const WebTabs = ({ canOpenModal: boolean canOpenInsight: boolean query: QuerySchema + docs: + | { + docsUrl: PostHogComDocsURL + title: string + description: string + } + | undefined }[] setActiveTabId: (id: string) => void openModal: (tileId: TileId, tabId: string) => void @@ -223,7 +234,16 @@ export const WebTabs = ({ return (
-

{activeTab?.title}

+

+ {activeTab?.title} + {activeTab?.docs && ( + + )} +

{tabs.length > 3 ? ( { + const [isOpen, setIsOpen] = useState(false) + + return ( + setIsOpen(false)} + overlay={ +
+
+

{title}

+ setIsOpen(false)} + size="xsmall" + icon={} + /> +
+

{description}

+
+ setIsOpen(false)} + targetBlank={true} + sideIcon={} + > + Learn more + +
+
+ } + > + setIsOpen(!isOpen)} size="small" icon={} /> +
+ ) +} + export const WebAnalyticsDashboard = (): JSX.Element => { return ( diff --git a/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts b/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts index b97a031a2fe4a..f8056c88ea228 100644 --- a/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts +++ b/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts @@ -5,6 +5,7 @@ import { windowValues } from 'kea-window-values' import api from 'lib/api' import { FEATURE_FLAGS, RETENTION_FIRST_TIME, STALE_EVENT_SECONDS } from 'lib/constants' import { dayjs } from 'lib/dayjs' +import { PostHogComDocsURL } from 'lib/lemon-ui/Link/Link' import { featureFlagLogic } from 'lib/logic/featureFlagLogic' import { getDefaultInterval, isNotNil, updateDatesWithInterval } from 'lib/utils' import { urls } from 'scenes/urls' @@ -70,6 +71,11 @@ interface BaseTile { layout: WebTileLayout } +export interface Docs { + docsUrl: PostHogComDocsURL + title: string + description: string +} export interface QueryTile extends BaseTile { title?: string query: QuerySchema @@ -78,6 +84,7 @@ export interface QueryTile extends BaseTile { insightProps: InsightLogicProps canOpenModal: boolean canOpenInsight?: boolean + docs?: Docs } export interface TabsTile extends BaseTile { @@ -93,6 +100,7 @@ export interface TabsTile extends BaseTile { insightProps: InsightLogicProps canOpenModal?: boolean canOpenInsight?: boolean + docs?: Docs }[] } @@ -116,8 +124,8 @@ export enum GraphsTab { } export enum SourceTab { - REFERRING_DOMAIN = 'REFERRING_DOMAIN', CHANNEL = 'CHANNEL', + REFERRING_DOMAIN = 'REFERRING_DOMAIN', UTM_SOURCE = 'UTM_SOURCE', UTM_MEDIUM = 'UTM_MEDIUM', UTM_CAMPAIGN = 'UTM_CAMPAIGN', @@ -371,7 +379,7 @@ export const webAnalyticsLogic = kea([ }), selectors(({ actions, values }) => ({ graphsTab: [(s) => [s._graphsTab], (graphsTab: string | null) => graphsTab || GraphsTab.UNIQUE_USERS], - sourceTab: [(s) => [s._sourceTab], (sourceTab: string | null) => sourceTab || SourceTab.REFERRING_DOMAIN], + sourceTab: [(s) => [s._sourceTab], (sourceTab: string | null) => sourceTab || SourceTab.CHANNEL], deviceTab: [(s) => [s._deviceTab], (deviceTab: string | null) => deviceTab || DeviceTab.DEVICE_TYPE], pathTab: [(s) => [s._pathTab], (pathTab: string | null) => pathTab || PathTab.PATH], geographyTab: [(s) => [s._geographyTab], (geographyTab: string | null) => geographyTab || GeographyTab.MAP], @@ -585,7 +593,7 @@ export const webAnalyticsLogic = kea([ { id: PathTab.INITIAL_PATH, title: 'Top entry paths', - linkText: 'Entry Path', + linkText: 'Entry path', query: { full: true, kind: NodeKind.DataTableNode, @@ -617,43 +625,50 @@ export const webAnalyticsLogic = kea([ setTabId: actions.setSourceTab, tabs: [ { - id: SourceTab.REFERRING_DOMAIN, - title: 'Top referrers', - linkText: 'Referring domain', + id: SourceTab.CHANNEL, + title: 'Top channels', + linkText: 'Channel', query: { full: true, kind: NodeKind.DataTableNode, source: { kind: NodeKind.WebStatsTableQuery, properties: webAnalyticsFilters, - breakdownBy: WebStatsBreakdown.InitialReferringDomain, + breakdownBy: WebStatsBreakdown.InitialChannelType, dateRange, sampling, limit: 10, }, }, - insightProps: createInsightProps(TileId.SOURCES, SourceTab.REFERRING_DOMAIN), + insightProps: createInsightProps(TileId.SOURCES, SourceTab.CHANNEL), canOpenModal: true, + docs: { + docsUrl: 'https://posthog.com/docs/data/channel-type', + title: 'Channels', + description: + 'Channels are the different sources that bring traffic to your website, e.g. Paid Search, Organic Social, Direct, etc.', + }, }, { - id: SourceTab.CHANNEL, - title: 'Top channels', - linkText: 'Channel', + id: SourceTab.REFERRING_DOMAIN, + title: 'Top referrers', + linkText: 'Referring domain', query: { full: true, kind: NodeKind.DataTableNode, source: { kind: NodeKind.WebStatsTableQuery, properties: webAnalyticsFilters, - breakdownBy: WebStatsBreakdown.InitialChannelType, + breakdownBy: WebStatsBreakdown.InitialReferringDomain, dateRange, sampling, limit: 10, }, }, - insightProps: createInsightProps(TileId.SOURCES, SourceTab.CHANNEL), + insightProps: createInsightProps(TileId.SOURCES, SourceTab.REFERRING_DOMAIN), canOpenModal: true, }, + { id: SourceTab.UTM_SOURCE, title: 'Top sources', diff --git a/frontend/src/styles/global.scss b/frontend/src/styles/global.scss index b0188572c656d..a3e9815c28ba9 100644 --- a/frontend/src/styles/global.scss +++ b/frontend/src/styles/global.scss @@ -226,40 +226,6 @@ input::-ms-clear { // Form & input styles -.input-set { - padding-bottom: 1rem; - color: var(--default); - - label { - font-size: 0.875rem; - font-weight: bold; - line-height: 1.25rem; - } - - .caption { - font-size: 0.875rem; - line-height: 1.25rem; - color: var(--muted); - } - - .ant-radio-button-wrapper { - // To properly handle label styles above - font-weight: normal !important; - line-height: 30px !important; - } - - &.errored { - .caption { - color: var(--danger); - } - - input[type='password'], - input[type='text'] { - border-color: var(--danger) !important; - } - } -} - .error-on-blur { &.errored:not(:focus) { border-color: var(--danger) !important; diff --git a/frontend/src/toolbar/Toolbar.stories.tsx b/frontend/src/toolbar/Toolbar.stories.tsx index 9b5e82d1db4f4..93947f5cfb4c8 100644 --- a/frontend/src/toolbar/Toolbar.stories.tsx +++ b/frontend/src/toolbar/Toolbar.stories.tsx @@ -131,6 +131,10 @@ export const FeatureFlags = (): JSX.Element => { return } +export const EventsDebuggerEmpty = (): JSX.Element => { + return +} + // Dark theme export const DefaultDark = (): JSX.Element => { return @@ -155,3 +159,7 @@ export const ActionsDark = (): JSX.Element => { export const FeatureFlagsDark = (): JSX.Element => { return } + +export const EventsDebuggerEmptyDark = (): JSX.Element => { + return +} diff --git a/frontend/src/toolbar/bar/Toolbar.scss b/frontend/src/toolbar/bar/Toolbar.scss index ec98167332fbd..2f2daae32fec1 100644 --- a/frontend/src/toolbar/bar/Toolbar.scss +++ b/frontend/src/toolbar/bar/Toolbar.scss @@ -111,7 +111,7 @@ justify-content: space-between; // fixed width so that animations work when changing width - width: 15.2rem; + width: 18.2rem; overflow: hidden; color: var(--text-3000); background-color: var(--bg-3000); diff --git a/frontend/src/toolbar/bar/Toolbar.tsx b/frontend/src/toolbar/bar/Toolbar.tsx index 8ed031f904d86..f86cd490a3223 100644 --- a/frontend/src/toolbar/bar/Toolbar.tsx +++ b/frontend/src/toolbar/bar/Toolbar.tsx @@ -4,6 +4,7 @@ import { IconBolt, IconCursorClick, IconDay, + IconLive, IconLogomark, IconNight, IconQuestion, @@ -20,6 +21,7 @@ import { useEffect, useRef } from 'react' import { ActionsToolbarMenu } from '~/toolbar/actions/ActionsToolbarMenu' import { toolbarLogic } from '~/toolbar/bar/toolbarLogic' +import { EventDebugMenu } from '~/toolbar/debug/EventDebugMenu' import { FlagsToolbarMenu } from '~/toolbar/flags/FlagsToolbarMenu' import { HeatmapToolbarMenu } from '~/toolbar/stats/HeatmapToolbarMenu' import { toolbarConfigLogic } from '~/toolbar/toolbarConfigLogic' @@ -98,6 +100,8 @@ export function ToolbarInfoMenu(): JSX.Element | null { ) : visibleMenu === 'hedgehog' ? ( + ) : visibleMenu === 'debugger' ? ( + ) : null useEffect(() => { @@ -204,6 +208,9 @@ export function Toolbar(): JSX.Element { + + + ) : ( diff --git a/frontend/src/toolbar/bar/toolbarLogic.ts b/frontend/src/toolbar/bar/toolbarLogic.ts index 7b01c978dcd92..678a7529e532d 100644 --- a/frontend/src/toolbar/bar/toolbarLogic.ts +++ b/frontend/src/toolbar/bar/toolbarLogic.ts @@ -12,7 +12,7 @@ import type { toolbarLogicType } from './toolbarLogicType' const MARGIN = 2 -export type MenuState = 'none' | 'heatmap' | 'actions' | 'flags' | 'inspect' | 'hedgehog' +export type MenuState = 'none' | 'heatmap' | 'actions' | 'flags' | 'inspect' | 'hedgehog' | 'debugger' export const toolbarLogic = kea([ path(['toolbar', 'bar', 'toolbarLogic']), diff --git a/frontend/src/toolbar/debug/EventDebugMenu.tsx b/frontend/src/toolbar/debug/EventDebugMenu.tsx new file mode 100644 index 0000000000000..2346c769f4bbe --- /dev/null +++ b/frontend/src/toolbar/debug/EventDebugMenu.tsx @@ -0,0 +1,74 @@ +import clsx from 'clsx' +import { useActions, useValues } from 'kea' +import { AnimatedCollapsible } from 'lib/components/AnimatedCollapsible' +import { TZLabel } from 'lib/components/TZLabel' +import { LemonSwitch } from 'lib/lemon-ui/LemonSwitch' +import { SimpleKeyValueList } from 'scenes/session-recordings/player/inspector/components/SimpleKeyValueList' + +import { eventDebugMenuLogic } from '~/toolbar/debug/eventDebugMenuLogic' + +import { ToolbarMenu } from '../bar/ToolbarMenu' + +export const EventDebugMenu = (): JSX.Element => { + const { filteredEvents, isCollapsedEventRow, expandedEvent, showRecordingSnapshots, snapshotCount, eventCount } = + useValues(eventDebugMenuLogic) + const { markExpanded, setShowRecordingSnapshots } = useActions(eventDebugMenuLogic) + + return ( + + +
+
+ Seen {snapshotCount} events. + Seen {eventCount} recording snapshots. +
+
+ setShowRecordingSnapshots(c)} + label="Show recording snapshot events" + /> +
+
+
+ +
+ {filteredEvents.length ? ( + filteredEvents.map((e, i) => { + return ( +
{ + expandedEvent === e.uuid ? markExpanded(null) : markExpanded(e.uuid || null) + }} + > +
+
{e.event}
+
+ +
+
+ +
+ +
+
+
+ ) + }) + ) : ( +
+ Interact with your page and then come back to the toolbar to see what events were generated. +
+ )} +
+
+ + View events from this page as they are sent to PostHog. + +
+ ) +} diff --git a/frontend/src/toolbar/debug/eventDebugMenuLogic.ts b/frontend/src/toolbar/debug/eventDebugMenuLogic.ts new file mode 100644 index 0000000000000..1b490687c3ad2 --- /dev/null +++ b/frontend/src/toolbar/debug/eventDebugMenuLogic.ts @@ -0,0 +1,78 @@ +import { actions, afterMount, connect, kea, path, reducers, selectors } from 'kea' +import { uuid } from 'lib/utils' +import { permanentlyMount } from 'lib/utils/kea-logic-builders' + +import { toolbarConfigLogic } from '~/toolbar/toolbarConfigLogic' +import { EventType } from '~/types' + +import type { eventDebugMenuLogicType } from './eventDebugMenuLogicType' + +export const eventDebugMenuLogic = kea([ + path(['toolbar', 'debug', 'eventDebugMenuLogic']), + connect(() => ({ + values: [toolbarConfigLogic, ['posthog']], + })), + actions({ + addEvent: (event: EventType) => ({ event }), + markExpanded: (id: string | null) => ({ id }), + setShowRecordingSnapshots: (show: boolean) => ({ show }), + }), + reducers({ + events: [ + [] as EventType[], + { + addEvent: (state, { event }) => { + if (event.uuid) { + event.uuid = uuid() + } + return [event, ...state] + }, + }, + ], + expandedEvent: [ + null as string | null, + { + markExpanded: (_, { id }) => id, + }, + ], + showRecordingSnapshots: [ + false, + { + setShowRecordingSnapshots: (_, { show }) => show, + }, + ], + }), + selectors({ + isCollapsedEventRow: [ + (s) => [s.expandedEvent], + (expandedEvent) => { + return (eventId: string | null): boolean => { + return eventId !== expandedEvent + } + }, + ], + snapshotCount: [(s) => [s.events], (events) => events.filter((e) => e.event !== '$snapshot').length], + eventCount: [(s) => [s.events], (events) => events.filter((e) => e.event === '$snapshot').length], + filteredEvents: [ + (s) => [s.showRecordingSnapshots, s.events], + (showRecordingSnapshots, events) => { + return events.filter((e) => { + if (showRecordingSnapshots) { + return true + } else { + return e.event !== '$snapshot' + } + }) + }, + ], + }), + afterMount(({ values, actions }) => { + values.posthog?.on('eventCaptured', (e) => { + if (!e.uuid) { + e.uuid = uuid() + } + actions.addEvent(e) + }) + }), + permanentlyMount(), +]) diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 32bd062be1587..0e0cd64843f27 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -596,7 +596,6 @@ export enum SavedInsightsTabs { export enum ReplayTabs { Recent = 'recent', Playlists = 'playlists', - FilePlayback = 'file-playback', Errors = 'errors', } @@ -694,7 +693,6 @@ export interface ElementPropertyFilter extends BasePropertyFilter { export interface SessionPropertyFilter extends BasePropertyFilter { type: PropertyFilterType.Session - key: '$session_duration' operator: PropertyOperator } @@ -804,6 +802,7 @@ export type EncodedRecordingSnapshot = { export const SnapshotSourceType = { blob: 'blob', realtime: 'realtime', + file: 'file', } as const export type SnapshotSourceType = (typeof SnapshotSourceType)[keyof typeof SnapshotSourceType] @@ -813,7 +812,12 @@ export interface SessionRecordingSnapshotSource { start_timestamp?: string end_timestamp?: string blob_key?: string - loaded: boolean +} + +export interface SessionRecordingSnapshotSourceResponse { + source: Pick + snapshots?: RecordingSnapshot[] + untransformed_snapshots?: RecordingSnapshot[] } export interface SessionRecordingSnapshotResponse { @@ -1078,6 +1082,7 @@ export interface CohortCriteriaType { operator_value?: PropertyFilterValue time_value?: number | string | null time_interval?: TimeUnitType | null + explicit_datetime?: string | null total_periods?: number | null min_periods?: number | null seq_event_type?: TaxonomicFilterGroupType | null @@ -1086,6 +1091,7 @@ export interface CohortCriteriaType { seq_time_interval?: TimeUnitType | null negation?: boolean value_property?: string | null // Transformed into 'value' for api calls + event_filters?: AnyPropertyFilter[] | null } export type EmptyCohortGroupType = Partial diff --git a/mypy-baseline.txt b/mypy-baseline.txt index a82ceecb185ce..e64dd4ad0aeff 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -93,10 +93,6 @@ posthog/plugins/utils.py:0: error: Subclass of "str" and "bytes" cannot exist: w posthog/plugins/utils.py:0: error: Statement is unreachable [unreachable] posthog/models/filters/base_filter.py:0: error: "HogQLContext" has no attribute "person_on_events_mode" [attr-defined] posthog/hogql/database/database.py:0: error: "FieldOrTable" has no attribute "fields" [attr-defined] -posthog/hogql/database/database.py:0: error: "FieldOrTable" has no attribute "fields" [attr-defined] -posthog/hogql/database/database.py:0: error: "FieldOrTable" has no attribute "fields" [attr-defined] -posthog/hogql/database/database.py:0: error: "FieldOrTable" has no attribute "fields" [attr-defined] -posthog/hogql/database/database.py:0: error: "FieldOrTable" has no attribute "fields" [attr-defined] posthog/hogql/database/database.py:0: error: Incompatible types (expression has type "Literal['view', 'lazy_table']", TypedDict item "type" has type "Literal['integer', 'float', 'string', 'datetime', 'date', 'boolean', 'array', 'json', 'lazy_table', 'virtual_table', 'field_traverser', 'expression']") [typeddict-item] posthog/warehouse/models/datawarehouse_saved_query.py:0: error: Argument 1 to "create_hogql_database" has incompatible type "int | None"; expected "int" [arg-type] posthog/warehouse/models/datawarehouse_saved_query.py:0: error: Incompatible types in assignment (expression has type "Expr", variable has type "SelectQuery | SelectUnionQuery") [assignment] @@ -138,9 +134,6 @@ posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Dict ent posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Dict entry 0 has incompatible type "str": "LifecycleFilter"; expected "str": "TrendsFilter" [dict-item] posthog/hogql_queries/legacy_compatibility/filter_to_query.py:0: error: Dict entry 0 has incompatible type "str": "StickinessFilter"; expected "str": "TrendsFilter" [dict-item] posthog/hogql_queries/legacy_compatibility/feature_flag.py:0: error: Item "AnonymousUser" of "User | AnonymousUser" has no attribute "email" [union-attr] -posthog/hogql/functions/cohort.py:0: error: Argument 1 to "escape_clickhouse_string" has incompatible type "str | None"; expected "float | int | str | list[Any] | tuple[Any, ...] | date | datetime | UUID | UUIDT" [arg-type] -posthog/hogql/functions/cohort.py:0: error: Argument 1 to "escape_clickhouse_string" has incompatible type "str | None"; expected "float | int | str | list[Any] | tuple[Any, ...] | date | datetime | UUID | UUIDT" [arg-type] -posthog/hogql/functions/cohort.py:0: error: Incompatible types in assignment (expression has type "ValuesQuerySet[Cohort, tuple[int, bool | None]]", variable has type "ValuesQuerySet[Cohort, tuple[int, bool | None, str | None]]") [assignment] posthog/api/utils.py:0: error: Incompatible types in assignment (expression has type "type[EventDefinition]", variable has type "type[EnterpriseEventDefinition]") [assignment] posthog/api/utils.py:0: error: Argument 1 to "UUID" has incompatible type "int | str"; expected "str | None" [arg-type] ee/billing/quota_limiting.py:0: error: List comprehension has incompatible type List[int]; expected List[str] [misc] @@ -262,8 +255,6 @@ posthog/hogql/transforms/in_cohort.py:0: note: Use https://github.com/hauntsanin posthog/hogql/transforms/in_cohort.py:0: error: Incompatible default for argument "context" (default has type "None", argument has type "HogQLContext") [assignment] posthog/hogql/transforms/in_cohort.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True posthog/hogql/transforms/in_cohort.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -posthog/hogql/transforms/in_cohort.py:0: error: Argument 1 to "escape_clickhouse_string" has incompatible type "str | None"; expected "float | int | str | list[Any] | tuple[Any, ...] | date | datetime | UUID | UUIDT" [arg-type] -posthog/hogql/transforms/in_cohort.py:0: error: Argument 1 to "escape_clickhouse_string" has incompatible type "str | None"; expected "float | int | str | list[Any] | tuple[Any, ...] | date | datetime | UUID | UUIDT" [arg-type] posthog/hogql/transforms/in_cohort.py:0: error: Argument "is_static" to "_add_join_for_cohort" of "InCohortResolver" has incompatible type "bool | None"; expected "bool" [arg-type] posthog/hogql/transforms/in_cohort.py:0: error: Incompatible types in assignment (expression has type "ValuesQuerySet[Cohort, tuple[int, bool | None]]", variable has type "ValuesQuerySet[Cohort, tuple[int, bool | None, str | None]]") [assignment] posthog/hogql/transforms/in_cohort.py:0: error: Argument "is_static" to "_add_join_for_cohort" of "InCohortResolver" has incompatible type "bool | None"; expected "bool" [arg-type] @@ -560,7 +551,6 @@ posthog/hogql/test/test_modifiers.py:0: error: Unsupported right operand type fo posthog/hogql/test/test_modifiers.py:0: error: Unsupported right operand type for in ("str | None") [operator] posthog/hogql/test/test_modifiers.py:0: error: Unsupported right operand type for in ("str | None") [operator] posthog/hogql/test/test_modifiers.py:0: error: Unsupported right operand type for in ("str | None") [operator] -posthog/hogql/test/test_modifiers.py:0: error: Unsupported right operand type for in ("str | None") [operator] posthog/hogql/test/test_filters.py:0: error: Incompatible default for argument "placeholders" (default has type "None", argument has type "dict[str, Any]") [assignment] posthog/hogql/test/test_filters.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True posthog/hogql/test/test_filters.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase diff --git a/package.json b/package.json index 0f3802e21dc2f..ea73ec78683ac 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "pmtiles": "^2.11.0", "postcss": "^8.4.31", "postcss-preset-env": "^9.3.0", - "posthog-js": "1.121.0", + "posthog-js": "1.125.0", "posthog-js-lite": "2.5.0", "prettier": "^2.8.8", "prop-types": "^15.7.2", diff --git a/plugin-server/functional_tests/analytics-ingestion/happy-path.test.ts b/plugin-server/functional_tests/analytics-ingestion/happy-path.test.ts index c788526bbb562..efa5bd3d49eaf 100644 --- a/plugin-server/functional_tests/analytics-ingestion/happy-path.test.ts +++ b/plugin-server/functional_tests/analytics-ingestion/happy-path.test.ts @@ -203,7 +203,7 @@ test.concurrent(`event ingestion: can $set and update person properties`, async }) test.concurrent( - `event ingestion: $process_person=false drops expected fields, doesn't include person properties`, + `event ingestion: $process_person_profile=false drops expected fields, doesn't include person properties`, async () => { const teamId = await createTeam(organizationId) const distinctId = new UUIDT().toString() @@ -229,7 +229,7 @@ test.concurrent( uuid: properylessUuid, event: 'custom event', properties: { - $process_person: false, + $process_person_profile: false, $group_0: 'group_key', $set: { c: 3, @@ -251,7 +251,7 @@ test.concurrent( expect(event).toEqual( expect.objectContaining({ person_properties: {}, - properties: { uuid: properylessUuid, $sent_at: expect.any(String), $process_person: false }, + properties: { uuid: properylessUuid, $sent_at: expect.any(String), $process_person_profile: false }, person_mode: 'propertyless', }) ) diff --git a/plugin-server/src/config/config.ts b/plugin-server/src/config/config.ts index 1efc0ae9aa3e3..ea51dc1da394d 100644 --- a/plugin-server/src/config/config.ts +++ b/plugin-server/src/config/config.ts @@ -100,8 +100,6 @@ export function getDefaultConfig(): PluginsServerConfig { JOB_QUEUE_S3_PREFIX: '', CRASH_IF_NO_PERSISTENT_JOB_QUEUE: false, HEALTHCHECK_MAX_STALE_SECONDS: 2 * 60 * 60, // 2 hours - PISCINA_USE_ATOMICS: true, - PISCINA_ATOMICS_TIMEOUT: 5000, SITE_URL: null, KAFKA_PARTITIONS_CONSUMED_CONCURRENTLY: 1, CLICKHOUSE_DISABLE_EXTERNAL_SCHEMAS_TEAMS: '', diff --git a/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer-v3.ts b/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer-v3.ts index a910765ab146f..09d0be4537589 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer-v3.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer-v3.ts @@ -65,6 +65,8 @@ export interface TeamIDWithConfig { } /** + * @deprecated Delete reduceRecordingMessages and associated tests when deleting this. + * * The SessionRecordingIngesterV3 * relies on EFS network storage to avoid the need to delay kafka commits and instead uses the disk * as the persistent volume for both blob data and the metadata around ingestion. diff --git a/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts b/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts index 525fb6b19d857..18bd06a710c3f 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/session-recordings-consumer.ts @@ -36,9 +36,8 @@ import { bufferFileDir, getPartitionsForTopic, now, - parseKafkaMessage, + parseKafkaBatch, queryWatermarkOffsets, - reduceRecordingMessages, } from './utils' // Must require as `tsc` strips unused `import` statements and just requiring this seems to init some globals @@ -103,12 +102,6 @@ const histogramKafkaBatchSizeKb = new Histogram({ buckets: BUCKETS_KB_WRITTEN, }) -const counterKafkaMessageReceived = new Counter({ - name: 'recording_blob_ingestion_kafka_message_received', - help: 'The number of messages we have received from Kafka', - labelNames: ['partition'], -}) - const counterCommitSkippedDueToPotentiallyBlockingSession = new Counter({ name: 'recording_blob_ingestion_commit_skipped_due_to_potentially_blocking_session', help: 'The number of times we skipped committing due to a potentially blocking session', @@ -339,47 +332,30 @@ export class SessionRecordingIngester { histogramKafkaBatchSize.observe(messages.length) histogramKafkaBatchSizeKb.observe(messages.reduce((acc, m) => (m.value?.length ?? 0) + acc, 0) / 1024) - let recordingMessages: IncomingRecordingMessage[] = [] + let recordingMessages: IncomingRecordingMessage[] await runInstrumentedFunction({ statsKey: `recordingingester.handleEachBatch.parseKafkaMessages`, func: async () => { - const parsedMessages: IncomingRecordingMessage[] = [] - for (const message of messages) { - const { partition, offset, timestamp } = message - - this.partitionMetrics[partition] = this.partitionMetrics[partition] || {} - const metrics = this.partitionMetrics[partition] - - // If we don't have a last known commit then set it to the offset before as that must be the last commit - metrics.lastMessageOffset = offset - // For some reason timestamp can be null. If it isn't, update our ingestion metrics - metrics.lastMessageTimestamp = timestamp || metrics.lastMessageTimestamp - - counterKafkaMessageReceived.inc({ partition }) - - const recordingMessage = await parseKafkaMessage( - message, - (token) => - this.teamsRefresher.get().then((teams) => ({ - teamId: teams[token]?.teamId || null, - consoleLogIngestionEnabled: teams[token]?.consoleLogIngestionEnabled ?? true, - })), - this.sharedClusterProducerWrapper - ) - - if (recordingMessage) { - parsedMessages.push(recordingMessage) + const { sessions, partitionStats } = await parseKafkaBatch( + messages, + (token) => + this.teamsRefresher.get().then((teams) => ({ + teamId: teams[token]?.teamId || null, + consoleLogIngestionEnabled: teams[token]?.consoleLogIngestionEnabled ?? true, + })), + this.sharedClusterProducerWrapper + ) + recordingMessages = sessions + for (const partitionStat of partitionStats) { + const metrics = this.partitionMetrics[partitionStat.partition] ?? {} + metrics.lastMessageOffset = partitionStat.offset + if (partitionStat.timestamp) { + // Could be empty on Kafka versions before KIP-32 + metrics.lastMessageTimestamp = partitionStat.timestamp } + this.partitionMetrics[partitionStat.partition] = metrics } - - recordingMessages = reduceRecordingMessages(parsedMessages) - - // TODO: Track metric for how many messages we reduced - status.info('🔁', `blob_ingester_consumer - reduced batch`, { - originalSize: messages.length, - reducedSize: recordingMessages.length, - }) }, }) heartbeat() diff --git a/plugin-server/src/main/ingestion-queues/session-recording/types.ts b/plugin-server/src/main/ingestion-queues/session-recording/types.ts index d61dadda9279e..9dd09f44eec95 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/types.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/types.ts @@ -28,3 +28,17 @@ export type PersistedRecordingMessage = { window_id?: string data: any } + +export type BatchStats = { + /** + * Subset of the kafka Message class, used to report metrics only + */ + readonly partition: number + readonly offset: number + readonly timestamp?: number +} + +export type ParsedBatch = { + sessions: IncomingRecordingMessage[] + partitionStats: BatchStats[] +} diff --git a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts index 5774d233d95f0..86f232fa57458 100644 --- a/plugin-server/src/main/ingestion-queues/session-recording/utils.ts +++ b/plugin-server/src/main/ingestion-queues/session-recording/utils.ts @@ -11,7 +11,13 @@ import { cloneObject } from '../../../utils/utils' import { captureIngestionWarning } from '../../../worker/ingestion/utils' import { eventDroppedCounter } from '../metrics' import { TeamIDWithConfig } from './session-recordings-consumer' -import { IncomingRecordingMessage, PersistedRecordingMessage } from './types' +import { IncomingRecordingMessage, ParsedBatch, PersistedRecordingMessage } from './types' + +const counterKafkaMessageReceived = new Counter({ + name: 'recording_blob_ingestion_kafka_message_received', + help: 'The number of messages we have received from Kafka', + labelNames: ['partition'], +}) const counterLibVersionWarning = new Counter({ name: 'lib_version_warning_counter', @@ -293,6 +299,69 @@ export const parseKafkaMessage = async ( } } +export const parseKafkaBatch = async ( + /** + * Parses and validates a batch of Kafka messages, merges messages for the same session into a single + * IncomingRecordingMessage to amortize processing and computes per-partition statistics. + */ + messages: Message[], + getTeamFn: (s: string) => Promise, + ingestionWarningProducer: KafkaProducerWrapper | undefined +): Promise => { + const lastMessageForPartition: Map = new Map() + const parsedSessions: Map = new Map() + + for (const message of messages) { + const partition = message.partition + lastMessageForPartition.set(partition, message) // We can assume messages for a single partition are ordered + counterKafkaMessageReceived.inc({ partition }) + + const parsedMessage = await parseKafkaMessage(message, getTeamFn, ingestionWarningProducer) + if (!parsedMessage) { + continue + } + + const session_key = `${parsedMessage.team_id}:${parsedMessage.session_id}` + const existingMessage = parsedSessions.get(session_key) + if (existingMessage === undefined) { + // First message for this session key, store it and continue looping for more + parsedSessions.set(session_key, parsedMessage) + continue + } + + for (const [windowId, events] of Object.entries(parsedMessage.eventsByWindowId)) { + if (existingMessage.eventsByWindowId[windowId]) { + existingMessage.eventsByWindowId[windowId].push(...events) + } else { + existingMessage.eventsByWindowId[windowId] = events + } + } + existingMessage.metadata.rawSize += parsedMessage.metadata.rawSize + + // Update the events ranges + existingMessage.metadata.lowOffset = Math.min( + existingMessage.metadata.lowOffset, + parsedMessage.metadata.lowOffset + ) + existingMessage.metadata.highOffset = Math.max( + existingMessage.metadata.highOffset, + parsedMessage.metadata.highOffset + ) + + // Update the events ranges + existingMessage.eventsRange.start = Math.min(existingMessage.eventsRange.start, parsedMessage.eventsRange.start) + existingMessage.eventsRange.end = Math.max(existingMessage.eventsRange.end, parsedMessage.eventsRange.end) + } + + return { + sessions: Array.from(parsedSessions.values()), + partitionStats: Array.from(lastMessageForPartition.values()), // Just cast the last message into the small BatchStats interface + } +} + +/** + * @deprecated Delete when removing session-recordings-consumer-v3 + */ export const reduceRecordingMessages = (messages: IncomingRecordingMessage[]): IncomingRecordingMessage[] => { /** * It can happen that a single batch contains all messages for the same session. diff --git a/plugin-server/src/main/services/http-server.ts b/plugin-server/src/main/services/http-server.ts index 2914e5cd92208..85c154dab66e7 100644 --- a/plugin-server/src/main/services/http-server.ts +++ b/plugin-server/src/main/services/http-server.ts @@ -119,10 +119,7 @@ async function getProfileByType(req: Request, res: Response) { const type = req.params.type const durationSeconds = typeof req.query.seconds === 'string' ? parseInt(req.query.seconds) : 30 - // Additional params for sampling heap profile, higher precision means bigger profile. - // Defaults are taken from https://v8.github.io/api/head/classv8_1_1HeapProfiler.html - const interval = typeof req.query.interval === 'string' ? parseInt(req.query.interval) : 512 * 1024 - const depth = typeof req.query.depth === 'string' ? parseInt(req.query.depth) : 16 + const interval = typeof req.query.interval === 'string' ? parseInt(req.query.interval) : undefined const sendHeaders = function (extension: string) { const fileName = `${type}-${DateTime.now().toUTC().toFormat('yyyyMMdd-HHmmss')}.${extension}` @@ -141,10 +138,15 @@ async function getProfileByType(req: Request, res: Response) { switch (type) { case 'cpu': - v8Profiler.startProfiling('cpu', true) + // See https://v8docs.nodesource.com/node-18.16/d2/d34/classv8_1_1_cpu_profiler.html + const mode = req.query.mode === '0' ? 0 : 1 // Default to 1 = kCallerLineNumbers + v8Profiler.setSamplingInterval(interval ?? 1000) // in microseconds + v8Profiler.startProfiling('cpu', true, mode) finishProfile = () => v8Profiler.stopProfiling('cpu') case 'heap': - v8Profiler.startSamplingHeapProfiling(interval, depth) + // See https://v8docs.nodesource.com/node-18.16/d7/d76/classv8_1_1_heap_profiler.html + const depth = typeof req.query.depth === 'string' ? parseInt(req.query.depth) : 16 + v8Profiler.startSamplingHeapProfiling(interval ?? 512 * 1024, depth) finishProfile = () => v8Profiler.stopSamplingHeapProfiling() } diff --git a/plugin-server/src/types.ts b/plugin-server/src/types.ts index 92b3426452a21..4d09e06de4ba1 100644 --- a/plugin-server/src/types.ts +++ b/plugin-server/src/types.ts @@ -172,8 +172,6 @@ export interface PluginsServerConfig { JOB_QUEUE_S3_PREFIX: string // S3 filename prefix for the S3 job queue CRASH_IF_NO_PERSISTENT_JOB_QUEUE: boolean // refuse to start unless there is a properly configured persistent job queue (e.g. graphile) HEALTHCHECK_MAX_STALE_SECONDS: number // maximum number of seconds the plugin server can go without ingesting events before the healthcheck fails - PISCINA_USE_ATOMICS: boolean // corresponds to the piscina useAtomics config option (https://github.com/piscinajs/piscina#constructor-new-piscinaoptions) - PISCINA_ATOMICS_TIMEOUT: number // (advanced) corresponds to the length of time a piscina worker should block for when looking for tasks SITE_URL: string | null KAFKA_PARTITIONS_CONSUMED_CONCURRENTLY: number // (advanced) how many kafka partitions the plugin server should consume from concurrently CONVERSION_BUFFER_ENABLED: boolean @@ -391,7 +389,6 @@ export interface Plugin { capabilities?: PluginCapabilities metrics?: StoredPluginMetrics is_stateless?: boolean - skipped_for_personless?: boolean public_jobs?: Record log_level?: PluginLogLevel } diff --git a/plugin-server/src/utils/event.ts b/plugin-server/src/utils/event.ts index 87f8736cc00cd..748500afc13e1 100644 --- a/plugin-server/src/utils/event.ts +++ b/plugin-server/src/utils/event.ts @@ -111,9 +111,9 @@ export function convertToIngestionEvent(event: RawClickHouseEvent, skipElementsC } } -/// Does normalization steps involving the $process_person property. This is currently a separate +/// Does normalization steps involving the $process_person_profile property. This is currently a separate /// function because `normalizeEvent` is called from multiple places, some early in the pipeline, -/// and we want to have one trusted place where `$process_person` is handled and passed through +/// and we want to have one trusted place where `$process_person_profile` is handled and passed through /// all of the processing steps. /// /// If `formPipelineEvent` is removed this can easily be combined with `normalizeEvent`. @@ -132,11 +132,11 @@ export function normalizeProcessPerson(event: PluginEvent, processPerson: boolea delete properties.$unset // Recorded for clarity and so that the property exists if it is ever sent elsewhere, // e.g. for migrations. - properties.$process_person = false + properties.$process_person_profile = false } else { // Removed as it is the default, note that we have record the `person_mode` column // in ClickHouse for all events. - delete properties.$process_person + delete properties.$process_person_profile } event.properties = properties diff --git a/plugin-server/src/worker/config.ts b/plugin-server/src/worker/config.ts deleted file mode 100644 index d964e4c26c381..0000000000000 --- a/plugin-server/src/worker/config.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { PluginsServerConfig } from '../types' - -// Copy From: node_modules/piscina/src/index.ts -- copied because it's not exported -export interface PiscinaOptions { - filename?: string | null - minThreads?: number - maxThreads?: number - idleTimeout?: number - maxQueue?: number | 'auto' - concurrentTasksPerWorker?: number - useAtomics?: boolean - resourceLimits?: any - argv?: string[] - execArgv?: string[] - env?: any - workerData?: any - niceIncrement?: number - trackUnmanagedFds?: boolean - atomicsTimeout?: number -} - -export function createConfig(serverConfig: PluginsServerConfig, filename: string): PiscinaOptions { - const config: PiscinaOptions = { - filename, - workerData: { serverConfig }, - resourceLimits: { - stackSizeMb: 10, - }, - useAtomics: serverConfig.PISCINA_USE_ATOMICS, - atomicsTimeout: serverConfig.PISCINA_ATOMICS_TIMEOUT, - } - - if (serverConfig.WORKER_CONCURRENCY && serverConfig.WORKER_CONCURRENCY > 0) { - config.minThreads = serverConfig.WORKER_CONCURRENCY - config.maxThreads = serverConfig.WORKER_CONCURRENCY - } - - if (serverConfig.TASKS_PER_WORKER > 1) { - config.concurrentTasksPerWorker = serverConfig.TASKS_PER_WORKER - } - - return config -} diff --git a/plugin-server/src/worker/ingestion/event-pipeline/pluginsProcessEventStep.ts b/plugin-server/src/worker/ingestion/event-pipeline/pluginsProcessEventStep.ts index a6069160383af..05e3a839e12b5 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/pluginsProcessEventStep.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/pluginsProcessEventStep.ts @@ -7,14 +7,13 @@ import { EventPipelineRunner } from './runner' export async function pluginsProcessEventStep( runner: EventPipelineRunner, - event: PluginEvent, - runDeprecatedPlugins: boolean + event: PluginEvent ): Promise { const processedEvent = await runInstrumentedFunction({ timeoutContext: () => ({ event: JSON.stringify(event), }), - func: () => runProcessEvent(runner.hub, event, runDeprecatedPlugins), + func: () => runProcessEvent(runner.hub, event), statsKey: 'kafka_queue.single_event', timeoutMessage: 'Still running plugins on event. Timeout warning after 30 sec!', teamId: event.team_id, diff --git a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts index c5c8e742cd083..9ad11391f0c2f 100644 --- a/plugin-server/src/worker/ingestion/event-pipeline/runner.ts +++ b/plugin-server/src/worker/ingestion/event-pipeline/runner.ts @@ -123,8 +123,8 @@ export class EventPipelineRunner { const kafkaAcks: Promise[] = [] let processPerson = true // The default. - if (event.properties && '$process_person' in event.properties) { - const propValue = event.properties.$process_person + if (event.properties && '$process_person_profile' in event.properties) { + const propValue = event.properties.$process_person_profile if (propValue === true) { // This is the default, and `true` is one of the two valid values. } else if (propValue === false) { @@ -136,7 +136,7 @@ export class EventPipelineRunner { captureIngestionWarning( this.hub.db.kafkaProducer, event.team_id, - 'invalid_event_when_process_person_is_false', + 'invalid_event_when_process_person_profile_is_false', { eventUuid: event.uuid, event: event.event, @@ -159,13 +159,13 @@ export class EventPipelineRunner { captureIngestionWarning( this.hub.db.kafkaProducer, event.team_id, - 'invalid_process_person', + 'invalid_process_person_profile', { eventUuid: event.uuid, event: event.event, distinctId: event.distinct_id, - $process_person: propValue, - message: 'Only a boolean value is valid for the $process_person property', + $process_person_profile: propValue, + message: 'Only a boolean value is valid for the $process_person_profile property', }, { alwaysSend: false } ) @@ -192,14 +192,7 @@ export class EventPipelineRunner { return this.registerLastStep('clientIngestionWarning', [event], kafkaAcks) } - // Some expensive, deprecated plugins are skipped when `$process_person=false` - const runDeprecatedPlugins = processPerson - const processedEvent = await this.runStep( - pluginsProcessEventStep, - [this, event, runDeprecatedPlugins], - event.team_id - ) - + const processedEvent = await this.runStep(pluginsProcessEventStep, [this, event], event.team_id) if (processedEvent == null) { // A plugin dropped the event. return this.registerLastStep('pluginsProcessEventStep', [event], kafkaAcks) diff --git a/plugin-server/src/worker/ingestion/person-state.ts b/plugin-server/src/worker/ingestion/person-state.ts index a71f8ee31acaa..00468129cfefc 100644 --- a/plugin-server/src/worker/ingestion/person-state.ts +++ b/plugin-server/src/worker/ingestion/person-state.ts @@ -90,7 +90,7 @@ export class PersonState { private teamId: number, private distinctId: string, private timestamp: DateTime, - private processPerson: boolean, // $process_person flag from the event + private processPerson: boolean, // $process_person_profile flag from the event private db: DB, private personOverrideWriter?: DeferredPersonOverrideWriter, uuid: UUIDT | undefined = undefined diff --git a/plugin-server/src/worker/plugins/loadPluginsFromDB.ts b/plugin-server/src/worker/plugins/loadPluginsFromDB.ts index 60fa35b34ef76..81282e0646794 100644 --- a/plugin-server/src/worker/plugins/loadPluginsFromDB.ts +++ b/plugin-server/src/worker/plugins/loadPluginsFromDB.ts @@ -25,16 +25,6 @@ const loadPluginsTotalMsSummary = new Summary({ percentiles: [0.5, 0.9, 0.95, 0.99], }) -// These are plugins that do I/O (fetch, cache, storage) that we want to deprecate. For now, we -// want to at least ensure they don't run for "personless" ($process_person=false) events. -const personlessPluginSkipList = [ - 'https://github.com/posthog/currency-normalization-plugin', - 'https://github.com/posthog/event-sequence-timer-plugin', - 'https://github.com/posthog/first-event-today', - 'https://github.com/posthog/first-time-event-tracker', - 'https://github.com/posthog/mailboxlayer-plugin', -] - export async function loadPluginsFromDB( hub: Hub ): Promise> { @@ -43,9 +33,6 @@ export async function loadPluginsFromDB( const plugins = new Map() for (const row of pluginRows) { - if (row.url && personlessPluginSkipList.includes(row.url.toLowerCase())) { - row.skipped_for_personless = true - } plugins.set(row.id, row) } loadPluginsMsSummary.observe(new Date().getTime() - startTimer.getTime()) diff --git a/plugin-server/src/worker/plugins/run.ts b/plugin-server/src/worker/plugins/run.ts index 30823adf66326..b0226fc57b145 100644 --- a/plugin-server/src/worker/plugins/run.ts +++ b/plugin-server/src/worker/plugins/run.ts @@ -208,13 +208,9 @@ export async function runComposeWebhook(hub: Hub, event: PostHogEvent): Promise< ) } -export async function runProcessEvent( - hub: Hub, - event: PluginEvent, - runDeprecatedPlugins = true -): Promise { +export async function runProcessEvent(hub: Hub, event: PluginEvent): Promise { const teamId = event.team_id - const pluginMethodsToRun = await getPluginMethodsForTeam(hub, teamId, 'processEvent', runDeprecatedPlugins) + const pluginMethodsToRun = await getPluginMethodsForTeam(hub, teamId, 'processEvent') let returnedEvent: PluginEvent | null = event const pluginsSucceeded: string[] = event.properties?.$plugins_succeeded || [] @@ -358,12 +354,9 @@ export async function runPluginTask( async function getPluginMethodsForTeam( hub: Hub, teamId: number, - method: M, - runDeprecatedPlugins = true + method: M ): Promise<[PluginConfig, VMMethods[M]][]> { - const pluginConfigs = (hub.pluginConfigsPerTeam.get(teamId) || []).filter((pluginConfig: PluginConfig) => - runDeprecatedPlugins ? true : !pluginConfig.plugin?.skipped_for_personless - ) + const pluginConfigs = hub.pluginConfigsPerTeam.get(teamId) || [] if (pluginConfigs.length === 0) { return [] } diff --git a/plugin-server/tests/main/ingestion-queues/session-recording/__snapshots__/utils.test.ts.snap b/plugin-server/tests/main/ingestion-queues/session-recording/__snapshots__/utils.test.ts.snap index 87ca515b22bd6..9a708df6f6c18 100644 --- a/plugin-server/tests/main/ingestion-queues/session-recording/__snapshots__/utils.test.ts.snap +++ b/plugin-server/tests/main/ingestion-queues/session-recording/__snapshots__/utils.test.ts.snap @@ -98,7 +98,174 @@ Array [ ] `; -exports[`session-recording utils parsing the message can parse a message correctly 1`] = ` +exports[`session-recording utils parseKafkaBatch can parse and reduce a batch of messages 1`] = ` +Array [ + Object { + "distinct_id": "c3936f0b-875f-4992-8e8a-26499d1f3a0a", + "eventsByWindowId": Object { + "b8d205d5-dd89-4465-b2d5-eb4d1eceb3ea": Array [ + Object { + "data": Object {}, + "timestamp": 123, + "type": 6, + }, + Object { + "data": Object {}, + "timestamp": 438, + "type": 6, + }, + ], + "c74d85fa-ccbb-43ba-981c-5e7d17f211de": Array [ + Object { + "data": Object {}, + "timestamp": 433, + "type": 6, + }, + ], + }, + "eventsRange": Object { + "end": 438, + "start": 123, + }, + "metadata": Object { + "consoleLogIngestionEnabled": true, + "highOffset": 235, + "lowOffset": 232, + "partition": 1, + "rawSize": 13, + "timestamp": 100, + "topic": "the_topic", + }, + "session_id": "e38da031-6341-4db8-ab00-af04f91f9962", + "snapshot_source": undefined, + "team_id": 1, + }, + Object { + "distinct_id": "207f0e52-f265-4932-86e5-cec62844d990", + "eventsByWindowId": Object { + "0bbe7878-6516-46b2-80cf-e387839d7313": Array [ + Object { + "data": Object {}, + "timestamp": 222, + "type": 6, + }, + ], + }, + "eventsRange": Object { + "end": 222, + "start": 222, + }, + "metadata": Object { + "consoleLogIngestionEnabled": true, + "highOffset": 233, + "lowOffset": 233, + "partition": 1, + "rawSize": 30, + "timestamp": 101, + "topic": "the_topic", + }, + "session_id": "1fc12a30-5a0f-4af8-808a-328423acf0c4", + "snapshot_source": undefined, + "team_id": 1, + }, + Object { + "distinct_id": "9696eba5-4f24-4f06-957b-10f98e26f2a9", + "eventsByWindowId": Object { + "1260fae8-08b5-4e5f-bea1-b8abd6250b70": Array [ + Object { + "data": Object {}, + "timestamp": 432, + "type": 6, + }, + ], + }, + "eventsRange": Object { + "end": 432, + "start": 432, + }, + "metadata": Object { + "consoleLogIngestionEnabled": true, + "highOffset": 500, + "lowOffset": 500, + "partition": 2, + "rawSize": 100, + "timestamp": 98, + "topic": "the_topic", + }, + "session_id": "cb91c812-98d0-4d5f-ae88-ffb68b7f51d3", + "snapshot_source": undefined, + "team_id": 1, + }, +] +`; + +exports[`session-recording utils parseKafkaBatch does not merge sessions for different teams 1`] = ` +Array [ + Object { + "distinct_id": "c3936f0b-875f-4992-8e8a-26499d1f3a0a", + "eventsByWindowId": Object { + "b8d205d5-dd89-4465-b2d5-eb4d1eceb3ea": Array [ + Object { + "data": Object {}, + "timestamp": 123, + "type": 6, + }, + Object { + "data": Object {}, + "timestamp": 124, + "type": 6, + }, + ], + }, + "eventsRange": Object { + "end": 124, + "start": 123, + }, + "metadata": Object { + "consoleLogIngestionEnabled": true, + "highOffset": 233, + "lowOffset": 232, + "partition": 1, + "rawSize": 9, + "timestamp": 100, + "topic": "the_topic", + }, + "session_id": "e38da031-6341-4db8-ab00-af04f91f9962", + "snapshot_source": undefined, + "team_id": 9, + }, + Object { + "distinct_id": "c3936f0b-875f-4992-8e8a-26499d1f3a0a", + "eventsByWindowId": Object { + "b8d205d5-dd89-4465-b2d5-eb4d1eceb3ea": Array [ + Object { + "data": Object {}, + "timestamp": 127, + "type": 6, + }, + ], + }, + "eventsRange": Object { + "end": 127, + "start": 127, + }, + "metadata": Object { + "consoleLogIngestionEnabled": true, + "highOffset": 234, + "lowOffset": 234, + "partition": 1, + "rawSize": 20, + "timestamp": 103, + "topic": "the_topic", + }, + "session_id": "e38da031-6341-4db8-ab00-af04f91f9962", + "snapshot_source": undefined, + "team_id": 13, + }, +] +`; + +exports[`session-recording utils parseKafkaMessage can parse a message correctly 1`] = ` Object { "distinct_id": "my-distinct-id", "eventsByWindowId": Object { diff --git a/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts b/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts index aa16c8a08a704..4e8f71f0cb27c 100644 --- a/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts +++ b/plugin-server/tests/main/ingestion-queues/session-recording/utils.test.ts @@ -7,10 +7,12 @@ import { getLagMultiplier, maxDefined, minDefined, + parseKafkaBatch, parseKafkaMessage, reduceRecordingMessages, } from '../../../../src/main/ingestion-queues/session-recording/utils' import { KafkaProducerWrapper } from '../../../../src/utils/db/kafka-producer-wrapper' +import { UUIDT } from '../../../../src/utils/utils' describe('session-recording utils', () => { const validMessage = (distinctId: number | string, headers?: MessageHeader[], value?: Record) => @@ -65,7 +67,7 @@ describe('session-recording utils', () => { partition: 1, } satisfies Message) - describe('parsing the message', () => { + describe('parseKafkaMessage', () => { let fakeProducer: KafkaProducerWrapper beforeEach(() => { Settings.now = () => new Date('2023-08-30T19:15:54.887316+00:00').getTime() @@ -345,6 +347,375 @@ describe('session-recording utils', () => { }) }) + describe('parseKafkaBatch', () => { + let fakeProducer: KafkaProducerWrapper + beforeEach(() => { + Settings.now = () => new Date('2023-08-30T19:15:54.887316+00:00').getTime() + fakeProducer = { queueMessage: jest.fn() } as unknown as KafkaProducerWrapper + }) + + it('can parse and reduce a batch of messages', async () => { + const sessions = [ + { + distinct_id: 'c3936f0b-875f-4992-8e8a-26499d1f3a0a', + $session_id: 'e38da031-6341-4db8-ab00-af04f91f9962', + $window_id: 'b8d205d5-dd89-4465-b2d5-eb4d1eceb3ea', + }, + { + distinct_id: '207f0e52-f265-4932-86e5-cec62844d990', + $session_id: '1fc12a30-5a0f-4af8-808a-328423acf0c4', + $window_id: '0bbe7878-6516-46b2-80cf-e387839d7313', + }, + { + distinct_id: '9696eba5-4f24-4f06-957b-10f98e26f2a9', + $session_id: 'cb91c812-98d0-4d5f-ae88-ffb68b7f51d3', + $window_id: '1260fae8-08b5-4e5f-bea1-b8abd6250b70', + }, + ] + const otherWindowId = 'c74d85fa-ccbb-43ba-981c-5e7d17f211de' + const eventUuids = Array.from(Array(6), () => new UUIDT().toString()) + const headers = [{ token: Buffer.from('the_token') }] + + const messages: Message[] = [ + // Six messages for three sessions on two partitions, second is invalid. + // The first session has three events on two windows. + { + headers, + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[0], + distinct_id: sessions[0].distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[0], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + type: 6, + data: {}, + timestamp: null, // Invalid, item will be skipped + }, + { + type: 6, + data: {}, + timestamp: 123, + }, + ], + ...sessions[0], + }, + }), + token: 'the_token', + }) + ), + timestamp: 100, + size: 5, + topic: 'the_topic', + offset: 232, + partition: 1, + }, + { + headers, + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[1], + distinct_id: sessions[2].distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({}), // Invalid, message will be skipped + token: 'the_token', + }) + ), + timestamp: 96, + size: 100, + topic: 'the_topic', + offset: 499, + partition: 2, + }, + { + headers, + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[2], + distinct_id: sessions[1].distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[2], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + data: {}, + timestamp: 222, + type: 6, + }, + ], + ...sessions[1], + }, + }), + token: 'the_token', + }) + ), + timestamp: 101, + size: 30, + topic: 'the_topic', + offset: 233, + partition: 1, + }, + { + headers, + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[3], + distinct_id: sessions[2].distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[3], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + data: {}, + timestamp: 432, + type: 6, + }, + ], + ...sessions[2], + }, + }), + token: 'the_token', + }) + ), + timestamp: 98, + size: 100, + topic: 'the_topic', + offset: 500, + partition: 2, + }, + { + headers, + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[4], + distinct_id: sessions[0].distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[4], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + data: {}, + timestamp: 433, + type: 6, + }, + ], + ...sessions[0], + $window_id: otherWindowId, + }, + }), + token: 'the_token', + }) + ), + timestamp: 106, + size: 4, + topic: 'the_topic', + offset: 234, + partition: 1, + }, + { + headers, + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[5], + distinct_id: sessions[0].distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[5], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + data: {}, + timestamp: 438, + type: 6, + }, + ], + ...sessions[0], + }, + }), + token: 'the_token', + }) + ), + timestamp: 107, + size: 4, + topic: 'the_topic', + offset: 235, + partition: 1, + }, + ] + + const parsedBatch = await parseKafkaBatch( + messages, + () => + Promise.resolve({ + teamId: 1, + consoleLogIngestionEnabled: true, + }), + fakeProducer + ) + + // Check returned partition statistics + expect(parsedBatch.partitionStats).toHaveLength(2) + parsedBatch.partitionStats.sort((a, b) => { + return a.partition - b.partition + }) + expect(parsedBatch.partitionStats[0]).toMatchObject({ + partition: 1, + offset: 235, + timestamp: 107, + }) + expect(parsedBatch.partitionStats[1]).toMatchObject({ + partition: 2, + offset: 500, + timestamp: 98, + }) + + // Check aggregated session data + expect(parsedBatch.sessions).toHaveLength(3) + expect(parsedBatch.sessions[0].eventsByWindowId[sessions[0].$window_id]).toHaveLength(2) + expect(parsedBatch.sessions[0].eventsByWindowId[otherWindowId]).toHaveLength(1) + expect(parsedBatch.sessions).toMatchSnapshot() + }) + + it('does not merge sessions for different teams', async () => { + const session = { + distinct_id: 'c3936f0b-875f-4992-8e8a-26499d1f3a0a', + $session_id: 'e38da031-6341-4db8-ab00-af04f91f9962', + $window_id: 'b8d205d5-dd89-4465-b2d5-eb4d1eceb3ea', + } + const eventUuids = Array.from(Array(3), () => new UUIDT().toString()) + + const messages: Message[] = [ + // Three messages with the same distinct_id and $session_id but two different tokens + { + headers: [{ token: Buffer.from('one_token') }], + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[0], + distinct_id: session.distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[0], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + type: 6, + data: {}, + timestamp: 123, + }, + ], + ...session, + }, + }), + token: 'one_token', + }) + ), + timestamp: 100, + size: 5, + topic: 'the_topic', + offset: 232, + partition: 1, + }, + { + headers: [{ token: Buffer.from('one_token') }], + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[0], + distinct_id: session.distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[0], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + type: 6, + data: {}, + timestamp: 124, + }, + ], + ...session, + }, + }), + token: 'one_token', + }) + ), + timestamp: 101, + size: 4, + topic: 'the_topic', + offset: 233, + partition: 1, + }, + { + headers: [{ token: Buffer.from('another_token') }], + value: Buffer.from( + JSON.stringify({ + uuid: eventUuids[0], + distinct_id: session.distinct_id, + ip: '127.0.0.1', + site_url: 'http://127.0.0.1:8000', + data: JSON.stringify({ + uuid: eventUuids[0], + event: '$snapshot_items', + properties: { + $snapshot_items: [ + { + type: 6, + data: {}, + timestamp: 127, + }, + ], + ...session, + }, + }), + token: 'another_token', + }) + ), + timestamp: 103, + size: 20, + topic: 'the_topic', + offset: 234, + partition: 1, + }, + ] + + const parsedBatch = await parseKafkaBatch( + messages, + (token: string) => + Promise.resolve({ + teamId: token.length, + consoleLogIngestionEnabled: true, + }), + fakeProducer + ) + + // Check aggregated session data + expect(parsedBatch.sessions).toHaveLength(2) + expect(parsedBatch.sessions[0].team_id).toEqual(9) + expect(parsedBatch.sessions[1].team_id).toEqual(13) + expect(parsedBatch.sessions).toMatchSnapshot() + }) + }) + describe('reduceMessages', () => { const messages: IncomingRecordingMessage[] = [ // Should merge diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/runner.test.ts.snap b/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/runner.test.ts.snap index 9e2e872a5b484..9cd0d244500ae 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/runner.test.ts.snap +++ b/plugin-server/tests/worker/ingestion/event-pipeline/__snapshots__/runner.test.ts.snap @@ -33,7 +33,6 @@ Array [ "timestamp": "2020-02-23T02:15:00.000Z", "uuid": "uuid1", }, - true, ], ], Array [ diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/normalizeEventStep.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/normalizeEventStep.test.ts index 52b659808597a..8fda4db2f2e93 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/normalizeEventStep.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/normalizeEventStep.test.ts @@ -25,7 +25,7 @@ describe('normalizeEventStep()', () => { a: 5, }, $browser: 'Chrome', - $process_person: true, // This is dropped, as it is implied + $process_person_profile: true, // This is dropped, as it is implied }, $set: { someProp: 'value', @@ -54,7 +54,7 @@ describe('normalizeEventStep()', () => { expect(timestamp).toEqual(DateTime.fromISO(event.timestamp!, { zone: 'utc' })) }) - it('normalizes $process_person=false events by dropping $set and related', async () => { + it('normalizes $process_person_profile=false events by dropping $set and related', async () => { await resetTestDatabase() const [hub, _] = await createHub() const organizationId = await createOrganization(hub.db.postgres) @@ -94,7 +94,7 @@ describe('normalizeEventStep()', () => { ...event, properties: { $browser: 'Chrome', - $process_person: false, + $process_person_profile: false, }, }) diff --git a/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts b/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts index c055b704eb37b..818d96f2656dc 100644 --- a/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts +++ b/plugin-server/tests/worker/ingestion/event-pipeline/runner.test.ts @@ -286,12 +286,12 @@ describe('EventPipelineRunner', () => { }) }) -describe('EventPipelineRunner $process_person=false', () => { - it('drops events that are not allowed when $process_person=false', async () => { +describe('EventPipelineRunner $process_person_profile=false', () => { + it('drops events that are not allowed when $process_person_profile=false', async () => { for (const eventName of ['$identify', '$create_alias', '$merge_dangerously', '$groupidentify']) { const event = { ...pipelineEvent, - properties: { $process_person: false }, + properties: { $process_person_profile: false }, event: eventName, team_id: 9, } @@ -311,7 +311,7 @@ describe('EventPipelineRunner $process_person=false', () => { JSON.parse(hub.db.kafkaProducer.queueMessage.mock.calls[0][0].kafkaMessage.messages[0].value) ).toMatchObject({ team_id: 9, - type: 'invalid_event_when_process_person_is_false', + type: 'invalid_event_when_process_person_profile_is_false', details: JSON.stringify({ eventUuid: 'uuid1', event: eventName, distinctId: 'my_id' }), }) } diff --git a/plugin-server/tests/worker/ingestion/person-state.test.ts b/plugin-server/tests/worker/ingestion/person-state.test.ts index 3423ad01f6ab6..09d5e7e58784b 100644 --- a/plugin-server/tests/worker/ingestion/person-state.test.ts +++ b/plugin-server/tests/worker/ingestion/person-state.test.ts @@ -173,8 +173,8 @@ describe('PersonState.update()', () => { expect(distinctIds).toEqual(expect.arrayContaining(['new-user'])) }) - it('creates person if they are new and $process_person=false', async () => { - // Note that eventually $process_person=false will be optimized so that the person is + it('creates person if they are new and $process_person_profile=false', async () => { + // Note that eventually $process_person_profile=false will be optimized so that the person is // *not* created here. const event_uuid = new UUIDT().toString() const processPerson = false @@ -183,7 +183,7 @@ describe('PersonState.update()', () => { event: '$pageview', distinct_id: 'new-user', uuid: event_uuid, - properties: { $process_person: false, $set: { a: 1 }, $set_once: { b: 2 } }, + properties: { $process_person_profile: false, $set: { a: 1 }, $set_once: { b: 2 } }, }, hub, processPerson @@ -216,7 +216,7 @@ describe('PersonState.update()', () => { expect(distinctIds).toEqual(expect.arrayContaining(['new-user'])) }) - it('does not attach existing person properties to $process_person=false events', async () => { + it('does not attach existing person properties to $process_person_profile=false events', async () => { const originalEventUuid = new UUIDT().toString() const person = await personState({ event: '$pageview', @@ -256,7 +256,7 @@ describe('PersonState.update()', () => { }).update() expect(personVerifyProps.properties).toEqual({ $creator_event_uuid: originalEventUuid, c: 420 }) - // But they don't when $process_person=false + // But they don't when $process_person_profile=false const processPersonFalseResult = await personState( { event: '$pageview', diff --git a/plugin-server/tests/worker/ingestion/process-event.test.ts b/plugin-server/tests/worker/ingestion/process-event.test.ts index 9e6c346c40675..19f822fbb0b6e 100644 --- a/plugin-server/tests/worker/ingestion/process-event.test.ts +++ b/plugin-server/tests/worker/ingestion/process-event.test.ts @@ -142,7 +142,7 @@ describe('EventsProcessor#createEvent()', () => { ) }) - it('when $process_person=false, emits event with without person properties or groups', async () => { + it('when $process_person_profile=false, emits event with without person properties or groups', async () => { const processPerson = false await eventsProcessor.createEvent( { ...preIngestionEvent, properties: { $group_0: 'group_key' } }, diff --git a/plugin-server/tests/worker/plugins.test.ts b/plugin-server/tests/worker/plugins.test.ts index 9909f01301d7e..47f0596228a85 100644 --- a/plugin-server/tests/worker/plugins.test.ts +++ b/plugin-server/tests/worker/plugins.test.ts @@ -44,11 +44,9 @@ describe('plugins', () => { }) test('setupPlugins and runProcessEvent', async () => { - // Use a Plugin URL that is skipped for "personless" ($process_person=false) events. - const plugin = { ...plugin60, url: 'https://github.com/posthog/first-event-today' } - getPluginRows.mockReturnValueOnce([plugin]) + getPluginRows.mockReturnValueOnce([{ ...plugin60 }]) getPluginAttachmentRows.mockReturnValueOnce([pluginAttachment1]) - getPluginConfigRows.mockReturnValueOnce([{ ...pluginConfig39, plugin: plugin }]) + getPluginConfigRows.mockReturnValueOnce([pluginConfig39]) await setupPlugins(hub) const { plugins, pluginConfigs } = hub @@ -69,7 +67,7 @@ describe('plugins', () => { expect(pluginConfig.error).toEqual(pluginConfig39.error) expect(pluginConfig.plugin).toEqual({ - ...plugin, + ...plugin60, capabilities: { jobs: [], scheduled_tasks: [], methods: ['processEvent'] }, }) @@ -97,7 +95,7 @@ describe('plugins', () => { [ 60, { - ...plugin, + ...plugin60, capabilities: { jobs: [], scheduled_tasks: [], methods: ['processEvent'] }, }, ], @@ -114,13 +112,6 @@ describe('plugins', () => { const returnedEvent = await runProcessEvent(hub, event) expect(event.properties!['processed']).toEqual(true) expect(returnedEvent!.properties!['processed']).toEqual(true) - - // Personless event skips the plugin - const personlessEvent = { event: '$test', properties: {}, team_id: 2 } as PluginEvent - const runDeprecatedPlugins = false - const returnedPersonlessEvent = await runProcessEvent(hub, personlessEvent, runDeprecatedPlugins) - expect(personlessEvent.properties!['processed']).toEqual(undefined) - expect(returnedPersonlessEvent!.properties!['processed']).toEqual(undefined) }) test('stateless plugins', async () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d1023255f099..a93193deb0284 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -254,8 +254,8 @@ dependencies: specifier: ^9.3.0 version: 9.3.0(postcss@8.4.31) posthog-js: - specifier: 1.121.0 - version: 1.121.0 + specifier: 1.125.0 + version: 1.125.0 posthog-js-lite: specifier: 2.5.0 version: 2.5.0 @@ -6289,7 +6289,7 @@ packages: '@storybook/client-logger': 7.6.17 '@storybook/core-events': 7.6.17 '@storybook/global': 5.0.0 - qs: 6.12.0 + qs: 6.12.1 telejson: 7.2.0 tiny-invariant: 1.3.3 dev: true @@ -6646,8 +6646,8 @@ packages: type-fest: 2.19.0 dev: true - /@storybook/csf@0.1.3: - resolution: {integrity: sha512-IPZvXXo4b3G+gpmgBSBqVM81jbp2ePOKsvhgJdhyZJtkYQCII7rg9KKLQhvBQM5sLaF1eU6r0iuwmyynC9d9SA==} + /@storybook/csf@0.1.4: + resolution: {integrity: sha512-B9UI/lsQMjF+oEfZCI6YXNoeuBcGZoOP5x8yKbe2tIEmsMjSztFKkpPzi5nLCnBk/MBtl6QJeI3ksJnbsWPkOw==} dependencies: type-fest: 2.19.0 dev: true @@ -6681,7 +6681,7 @@ packages: '@storybook/channels': 7.6.17 '@storybook/client-logger': 7.6.17 '@storybook/core-events': 7.6.17 - '@storybook/csf': 0.1.3 + '@storybook/csf': 0.1.4 '@storybook/global': 5.0.0 '@storybook/router': 7.6.17 '@storybook/theming': 7.6.17(react-dom@18.2.0)(react@18.2.0) @@ -6796,14 +6796,14 @@ packages: '@storybook/channels': 7.6.17 '@storybook/client-logger': 7.6.17 '@storybook/core-events': 7.6.17 - '@storybook/csf': 0.1.3 + '@storybook/csf': 0.1.4 '@storybook/global': 5.0.0 '@storybook/types': 7.6.17 - '@types/qs': 6.9.14 + '@types/qs': 6.9.15 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 - qs: 6.12.0 + qs: 6.12.1 synchronous-promise: 2.0.17 ts-dedent: 2.2.0 util-deprecate: 1.0.2 @@ -6963,7 +6963,7 @@ packages: dependencies: '@storybook/client-logger': 7.6.17 memoizerific: 1.11.3 - qs: 6.12.0 + qs: 6.12.1 dev: true /@storybook/router@7.6.4: @@ -8203,8 +8203,8 @@ packages: resolution: {integrity: sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==} dev: false - /@types/qs@6.9.14: - resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} + /@types/qs@6.9.15: + resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} dev: true /@types/query-selector-shadow-dom@1.0.0: @@ -17457,8 +17457,8 @@ packages: resolution: {integrity: sha512-Urvlp0Vu9h3td0BVFWt0QXFJDoOZcaAD83XM9d91NKMKTVPZtfU0ysoxstIf5mw/ce9ZfuMgpWPaagrZI4rmSg==} dev: false - /posthog-js@1.121.0: - resolution: {integrity: sha512-tjWPQevOs/xWDX99CUB4yp03US0hOSjmLx7fHn+5JNRvJ14pAPffuMDvNyogcBM5of08E0i+ajOzMmu7vhighw==} + /posthog-js@1.125.0: + resolution: {integrity: sha512-9DZIwIMvq6X6lL1GCzs+bibJ6L+hYhlv9T+OmA/PIGQmI1vSC8YJtUIFm94X1SeQ6oIYz/ZWebGD/owFuJFZOw==} dependencies: fflate: 0.4.8 preact: 10.20.2 @@ -17843,6 +17843,13 @@ packages: side-channel: 1.0.6 dev: true + /qs@6.12.1: + resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.6 + dev: true + /qs@6.9.7: resolution: {integrity: sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==} engines: {node: '>=0.6'} diff --git a/posthog/api/action.py b/posthog/api/action.py index 37a9d8ec94963..8c3caf435e343 100644 --- a/posthog/api/action.py +++ b/posthog/api/action.py @@ -1,30 +1,21 @@ -from typing import Any, Dict, List, Optional, cast +from typing import Any, Dict, List, cast -from dateutil.relativedelta import relativedelta from django.db.models import Count, Prefetch -from django.utils.timezone import now from rest_framework import request, serializers, viewsets -from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.settings import api_settings from rest_framework_csv import renderers as csvrenderers from posthog.api.routing import TeamAndOrgViewSetMixin from posthog.api.shared import UserBasicSerializer -from posthog.api.utils import get_target_entity from posthog.auth import ( TemporaryTokenAuthentication, ) -from posthog.client import sync_execute -from posthog.constants import LIMIT, TREND_FILTER_TYPE_EVENTS +from posthog.constants import TREND_FILTER_TYPE_EVENTS from posthog.event_usage import report_user_action -from posthog.hogql.hogql import HogQLContext -from posthog.models import Action, ActionStep, Filter, Person -from posthog.models.action.util import format_action_filter -from posthog.queries.trends.trends_actors import TrendsActors +from posthog.models import Action, ActionStep from .forbid_destroy_model import ForbidDestroyModel -from .person import get_person_name from .tagged_item import TaggedItemSerializerMixin, TaggedItemViewSetMixin @@ -195,75 +186,3 @@ def list(self, request: request.Request, *args: Any, **kwargs: Any) -> Response: actions, many=True, context={"request": request} ).data # type: ignore return Response({"results": actions_list}) - - # NOTE: Deprecated in favour of `persons/trends` endpoint - # Once the old way of exporting CSVs is removed, this endpoint can be removed - @action(methods=["GET"], detail=False) - def people(self, request: request.Request, *args: Any, **kwargs: Any) -> Response: - team = self.team - filter = Filter(request=request, team=self.team) - if not filter.limit: - filter = filter.shallow_clone({LIMIT: 100}) - - entity = get_target_entity(filter) - - actors, serialized_actors, raw_count = TrendsActors(team, entity, filter).get_actors() - - current_url = request.get_full_path() - next_url: Optional[str] = request.get_full_path() - limit = filter.limit or 100 - offset = filter.offset - if raw_count >= limit and next_url: - if "offset" in next_url: - next_url = next_url[1:] - next_url = next_url.replace("offset=" + str(offset), "offset=" + str(offset + limit)) - else: - next_url = f"{next_url}{'&' if '?' in next_url else '?'}offset={offset+limit}" - else: - next_url = None - - if request.accepted_renderer.format == "csv": - content = [ - { - "Name": get_person_name(team, person), - "Distinct ID": person.distinct_ids[0] if person.distinct_ids else "", - "Internal ID": str(person.uuid), - "Email": person.properties.get("email"), - "Properties": person.properties, - } - for person in actors - if isinstance(person, Person) - ] - return Response(content) - - return Response( - { - "results": [{"people": serialized_actors, "count": len(serialized_actors)}], - "next": next_url, - "previous": current_url[1:], - "missing_persons": raw_count - len(serialized_actors), - } - ) - - @action(methods=["GET"], detail=True) - def count(self, request: request.Request, **kwargs) -> Response: - action = self.get_object() - # NOTE: never accepts cohort parameters so no need for explicit person_id_joined_alias - hogql_context = HogQLContext(within_non_hogql_query=True, team_id=action.team_id) - query, params = format_action_filter(team_id=action.team_id, action=action, hogql_context=hogql_context) - if query == "": - return Response({"count": 0}) - - results = sync_execute( - "SELECT count(1) FROM events WHERE team_id = %(team_id)s AND timestamp < %(before)s AND timestamp > %(after)s AND {}".format( - query - ), - { - "team_id": action.team_id, - "before": now().strftime("%Y-%m-%d %H:%M:%S.%f"), - "after": (now() - relativedelta(months=3)).strftime("%Y-%m-%d %H:%M:%S.%f"), - **params, - **hogql_context.values, - }, - ) - return Response({"count": results[0][0]}) diff --git a/posthog/api/instance_status.py b/posthog/api/instance_status.py index 7e800dacfee8c..c0dff3a3e4a1c 100644 --- a/posthog/api/instance_status.py +++ b/posthog/api/instance_status.py @@ -94,7 +94,7 @@ def list(self, request: Request) -> Response: } ) if postgres_alive: - postgres_version = connection.cursor().connection.server_version + postgres_version = connection.cursor().connection.info.server_version metrics.append( { "key": "pg_version", diff --git a/posthog/api/property_definition.py b/posthog/api/property_definition.py index 7c026e4e634d4..584644f902b33 100644 --- a/posthog/api/property_definition.py +++ b/posthog/api/property_definition.py @@ -131,8 +131,8 @@ def with_properties_to_filter(self, properties_to_filter: Optional[str]) -> "Que if properties_to_filter: return dataclasses.replace( self, - name_filter="AND name IN %(names)s", - params={**self.params, "names": tuple(properties_to_filter.split(","))}, + name_filter="AND name = ANY(%(names)s)", + params={**self.params, "names": properties_to_filter.split(",")}, ) else: return self @@ -141,7 +141,7 @@ def with_is_numerical_flag(self, is_numerical: Optional[str]) -> "QueryContext": if is_numerical: return dataclasses.replace( self, - numerical_filter="AND is_numerical = true AND name NOT IN ('distinct_id', 'timestamp')", + numerical_filter="AND is_numerical = true AND NOT name = ANY(ARRAY['distinct_id', 'timestamp'])", ) else: return self @@ -207,7 +207,7 @@ def with_event_property_filter( if event_names and len(event_names) > 0: event_property_field = f"{self.posthog_eventproperty_table_join_alias}.property is not null" - event_name_join_filter = "AND event in %(event_names)s" + event_name_join_filter = "AND event = ANY(%(event_names)s)" return dataclasses.replace( self, @@ -216,7 +216,7 @@ def with_event_property_filter( event_name_join_filter=event_name_join_filter, event_name_filter=event_name_filter, event_property_join_type="INNER JOIN" if filter_by_event_names else "LEFT JOIN", - params={**self.params, "event_names": tuple(event_names or [])}, + params={**self.params, "event_names": list(map(str, event_names or []))}, ) def with_search(self, search_query: str, search_kwargs: Dict) -> "QueryContext": @@ -230,7 +230,7 @@ def with_excluded_properties(self, excluded_properties: Optional[str], type: str if excluded_properties: excluded_properties = json.loads(excluded_properties) - excluded_list = tuple( + excluded_list = list( set.union( set(excluded_properties or []), EVENTS_HIDDEN_PROPERTY_DEFINITIONS if type == "event" else [], @@ -239,7 +239,7 @@ def with_excluded_properties(self, excluded_properties: Optional[str], type: str return dataclasses.replace( self, excluded_properties_filter=( - f"AND {self.property_definition_table}.name NOT IN %(excluded_properties)s" + f"AND NOT {self.property_definition_table}.name = ANY(%(excluded_properties)s)" if len(excluded_list) > 0 else "" ), @@ -300,7 +300,11 @@ def _join_on_event_property(self): # frontend/scripts/print_property_name_aliases.ts for how to regenerate PROPERTY_NAME_ALIASES = { "$autocapture_disabled_server_side": "Autocapture Disabled Server-Side", + "$client_session_initial_referring_host": "Referrer Host", + "$client_session_initial_utm_content": "Initial UTM Source", + "$client_session_initial_utm_term": "Initial UTM Source", "$console_log_recording_enabled_server_side": "Console Log Recording Enabled Server-Side", + "$el_text": "Element Text", "$exception_colno": "Exception source column number", "$exception_handled": "Exception was handled", "$exception_lineno": "Exception source line number", @@ -320,7 +324,14 @@ def _join_on_event_property(self): "$lib_version__patch": "Library Version (Patch)", "$performance_raw": "Browser Performance", "$referrer": "Referrer URL", + "$selected_content": "Copied content", "$session_recording_recorder_version_server_side": "Session Recording Recorder Version Server-Side", + "$user_agent": "Raw User Agent", + "build": "App Build", + "previous_build": "App Previous Build", + "previous_version": "App Previous Version", + "referring_application": "Referrer Application", + "version": "App Version", } @@ -339,7 +350,23 @@ def add_name_alias_to_search_query(search_term: str): if not entries: return "" - return f"""OR name IN ({", ".join(entries)})""" + return f"""OR name = ANY(ARRAY[{", ".join(entries)}])""" + + +def add_latest_means_not_initial(search_term: str): + trigger_word = "latest" + opposite_word = "initial" + + if not search_term: + return "" + + normalised_search_term = search_term.lower() + search_words = normalised_search_term.split() + + if any(word in trigger_word for word in search_words): + return f" OR NOT name ilike '%%{opposite_word}%%'" + + return "" # Event properties generated by ingestion we don't want to show to users @@ -498,6 +525,10 @@ def get_queryset(self): search = query.validated_data.get("search") search_extra = add_name_alias_to_search_query(search) + + if query.validated_data.get("type") == "person": + search_extra += add_latest_means_not_initial(search) + search_query, search_kwargs = term_search_filter_sql(self.search_fields, search, search_extra) query_context = ( diff --git a/posthog/api/test/__snapshots__/test_action.ambr b/posthog/api/test/__snapshots__/test_action.ambr index 3b71cb1191f91..a92d37c6b730b 100644 --- a/posthog/api/test/__snapshots__/test_action.ambr +++ b/posthog/api/test/__snapshots__/test_action.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.1 @@ -80,7 +80,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.10 @@ -134,7 +134,7 @@ GROUP BY "posthog_action"."id", "posthog_user"."id" ORDER BY "posthog_action"."last_calculated_at" DESC, - "posthog_action"."name" ASC /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + "posthog_action"."name" ASC ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.11 @@ -158,7 +158,7 @@ 3, 4, 5 /* ... */) - ORDER BY "posthog_actionstep"."id" ASC /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + ORDER BY "posthog_actionstep"."id" ASC ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.12 @@ -189,7 +189,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.13 @@ -242,7 +242,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.14 @@ -274,7 +274,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.15 @@ -300,7 +300,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.16 @@ -354,7 +354,7 @@ GROUP BY "posthog_action"."id", "posthog_user"."id" ORDER BY "posthog_action"."last_calculated_at" DESC, - "posthog_action"."name" ASC /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + "posthog_action"."name" ASC ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.17 @@ -378,7 +378,7 @@ 3, 4, 5 /* ... */) - ORDER BY "posthog_actionstep"."id" ASC /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + ORDER BY "posthog_actionstep"."id" ASC ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.2 @@ -410,7 +410,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.3 @@ -421,7 +421,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.4 @@ -447,7 +447,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.5 @@ -501,7 +501,7 @@ GROUP BY "posthog_action"."id", "posthog_user"."id" ORDER BY "posthog_action"."last_calculated_at" DESC, - "posthog_action"."name" ASC /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + "posthog_action"."name" ASC ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.6 @@ -532,7 +532,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.7 @@ -585,7 +585,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.8 @@ -617,7 +617,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestActionApi.test_listing_actions_is_not_nplus1.9 @@ -643,6 +643,6 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_actions-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/actions/%3F%24'*/ + LIMIT 21 ''' # --- diff --git a/posthog/api/test/__snapshots__/test_annotation.ambr b/posthog/api/test/__snapshots__/test_annotation.ambr index b75f8a9661f7e..043697e9d0d46 100644 --- a/posthog/api/test/__snapshots__/test_annotation.ambr +++ b/posthog/api/test/__snapshots__/test_annotation.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.1 @@ -80,7 +80,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.10 @@ -111,7 +111,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.11 @@ -164,7 +164,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.12 @@ -196,7 +196,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.13 @@ -206,7 +206,7 @@ WHERE ((("posthog_annotation"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_annotation"."scope" = 'organization') OR "posthog_annotation"."team_id" = 2) - AND NOT "posthog_annotation"."deleted") /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + AND NOT "posthog_annotation"."deleted") ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.14 @@ -285,7 +285,7 @@ OR "posthog_annotation"."team_id" = 2) AND NOT "posthog_annotation"."deleted") ORDER BY "posthog_annotation"."date_marker" DESC - LIMIT 1000 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + LIMIT 1000 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.15 @@ -396,7 +396,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.3 @@ -407,7 +407,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.4 @@ -417,7 +417,7 @@ WHERE ((("posthog_annotation"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_annotation"."scope" = 'organization') OR "posthog_annotation"."team_id" = 2) - AND NOT "posthog_annotation"."deleted") /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + AND NOT "posthog_annotation"."deleted") ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.5 @@ -448,7 +448,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.6 @@ -501,7 +501,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.7 @@ -533,7 +533,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.8 @@ -543,7 +543,7 @@ WHERE ((("posthog_annotation"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_annotation"."scope" = 'organization') OR "posthog_annotation"."team_id" = 2) - AND NOT "posthog_annotation"."deleted") /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + AND NOT "posthog_annotation"."deleted") ''' # --- # name: TestAnnotation.test_retrieving_annotation_is_not_n_plus_1.9 @@ -622,6 +622,6 @@ OR "posthog_annotation"."team_id" = 2) AND NOT "posthog_annotation"."deleted") ORDER BY "posthog_annotation"."date_marker" DESC - LIMIT 1000 /*controller='project_annotations-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/annotations/%3F%24'*/ + LIMIT 1000 ''' # --- diff --git a/posthog/api/test/__snapshots__/test_cohort.ambr b/posthog/api/test/__snapshots__/test_cohort.ambr index 06817542b9a88..17cf49bcfa7ee 100644 --- a/posthog/api/test/__snapshots__/test_cohort.ambr +++ b/posthog/api/test/__snapshots__/test_cohort.ambr @@ -1,7 +1,7 @@ # serializer version: 1 # name: TestCohort.test_async_deletion_of_cohort ''' - /* user_id:126 celery:posthog.tasks.calculate_cohort.calculate_cohort_ch */ + /* user_id:123 celery:posthog.tasks.calculate_cohort.calculate_cohort_ch */ SELECT count(DISTINCT person_id) FROM cohortpeople WHERE team_id = 2 @@ -11,7 +11,7 @@ # --- # name: TestCohort.test_async_deletion_of_cohort.1 ''' - /* user_id:126 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ + /* user_id:123 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ INSERT INTO cohortpeople SELECT id, 2 as cohort_id, @@ -24,7 +24,8 @@ (SELECT pdi.person_id AS person_id, countIf(timestamp > now() - INTERVAL 1 day AND timestamp < now() - AND event = '$pageview') > 0 AS performed_event_condition_1_level_level_0_level_1_level_0_0 + AND event = '$pageview' + AND 1=1) > 0 AS performed_event_condition_1_level_level_0_level_1_level_0_0 FROM events e INNER JOIN (SELECT distinct_id, @@ -84,7 +85,7 @@ # --- # name: TestCohort.test_async_deletion_of_cohort.2 ''' - /* user_id:126 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ + /* user_id:123 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ SELECT count(DISTINCT person_id) FROM cohortpeople WHERE team_id = 2 @@ -94,7 +95,7 @@ # --- # name: TestCohort.test_async_deletion_of_cohort.3 ''' - /* user_id:126 celery:posthog.tasks.calculate_cohort.clear_stale_cohort */ + /* user_id:123 celery:posthog.tasks.calculate_cohort.clear_stale_cohort */ SELECT count() FROM cohortpeople WHERE team_id = 2 @@ -104,7 +105,7 @@ # --- # name: TestCohort.test_async_deletion_of_cohort.4 ''' - /* user_id:126 celery:posthog.tasks.calculate_cohort.calculate_cohort_ch */ + /* user_id:123 celery:posthog.tasks.calculate_cohort.calculate_cohort_ch */ SELECT count(DISTINCT person_id) FROM cohortpeople WHERE team_id = 2 @@ -114,7 +115,7 @@ # --- # name: TestCohort.test_async_deletion_of_cohort.5 ''' - /* user_id:126 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ + /* user_id:123 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ INSERT INTO cohortpeople SELECT id, 2 as cohort_id, @@ -148,7 +149,7 @@ # --- # name: TestCohort.test_async_deletion_of_cohort.6 ''' - /* user_id:126 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ + /* user_id:123 cohort_calculation:posthog.tasks.calculate_cohort.calculate_cohort_ch */ SELECT count(DISTINCT person_id) FROM cohortpeople WHERE team_id = 2 @@ -158,7 +159,7 @@ # --- # name: TestCohort.test_async_deletion_of_cohort.7 ''' - /* user_id:126 celery:posthog.tasks.calculate_cohort.clear_stale_cohort */ + /* user_id:123 celery:posthog.tasks.calculate_cohort.clear_stale_cohort */ SELECT count() FROM cohortpeople WHERE team_id = 2 diff --git a/posthog/api/test/__snapshots__/test_decide.ambr b/posthog/api/test/__snapshots__/test_decide.ambr index 7636905bca90b..b60f0660121b9 100644 --- a/posthog/api/test/__snapshots__/test_decide.ambr +++ b/posthog/api/test/__snapshots__/test_decide.ambr @@ -30,7 +30,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.1 @@ -90,7 +90,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='team-detail',route='api/projects/%28%3FP%3Cid%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.10 @@ -138,7 +138,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='team-detail',route='api/projects/%28%3FP%3Cid%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.3 @@ -146,7 +146,7 @@ SELECT 1 AS "a" FROM "posthog_grouptypemapping" WHERE "posthog_grouptypemapping"."team_id" = 2 - LIMIT 1 /*controller='team-detail',route='api/projects/%28%3FP%3Cid%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.4 @@ -157,7 +157,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='team-detail',route='api/projects/%28%3FP%3Cid%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.5 @@ -168,7 +168,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='team-detail',route='api/projects/%28%3FP%3Cid%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.6 @@ -179,7 +179,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:GROUPS_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='team-detail',route='api/projects/%28%3FP%3Cid%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDecide.test_decide_doesnt_error_out_when_database_is_down.7 @@ -554,9 +554,9 @@ # --- # name: TestDecide.test_flag_with_regular_cohorts.4 ''' - SELECT (("posthog_person"."properties" -> '$some_prop_1') = '"something_1"' + SELECT (("posthog_person"."properties" -> '$some_prop_1') = '"something_1"'::jsonb AND "posthog_person"."properties" ? '$some_prop_1' - AND NOT (("posthog_person"."properties" -> '$some_prop_1') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> '$some_prop_1') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = 'example_id_1' @@ -590,9 +590,9 @@ # --- # name: TestDecide.test_flag_with_regular_cohorts.6 ''' - SELECT (("posthog_person"."properties" -> '$some_prop_1') = '"something_1"' + SELECT (("posthog_person"."properties" -> '$some_prop_1') = '"something_1"'::jsonb AND "posthog_person"."properties" ? '$some_prop_1' - AND NOT (("posthog_person"."properties" -> '$some_prop_1') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> '$some_prop_1') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = 'another_id' diff --git a/posthog/api/test/__snapshots__/test_early_access_feature.ambr b/posthog/api/test/__snapshots__/test_early_access_feature.ambr index 7a472bdce6edc..3838fa80136f0 100644 --- a/posthog/api/test/__snapshots__/test_early_access_feature.ambr +++ b/posthog/api/test/__snapshots__/test_early_access_feature.ambr @@ -186,7 +186,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."api_token" = 'token123' - LIMIT 21 /*controller='posthog.api.early_access_feature.early_access_features',route='%5Eapi/early_access_features/%3F%28%3F%3A%5B%3F%23%5D.%2A%29%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPreviewList.test_early_access_features.5 @@ -217,6 +217,6 @@ FROM "posthog_earlyaccessfeature" LEFT OUTER JOIN "posthog_featureflag" ON ("posthog_earlyaccessfeature"."feature_flag_id" = "posthog_featureflag"."id") WHERE ("posthog_earlyaccessfeature"."stage" = 'beta' - AND "posthog_earlyaccessfeature"."team_id" = 2) /*controller='posthog.api.early_access_feature.early_access_features',route='%5Eapi/early_access_features/%3F%28%3F%3A%5B%3F%23%5D.%2A%29%3F%24'*/ + AND "posthog_earlyaccessfeature"."team_id" = 2) ''' # --- diff --git a/posthog/api/test/__snapshots__/test_element.ambr b/posthog/api/test/__snapshots__/test_element.ambr index 67722a01933c0..b849de02d476e 100644 --- a/posthog/api/test/__snapshots__/test_element.ambr +++ b/posthog/api/test/__snapshots__/test_element.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestElement.test_element_stats_postgres_queries_are_as_expected.1 @@ -87,7 +87,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='element-stats',route='api/element/stats/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestElement.test_element_stats_postgres_queries_are_as_expected.2 @@ -119,7 +119,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='element-stats',route='api/element/stats/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestElement.test_element_stats_postgres_queries_are_as_expected.3 @@ -130,7 +130,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='element-stats',route='api/element/stats/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestElement.test_element_stats_postgres_queries_are_as_expected.4 @@ -141,6 +141,6 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:HEATMAP_SAMPLE_N' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='element-stats',route='api/element/stats/%3F%24'*/ + LIMIT 1 ''' # --- diff --git a/posthog/api/test/__snapshots__/test_feature_flag.ambr b/posthog/api/test/__snapshots__/test_feature_flag.ambr index 7e40a7eb03e1e..8abae0e521e2d 100644 --- a/posthog/api/test/__snapshots__/test_feature_flag.ambr +++ b/posthog/api/test/__snapshots__/test_feature_flag.ambr @@ -397,9 +397,9 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'key') = '"value"' + AND ("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 2 ''' @@ -429,8 +429,8 @@ SELECT "posthog_person"."uuid" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND "posthog_person"."uuid" IN ('00000000-0000-0000-0000-000000000000'::uuid, - '00000000-0000-0000-0000-000000000001'::uuid /* ... */) + AND "posthog_person"."uuid" IN ('00000000000040008000000000000000'::uuid, + '00000000000040008000000000000001'::uuid) AND NOT (EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U1 @@ -513,9 +513,9 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'key') = '"value"' + AND ("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 2 OFFSET 2 @@ -555,9 +555,9 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'key') = '"value"' + AND ("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 2 OFFSET 4 @@ -568,8 +568,7 @@ SELECT "posthog_person"."uuid" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND "posthog_person"."uuid" IN ('00000000-0000-0000-0000-000000000000'::uuid, - '00000000-0000-0000-0000-000000000001'::uuid /* ... */) + AND "posthog_person"."uuid" IN ('00000000000040008000000000000002'::uuid) AND NOT (EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U1 @@ -631,8 +630,10 @@ SELECT "posthog_person"."uuid" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND "posthog_person"."uuid" IN ('00000000-0000-0000-0000-000000000000'::uuid, - '00000000-0000-0000-0000-000000000001'::uuid /* ... */) + AND "posthog_person"."uuid" IN ('00000000000040008000000000000000'::uuid, + '00000000000040008000000000000001'::uuid, + '00000000000040008000000000000002'::uuid, + '00000000000040008000000000000003'::uuid) AND NOT (EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U1 @@ -739,14 +740,14 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ((("posthog_person"."properties" -> 'group') = '"none"' + AND ((("posthog_person"."properties" -> 'group') = '"none"'::jsonb AND "posthog_person"."properties" ? 'group' - AND NOT (("posthog_person"."properties" -> 'group') = 'null')) - OR (("posthog_person"."properties" -> 'group2') IN ('1', - '2', - '3') + AND NOT (("posthog_person"."properties" -> 'group') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'group2') IN ('1'::jsonb, + '2'::jsonb, + '3'::jsonb) AND "posthog_person"."properties" ? 'group2' - AND NOT (("posthog_person"."properties" -> 'group2') = 'null')) + AND NOT (("posthog_person"."properties" -> 'group2') = 'null'::jsonb)) OR EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U0 @@ -754,12 +755,12 @@ AND U0."cohort_id" = 2 AND U0."person_id" = ("posthog_person"."id")) LIMIT 1) - OR (("posthog_person"."properties" -> 'does-not-exist') = '"none"' + OR (("posthog_person"."properties" -> 'does-not-exist') = '"none"'::jsonb AND "posthog_person"."properties" ? 'does-not-exist' - AND NOT (("posthog_person"."properties" -> 'does-not-exist') = 'null')) - OR (("posthog_person"."properties" -> 'key') = '"value"' + AND NOT (("posthog_person"."properties" -> 'does-not-exist') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')))) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)))) ORDER BY "posthog_person"."id" ASC LIMIT 1000 ''' @@ -874,14 +875,14 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ((("posthog_person"."properties" -> 'group') = '"none"' + AND ((("posthog_person"."properties" -> 'group') = '"none"'::jsonb AND "posthog_person"."properties" ? 'group' - AND NOT (("posthog_person"."properties" -> 'group') = 'null')) - OR (("posthog_person"."properties" -> 'group2') IN ('1', - '2', - '3') + AND NOT (("posthog_person"."properties" -> 'group') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'group2') IN ('1'::jsonb, + '2'::jsonb, + '3'::jsonb) AND "posthog_person"."properties" ? 'group2' - AND NOT (("posthog_person"."properties" -> 'group2') = 'null')) + AND NOT (("posthog_person"."properties" -> 'group2') = 'null'::jsonb)) OR EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U0 @@ -889,12 +890,12 @@ AND U0."cohort_id" = 2 AND U0."person_id" = ("posthog_person"."id")) LIMIT 1) - OR (("posthog_person"."properties" -> 'does-not-exist') = '"none"' + OR (("posthog_person"."properties" -> 'does-not-exist') = '"none"'::jsonb AND "posthog_person"."properties" ? 'does-not-exist' - AND NOT (("posthog_person"."properties" -> 'does-not-exist') = 'null')) - OR (("posthog_person"."properties" -> 'key') = '"value"' + AND NOT (("posthog_person"."properties" -> 'does-not-exist') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')))) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)))) ORDER BY "posthog_person"."id" ASC LIMIT 1000 OFFSET 1000 @@ -993,8 +994,8 @@ SELECT "posthog_person"."uuid" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND "posthog_person"."uuid" IN ('00000000-0000-0000-0000-000000000000'::uuid, - '00000000-0000-0000-0000-000000000001'::uuid /* ... */) + AND "posthog_person"."uuid" IN ('00000000000040008000000000000000'::uuid, + '00000000000040008000000000000001'::uuid) AND NOT (EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U1 @@ -1079,7 +1080,7 @@ WHERE ("posthog_person"."team_id" = 2 AND UPPER(("posthog_person"."properties" ->> 'key')::text) LIKE UPPER('%value%') AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 1000 ''' @@ -1120,7 +1121,7 @@ WHERE ("posthog_person"."team_id" = 2 AND UPPER(("posthog_person"."properties" ->> 'key')::text) LIKE UPPER('%value%') AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 1000 OFFSET 1000 @@ -1131,8 +1132,7 @@ SELECT "posthog_person"."uuid" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND "posthog_person"."uuid" IN ('00000000-0000-0000-0000-000000000000'::uuid, - '00000000-0000-0000-0000-000000000001'::uuid /* ... */) + AND "posthog_person"."uuid" IN ('00000000000040008000000000000000'::uuid) AND NOT (EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U1 @@ -1330,9 +1330,9 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'key') = '"value"' + AND ("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 1000 ''' @@ -1413,9 +1413,9 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'key') = '"value"' + AND ("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 1000 OFFSET 1000 @@ -1426,8 +1426,7 @@ SELECT "posthog_person"."uuid" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND "posthog_person"."uuid" IN ('00000000-0000-0000-0000-000000000000'::uuid, - '00000000-0000-0000-0000-000000000001'::uuid /* ... */) + AND "posthog_person"."uuid" IN ('00000000000040008000000000000002'::uuid) AND NOT (EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U1 @@ -1524,7 +1523,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.1 @@ -1577,7 +1576,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.10 @@ -1594,12 +1593,12 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'key') = '"value"' + AND ("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC LIMIT 10000 - OFFSET 10000 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + OFFSET 10000 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.11 @@ -1607,14 +1606,13 @@ SELECT "posthog_person"."uuid" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND "posthog_person"."uuid" IN ('00000000-0000-0000-0000-000000000000'::uuid, - '00000000-0000-0000-0000-000000000001'::uuid /* ... */) + AND "posthog_person"."uuid" IN ('00000000000040008000000000000000'::uuid) AND NOT (EXISTS (SELECT 1 AS "a" FROM "posthog_cohortpeople" U1 WHERE (U1."cohort_id" = 2 AND U1."person_id" = ("posthog_person"."id")) - LIMIT 1))) /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 1))) ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.12 @@ -1674,7 +1672,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.13 @@ -1734,12 +1732,12 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.14 ''' - /* user_id:201 celery:posthog.tasks.calculate_cohort.insert_cohort_from_feature_flag */ + /* user_id:199 celery:posthog.tasks.calculate_cohort.insert_cohort_from_feature_flag */ SELECT count(DISTINCT person_id) FROM person_static_cohort WHERE team_id = 2 @@ -1795,7 +1793,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.3 @@ -1806,7 +1804,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.4 @@ -1832,7 +1830,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.5 @@ -1881,7 +1879,7 @@ LEFT OUTER JOIN "posthog_user" ON ("posthog_featureflag"."created_by_id" = "posthog_user"."id") WHERE ("posthog_featureflag"."team_id" = 2 AND "posthog_featureflag"."id" = 2) - LIMIT 21 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.6 @@ -1904,7 +1902,7 @@ FROM "posthog_featureflag" WHERE ("posthog_featureflag"."key" = 'some-feature' AND "posthog_featureflag"."team_id" = 2) - LIMIT 21 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.7 @@ -1929,7 +1927,7 @@ FROM "posthog_cohort" WHERE ("posthog_cohort"."id" = 2 AND "posthog_cohort"."team_id" = 2) - LIMIT 21 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.8 @@ -1946,11 +1944,11 @@ "posthog_person"."version" FROM "posthog_person" WHERE ("posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'key') = '"value"' + AND ("posthog_person"."properties" -> 'key') = '"value"'::jsonb AND "posthog_person"."properties" ? 'key' - AND NOT (("posthog_person"."properties" -> 'key') = 'null')) + AND NOT (("posthog_person"."properties" -> 'key') = 'null'::jsonb)) ORDER BY "posthog_person"."id" ASC - LIMIT 10000 /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + LIMIT 10000 ''' # --- # name: TestFeatureFlag.test_creating_static_cohort.9 @@ -1970,7 +1968,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_feature_flags-create-static-cohort-for-flag',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/create_static_cohort_for_flag/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestResiliency.test_feature_flags_v3_with_experience_continuity_working_slow_db @@ -1980,8 +1978,7 @@ person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('example_id', - 'random') ), + AND distinct_id = ANY('{example_id,random}') ), existing_overrides AS (SELECT team_id, person_id, @@ -2010,8 +2007,7 @@ person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('example_id', - 'random') ), + AND distinct_id = ANY('{example_id,random}') ), existing_overrides AS (SELECT team_id, person_id, @@ -2072,9 +2068,9 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_experience_continuity_working_slow_db.4 ''' - SELECT (("posthog_person"."properties" -> 'email') = '"tim@posthog.com"' + SELECT (("posthog_person"."properties" -> 'email') = '"tim@posthog.com"'::jsonb AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0", + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0", (true) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") @@ -2085,15 +2081,12 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_experience_continuity_working_slow_db.5 ''' - SELECT pg_sleep(1); - WITH target_person_ids AS (SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('example_id', - 'random') ), + AND distinct_id = ANY('{example_id,random}') ), existing_overrides AS (SELECT team_id, person_id, @@ -2117,8 +2110,6 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_experience_continuity_working_slow_db.6 ''' - SELECT pg_sleep(1); - SELECT "posthog_persondistinctid"."person_id", "posthog_persondistinctid"."distinct_id" FROM "posthog_persondistinctid" @@ -2129,8 +2120,6 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_experience_continuity_working_slow_db.7 ''' - SELECT pg_sleep(1); - SELECT "posthog_persondistinctid"."person_id", "posthog_persondistinctid"."distinct_id" FROM "posthog_persondistinctid" @@ -2140,8 +2129,6 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_group_properties_and_slow_db ''' - SELECT pg_sleep(1); - SELECT "posthog_grouptypemapping"."id", "posthog_grouptypemapping"."team_id", "posthog_grouptypemapping"."group_type", @@ -2154,8 +2141,6 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_group_properties_and_slow_db.1 ''' - SELECT pg_sleep(1); - SELECT "posthog_grouptypemapping"."id", "posthog_grouptypemapping"."team_id", "posthog_grouptypemapping"."group_type", @@ -2168,8 +2153,6 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_group_properties_and_slow_db.2 ''' - SELECT pg_sleep(1); - SELECT "posthog_grouptypemapping"."id", "posthog_grouptypemapping"."team_id", "posthog_grouptypemapping"."group_type", @@ -2182,14 +2165,12 @@ # --- # name: TestResiliency.test_feature_flags_v3_with_slow_db_doesnt_try_to_compute_conditions_again ''' - SELECT pg_sleep(1); - - SELECT (("posthog_person"."properties" -> 'email') = '"tim@posthog.com"' + SELECT (("posthog_person"."properties" -> 'email') = '"tim@posthog.com"'::jsonb AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0", - (("posthog_person"."properties" -> 'email') = '"tim@posthog.com"' + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0", + (("posthog_person"."properties" -> 'email') = '"tim@posthog.com"'::jsonb AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0", + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0", (true) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") diff --git a/posthog/api/test/__snapshots__/test_insight.ambr b/posthog/api/test/__snapshots__/test_insight.ambr index 6495d532782b2..9e1f952147f44 100644 --- a/posthog/api/test/__snapshots__/test_insight.ambr +++ b/posthog/api/test/__snapshots__/test_insight.ambr @@ -666,7 +666,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.1 @@ -719,7 +719,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.10 @@ -772,7 +772,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.11 @@ -790,7 +790,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.12 @@ -825,7 +825,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.13 @@ -848,7 +848,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.14 @@ -908,7 +908,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.15 @@ -934,7 +934,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.16 @@ -958,7 +958,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_dashboardtile" ON ("posthog_dashboard"."id" = "posthog_dashboardtile"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.17 @@ -979,7 +979,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.18 @@ -990,7 +990,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.19 @@ -1017,7 +1017,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.2 @@ -1049,7 +1049,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.20 @@ -1087,7 +1087,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.22 @@ -1140,7 +1140,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.23 @@ -1172,7 +1172,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.24 @@ -1198,7 +1198,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.25 @@ -1207,8 +1207,8 @@ FROM "posthog_dashboarditem" WHERE (NOT ("posthog_dashboarditem"."deleted") AND "posthog_dashboarditem"."team_id" = 2 - AND NOT ("posthog_dashboarditem"."filters" = '{}' - AND "posthog_dashboarditem"."query" IS NOT NULL)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND NOT ("posthog_dashboarditem"."filters" = '{}'::jsonb + AND "posthog_dashboarditem"."query" IS NOT NULL)) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.26 @@ -1350,10 +1350,10 @@ LEFT OUTER JOIN "posthog_user" T4 ON ("posthog_dashboarditem"."last_modified_by_id" = T4."id") WHERE (NOT ("posthog_dashboarditem"."deleted") AND "posthog_dashboarditem"."team_id" = 2 - AND NOT ("posthog_dashboarditem"."filters" = '{}' + AND NOT ("posthog_dashboarditem"."filters" = '{}'::jsonb AND "posthog_dashboarditem"."query" IS NOT NULL)) ORDER BY "posthog_dashboarditem"."order" ASC - LIMIT 100 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 100 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.27 @@ -1456,7 +1456,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.28 @@ -1571,7 +1571,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.29 @@ -1589,7 +1589,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.3 @@ -1613,25 +1613,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ - ''' -# --- -# name: TestInsight.test_listing_insights_does_not_nplus1.30 - ''' - SELECT "posthog_taggeditem"."id", - "posthog_taggeditem"."tag_id", - "posthog_taggeditem"."dashboard_id", - "posthog_taggeditem"."insight_id", - "posthog_taggeditem"."event_definition_id", - "posthog_taggeditem"."property_definition_id", - "posthog_taggeditem"."action_id", - "posthog_taggeditem"."feature_flag_id" - FROM "posthog_taggeditem" - WHERE "posthog_taggeditem"."insight_id" IN (1, - 2, - 3, - 4, - 5 /* ... */) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.4 @@ -1684,7 +1666,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.5 @@ -1719,7 +1701,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.6 @@ -1779,7 +1761,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.7 @@ -1806,7 +1788,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.8 @@ -1866,7 +1848,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestInsight.test_listing_insights_does_not_nplus1.9 @@ -1926,6 +1908,6 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- diff --git a/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr b/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr index 38996ee675b74..7eeea8ed7c405 100644 --- a/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr +++ b/posthog/api/test/__snapshots__/test_organization_feature_flag.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.1 @@ -53,7 +53,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.10 @@ -76,7 +76,7 @@ FROM "posthog_featureflag" WHERE ("posthog_featureflag"."active" AND NOT "posthog_featureflag"."deleted" - AND "posthog_featureflag"."team_id" = 2) /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + AND "posthog_featureflag"."team_id" = 2) ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.11 @@ -136,7 +136,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.12 @@ -147,7 +147,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."dashboard_id" = 2) /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + AND "posthog_dashboardtile"."dashboard_id" = 2) ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.13 @@ -173,7 +173,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.14 @@ -184,7 +184,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."dashboard_id" = 2) /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + AND "posthog_dashboardtile"."dashboard_id" = 2) ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.15 @@ -237,7 +237,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.16 @@ -272,7 +272,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.17 @@ -332,7 +332,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.18 @@ -343,7 +343,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.19 @@ -354,7 +354,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.2 @@ -363,7 +363,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.20 @@ -374,7 +374,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.21 @@ -385,7 +385,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.22 @@ -396,7 +396,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.23 @@ -407,7 +407,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.24 @@ -418,7 +418,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.25 @@ -429,7 +429,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.26 @@ -440,7 +440,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.27 @@ -451,7 +451,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.28 @@ -462,7 +462,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.29 @@ -473,7 +473,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.3 @@ -484,7 +484,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.30 @@ -537,7 +537,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.31 @@ -555,7 +555,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.32 @@ -590,7 +590,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.33 @@ -613,7 +613,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.34 @@ -673,7 +673,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.35 @@ -684,7 +684,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.36 @@ -695,7 +695,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.37 @@ -706,7 +706,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.38 @@ -717,7 +717,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.39 @@ -728,7 +728,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.4 @@ -751,7 +751,7 @@ FROM "posthog_featureflag" WHERE ("posthog_featureflag"."key" = 'copied-flag-key' AND "posthog_featureflag"."team_id" = 2) - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.40 @@ -762,7 +762,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.41 @@ -815,7 +815,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.42 @@ -850,7 +850,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.43 @@ -910,7 +910,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.44 @@ -921,7 +921,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.45 @@ -932,7 +932,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.46 @@ -943,7 +943,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.47 @@ -954,7 +954,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.48 @@ -965,7 +965,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.49 @@ -976,7 +976,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.5 @@ -1002,7 +1002,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.50 @@ -1013,7 +1013,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.51 @@ -1024,7 +1024,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.52 @@ -1035,7 +1035,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.53 @@ -1046,7 +1046,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.54 @@ -1057,7 +1057,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.55 @@ -1068,7 +1068,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.56 @@ -1121,7 +1121,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.57 @@ -1139,7 +1139,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.58 @@ -1174,7 +1174,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.59 @@ -1197,7 +1197,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.6 @@ -1250,7 +1250,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.60 @@ -1310,7 +1310,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.61 @@ -1321,7 +1321,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.62 @@ -1332,7 +1332,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.63 @@ -1343,7 +1343,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.64 @@ -1354,7 +1354,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.65 @@ -1365,7 +1365,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.66 @@ -1376,7 +1376,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.67 @@ -1399,7 +1399,7 @@ FROM "posthog_featureflag" WHERE ("posthog_featureflag"."active" AND NOT "posthog_featureflag"."deleted" - AND "posthog_featureflag"."team_id" = 2) /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + AND "posthog_featureflag"."team_id" = 2) ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.68 @@ -1459,7 +1459,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.69 @@ -1479,7 +1479,7 @@ "posthog_experiment"."updated_at", "posthog_experiment"."archived" FROM "posthog_experiment" - WHERE "posthog_experiment"."feature_flag_id" = 2 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + WHERE "posthog_experiment"."feature_flag_id" = 2 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.7 @@ -1504,7 +1504,7 @@ AND "posthog_featureflag"."key" = 'copied-flag-key' AND "posthog_featureflag"."team_id" = 2) ORDER BY "posthog_featureflag"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.70 @@ -1526,7 +1526,7 @@ "posthog_survey"."updated_at", "posthog_survey"."archived" FROM "posthog_survey" - WHERE "posthog_survey"."linked_flag_id" = 2 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + WHERE "posthog_survey"."linked_flag_id" = 2 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.71 @@ -1540,7 +1540,7 @@ "posthog_earlyaccessfeature"."documentation_url", "posthog_earlyaccessfeature"."created_at" FROM "posthog_earlyaccessfeature" - WHERE "posthog_earlyaccessfeature"."feature_flag_id" = 2 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + WHERE "posthog_earlyaccessfeature"."feature_flag_id" = 2 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.72 @@ -1564,7 +1564,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_featureflagdashboards" ON ("posthog_dashboard"."id" = "posthog_featureflagdashboards"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_featureflagdashboards"."feature_flag_id" = 2) /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + AND "posthog_featureflagdashboards"."feature_flag_id" = 2) ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.8 @@ -1574,7 +1574,7 @@ WHERE (NOT "posthog_featureflag"."deleted" AND "posthog_featureflag"."key" = 'copied-flag-key' AND "posthog_featureflag"."team_id" = 2) - LIMIT 1 /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagCopy.test_copy_feature_flag_create_new.9 @@ -1597,7 +1597,7 @@ FROM "posthog_featureflag" WHERE ("posthog_featureflag"."deleted" AND "posthog_featureflag"."key" = 'copied-flag-key' - AND "posthog_featureflag"."team_id" = 2) /*controller='organization_feature_flags-copy-flags',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/copy_flags/%3F%24'*/ + AND "posthog_featureflag"."team_id" = 2) ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success @@ -1628,7 +1628,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success.1 @@ -1654,7 +1654,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_feature_flags-detail',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cfeature_flag_key%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success.2 @@ -1663,7 +1663,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_feature_flags-detail',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cfeature_flag_key%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success.3 @@ -1674,7 +1674,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_feature_flags-detail',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cfeature_flag_key%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success.4 @@ -1726,7 +1726,7 @@ "posthog_team"."external_data_workspace_id", "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" - WHERE "posthog_team"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid /*controller='organization_feature_flags-detail',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cfeature_flag_key%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + WHERE "posthog_team"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success.5 @@ -1753,7 +1753,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='organization_feature_flags-detail',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cfeature_flag_key%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success.6 @@ -1785,7 +1785,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-detail',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cfeature_flag_key%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestOrganizationFeatureFlagGet.test_get_feature_flag_success.7 @@ -1817,6 +1817,6 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /*controller='organization_feature_flags-detail',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/feature_flags/%28%3FP%3Cfeature_flag_key%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- diff --git a/posthog/api/test/__snapshots__/test_plugin.ambr b/posthog/api/test/__snapshots__/test_plugin.ambr index d6ea19bbacc2f..e279c542c114c 100644 --- a/posthog/api/test/__snapshots__/test_plugin.ambr +++ b/posthog/api/test/__snapshots__/test_plugin.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.1 @@ -53,7 +53,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.10 @@ -67,7 +67,7 @@ FROM "posthog_pluginconfig" U0 INNER JOIN "posthog_team" U1 ON (U0."team_id" = U1."id") WHERE (NOT U0."deleted" - AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.11 @@ -126,7 +126,7 @@ INNER JOIN "posthog_team" U1 ON (U0."team_id" = U1."id") WHERE (NOT U0."deleted" AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) - LIMIT 100 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 100 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.12 @@ -157,7 +157,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.13 @@ -183,7 +183,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.14 @@ -209,7 +209,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.15 @@ -218,7 +218,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.16 @@ -232,7 +232,7 @@ FROM "posthog_pluginconfig" U0 INNER JOIN "posthog_team" U1 ON (U0."team_id" = U1."id") WHERE (NOT U0."deleted" - AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.17 @@ -291,7 +291,7 @@ INNER JOIN "posthog_team" U1 ON (U0."team_id" = U1."id") WHERE (NOT U0."deleted" AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) - LIMIT 100 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 100 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.18 @@ -322,7 +322,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.19 @@ -348,7 +348,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.2 @@ -374,7 +374,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.20 @@ -400,7 +400,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.21 @@ -409,7 +409,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.22 @@ -423,7 +423,7 @@ FROM "posthog_pluginconfig" U0 INNER JOIN "posthog_team" U1 ON (U0."team_id" = U1."id") WHERE (NOT U0."deleted" - AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.23 @@ -482,7 +482,7 @@ INNER JOIN "posthog_team" U1 ON (U0."team_id" = U1."id") WHERE (NOT U0."deleted" AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) - LIMIT 100 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 100 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.3 @@ -491,7 +491,7 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.4 @@ -502,7 +502,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.5 @@ -516,7 +516,7 @@ FROM "posthog_pluginconfig" U0 INNER JOIN "posthog_team" U1 ON (U0."team_id" = U1."id") WHERE (NOT U0."deleted" - AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + AND U1."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid))) ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.6 @@ -547,7 +547,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.7 @@ -573,7 +573,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.8 @@ -599,7 +599,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestPluginAPI.test_listing_plugins_is_not_nplus1.9 @@ -608,6 +608,6 @@ FROM "posthog_organizationmembership" WHERE ("posthog_organizationmembership"."organization_id" = '00000000-0000-0000-0000-000000000000'::uuid AND "posthog_organizationmembership"."user_id" = 2) - LIMIT 1 /*controller='organization_plugins-list',route='api/organizations/%28%3FP%3Cparent_lookup_organization_id%3E%5B%5E/.%5D%2B%29/plugins/%3F%24'*/ + LIMIT 1 ''' # --- diff --git a/posthog/api/test/__snapshots__/test_preflight.ambr b/posthog/api/test/__snapshots__/test_preflight.ambr index b4c8a06aad816..09c2089e7e46b 100644 --- a/posthog/api/test/__snapshots__/test_preflight.ambr +++ b/posthog/api/test/__snapshots__/test_preflight.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestPreflight.test_cloud_preflight_limited_db_queries.1 @@ -38,7 +38,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" IN ('constance:posthog:SLACK_APP_CLIENT_ID', 'constance:posthog:SLACK_APP_CLIENT_SECRET', - 'constance:posthog:SLACK_APP_SIGNING_SECRET') /*controller='posthog.views.preflight_check',route='%5E_preflight/%3F%28%3F%3A%5B%3F%23%5D.%2A%29%3F%24'*/ + 'constance:posthog:SLACK_APP_SIGNING_SECRET') ''' # --- # name: TestPreflight.test_cloud_preflight_limited_db_queries.2 @@ -98,6 +98,6 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='posthog.views.preflight_check',route='%5E_preflight/%3F%28%3F%3A%5B%3F%23%5D.%2A%29%3F%24'*/ + LIMIT 21 ''' # --- diff --git a/posthog/api/test/__snapshots__/test_query.ambr b/posthog/api/test/__snapshots__/test_query.ambr index fd0991a345668..80df09eb3d411 100644 --- a/posthog/api/test/__snapshots__/test_query.ambr +++ b/posthog/api/test/__snapshots__/test_query.ambr @@ -157,7 +157,7 @@ # --- # name: TestQuery.test_full_hogql_query_async ''' - /* user_id:469 celery:posthog.tasks.tasks.process_query_task */ + /* user_id:465 celery:posthog.tasks.tasks.process_query_task */ SELECT events.uuid AS uuid, events.event AS event, events.properties AS properties, diff --git a/posthog/api/test/__snapshots__/test_survey.ambr b/posthog/api/test/__snapshots__/test_survey.ambr index 97493427f7527..6798d297f4652 100644 --- a/posthog/api/test/__snapshots__/test_survey.ambr +++ b/posthog/api/test/__snapshots__/test_survey.ambr @@ -159,7 +159,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."api_token" = 'token123' - LIMIT 21 /*controller='posthog.api.survey.surveys',route='%5Eapi/surveys/%3F%28%3F%3A%5B%3F%23%5D.%2A%29%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSurveysAPIList.test_list_surveys.6 @@ -214,6 +214,6 @@ LEFT OUTER JOIN "posthog_featureflag" ON ("posthog_survey"."linked_flag_id" = "posthog_featureflag"."id") LEFT OUTER JOIN "posthog_featureflag" T4 ON ("posthog_survey"."targeting_flag_id" = T4."id") WHERE ("posthog_survey"."team_id" = 2 - AND NOT ("posthog_survey"."archived")) /*controller='posthog.api.survey.surveys',route='%5Eapi/surveys/%3F%28%3F%3A%5B%3F%23%5D.%2A%29%3F%24'*/ + AND NOT ("posthog_survey"."archived")) ''' # --- diff --git a/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr b/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr index 9ae54e6e582eb..2cd5eea5a05f6 100644 --- a/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr +++ b/posthog/api/test/dashboards/__snapshots__/test_dashboard.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.1 @@ -80,7 +80,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.10 @@ -91,7 +91,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.11 @@ -118,7 +118,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.12 @@ -126,7 +126,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."insight_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_taggeditem"."insight_id" = 2 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.13 @@ -157,7 +157,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.14 @@ -210,7 +210,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.15 @@ -242,7 +242,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.16 @@ -268,7 +268,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.17 @@ -393,7 +393,7 @@ WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."team_id" = 2 AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.18 @@ -415,7 +415,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.19 @@ -433,7 +433,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.2 @@ -465,7 +465,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.20 @@ -639,7 +639,7 @@ 3, 4, 5 /* ... */)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.21 @@ -660,7 +660,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.22 @@ -770,7 +770,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.23 @@ -795,7 +795,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.24 @@ -821,7 +821,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.25 @@ -996,7 +996,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.26 @@ -1017,7 +1017,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.27 @@ -1127,7 +1127,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.28 @@ -1152,7 +1152,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.29 @@ -1178,7 +1178,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.3 @@ -1202,7 +1202,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.30 @@ -1224,7 +1224,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.31 @@ -1251,7 +1251,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.32 @@ -1305,7 +1305,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.5 @@ -1365,7 +1365,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.6 @@ -1425,7 +1425,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.7 @@ -1451,7 +1451,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.8 @@ -1475,7 +1475,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_dashboardtile" ON ("posthog_dashboard"."id" = "posthog_dashboardtile"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_adding_insights_is_not_nplus1_for_gets.9 @@ -1496,7 +1496,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1 @@ -1527,7 +1527,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.1 @@ -1580,7 +1580,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.10 @@ -1591,7 +1591,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.11 @@ -1602,7 +1602,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.12 @@ -1613,7 +1613,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.13 @@ -1640,7 +1640,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.14 @@ -1700,7 +1700,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.15 @@ -1760,7 +1760,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.16 @@ -1771,7 +1771,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.17 @@ -1782,7 +1782,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.18 @@ -1793,7 +1793,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.19 @@ -1804,7 +1804,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.2 @@ -1836,7 +1836,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.20 @@ -1847,7 +1847,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.21 @@ -1858,7 +1858,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.22 @@ -1911,7 +1911,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.23 @@ -1929,7 +1929,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.24 @@ -1964,7 +1964,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.25 @@ -1987,7 +1987,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.26 @@ -2047,7 +2047,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.27 @@ -2058,7 +2058,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.28 @@ -2069,7 +2069,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.29 @@ -2080,7 +2080,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.3 @@ -2104,7 +2104,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.30 @@ -2115,7 +2115,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.31 @@ -2126,7 +2126,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.32 @@ -2137,7 +2137,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.33 @@ -2163,7 +2163,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.34 @@ -2187,7 +2187,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_dashboardtile" ON ("posthog_dashboard"."id" = "posthog_dashboardtile"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.35 @@ -2208,7 +2208,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.36 @@ -2219,7 +2219,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.37 @@ -2230,7 +2230,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.38 @@ -2241,7 +2241,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.39 @@ -2252,7 +2252,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.4 @@ -2305,7 +2305,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.40 @@ -2316,7 +2316,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.41 @@ -2327,7 +2327,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.42 @@ -2338,7 +2338,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.43 @@ -2349,7 +2349,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.44 @@ -2360,7 +2360,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.45 @@ -2371,7 +2371,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.46 @@ -2382,7 +2382,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.47 @@ -2393,7 +2393,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.48 @@ -2404,7 +2404,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.49 @@ -2431,7 +2431,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.5 @@ -2466,7 +2466,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.50 @@ -2497,7 +2497,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.51 @@ -2550,7 +2550,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.52 @@ -2582,7 +2582,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.53 @@ -2608,7 +2608,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.54 @@ -2616,7 +2616,7 @@ SELECT COUNT(*) AS "__count" FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboard"."team_id" = 2) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND "posthog_dashboard"."team_id" = 2) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.55 @@ -2741,7 +2741,7 @@ WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."team_id" = 2) ORDER BY "posthog_dashboard"."name" ASC - LIMIT 300 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 300 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.56 @@ -2759,7 +2759,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.57 @@ -2837,7 +2837,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.7 @@ -2848,7 +2848,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.8 @@ -2859,7 +2859,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_listing_dashboards_is_not_nplus1.9 @@ -2870,7 +2870,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles @@ -2901,7 +2901,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.1 @@ -2954,7 +2954,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.10 @@ -2968,7 +2968,7 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.100 @@ -3003,7 +3003,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.101 @@ -3063,7 +3063,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.102 @@ -3074,7 +3074,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.103 @@ -3085,7 +3085,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.104 @@ -3096,7 +3096,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.105 @@ -3107,7 +3107,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.106 @@ -3118,7 +3118,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.107 @@ -3129,7 +3129,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.108 @@ -3156,7 +3156,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.109 @@ -3216,7 +3216,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.11 @@ -3385,7 +3385,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.110 @@ -3445,7 +3445,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.111 @@ -3456,7 +3456,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.112 @@ -3467,7 +3467,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.113 @@ -3478,7 +3478,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.114 @@ -3489,7 +3489,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.115 @@ -3500,7 +3500,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.116 @@ -3511,7 +3511,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.117 @@ -3564,7 +3564,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.118 @@ -3582,7 +3582,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.119 @@ -3617,7 +3617,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.12 @@ -3625,7 +3625,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.120 @@ -3648,7 +3648,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.121 @@ -3708,7 +3708,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.122 @@ -3719,7 +3719,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.123 @@ -3730,7 +3730,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.124 @@ -3741,7 +3741,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.125 @@ -3752,7 +3752,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.126 @@ -3763,7 +3763,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.127 @@ -3774,7 +3774,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.128 @@ -3800,7 +3800,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.129 @@ -3824,7 +3824,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_dashboardtile" ON ("posthog_dashboard"."id" = "posthog_dashboardtile"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.13 @@ -3855,7 +3855,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.130 @@ -3876,7 +3876,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.131 @@ -3887,7 +3887,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.132 @@ -3898,7 +3898,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.133 @@ -3909,7 +3909,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.134 @@ -3920,7 +3920,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.135 @@ -3931,7 +3931,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.136 @@ -3942,7 +3942,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.137 @@ -3953,7 +3953,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.138 @@ -3964,7 +3964,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.139 @@ -3975,7 +3975,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.14 @@ -4028,7 +4028,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.140 @@ -4039,7 +4039,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.141 @@ -4050,7 +4050,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.142 @@ -4061,7 +4061,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.143 @@ -4072,7 +4072,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.144 @@ -4099,7 +4099,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.145 @@ -4107,7 +4107,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."insight_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_taggeditem"."insight_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.146 @@ -4138,7 +4138,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.147 @@ -4191,7 +4191,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.148 @@ -4223,7 +4223,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.149 @@ -4247,7 +4247,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.15 @@ -4279,7 +4279,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.150 @@ -4332,7 +4332,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.151 @@ -4367,7 +4367,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.152 @@ -4427,7 +4427,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.153 @@ -4438,7 +4438,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.154 @@ -4449,7 +4449,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.155 @@ -4460,7 +4460,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.156 @@ -4471,7 +4471,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.157 @@ -4482,7 +4482,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.158 @@ -4493,7 +4493,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.159 @@ -4520,7 +4520,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.16 @@ -4531,7 +4531,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."dashboard_id" = 2) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND "posthog_dashboardtile"."dashboard_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.160 @@ -4591,7 +4591,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.161 @@ -4651,7 +4651,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.162 @@ -4662,7 +4662,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.163 @@ -4673,7 +4673,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.164 @@ -4684,7 +4684,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.165 @@ -4695,7 +4695,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.166 @@ -4706,7 +4706,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.167 @@ -4717,7 +4717,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.168 @@ -4770,7 +4770,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.169 @@ -4788,7 +4788,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.17 @@ -4814,7 +4814,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.170 @@ -4849,7 +4849,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.171 @@ -4872,7 +4872,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.172 @@ -4932,7 +4932,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.173 @@ -4943,7 +4943,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.174 @@ -4954,7 +4954,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.175 @@ -4965,7 +4965,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.176 @@ -4976,7 +4976,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.177 @@ -4987,7 +4987,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.178 @@ -4998,7 +4998,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.179 @@ -5024,7 +5024,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.18 @@ -5036,7 +5036,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") AND "posthog_dashboardtile"."dashboard_id" = 2 - AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.180 @@ -5060,7 +5060,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_dashboardtile" ON ("posthog_dashboard"."id" = "posthog_dashboardtile"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.181 @@ -5081,7 +5081,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.182 @@ -5092,7 +5092,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.183 @@ -5103,7 +5103,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.184 @@ -5114,7 +5114,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.185 @@ -5125,7 +5125,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.186 @@ -5136,7 +5136,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.187 @@ -5147,7 +5147,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.188 @@ -5158,7 +5158,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.189 @@ -5169,7 +5169,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.19 @@ -5183,7 +5183,7 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.190 @@ -5194,7 +5194,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.191 @@ -5205,7 +5205,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.192 @@ -5216,7 +5216,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.193 @@ -5227,7 +5227,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.194 @@ -5238,7 +5238,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.195 @@ -5265,7 +5265,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.196 @@ -5273,7 +5273,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."insight_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_taggeditem"."insight_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.197 @@ -5304,7 +5304,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.198 @@ -5357,7 +5357,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.199 @@ -5389,7 +5389,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.2 @@ -5421,14 +5421,14 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.20 ''' SELECT COUNT(*) AS "__count" FROM "posthog_taggeditem" - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.200 @@ -5452,7 +5452,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.201 @@ -5505,7 +5505,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.202 @@ -5540,7 +5540,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.203 @@ -5600,7 +5600,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.204 @@ -5611,7 +5611,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.205 @@ -5622,7 +5622,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.206 @@ -5633,7 +5633,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.207 @@ -5644,7 +5644,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.208 @@ -5655,7 +5655,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.209 @@ -5666,7 +5666,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.21 @@ -5726,7 +5726,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.210 @@ -5753,7 +5753,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.211 @@ -5813,7 +5813,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.212 @@ -5873,7 +5873,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.213 @@ -5884,7 +5884,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.214 @@ -5895,7 +5895,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.215 @@ -5906,7 +5906,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.216 @@ -5917,7 +5917,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.217 @@ -5928,7 +5928,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.218 @@ -5939,7 +5939,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.219 @@ -5992,7 +5992,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.22 @@ -6006,7 +6006,7 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.220 @@ -6024,7 +6024,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.221 @@ -6059,7 +6059,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.222 @@ -6082,7 +6082,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.223 @@ -6142,7 +6142,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.224 @@ -6153,7 +6153,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.225 @@ -6164,7 +6164,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.226 @@ -6175,7 +6175,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.227 @@ -6186,7 +6186,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.228 @@ -6197,7 +6197,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.229 @@ -6208,7 +6208,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.23 @@ -6377,7 +6377,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.230 @@ -6403,7 +6403,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.231 @@ -6427,7 +6427,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_dashboardtile" ON ("posthog_dashboard"."id" = "posthog_dashboardtile"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.232 @@ -6448,7 +6448,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.233 @@ -6459,7 +6459,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.234 @@ -6470,7 +6470,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.235 @@ -6481,7 +6481,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.236 @@ -6492,7 +6492,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.237 @@ -6503,7 +6503,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.238 @@ -6514,7 +6514,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.239 @@ -6525,7 +6525,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.24 @@ -6533,7 +6533,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.240 @@ -6544,7 +6544,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.241 @@ -6555,7 +6555,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.242 @@ -6566,7 +6566,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.243 @@ -6577,7 +6577,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.244 @@ -6588,7 +6588,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.245 @@ -6599,7 +6599,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.246 @@ -6626,7 +6626,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.247 @@ -6634,7 +6634,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."insight_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_taggeditem"."insight_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.248 @@ -6665,7 +6665,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.249 @@ -6718,7 +6718,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.25 @@ -6749,7 +6749,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.250 @@ -6781,7 +6781,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.251 @@ -6807,7 +6807,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.252 @@ -6932,7 +6932,7 @@ WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."team_id" = 2 AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.253 @@ -6954,7 +6954,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.254 @@ -6972,7 +6972,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.255 @@ -7146,7 +7146,7 @@ 3, 4, 5 /* ... */)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.256 @@ -7167,7 +7167,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.257 @@ -7277,7 +7277,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.258 @@ -7302,7 +7302,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.259 @@ -7328,7 +7328,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.26 @@ -7381,7 +7381,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.260 @@ -7556,7 +7556,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.261 @@ -7577,7 +7577,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.262 @@ -7687,7 +7687,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.263 @@ -7712,7 +7712,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.264 @@ -7738,7 +7738,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.265 @@ -7760,7 +7760,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.266 @@ -7771,7 +7771,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.267 @@ -7782,7 +7782,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.268 @@ -7793,7 +7793,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.269 @@ -7804,7 +7804,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.27 @@ -7836,7 +7836,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.270 @@ -7847,7 +7847,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.271 @@ -7858,7 +7858,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.272 @@ -7869,7 +7869,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.273 @@ -7880,7 +7880,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.274 @@ -7891,7 +7891,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.275 @@ -7902,7 +7902,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.276 @@ -7913,7 +7913,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.277 @@ -7924,7 +7924,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.278 @@ -7951,7 +7951,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.279 @@ -7962,7 +7962,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.28 @@ -7986,7 +7986,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.280 @@ -7997,7 +7997,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.281 @@ -8008,7 +8008,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.282 @@ -8019,7 +8019,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.283 @@ -8030,7 +8030,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.284 @@ -8041,7 +8041,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.285 @@ -8052,7 +8052,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.286 @@ -8063,7 +8063,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.287 @@ -8074,7 +8074,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.288 @@ -8085,7 +8085,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.289 @@ -8096,7 +8096,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.29 @@ -8120,7 +8120,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.290 @@ -8131,7 +8131,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.291 @@ -8142,7 +8142,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.292 @@ -8153,7 +8153,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.293 @@ -8164,7 +8164,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.294 @@ -8175,7 +8175,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.295 @@ -8186,7 +8186,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.296 @@ -8197,7 +8197,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.297 @@ -8208,7 +8208,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.298 @@ -8219,7 +8219,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.299 @@ -8230,7 +8230,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.3 @@ -8241,7 +8241,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.30 @@ -8294,7 +8294,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.300 @@ -8305,7 +8305,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.301 @@ -8316,7 +8316,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.302 @@ -8327,7 +8327,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.303 @@ -8338,7 +8338,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.304 @@ -8349,7 +8349,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.305 @@ -8360,7 +8360,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.306 @@ -8371,7 +8371,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.307 @@ -8382,7 +8382,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.308 @@ -8393,7 +8393,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.309 @@ -8404,7 +8404,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.31 @@ -8439,7 +8439,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.310 @@ -8450,7 +8450,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.311 @@ -8461,7 +8461,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.312 @@ -8472,7 +8472,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.313 @@ -8483,7 +8483,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.314 @@ -8494,7 +8494,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.315 @@ -8565,7 +8565,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.33 @@ -8576,7 +8576,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.34 @@ -8587,7 +8587,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.35 @@ -8598,7 +8598,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.36 @@ -8609,7 +8609,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.37 @@ -8620,7 +8620,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.38 @@ -8631,7 +8631,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.39 @@ -8658,7 +8658,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.4 @@ -8669,7 +8669,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."dashboard_id" = 2) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND "posthog_dashboardtile"."dashboard_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.40 @@ -8729,7 +8729,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.41 @@ -8789,7 +8789,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.42 @@ -8800,7 +8800,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.43 @@ -8811,7 +8811,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.44 @@ -8822,7 +8822,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.45 @@ -8833,7 +8833,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.46 @@ -8844,7 +8844,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.47 @@ -8855,7 +8855,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.48 @@ -8908,7 +8908,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.49 @@ -8926,7 +8926,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.5 @@ -8952,7 +8952,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.50 @@ -8987,7 +8987,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.51 @@ -9010,7 +9010,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.52 @@ -9070,7 +9070,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.53 @@ -9081,7 +9081,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.54 @@ -9092,7 +9092,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.55 @@ -9103,7 +9103,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.56 @@ -9114,7 +9114,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.57 @@ -9125,7 +9125,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.58 @@ -9136,7 +9136,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.59 @@ -9196,7 +9196,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.6 @@ -9208,7 +9208,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") AND "posthog_dashboardtile"."dashboard_id" = 2 - AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.60 @@ -9219,7 +9219,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.61 @@ -9230,7 +9230,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.62 @@ -9241,7 +9241,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.63 @@ -9252,7 +9252,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.64 @@ -9263,7 +9263,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.65 @@ -9274,7 +9274,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.66 @@ -9327,7 +9327,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.67 @@ -9345,7 +9345,7 @@ "posthog_dashboardtile"."deleted" FROM "posthog_dashboardtile" WHERE "posthog_dashboardtile"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.68 @@ -9380,7 +9380,7 @@ "posthog_dashboarditem"."tags" FROM "posthog_dashboarditem" WHERE "posthog_dashboarditem"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.69 @@ -9403,7 +9403,7 @@ "posthog_dashboard"."is_shared" FROM "posthog_dashboard" WHERE "posthog_dashboard"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.7 @@ -9417,7 +9417,7 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.70 @@ -9477,7 +9477,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.71 @@ -9488,7 +9488,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.72 @@ -9499,7 +9499,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.73 @@ -9510,7 +9510,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.74 @@ -9521,7 +9521,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.75 @@ -9532,7 +9532,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.76 @@ -9543,7 +9543,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.77 @@ -9569,7 +9569,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.78 @@ -9593,7 +9593,7 @@ FROM "posthog_dashboard" INNER JOIN "posthog_dashboardtile" ON ("posthog_dashboard"."id" = "posthog_dashboardtile"."dashboard_id") WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.79 @@ -9614,14 +9614,14 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.8 ''' SELECT COUNT(*) AS "__count" FROM "posthog_taggeditem" - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.80 @@ -9632,7 +9632,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.81 @@ -9643,7 +9643,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.82 @@ -9654,7 +9654,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.83 @@ -9665,7 +9665,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.84 @@ -9676,7 +9676,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.85 @@ -9687,7 +9687,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.86 @@ -9698,7 +9698,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.87 @@ -9709,7 +9709,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.88 @@ -9720,7 +9720,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.89 @@ -9731,7 +9731,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.9 @@ -9791,7 +9791,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.90 @@ -9802,7 +9802,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.91 @@ -9813,7 +9813,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.92 @@ -9824,7 +9824,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."insight_id" = 2) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + AND "posthog_dashboardtile"."insight_id" = 2) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.93 @@ -9851,7 +9851,7 @@ 2, 3, 4, - 5 /* ... */)) /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + 5 /* ... */)) ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.94 @@ -9859,7 +9859,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."insight_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_taggeditem"."insight_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.95 @@ -9890,7 +9890,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.96 @@ -9943,7 +9943,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.97 @@ -9975,7 +9975,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.98 @@ -9999,7 +9999,7 @@ FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_loading_individual_dashboard_does_not_prefetch_all_possible_tiles.99 @@ -10052,7 +10052,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_insights-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/insights/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard @@ -10094,7 +10094,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard.10 @@ -10269,7 +10269,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_retrieve_dashboard.11 @@ -10443,7 +10443,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_retrieve_dashboard.2 @@ -10496,7 +10496,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard.3 @@ -10528,7 +10528,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard.4 @@ -10539,7 +10539,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_retrieve_dashboard.5 @@ -10565,7 +10565,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard.6 @@ -10690,7 +10690,7 @@ WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."team_id" = 2 AND "posthog_dashboard"."id" = 2) - LIMIT 21 /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard.7 @@ -10712,7 +10712,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_retrieve_dashboard.8 @@ -10730,7 +10730,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_retrieve_dashboard.9 @@ -10904,7 +10904,7 @@ 3, 4, 5 /* ... */)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%28%3FP%3Cpk%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_retrieve_dashboard_list @@ -10935,7 +10935,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.1 @@ -10988,7 +10988,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.10 @@ -11002,7 +11002,7 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.11 @@ -11171,7 +11171,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.12 @@ -11179,7 +11179,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.13 @@ -11210,7 +11210,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.14 @@ -11263,7 +11263,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.15 @@ -11295,7 +11295,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.16 @@ -11306,7 +11306,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."dashboard_id" = 2) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND "posthog_dashboardtile"."dashboard_id" = 2) ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.17 @@ -11332,7 +11332,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.18 @@ -11344,7 +11344,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") AND "posthog_dashboardtile"."dashboard_id" = 2 - AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.19 @@ -11358,7 +11358,7 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.2 @@ -11390,14 +11390,14 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.20 ''' SELECT COUNT(*) AS "__count" FROM "posthog_taggeditem" - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.21 @@ -11457,7 +11457,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.22 @@ -11471,7 +11471,7 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.23 @@ -11640,7 +11640,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND (NOT "posthog_dashboarditem"."deleted" OR "posthog_dashboardtile"."insight_id" IS NULL)) - ORDER BY "posthog_dashboarditem"."order" ASC /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + ORDER BY "posthog_dashboarditem"."order" ASC ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.24 @@ -11648,7 +11648,7 @@ SELECT "posthog_tag"."name" FROM "posthog_taggeditem" INNER JOIN "posthog_tag" ON ("posthog_taggeditem"."tag_id" = "posthog_tag"."id") - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.25 @@ -11679,7 +11679,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.26 @@ -11732,7 +11732,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.27 @@ -11764,7 +11764,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.28 @@ -11790,7 +11790,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.29 @@ -11798,7 +11798,7 @@ SELECT COUNT(*) AS "__count" FROM "posthog_dashboard" WHERE (NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboard"."team_id" = 2) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND "posthog_dashboard"."team_id" = 2) ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.3 @@ -11809,7 +11809,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.30 @@ -11934,7 +11934,7 @@ WHERE (NOT ("posthog_dashboard"."deleted") AND "posthog_dashboard"."team_id" = 2) ORDER BY "posthog_dashboard"."name" ASC - LIMIT 100 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 100 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.31 @@ -11956,7 +11956,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.32 @@ -11974,7 +11974,7 @@ 2, 3, 4, - 5 /* ... */) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + 5 /* ... */) ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.33 @@ -12003,7 +12003,7 @@ WHERE (NOT ("posthog_dashboardtile"."deleted" AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") - AND "posthog_dashboardtile"."dashboard_id" = 2) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND "posthog_dashboardtile"."dashboard_id" = 2) ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.5 @@ -12029,7 +12029,7 @@ "posthog_organization"."available_features" FROM "posthog_organization" WHERE "posthog_organization"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.6 @@ -12041,7 +12041,7 @@ AND "posthog_dashboardtile"."deleted" IS NOT NULL) AND NOT ("posthog_dashboard"."deleted") AND "posthog_dashboardtile"."dashboard_id" = 2 - AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + AND NOT ("posthog_dashboardtile"."insight_id" IS NULL)) ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.7 @@ -12055,14 +12055,14 @@ "posthog_sharingconfiguration"."enabled", "posthog_sharingconfiguration"."access_token" FROM "posthog_sharingconfiguration" - WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_sharingconfiguration"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.8 ''' SELECT COUNT(*) AS "__count" FROM "posthog_taggeditem" - WHERE "posthog_taggeditem"."dashboard_id" = 2 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + WHERE "posthog_taggeditem"."dashboard_id" = 2 ''' # --- # name: TestDashboard.test_retrieve_dashboard_list.9 @@ -12122,6 +12122,6 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_dashboards-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/dashboards/%3F%24'*/ + LIMIT 21 ''' # --- diff --git a/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr b/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr index eaa59d4e760a8..e8aca8271e9d7 100644 --- a/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr +++ b/posthog/api/test/notebooks/__snapshots__/test_notebook.ambr @@ -27,7 +27,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.1 @@ -80,7 +80,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_notebooks-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.10 @@ -101,7 +101,7 @@ WHERE "posthog_notebook"."id" = '00000000-0000-0000-0000-000000000000'::uuid LIMIT 21 FOR - UPDATE /*controller='project_notebooks-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%28%3FP%3Cshort_id%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + UPDATE ''' # --- # name: TestNotebooks.test_updates_notebook.11 @@ -133,7 +133,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /*controller='project_notebooks-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%28%3FP%3Cshort_id%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.12 @@ -164,7 +164,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.13 @@ -217,7 +217,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_notebooks-all-activity',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/activity/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.14 @@ -249,7 +249,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_notebooks-all-activity',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/activity/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestNotebooks.test_updates_notebook.15 @@ -260,7 +260,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_notebooks-all-activity',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/activity/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestNotebooks.test_updates_notebook.16 @@ -268,7 +268,7 @@ SELECT COUNT(*) AS "__count" FROM "posthog_activitylog" WHERE ("posthog_activitylog"."scope" = 'Notebook' - AND "posthog_activitylog"."team_id" = 2) /*controller='project_notebooks-all-activity',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/activity/%3F%24'*/ + AND "posthog_activitylog"."team_id" = 2) ''' # --- # name: TestNotebooks.test_updates_notebook.17 @@ -314,7 +314,7 @@ WHERE ("posthog_activitylog"."scope" = 'Notebook' AND "posthog_activitylog"."team_id" = 2) ORDER BY "posthog_activitylog"."created_at" DESC - LIMIT 2 /*controller='project_notebooks-all-activity',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/activity/%3F%24'*/ + LIMIT 2 ''' # --- # name: TestNotebooks.test_updates_notebook.2 @@ -346,7 +346,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_notebooks-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestNotebooks.test_updates_notebook.3 @@ -357,7 +357,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_notebooks-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestNotebooks.test_updates_notebook.4 @@ -388,7 +388,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.5 @@ -441,7 +441,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_notebooks-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%28%3FP%3Cshort_id%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.6 @@ -473,7 +473,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_notebooks-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%28%3FP%3Cshort_id%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestNotebooks.test_updates_notebook.7 @@ -484,7 +484,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_notebooks-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%28%3FP%3Cshort_id%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestNotebooks.test_updates_notebook.8 @@ -610,7 +610,7 @@ LEFT OUTER JOIN "posthog_user" T4 ON ("posthog_notebook"."last_modified_by_id" = T4."id") WHERE ("posthog_notebook"."team_id" = 2 AND "posthog_notebook"."short_id" = '00000000') - LIMIT 21 /*controller='project_notebooks-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%28%3FP%3Cshort_id%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestNotebooks.test_updates_notebook.9 @@ -629,6 +629,6 @@ "posthog_notebook"."last_modified_by_id" FROM "posthog_notebook" WHERE "posthog_notebook"."id" = '00000000-0000-0000-0000-000000000000'::uuid - LIMIT 21 /*controller='project_notebooks-detail',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/notebooks/%28%3FP%3Cshort_id%3E%5B%5E/.%5D%2B%29/%3F%24'*/ + LIMIT 21 ''' # --- diff --git a/posthog/api/test/test_action.py b/posthog/api/test/test_action.py index c86d14d4156b1..295d9025c0eb7 100644 --- a/posthog/api/test/test_action.py +++ b/posthog/api/test/test_action.py @@ -1,15 +1,13 @@ -import json from unittest.mock import patch from freezegun import freeze_time from rest_framework import status -from posthog.models import Action, ActionStep, Organization, Tag, User +from posthog.models import Action, ActionStep, Tag, User from posthog.test.base import ( APIBaseTest, ClickhouseTestMixin, QueryMatchingTest, - _create_event, snapshot_postgres_queries_context, FuzzyInt, ) @@ -257,100 +255,6 @@ def test_create_action_event_with_space(self, patch_capture, *args): action = Action.objects.get() self.assertEqual(action.steps.get().event, "test_event ") - @freeze_time("2021-12-12") - def test_get_event_count(self, *args): - team2 = Organization.objects.bootstrap(None, team_fields={"name": "bla"})[2] - action = Action.objects.create(team=self.team, name="bla") - ActionStep.objects.create(action=action, event="custom event") - _create_event( - event="custom event", - team=self.team, - distinct_id="test", - timestamp="2021-12-04T19:20:00Z", - ) - _create_event( - event="another event", - team=self.team, - distinct_id="test", - timestamp="2021-12-04T19:20:00Z", - ) - # test team leakage - _create_event( - event="custom event", - team=team2, - distinct_id="test", - timestamp="2021-12-04T19:20:00Z", - ) - - response = self.client.get(f"/api/projects/{self.team.id}/actions/{action.id}/count").json() - self.assertEqual(response, {"count": 1}) - - @freeze_time("2021-12-10") - def test_hogql_filter(self, *args): - action = Action.objects.create(team=self.team, name="bla") - ActionStep.objects.create( - action=action, - event="custom event", - properties=[{"key": "'a%sd' != 'sdf'", "type": "hogql"}], - ) - _create_event( - event="custom event", - team=self.team, - distinct_id="test", - timestamp="2021-12-04T19:20:00Z", - ) - _create_event( - event="another event", - team=self.team, - distinct_id="test", - timestamp="2021-12-04T19:21:00Z", - ) - - # action count - response = self.client.get(f"/api/projects/{self.team.id}/actions/{action.id}/count").json() - self.assertEqual(response, {"count": 1}) - # events list - response = self.client.get(f"/api/projects/{self.team.id}/events/?action_id={action.id}").json() - self.assertEqual(len(response["results"]), 1) - # trends insight - response = self.client.get( - f"/api/projects/{self.team.id}/insights/trend/?actions={json.dumps([{'type': 'actions', 'id': action.id}])}" - ).json() - self.assertEqual(response["result"][0]["count"], 1) - - @freeze_time("2021-12-10") - def test_hogql_filter_no_event(self, *args): - action = Action.objects.create(team=self.team, name="bla") - ActionStep.objects.create( - action=action, - event=None, - properties=[{"key": "event like 'blue %'", "type": "hogql"}], - ) - _create_event( - event="blue event", - team=self.team, - distinct_id="test", - timestamp="2021-12-04T19:20:00Z", - ) - _create_event( - event="green event", - team=self.team, - distinct_id="test", - timestamp="2021-12-04T19:21:00Z", - ) - - # action count - response = self.client.get(f"/api/projects/{self.team.id}/actions/{action.id}/count").json() - self.assertEqual(response, {"count": 1}) - # events list - response = self.client.get(f"/api/projects/{self.team.id}/events/?action_id={action.id}").json() - self.assertEqual(len(response["results"]), 1) - # trends insight - response = self.client.get( - f"/api/projects/{self.team.id}/insights/trend/?actions={json.dumps([{'type': 'actions', 'id': action.id}])}" - ).json() - self.assertEqual(response["result"][0]["count"], 1) - @freeze_time("2021-12-12") def test_listing_actions_is_not_nplus1(self) -> None: with self.assertNumQueries(7), snapshot_postgres_queries_context(self): diff --git a/posthog/api/test/test_cohort.py b/posthog/api/test/test_cohort.py index fa0c63be36bf1..282a68d4787a6 100644 --- a/posthog/api/test/test_cohort.py +++ b/posthog/api/test/test_cohort.py @@ -695,6 +695,84 @@ def test_creating_update_and_calculating_with_new_cohort_filters(self, patch_cap self.assertEqual(response.status_code, 200, response.content) self.assertEqual(2, len(response.json()["results"])) + @patch("posthog.api.cohort.report_user_action") + def test_calculating_with_new_cohort_event_filters(self, patch_capture): + _create_person( + distinct_ids=["p1"], + team_id=self.team.pk, + properties={"$some_prop": "something"}, + ) + _create_event( + team=self.team, + event="$pageview", + distinct_id="p1", + properties={"$filter_prop": "something"}, + timestamp=datetime.now() - timedelta(hours=12), + ) + + _create_person( + distinct_ids=["p2"], + team_id=self.team.pk, + properties={"$some_prop": "not it"}, + ) + _create_event( + team=self.team, + event="$pageview", + distinct_id="p2", + properties={"$filter_prop": "something2"}, + timestamp=datetime.now() - timedelta(hours=12), + ) + + _create_person( + distinct_ids=["p3"], + team_id=self.team.pk, + properties={"$some_prop": "something"}, + ) + _create_event( + team=self.team, + event="$pageview", + distinct_id="p3", + properties={"$filter_prop": "something2"}, + timestamp=datetime.now() - timedelta(days=12), + ) + + flush_persons_and_events() + + response = self.client.post( + f"/api/projects/{self.team.id}/cohorts", + data={ + "name": "cohort A", + "filters": { + "properties": { + "type": "OR", + "values": [ + { + "key": "$pageview", + "event_type": "events", + "time_value": 1, + "time_interval": "day", + "value": "performed_event", + "type": "behavioral", + "event_filters": [ + {"key": "$filter_prop", "value": "something", "operator": "exact", "type": "event"} + ], + }, + ], + } + }, + }, + ) + self.assertEqual(response.status_code, 201, response.content) + + cohort_id = response.json()["id"] + + while response.json()["is_calculating"]: + response = self.client.get(f"/api/projects/{self.team.id}/cohorts/{cohort_id}") + + response = self.client.get(f"/api/projects/{self.team.id}/cohorts/{cohort_id}/persons/?cohort={cohort_id}") + self.assertEqual(response.status_code, 200, response.content) + self.assertEqual(1, len(response.json()["results"])) + @patch("posthog.api.cohort.report_user_action") def test_creating_update_and_calculating_with_new_cohort_query(self, patch_capture): _create_person( diff --git a/posthog/api/test/test_decide.py b/posthog/api/test/test_decide.py index 7cb58bbce2324..05b8f11d78dd6 100644 --- a/posthog/api/test/test_decide.py +++ b/posthog/api/test/test_decide.py @@ -3656,7 +3656,7 @@ def test_decide_uses_read_replica(self, mock_is_connected): # make sure we have the flags in cache response = self._post_decide(api_version=3) - with self.assertNumQueries(2, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(4, using="replica"), self.assertNumQueries(0, using="default"): response = self._post_decide(api_version=3) # Replica queries: # E 1. SET LOCAL statement_timeout = 600 @@ -3833,7 +3833,7 @@ def test_decide_uses_read_replica_for_cohorts_based_flags(self, mock_is_connecte # make sure we have the flags in cache response = self._post_decide(api_version=3) - with self.assertNumQueries(3, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(5, using="replica"), self.assertNumQueries(0, using="default"): response = self._post_decide(api_version=3, distinct_id="cohort_founder") # Replica queries: # E 1. SET LOCAL statement_timeout = 600 @@ -3851,7 +3851,7 @@ def test_decide_uses_read_replica_for_cohorts_based_flags(self, mock_is_connecte }, ) - with self.assertNumQueries(3, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(5, using="replica"), self.assertNumQueries(0, using="default"): response = self._post_decide(api_version=3, distinct_id="example_id") # Replica queries: # E 1. SET LOCAL statement_timeout = 600 @@ -3869,7 +3869,7 @@ def test_decide_uses_read_replica_for_cohorts_based_flags(self, mock_is_connecte }, ) - with self.assertNumQueries(3, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(5, using="replica"), self.assertNumQueries(0, using="default"): response = self._post_decide(api_version=3, distinct_id="cohort_secondary") # Replica queries: # E 1. SET LOCAL statement_timeout = 600 @@ -3962,7 +3962,7 @@ def test_feature_flags_v3_consistent_flags(self, mock_is_connected): # make sure caches are populated response = self._post_decide() - with self.assertNumQueries(5, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(9, using="replica"), self.assertNumQueries(0, using="default"): # E 1. SET LOCAL statement_timeout = 300 # E 2. SELECT "posthog_persondistinctid"."person_id", "posthog_persondistinctid"."distinct_id" FROM "posthog_persondistinctid" # WHERE ("posthog_persondistinctid"."distinct_id" IN ('example_id') AND "posthog_persondistinctid"."team_id" = 1) @@ -3995,7 +3995,7 @@ def test_feature_flags_v3_consistent_flags(self, mock_is_connected): ) # new request with hash key overrides but not writes should not go to main database - with self.assertNumQueries(7, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(13, using="replica"), self.assertNumQueries(0, using="default"): # Replica queries: # E 1. SET LOCAL statement_timeout = 300 # E 2. WITH some CTEs, @@ -4024,7 +4024,7 @@ def test_feature_flags_v3_consistent_flags(self, mock_is_connected): # now main database is down, but does not affect replica with connections["default"].execute_wrapper(QueryTimeoutWrapper()), self.assertNumQueries( - 7, using="replica" + 13, using="replica" ), self.assertNumQueries(0, using="default"): # Replica queries: # E 1. SET LOCAL statement_timeout = 300 @@ -4134,7 +4134,7 @@ def test_feature_flags_v3_consistent_flags_with_write_on_hash_key_overrides(self # make sure caches are populated response = self._post_decide(api_version=3) - with self.assertNumQueries(5, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(9, using="replica"), self.assertNumQueries(0, using="default"): # E 1. SET LOCAL statement_timeout = 300 # E 2. SELECT "posthog_persondistinctid"."person_id", "posthog_persondistinctid"."distinct_id" FROM "posthog_persondistinctid" # WHERE ("posthog_persondistinctid"."distinct_id" IN ('example_id') AND "posthog_persondistinctid"."team_id" = 1) @@ -4153,7 +4153,7 @@ def test_feature_flags_v3_consistent_flags_with_write_on_hash_key_overrides(self PersonDistinctId.objects.using("default").create(person=person, distinct_id="other_id", team=self.team) # request with hash key overrides and _new_ writes should go to main database - with self.assertNumQueries(4, using="replica"), self.assertNumQueries(5, using="default"): + with self.assertNumQueries(8, using="replica"), self.assertNumQueries(9, using="default"): # Replica queries: # E 1. SET LOCAL statement_timeout = 300 # E 2. WITH some CTEs, @@ -4244,7 +4244,7 @@ def test_feature_flags_v2_with_groups(self, mock_is_connected): version=0, ) - with self.assertNumQueries(2, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(4, using="replica"), self.assertNumQueries(0, using="default"): # E 1. SET LOCAL statement_timeout = 300 # E 2. SELECT "posthog_grouptypemapping"."id", -- a.k.a. get group type mappings response = self._post_decide(distinct_id="example_id") @@ -4254,7 +4254,7 @@ def test_feature_flags_v2_with_groups(self, mock_is_connected): ) self.assertFalse(response.json()["errorsWhileComputingFlags"]) - with self.assertNumQueries(5, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(9, using="replica"), self.assertNumQueries(0, using="default"): # E 1. SET LOCAL statement_timeout = 300 # E 2. SELECT "posthog_grouptypemapping"."id", "posthog_grouptypemapping"."team_id", -- a.k.a get group type mappings @@ -4271,7 +4271,7 @@ def test_feature_flags_v2_with_groups(self, mock_is_connected): ) self.assertFalse(response.json()["errorsWhileComputingFlags"]) - with self.assertNumQueries(5, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(9, using="replica"), self.assertNumQueries(0, using="default"): # E 2. SET LOCAL statement_timeout = 300 # E 3. SELECT "posthog_grouptypemapping"."id", "posthog_grouptypemapping"."team_id", -- a.k.a get group type mappings @@ -4317,7 +4317,7 @@ def test_site_apps_in_decide_use_replica(self, mock_is_connected): # update caches self._post_decide(api_version=3) - with self.assertNumQueries(2, using="replica"), self.assertNumQueries(0, using="default"): + with self.assertNumQueries(4, using="replica"), self.assertNumQueries(0, using="default"): response = self._post_decide(api_version=3) self.assertEqual(response.status_code, status.HTTP_200_OK) injected = response.json()["siteApps"] @@ -4420,7 +4420,7 @@ def test_local_evaluation(self, mock_rate_limit, mock_capture): response = self.client.get(f"/api/feature_flag/local_evaluation") self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) - with self.assertNumQueries(3, using="replica"), self.assertNumQueries(3, using="default"): + with self.assertNumQueries(3, using="replica"), self.assertNumQueries(5, using="default"): # Captured queries for write DB: # E 1. UPDATE "posthog_personalapikey" SET "last_used_at" = '2023-08-01T11:26:50.728057+00:00' # E 2. SELECT "posthog_team"."id", "posthog_team"."uuid", "posthog_team"."organization_id" @@ -4661,7 +4661,7 @@ def test_local_evaluation_for_cohorts(self, mock_rate_limit, mock_capture): PersonalAPIKey.objects.create(label="X", user=self.user, secure_value=hash_key_value(personal_api_key)) cache.clear() - with self.assertNumQueries(4, using="replica"), self.assertNumQueries(3, using="default"): + with self.assertNumQueries(4, using="replica"), self.assertNumQueries(5, using="default"): # Captured queries for write DB: # E 1. UPDATE "posthog_personalapikey" SET "last_used_at" = '2023-08-01T11:26:50.728057+00:00' # E 2. SELECT "posthog_team"."id", "posthog_team"."uuid", "posthog_team"."organization_id" @@ -4931,7 +4931,7 @@ def test_local_evaluation_for_arbitrary_cohorts(self, mock_rate_limit, mock_capt client.logout() self.client.logout() - with self.assertNumQueries(4, using="replica"), self.assertNumQueries(3, using="default"): + with self.assertNumQueries(4, using="replica"), self.assertNumQueries(5, using="default"): # Captured queries for write DB: # E 1. UPDATE "posthog_personalapikey" SET "last_used_at" = '2023-08-01T11:26:50.728057+00:00' # E 2. SELECT "posthog_team"."id", "posthog_team"."uuid", "posthog_team"."organization_id" diff --git a/posthog/api/test/test_feature_flag.py b/posthog/api/test/test_feature_flag.py index 8a6010bbed37e..770883a191490 100644 --- a/posthog/api/test/test_feature_flag.py +++ b/posthog/api/test/test_feature_flag.py @@ -4962,7 +4962,7 @@ def test_feature_flags_v3_with_group_properties(self, *args): self.assertTrue(serialized_data.is_valid()) serialized_data.save() - with self.assertNumQueries(4): + with self.assertNumQueries(8): # one query to get group type mappings, another to get group properties # 2 to set statement timeout all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id", groups={"organization": "org:1"}) @@ -4972,7 +4972,7 @@ def test_feature_flags_v3_with_group_properties(self, *args): # now db is down with snapshot_postgres_queries_context(self), connection.execute_wrapper(QueryTimeoutWrapper()): - with self.assertNumQueries(1): + with self.assertNumQueries(3): all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id", groups={"organization": "org:1"}) self.assertTrue("group-flag" not in all_flags) @@ -4981,7 +4981,7 @@ def test_feature_flags_v3_with_group_properties(self, *args): self.assertTrue(errors) # # now db is down, but decide was sent correct group property overrides - with self.assertNumQueries(1): + with self.assertNumQueries(3): all_flags, _, _, errors = get_all_feature_flags( team_id, "random", @@ -4994,7 +4994,7 @@ def test_feature_flags_v3_with_group_properties(self, *args): self.assertTrue(errors) # # now db is down, but decide was sent different group property overrides - with self.assertNumQueries(1): + with self.assertNumQueries(3): all_flags, _, _, errors = get_all_feature_flags( team_id, "exam", @@ -5060,7 +5060,7 @@ def test_feature_flags_v3_with_person_properties(self, mock_counter, *args): self.assertTrue(serialized_data.is_valid()) serialized_data.save() - with self.assertNumQueries(2): + with self.assertNumQueries(4): # 1 query to get person properties # 1 to set statement timeout all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id") @@ -5158,7 +5158,7 @@ def test_feature_flags_v3_with_a_working_slow_db(self, mock_postgres_check): self.assertTrue(serialized_data.is_valid()) serialized_data.save() - with self.assertNumQueries(2): + with self.assertNumQueries(4): # 1 query to set statement timeout # 1 query to get person properties all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id") @@ -5366,7 +5366,7 @@ def test_feature_flags_v3_with_slow_db_doesnt_try_to_compute_conditions_again(se created_by=self.user, ) - with self.assertNumQueries(2): + with self.assertNumQueries(4): # 1 query to get person properties # 1 query to set statement timeout all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id") @@ -5379,7 +5379,7 @@ def test_feature_flags_v3_with_slow_db_doesnt_try_to_compute_conditions_again(se with snapshot_postgres_queries_context(self), connection.execute_wrapper(slow_query), patch( "posthog.models.feature_flag.flag_matching.FLAG_MATCHING_QUERY_TIMEOUT_MS", 500, - ), self.assertNumQueries(2): + ), self.assertNumQueries(4): # no extra queries to get person properties for the second flag after first one failed all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id") @@ -5458,7 +5458,7 @@ def test_feature_flags_v3_with_group_properties_and_slow_db(self, mock_counter, self.assertTrue(serialized_data.is_valid()) serialized_data.save() - with self.assertNumQueries(4): + with self.assertNumQueries(8): # one query to get group type mappings, another to get group properties # 2 queries to set statement timeout all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id", groups={"organization": "org:1"}) @@ -5471,7 +5471,7 @@ def test_feature_flags_v3_with_group_properties_and_slow_db(self, mock_counter, "posthog.models.feature_flag.flag_matching.FLAG_MATCHING_QUERY_TIMEOUT_MS", 500, ): - with self.assertNumQueries(2): + with self.assertNumQueries(4): all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id", groups={"organization": "org:1"}) self.assertTrue("group-flag" not in all_flags) @@ -5480,7 +5480,7 @@ def test_feature_flags_v3_with_group_properties_and_slow_db(self, mock_counter, self.assertTrue(errors) # # now db is slow, but decide was sent correct group property overrides - with self.assertNumQueries(2): + with self.assertNumQueries(4): all_flags, _, _, errors = get_all_feature_flags( team_id, "random", @@ -5502,7 +5502,7 @@ def test_feature_flags_v3_with_group_properties_and_slow_db(self, mock_counter, ) # # now db is down, but decide was sent different group property overrides - with self.assertNumQueries(2): + with self.assertNumQueries(4): all_flags, _, _, errors = get_all_feature_flags( team_id, "exam", @@ -5569,7 +5569,7 @@ def test_feature_flags_v3_with_experience_continuity_working_slow_db(self, mock_ self.assertTrue(serialized_data.is_valid()) serialized_data.save() - with snapshot_postgres_queries_context(self), self.assertNumQueries(9): + with snapshot_postgres_queries_context(self), self.assertNumQueries(17): all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id", hash_key_override="random") self.assertTrue(all_flags["property-flag"]) @@ -5589,7 +5589,7 @@ def test_feature_flags_v3_with_experience_continuity_working_slow_db(self, mock_ # # now db is slow, but decide was sent email parameter with correct email # still need to get hash key override from db, so should time out - with self.assertNumQueries(2): + with self.assertNumQueries(4): all_flags, _, _, errors = get_all_feature_flags( team_id, "random", @@ -5661,7 +5661,7 @@ def test_feature_flags_v3_with_experience_continuity_and_incident_mode(self, moc self.assertTrue(serialized_data.is_valid()) serialized_data.save() - with self.assertNumQueries(5), self.settings(DECIDE_SKIP_HASH_KEY_OVERRIDE_WRITES=True): + with self.assertNumQueries(9), self.settings(DECIDE_SKIP_HASH_KEY_OVERRIDE_WRITES=True): all_flags, _, _, errors = get_all_feature_flags(team_id, "example_id", hash_key_override="random") self.assertTrue(all_flags["property-flag"]) diff --git a/posthog/api/test/test_persons_trends.py b/posthog/api/test/test_persons_trends.py index 24ccbf2bc7838..6d9ce30a9f158 100644 --- a/posthog/api/test/test_persons_trends.py +++ b/posthog/api/test/test_persons_trends.py @@ -658,47 +658,6 @@ def _create_multiple_people(self): flush_persons_and_events() return (person1, person2, person3, person4) - def test_people_csv(self): - person1, _, _, _ = self._create_multiple_people() - people = self.client.get( - f"/api/projects/{self.team.id}/actions/people.csv", - data={ - "date_from": "2020-01-01", - "date_to": "2020-01-07", - ENTITY_TYPE: "events", - ENTITY_ID: "watched movie", - "display": "ActionsLineGraphCumulative", - "entity_math": "dau", - "events": json.dumps([{"id": "watched movie", "type": "events", "math": "dau"}]), - }, - ) - resp = people.content.decode("utf-8").split("\r\n") - resp = sorted(resp) - self.assertEqual(len(resp), 6) # header, 4 people, empty line - self.assertEqual(resp[1], "Distinct ID,Email,Internal ID,Name,Properties.name") - self.assertEqual(resp[2].split(",")[0], "person1") - - def test_people_csv_returns_400_on_no_entity_id_provided(self): - response = self.client.get( - f"/api/projects/{self.team.id}/actions/people", - data={ - "date_from": "2020-01-01", - "date_to": "2020-01-07", - # Here we don't provide an entity_id or entity_type, which are - # required - }, - ) - self.assertEqual(response.status_code, 400) - self.assertEqual( - json.loads(response.content), - { - "type": "validation_error", - "code": "invalid_input", - "detail": "An entity id and the entity type must be provided to determine an entity", - "attr": None, - }, - ) - def test_breakdown_by_cohort_people_endpoint(self): person1, _, _, _ = self._create_multiple_people() cohort = _create_cohort( diff --git a/posthog/api/test/test_property_definition.py b/posthog/api/test/test_property_definition.py index 3d68b73facd59..77dca5e833076 100644 --- a/posthog/api/test/test_property_definition.py +++ b/posthog/api/test/test_property_definition.py @@ -1,3 +1,4 @@ +import json from typing import Dict, List, Optional, Union from unittest.mock import ANY, patch @@ -318,6 +319,14 @@ def test_person_property_filter(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual([row["name"] for row in response.json()["results"]], ["event property"]) + response = self.client.get(f"/api/projects/{self.team.pk}/property_definitions/?type=person&search=latest") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual([row["name"] for row in response.json()["results"]], ["another", "person property"]) + + response = self.client.get(f"/api/projects/{self.team.pk}/property_definitions/?type=person&search=late") + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual([row["name"] for row in response.json()["results"]], ["another", "person property"]) + def test_group_property_filter(self): PropertyDefinition.objects.create( team=self.team, @@ -405,6 +414,11 @@ def test_delete_property_definition(self, mock_capture): assert activity_log.detail["name"] == "test_property" assert activity_log.activity == "deleted" + def test_event_name_filter_json_contains_int(self): + event_name_json = json.dumps([1]) + response = self.client.get(f"/api/projects/{self.team.pk}/property_definitions/?event_names={event_name_json}") + self.assertEqual(response.status_code, status.HTTP_200_OK) + def test_can_report_event_property_coexistence_when_custom_event_has_no_session_id(self) -> None: EventProperty.objects.create(team=self.team, event="$pageview", property="$session_id") diff --git a/posthog/api/test/test_team.py b/posthog/api/test/test_team.py index 11bc5c664e1dd..d23efe81cf7d8 100644 --- a/posthog/api/test/test_team.py +++ b/posthog/api/test/test_team.py @@ -204,47 +204,6 @@ def test_update_project_timezone(self): ] ) - @freeze_time("2022-02-08") - def test_activity_log_tracks_extra_settings(self): - self._assert_activity_log_is_empty() - - response = self.client.patch("/api/projects/@current/", {"extra_settings": {"poe_v2_enabled": True}}) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - response_data = response.json() - self.assertEqual(response_data["name"], self.team.name) - self.assertEqual(response_data["extra_settings"], {"poe_v2_enabled": True}) - - self._assert_activity_log( - [ - { - "activity": "updated", - "created_at": "2022-02-08T00:00:00Z", - "detail": { - "changes": [ - { - "action": "created", - "after": {"poe_v2_enabled": True}, - "before": None, - "field": "extra_settings", - "type": "Team", - }, - ], - "name": "Default project", - "short_id": None, - "trigger": None, - "type": None, - }, - "item_id": str(self.team.pk), - "scope": "Team", - "user": { - "email": "user1@posthog.com", - "first_name": "", - }, - }, - ] - ) - def test_update_test_filter_default_checked(self): response = self.client.patch("/api/projects/@current/", {"test_account_filters_default_checked": "true"}) self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/posthog/clickhouse/client/connection.py b/posthog/clickhouse/client/connection.py index fbbfd08086822..31ae6cd291de0 100644 --- a/posthog/clickhouse/client/connection.py +++ b/posthog/clickhouse/client/connection.py @@ -38,7 +38,7 @@ def get_pool(workload: Workload, team_id=None, readonly=False): if ( workload == Workload.OFFLINE or workload == Workload.DEFAULT and _default_workload == Workload.OFFLINE ) and settings.CLICKHOUSE_OFFLINE_CLUSTER_HOST is not None: - return make_ch_pool(host=settings.CLICKHOUSE_OFFLINE_CLUSTER_HOST) + return make_ch_pool(host=settings.CLICKHOUSE_OFFLINE_CLUSTER_HOST, verify=False) return make_ch_pool() diff --git a/posthog/clickhouse/client/escape.py b/posthog/clickhouse/client/escape.py index c1a2ae1cf4197..49e7b1047f372 100644 --- a/posthog/clickhouse/client/escape.py +++ b/posthog/clickhouse/client/escape.py @@ -89,7 +89,6 @@ def escape_param_for_clickhouse(param: Any) -> str: version_patch="placeholder server_info value", revision="placeholder server_info value", display_name="placeholder server_info value", - used_revision="placeholder server_info value", timezone="UTC", ) return escape_param(param, context=context) diff --git a/posthog/constants.py b/posthog/constants.py index 78175d9386f97..b9e6f2ce14f18 100644 --- a/posthog/constants.py +++ b/posthog/constants.py @@ -262,6 +262,14 @@ class ExperimentSignificanceCode(str, Enum): HIGH_P_VALUE = "high_p_value" +class ExperimentNoResultsErrorKeys(str, Enum): + NO_EVENTS = "no-events" + NO_FLAG_INFO = "no-flag-info" + NO_CONTROL_VARIANT = "no-control-variant" + NO_TEST_VARIANT = "no-test-variant" + NO_RESULTS = "no-results" + + class PropertyOperatorType(str, Enum): AND = "AND" OR = "OR" diff --git a/posthog/hogql/database/database.py b/posthog/hogql/database/database.py index e2b17908b4320..1058c5eb30122 100644 --- a/posthog/hogql/database/database.py +++ b/posthog/hogql/database/database.py @@ -34,13 +34,12 @@ from posthog.hogql.database.schema.person_distinct_id_overrides import ( PersonDistinctIdOverridesTable, RawPersonDistinctIdOverridesTable, - join_with_person_distinct_id_overrides_table, ) from posthog.hogql.database.schema.person_distinct_ids import ( PersonDistinctIdsTable, RawPersonDistinctIdsTable, ) -from posthog.hogql.database.schema.persons import PersonsTable, RawPersonsTable +from posthog.hogql.database.schema.persons import PersonsTable, RawPersonsTable, join_with_persons_table from posthog.hogql.database.schema.person_overrides import ( PersonOverridesTable, RawPersonOverridesTable, @@ -143,6 +142,26 @@ def add_warehouse_tables(self, **field_definitions: Any): self._warehouse_table_names.append(f_name) +def _use_person_properties_from_events(database: Database) -> None: + database.events.fields["person"] = FieldTraverser(chain=["poe"]) + + +def _use_person_id_from_person_overrides(database: Database) -> None: + database.events.fields["event_person_id"] = StringDatabaseField(name="person_id") + database.events.fields["override"] = LazyJoin( + from_field=["event_person_id"], + join_table=PersonOverridesTable(), + join_function=join_with_person_overrides_table, + ) + database.events.fields["person_id"] = ExpressionField( + name="person_id", + expr=parse_expr( + "ifNull(nullIf(override.override_person_id, '00000000-0000-0000-0000-000000000000'), event_person_id)", + start=None, + ), + ) + + def create_hogql_database( team_id: int, modifiers: Optional[HogQLQueryModifiers] = None, team_arg: Optional["Team"] = None ) -> Database: @@ -163,52 +182,22 @@ def create_hogql_database( database.events.fields["person"] = FieldTraverser(chain=["pdi", "person"]) database.events.fields["person_id"] = FieldTraverser(chain=["pdi", "person_id"]) - elif modifiers.personsOnEventsMode == PersonsOnEventsMode.v1_mixed: - # person.id via a join, person.properties on events - database.events.fields["person_id"] = FieldTraverser(chain=["pdi", "person_id"]) - database.events.fields["person"] = FieldTraverser(chain=["poe"]) - database.events.fields["poe"].fields["id"] = FieldTraverser(chain=["..", "pdi", "person_id"]) - database.events.fields["poe"].fields["created_at"] = FieldTraverser(chain=["..", "pdi", "person", "created_at"]) - database.events.fields["poe"].fields["properties"] = StringJSONDatabaseField(name="person_properties") - - elif modifiers.personsOnEventsMode == PersonsOnEventsMode.v1_enabled: - database.events.fields["person"] = FieldTraverser(chain=["poe"]) + elif modifiers.personsOnEventsMode == PersonsOnEventsMode.person_id_no_override_properties_on_events: database.events.fields["person_id"] = StringDatabaseField(name="person_id") + _use_person_properties_from_events(database) - elif modifiers.personsOnEventsMode == PersonsOnEventsMode.v2_enabled: - database.events.fields["event_person_id"] = StringDatabaseField(name="person_id") - database.events.fields["override"] = LazyJoin( - from_field=["event_person_id"], - join_table=PersonOverridesTable(), - join_function=join_with_person_overrides_table, - ) - database.events.fields["person_id"] = ExpressionField( - name="person_id", - expr=parse_expr( - "ifNull(nullIf(override.override_person_id, '00000000-0000-0000-0000-000000000000'), event_person_id)", - start=None, - ), - ) + elif modifiers.personsOnEventsMode == PersonsOnEventsMode.person_id_override_properties_on_events: + _use_person_id_from_person_overrides(database) + _use_person_properties_from_events(database) database.events.fields["poe"].fields["id"] = database.events.fields["person_id"] - database.events.fields["person"] = FieldTraverser(chain=["poe"]) - - elif modifiers.personsOnEventsMode == PersonsOnEventsMode.v3_enabled: - database.events.fields["event_person_id"] = StringDatabaseField(name="person_id") - database.events.fields["override"] = LazyJoin( - from_field=["distinct_id"], # ??? - join_table=PersonDistinctIdOverridesTable(), - join_function=join_with_person_distinct_id_overrides_table, - ) - database.events.fields["person_id"] = ExpressionField( - name="person_id", - expr=parse_expr( - # NOTE: assumes `join_use_nulls = 0` (the default), as ``override.distinct_id`` is not Nullable - "if(not(empty(override.distinct_id)), override.person_id, event_person_id)", - start=None, - ), + + elif modifiers.personsOnEventsMode == PersonsOnEventsMode.person_id_override_properties_joined: + _use_person_id_from_person_overrides(database) + database.events.fields["person"] = LazyJoin( + from_field=["person_id"], + join_table=PersonsTable(), + join_function=join_with_persons_table, ) - database.events.fields["poe"].fields["id"] = database.events.fields["person_id"] - database.events.fields["person"] = FieldTraverser(chain=["poe"]) database.persons.fields["$virt_initial_referring_domain_type"] = create_initial_domain_type( "$virt_initial_referring_domain_type" diff --git a/posthog/hogql/database/schema/util/session_where_clause_extractor.py b/posthog/hogql/database/schema/util/session_where_clause_extractor.py index 83933bdde8b85..72ed8b38388ca 100644 --- a/posthog/hogql/database/schema/util/session_where_clause_extractor.py +++ b/posthog/hogql/database/schema/util/session_where_clause_extractor.py @@ -154,6 +154,26 @@ def visit_call(self, node: ast.Call) -> ast.Expr: return self.visit_and(ast.And(exprs=node.args)) elif node.name == "or": return self.visit_or(ast.Or(exprs=node.args)) + elif node.name == "greaterOrEquals": + return self.visit_compare_operation( + ast.CompareOperation(op=CompareOperationOp.GtEq, left=node.args[0], right=node.args[1]) + ) + elif node.name == "greater": + return self.visit_compare_operation( + ast.CompareOperation(op=CompareOperationOp.Gt, left=node.args[0], right=node.args[1]) + ) + elif node.name == "lessOrEquals": + return self.visit_compare_operation( + ast.CompareOperation(op=CompareOperationOp.LtEq, left=node.args[0], right=node.args[1]) + ) + elif node.name == "less": + return self.visit_compare_operation( + ast.CompareOperation(op=CompareOperationOp.Lt, left=node.args[0], right=node.args[1]) + ) + elif node.name == "equals": + return self.visit_compare_operation( + ast.CompareOperation(op=CompareOperationOp.Eq, left=node.args[0], right=node.args[1]) + ) return ast.Constant(value=True) def visit_field(self, node: ast.Field) -> ast.Expr: diff --git a/posthog/hogql/database/schema/util/test/test_session_where_clause_extractor.py b/posthog/hogql/database/schema/util/test/test_session_where_clause_extractor.py index bc5324e739ad9..55078df6ef4d4 100644 --- a/posthog/hogql/database/schema/util/test/test_session_where_clause_extractor.py +++ b/posthog/hogql/database/schema/util/test/test_session_where_clause_extractor.py @@ -190,6 +190,16 @@ def test_minus_function(self): expected = f("((raw_sessions.min_timestamp + toIntervalDay(3)) >= minus(today(), 2))") assert expected == actual + def test_less_function(self): + actual = f(self.inliner.get_inner_where(parse("SELECT * FROM sessions WHERE less(min_timestamp, today())"))) + expected = f("((raw_sessions.min_timestamp - toIntervalDay(3)) <= today())") + assert expected == actual + + def test_less_function_second_arg(self): + actual = f(self.inliner.get_inner_where(parse("SELECT * FROM sessions WHERE less(today(), min_timestamp)"))) + expected = f("((raw_sessions.min_timestamp + toIntervalDay(3)) >= today())") + assert expected == actual + def test_real_example(self): actual = f( self.inliner.get_inner_where( diff --git a/posthog/hogql/escape_sql.py b/posthog/hogql/escape_sql.py index 88eda5cafa4e4..0d0f12d0d2dea 100644 --- a/posthog/hogql/escape_sql.py +++ b/posthog/hogql/escape_sql.py @@ -61,7 +61,7 @@ def escape_hogql_string( def escape_clickhouse_string( - name: float | int | str | list | tuple | date | datetime | UUID | UUIDT, + name: Optional[float | int | str | list | tuple | date | datetime | UUID | UUIDT], timezone: Optional[str] = None, ) -> str: return SQLValueEscaper(timezone=timezone, dialect="clickhouse").visit(name) diff --git a/posthog/hogql/functions/__init__.py b/posthog/hogql/functions/__init__.py index 5dff22c3a185b..3e1dadb2513fb 100644 --- a/posthog/hogql/functions/__init__.py +++ b/posthog/hogql/functions/__init__.py @@ -1,9 +1,9 @@ from .mapping import ( - find_clickhouse_function, + find_hogql_function, validate_function_args, HogQLFunctionMeta, - HOGQL_AGGREGATIONS, - HOGQL_POSTHOG_FUNCTIONS, + find_hogql_aggregation, + find_hogql_posthog_function, ADD_OR_NULL_DATETIME_FUNCTIONS, FIRST_ARG_DATETIME_FUNCTIONS, ) @@ -11,11 +11,11 @@ from .sparkline import sparkline __all__ = [ - "find_clickhouse_function", + "find_hogql_function", "validate_function_args", "HogQLFunctionMeta", - "HOGQL_AGGREGATIONS", - "HOGQL_POSTHOG_FUNCTIONS", + "find_hogql_aggregation", + "find_hogql_posthog_function", "ADD_OR_NULL_DATETIME_FUNCTIONS", "FIRST_ARG_DATETIME_FUNCTIONS", "cohort", diff --git a/posthog/hogql/functions/cohort.py b/posthog/hogql/functions/cohort.py index c87a6b7fa69d2..fc5077f610a4f 100644 --- a/posthog/hogql/functions/cohort.py +++ b/posthog/hogql/functions/cohort.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Optional from posthog.hogql import ast from posthog.hogql.context import HogQLContext @@ -7,12 +7,16 @@ from posthog.hogql.parser import parse_expr -def cohort_subquery(cohort_id, is_static) -> ast.Expr: +def cohort_subquery(cohort_id, is_static, version: Optional[int] = None) -> ast.Expr: if is_static: sql = "(SELECT person_id FROM static_cohort_people WHERE cohort_id = {cohort_id})" + elif version is not None: + sql = "(SELECT person_id FROM raw_cohort_people WHERE cohort_id = {cohort_id} AND version = {version})" else: sql = "(SELECT person_id FROM raw_cohort_people WHERE cohort_id = {cohort_id} GROUP BY person_id, cohort_id, version HAVING sum(sign) > 0)" - return parse_expr(sql, {"cohort_id": ast.Constant(value=cohort_id)}, start=None) # clear the source start position + return parse_expr( + sql, {"cohort_id": ast.Constant(value=cohort_id), "version": ast.Constant(value=version)}, start=None + ) # clear the source start position def cohort_query_node(node: ast.Expr, context: HogQLContext) -> ast.Expr: @@ -27,30 +31,32 @@ def cohort(node: ast.Expr, args: List[ast.Expr], context: HogQLContext) -> ast.E from posthog.models import Cohort if (isinstance(arg.value, int) or isinstance(arg.value, float)) and not isinstance(arg.value, bool): - cohorts = Cohort.objects.filter(id=int(arg.value), team_id=context.team_id).values_list( - "id", "is_static", "name" + cohorts1 = Cohort.objects.filter(id=int(arg.value), team_id=context.team_id).values_list( + "id", "is_static", "version", "name" ) - if len(cohorts) == 1: + if len(cohorts1) == 1: context.add_notice( start=arg.start, end=arg.end, - message=f"Cohort #{cohorts[0][0]} can also be specified as {escape_clickhouse_string(cohorts[0][2])}", - fix=escape_clickhouse_string(cohorts[0][2]), + message=f"Cohort #{cohorts1[0][0]} can also be specified as {escape_clickhouse_string(cohorts1[0][3])}", + fix=escape_clickhouse_string(cohorts1[0][3]), ) - return cohort_subquery(cohorts[0][0], cohorts[0][1]) + return cohort_subquery(cohorts1[0][0], cohorts1[0][1], cohorts1[0][2]) raise QueryError(f"Could not find cohort with ID {arg.value}", node=arg) if isinstance(arg.value, str): - cohorts = Cohort.objects.filter(name=arg.value, team_id=context.team_id).values_list("id", "is_static") - if len(cohorts) == 1: + cohorts2 = Cohort.objects.filter(name=arg.value, team_id=context.team_id).values_list( + "id", "is_static", "version" + ) + if len(cohorts2) == 1: context.add_notice( start=arg.start, end=arg.end, - message=f"Searching for cohort by name. Replace with numeric ID {cohorts[0][0]} to protect against renaming.", - fix=str(cohorts[0][0]), + message=f"Searching for cohort by name. Replace with numeric ID {cohorts2[0][0]} to protect against renaming.", + fix=str(cohorts2[0][0]), ) - return cohort_subquery(cohorts[0][0], cohorts[0][1]) - elif len(cohorts) > 1: + return cohort_subquery(cohorts2[0][0], cohorts2[0][1], cohorts2[0][2]) + elif len(cohorts2) > 1: raise QueryError(f"Found multiple cohorts with name '{arg.value}'", node=arg) raise QueryError(f"Could not find a cohort with the name '{arg.value}'", node=arg) diff --git a/posthog/hogql/functions/mapping.py b/posthog/hogql/functions/mapping.py index 0e457a7af0c22..9aff4371135ae 100644 --- a/posthog/hogql/functions/mapping.py +++ b/posthog/hogql/functions/mapping.py @@ -577,17 +577,16 @@ class HogQLFunctionMeta: # Permitted HogQL aggregations HOGQL_AGGREGATIONS: Dict[str, HogQLFunctionMeta] = { # Standard aggregate functions - "count": HogQLFunctionMeta("count", 0, 1, aggregate=True), - "COUNT": HogQLFunctionMeta("count", 0, 1, aggregate=True), + "count": HogQLFunctionMeta("count", 0, 1, aggregate=True, case_sensitive=False), "countIf": HogQLFunctionMeta("countIf", 1, 2, aggregate=True), "countDistinctIf": HogQLFunctionMeta("countIf", 1, 2, aggregate=True), - "min": HogQLFunctionMeta("min", 1, 1, aggregate=True), + "min": HogQLFunctionMeta("min", 1, 1, aggregate=True, case_sensitive=False), "minIf": HogQLFunctionMeta("minIf", 2, 2, aggregate=True), - "max": HogQLFunctionMeta("max", 1, 1, aggregate=True), + "max": HogQLFunctionMeta("max", 1, 1, aggregate=True, case_sensitive=False), "maxIf": HogQLFunctionMeta("maxIf", 2, 2, aggregate=True), - "sum": HogQLFunctionMeta("sum", 1, 1, aggregate=True), + "sum": HogQLFunctionMeta("sum", 1, 1, aggregate=True, case_sensitive=False), "sumIf": HogQLFunctionMeta("sumIf", 2, 2, aggregate=True), - "avg": HogQLFunctionMeta("avg", 1, 1, aggregate=True), + "avg": HogQLFunctionMeta("avg", 1, 1, aggregate=True, case_sensitive=False), "avgIf": HogQLFunctionMeta("avgIf", 2, 2, aggregate=True), "any": HogQLFunctionMeta("any", 1, 1, aggregate=True), "anyIf": HogQLFunctionMeta("anyIf", 2, 2, aggregate=True), @@ -781,12 +780,12 @@ class HogQLFunctionMeta: ) -def find_clickhouse_function(name: str) -> Optional[HogQLFunctionMeta]: - func = HOGQL_CLICKHOUSE_FUNCTIONS.get(name) +def _find_function(name: str, functions: Dict[str, HogQLFunctionMeta]) -> Optional[HogQLFunctionMeta]: + func = functions.get(name) if func is not None: return func - func = HOGQL_CLICKHOUSE_FUNCTIONS.get(name.lower()) + func = functions.get(name.lower()) if func is None: return None # If we haven't found a function with the case preserved, but we have found it in lowercase, @@ -795,3 +794,15 @@ def find_clickhouse_function(name: str) -> Optional[HogQLFunctionMeta]: return None return func + + +def find_hogql_aggregation(name: str) -> Optional[HogQLFunctionMeta]: + return _find_function(name, HOGQL_AGGREGATIONS) + + +def find_hogql_function(name: str) -> Optional[HogQLFunctionMeta]: + return _find_function(name, HOGQL_CLICKHOUSE_FUNCTIONS) + + +def find_hogql_posthog_function(name: str) -> Optional[HogQLFunctionMeta]: + return _find_function(name, HOGQL_POSTHOG_FUNCTIONS) diff --git a/posthog/hogql/modifiers.py b/posthog/hogql/modifiers.py index 8452016dc1411..3c6fa11a9fc3b 100644 --- a/posthog/hogql/modifiers.py +++ b/posthog/hogql/modifiers.py @@ -1,12 +1,7 @@ from typing import Optional, TYPE_CHECKING -from posthog.schema import ( - HogQLQueryModifiers, - InCohortVia, - MaterializationMode, - PersonsArgMaxVersion, - PersonsOnEventsMode, -) +from posthog.schema import HogQLQueryModifiers, InCohortVia, MaterializationMode, PersonsArgMaxVersion +from posthog.utils import PersonOnEventsMode if TYPE_CHECKING: from posthog.models import Team @@ -21,10 +16,7 @@ def create_default_modifiers_for_team( modifiers = modifiers.model_copy() if modifiers.personsOnEventsMode is None: - if team.person_on_events_v3_querying_enabled: - modifiers.personsOnEventsMode = PersonsOnEventsMode.v3_enabled - else: - modifiers.personsOnEventsMode = team.person_on_events_mode + modifiers.personsOnEventsMode = team.person_on_events_mode or PersonOnEventsMode.DISABLED if modifiers.personsArgMaxVersion is None: modifiers.personsArgMaxVersion = PersonsArgMaxVersion.auto diff --git a/posthog/hogql/printer.py b/posthog/hogql/printer.py index c66a6a323fc6e..3b6ad33dd876d 100644 --- a/posthog/hogql/printer.py +++ b/posthog/hogql/printer.py @@ -14,9 +14,9 @@ from posthog.hogql.functions import ( ADD_OR_NULL_DATETIME_FUNCTIONS, FIRST_ARG_DATETIME_FUNCTIONS, - HOGQL_AGGREGATIONS, - HOGQL_POSTHOG_FUNCTIONS, - find_clickhouse_function, + find_hogql_aggregation, + find_hogql_posthog_function, + find_hogql_function, ) from posthog.hogql.context import HogQLContext from posthog.hogql.database.models import Table, FunctionCallTable, SavedQuery @@ -725,7 +725,7 @@ def visit_call(self, node: ast.Call): op=op, ) ) - elif func_meta := HOGQL_AGGREGATIONS.get(node.name): + elif func_meta := find_hogql_aggregation(node.name): validate_function_args( node.args, func_meta.min_args, @@ -747,7 +747,7 @@ def visit_call(self, node: ast.Call): # check that we're not running inside another aggregate for stack_node in self.stack: - if stack_node != node and isinstance(stack_node, ast.Call) and stack_node.name in HOGQL_AGGREGATIONS: + if stack_node != node and isinstance(stack_node, ast.Call) and find_hogql_aggregation(stack_node.name): raise QueryError( f"Aggregation '{node.name}' cannot be nested inside another aggregation '{stack_node.name}'." ) @@ -759,7 +759,7 @@ def visit_call(self, node: ast.Call): args_part = f"({f'DISTINCT ' if node.distinct else ''}{', '.join(args)})" return f"{func_meta.clickhouse_name}{params_part}{args_part}" - elif func_meta := find_clickhouse_function(node.name): + elif func_meta := find_hogql_function(node.name): validate_function_args(node.args, func_meta.min_args, func_meta.max_args, node.name) if func_meta.min_params: if node.params is None: @@ -857,7 +857,7 @@ def visit_call(self, node: ast.Call): return f"{relevant_clickhouse_name}{params_part}{args_part}" else: return f"{node.name}({', '.join([self.visit(arg) for arg in node.args])})" - elif func_meta := HOGQL_POSTHOG_FUNCTIONS.get(node.name): + elif func_meta := find_hogql_posthog_function(node.name): validate_function_args(node.args, func_meta.min_args, func_meta.max_args, node.name) args = [self.visit(arg) for arg in node.args] diff --git a/posthog/hogql/property.py b/posthog/hogql/property.py index 718e8e5ae9e25..6b70de5759b54 100644 --- a/posthog/hogql/property.py +++ b/posthog/hogql/property.py @@ -12,7 +12,7 @@ ) from posthog.hogql import ast from posthog.hogql.base import AST -from posthog.hogql.functions import HOGQL_AGGREGATIONS +from posthog.hogql.functions import find_hogql_aggregation from posthog.hogql.errors import NotImplementedError from posthog.hogql.parser import parse_expr from posthog.hogql.visitor import TraversingVisitor, clone_expr @@ -59,7 +59,7 @@ def visit_select_query(self, node: ast.SelectQuery): pass def visit_call(self, node: ast.Call): - if node.name in HOGQL_AGGREGATIONS: + if find_hogql_aggregation(node.name): self.has_aggregation = True else: for arg in node.args: diff --git a/posthog/hogql/query.py b/posthog/hogql/query.py index f2e7a0bbcef37..65c0c9d71356f 100644 --- a/posthog/hogql/query.py +++ b/posthog/hogql/query.py @@ -1,3 +1,4 @@ +import dataclasses from typing import Dict, Optional, Union, cast from posthog.clickhouse.client.connection import Workload @@ -39,10 +40,14 @@ def execute_hogql_query( timings: Optional[HogQLTimings] = None, explain: Optional[bool] = False, pretty: Optional[bool] = True, + context: Optional[HogQLContext] = None, ) -> HogQLQueryResponse: if timings is None: timings = HogQLTimings() + if context is None: + context = HogQLContext(team_id=team.pk) + query_modifiers = create_default_modifiers_for_team(team, modifiers) with timings.measure("query"): @@ -82,13 +87,16 @@ def execute_hogql_query( # Get printed HogQL query, and returned columns. Using a cloned query. with timings.measure("hogql"): with timings.measure("prepare_ast"): - hogql_query_context = HogQLContext( + hogql_query_context = dataclasses.replace( + context, + # set the team.pk here so someone can't pass a context for a different team 🤷‍️ team_id=team.pk, team=team, enable_select_queries=True, timings=timings, modifiers=query_modifiers, ) + with timings.measure("clone"): cloned_query = clone_expr(select_query, True) select_query_hogql = cast( @@ -125,13 +133,16 @@ def execute_hogql_query( # Print the ClickHouse SQL query with timings.measure("print_ast"): - clickhouse_context = HogQLContext( + clickhouse_context = dataclasses.replace( + context, + # set the team.pk here so someone can't pass a context for a different team 🤷‍️ team_id=team.pk, team=team, enable_select_queries=True, timings=timings, modifiers=query_modifiers, ) + clickhouse_sql = print_ast( select_query, context=clickhouse_context, diff --git a/posthog/hogql/resolver.py b/posthog/hogql/resolver.py index 03dd821027c69..2c578c85e4913 100644 --- a/posthog/hogql/resolver.py +++ b/posthog/hogql/resolver.py @@ -4,7 +4,7 @@ from posthog.hogql import ast from posthog.hogql.ast import FieldTraverserType, ConstantType -from posthog.hogql.functions import HOGQL_POSTHOG_FUNCTIONS +from posthog.hogql.functions import find_hogql_posthog_function from posthog.hogql.context import HogQLContext from posthog.hogql.database.models import ( StringJSONDatabaseField, @@ -384,7 +384,7 @@ def visit_alias(self, node: ast.Alias): def visit_call(self, node: ast.Call): """Visit function calls.""" - if func_meta := HOGQL_POSTHOG_FUNCTIONS.get(node.name): + if func_meta := find_hogql_posthog_function(node.name): validate_function_args(node.args, func_meta.min_args, func_meta.max_args, node.name) if node.name == "sparkline": return self.visit(sparkline(node=node, args=node.args)) diff --git a/posthog/hogql/test/test_mapping.py b/posthog/hogql/test/test_mapping.py index fe20497f69578..b13b2d1c744b2 100644 --- a/posthog/hogql/test/test_mapping.py +++ b/posthog/hogql/test/test_mapping.py @@ -1,21 +1,44 @@ from posthog.test.base import BaseTest -from posthog.hogql.functions.mapping import find_clickhouse_function, HogQLFunctionMeta +from typing import Optional +from posthog.hogql.functions.mapping import ( + find_hogql_function, + find_hogql_aggregation, + find_hogql_posthog_function, + HogQLFunctionMeta, +) class TestMappings(BaseTest): - def _get_clickhouse_function(self, name: str) -> HogQLFunctionMeta: - result = find_clickhouse_function(name) - assert result is not None - return result + def _return_present_function(self, function: Optional[HogQLFunctionMeta]) -> HogQLFunctionMeta: + assert function is not None + return function + + def _get_hogql_function(self, name: str) -> HogQLFunctionMeta: + return self._return_present_function(find_hogql_function(name)) + + def _get_hogql_aggregation(self, name: str) -> HogQLFunctionMeta: + return self._return_present_function(find_hogql_aggregation(name)) + + def _get_hogql_posthog_function(self, name: str) -> HogQLFunctionMeta: + return self._return_present_function(find_hogql_posthog_function(name)) def test_find_case_sensitive_function(self): - self.assertEquals(self._get_clickhouse_function("toString").clickhouse_name, "toString") - self.assertEquals(find_clickhouse_function("TOString"), None) - self.assertEquals(find_clickhouse_function("PlUs"), None) + self.assertEquals(self._get_hogql_function("toString").clickhouse_name, "toString") + self.assertEquals(find_hogql_function("TOString"), None) + self.assertEquals(find_hogql_function("PlUs"), None) + + self.assertEquals(self._get_hogql_aggregation("countIf").clickhouse_name, "countIf") + self.assertEquals(find_hogql_aggregation("COUNTIF"), None) + + self.assertEquals(self._get_hogql_posthog_function("sparkline").clickhouse_name, "sparkline") + self.assertEquals(find_hogql_posthog_function("SPARKLINE"), None) def test_find_case_insensitive_function(self): - self.assertEquals(self._get_clickhouse_function("coalesce").clickhouse_name, "coalesce") - self.assertEquals(self._get_clickhouse_function("CoAlesce").clickhouse_name, "coalesce") + self.assertEquals(self._get_hogql_function("CoAlesce").clickhouse_name, "coalesce") + + self.assertEquals(self._get_hogql_aggregation("SuM").clickhouse_name, "sum") def test_find_non_existent_function(self): - self.assertEquals(find_clickhouse_function("functionThatDoesntExist"), None) + self.assertEquals(find_hogql_function("functionThatDoesntExist"), None) + self.assertEquals(find_hogql_aggregation("functionThatDoesntExist"), None) + self.assertEquals(find_hogql_posthog_function("functionThatDoesntExist"), None) diff --git a/posthog/hogql/test/test_modifiers.py b/posthog/hogql/test/test_modifiers.py index a33d57575e2f4..9dc22d96bfa07 100644 --- a/posthog/hogql/test/test_modifiers.py +++ b/posthog/hogql/test/test_modifiers.py @@ -1,3 +1,4 @@ +from typing import NamedTuple from posthog.hogql.modifiers import create_default_modifiers_for_team from posthog.hogql.query import execute_hogql_query from posthog.models import Cohort @@ -7,30 +8,23 @@ class TestModifiers(BaseTest): - @override_settings( - PERSON_ON_EVENTS_OVERRIDE=False, - PERSON_ON_EVENTS_V2_OVERRIDE=False, - PERSON_ON_EVENTS_V3_OVERRIDE=False, - ) + @override_settings(PERSON_ON_EVENTS_OVERRIDE=False, PERSON_ON_EVENTS_V2_OVERRIDE=False) def test_create_default_modifiers_for_team_init(self): assert self.team.person_on_events_mode == "disabled" modifiers = create_default_modifiers_for_team(self.team) assert modifiers.personsOnEventsMode == PersonsOnEventsMode.disabled # NB! not a None modifiers = create_default_modifiers_for_team( self.team, - HogQLQueryModifiers(personsOnEventsMode=PersonsOnEventsMode.v1_enabled), + HogQLQueryModifiers(personsOnEventsMode=PersonsOnEventsMode.person_id_no_override_properties_on_events), ) - assert modifiers.personsOnEventsMode == PersonsOnEventsMode.v1_enabled + assert modifiers.personsOnEventsMode == PersonsOnEventsMode.person_id_no_override_properties_on_events modifiers = create_default_modifiers_for_team( self.team, - HogQLQueryModifiers(personsOnEventsMode=PersonsOnEventsMode.v2_enabled), + HogQLQueryModifiers(personsOnEventsMode=PersonsOnEventsMode.person_id_override_properties_on_events), ) - assert modifiers.personsOnEventsMode == PersonsOnEventsMode.v2_enabled + assert modifiers.personsOnEventsMode == PersonsOnEventsMode.person_id_override_properties_on_events - with override_settings(PERSON_ON_EVENTS_V3_OVERRIDE=True): - assert create_default_modifiers_for_team(self.team).personsOnEventsMode == PersonsOnEventsMode.v3_enabled - - def test_modifiers_persons_on_events_mode_v1_enabled(self): + def test_modifiers_persons_on_events_mode_person_id_override_properties_on_events(self): query = "SELECT event, person_id FROM events" # Control @@ -45,59 +39,79 @@ def test_modifiers_persons_on_events_mode_v1_enabled(self): response = execute_hogql_query( query, team=self.team, - modifiers=HogQLQueryModifiers(personsOnEventsMode=PersonsOnEventsMode.v1_enabled), + modifiers=HogQLQueryModifiers( + personsOnEventsMode=PersonsOnEventsMode.person_id_no_override_properties_on_events + ), ) assert " JOIN " not in response.clickhouse def test_modifiers_persons_on_events_mode_mapping(self): query = "SELECT event, person.id, person.properties, person.created_at FROM events" - test_cases = [ - ( + class TestCase(NamedTuple): + mode: PersonsOnEventsMode + expected_columns: list[str] + other_expected_values: list[str] = [] + + test_cases: list[TestCase] = [ + TestCase( PersonsOnEventsMode.disabled, - "events.event AS event", - "events__pdi__person.id AS id", - "events__pdi__person.properties AS properties", - "toTimeZone(events__pdi__person.created_at, %(hogql_val_0)s) AS created_at", - ), - ( - PersonsOnEventsMode.v1_enabled, - "events.event AS event", - "events.person_id AS id", - "events.person_properties AS properties", - "toTimeZone(events.person_created_at, %(hogql_val_0)s) AS created_at", + [ + "events.event AS event", + "events__pdi__person.id AS id", + "events__pdi__person.properties AS properties", + "toTimeZone(events__pdi__person.created_at, %(hogql_val_0)s) AS created_at", + ], ), - ( - PersonsOnEventsMode.v1_mixed, - "events.event AS event", - "events__pdi.person_id AS id", - "events.person_properties AS properties", - "toTimeZone(events__pdi__person.created_at, %(hogql_val_0)s) AS created_at", + TestCase( + PersonsOnEventsMode.person_id_no_override_properties_on_events, + [ + "events.event AS event", + "events.person_id AS id", + "events.person_properties AS properties", + "toTimeZone(events.person_created_at, %(hogql_val_0)s) AS created_at", + ], ), - ( - PersonsOnEventsMode.v2_enabled, - "events.event AS event", - "ifNull(nullIf(events__override.override_person_id, %(hogql_val_0)s), events.person_id) AS id", - "events.person_properties AS properties", - "toTimeZone(events.person_created_at, %(hogql_val_1)s) AS created_at", + TestCase( + PersonsOnEventsMode.person_id_override_properties_on_events, + [ + "events.event AS event", + "ifNull(nullIf(events__override.override_person_id, %(hogql_val_0)s), events.person_id) AS id", + "events.person_properties AS properties", + "toTimeZone(events.person_created_at, %(hogql_val_1)s) AS created_at", + ], + [ + "events__override ON equals(events.person_id, events__override.old_person_id)", + ], ), - ( - PersonsOnEventsMode.v3_enabled, - "events.event AS event", - "if(not(empty(events__override.distinct_id)), events__override.person_id, events.person_id) AS id", - "events.person_properties AS properties", - "toTimeZone(events.person_created_at, %(hogql_val_0)s) AS created_at", + TestCase( + PersonsOnEventsMode.person_id_override_properties_joined, + [ + "events.event AS event", + "events__person.id AS id", + "events__person.properties AS properties", + "toTimeZone(events__person.created_at, %(hogql_val_1)s) AS created_at", + ], + [ + "events__person ON equals(ifNull(nullIf(events__override.override_person_id, %(hogql_val_0)s), events.person_id), events__person.id)", + "events__override ON equals(events.person_id, events__override.old_person_id)", + ], ), ] - for mode, *expected in test_cases: - response = execute_hogql_query( + for test_case in test_cases: + clickhouse_query = execute_hogql_query( query, team=self.team, - modifiers=HogQLQueryModifiers(personsOnEventsMode=mode), + modifiers=HogQLQueryModifiers(personsOnEventsMode=test_case.mode), pretty=False, - ) - assert f"SELECT {', '.join(expected)} FROM" in response.clickhouse, f"PoE mode: {mode}" + ).clickhouse + assert clickhouse_query is not None + assert ( + f"SELECT {', '.join(test_case.expected_columns)} FROM" in clickhouse_query + ), f"PoE mode: {test_case.mode}" + for value in test_case.other_expected_values: + assert value in clickhouse_query def test_modifiers_persons_argmax_version_v2(self): query = "SELECT * FROM persons" diff --git a/posthog/hogql/test/test_printer.py b/posthog/hogql/test/test_printer.py index ab0c839a0b848..a4d5337071b3d 100644 --- a/posthog/hogql/test/test_printer.py +++ b/posthog/hogql/test/test_printer.py @@ -156,7 +156,9 @@ def test_fields_and_properties(self): context = HogQLContext( team_id=self.team.pk, within_non_hogql_query=True, - modifiers=HogQLQueryModifiers(personsOnEventsMode=PersonOnEventsMode.V1_ENABLED), + modifiers=HogQLQueryModifiers( + personsOnEventsMode=PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS + ), ) self.assertEqual( self._expr("person.properties.bla", context), @@ -1588,3 +1590,7 @@ def test_case_insensitive_functions(self): self._expr("CoALESce(1)", context), "coalesce(1)", ) + self.assertEqual( + self._expr("SuM(1)", context), + "sum(1)", + ) diff --git a/posthog/hogql/transforms/lazy_tables.py b/posthog/hogql/transforms/lazy_tables.py index e93a2fcfe47b4..bd3a3550034cd 100644 --- a/posthog/hogql/transforms/lazy_tables.py +++ b/posthog/hogql/transforms/lazy_tables.py @@ -55,6 +55,10 @@ def visit_field(self, node: ast.Field): class LazyFinder(TraversingVisitor): found_lazy: bool = False + max_type_visits: int = 3 + + def __init__(self) -> None: + self.visited_field_type_counts: Dict[int, int] = {} def visit_lazy_join_type(self, node: ast.LazyJoinType): self.found_lazy = True @@ -62,6 +66,13 @@ def visit_lazy_join_type(self, node: ast.LazyJoinType): def visit_lazy_table_type(self, node: ast.TableType): self.found_lazy = True + def visit_field_type(self, node: ast.FieldType): + node_ref = id(node) + visited_count = self.visited_field_type_counts.get(node_ref, 0) + if visited_count < self.max_type_visits: + self.visited_field_type_counts[node_ref] = visited_count + 1 + self.visit(node.table_type) + class LazyTableResolver(TraversingVisitor): lazy_finder_counter = 0 @@ -375,6 +386,13 @@ def create_override(table_name: str, field_chain: List[str | int]) -> None: else: node.select_from = join_to_add + # Collect any fields or properties that may have been added from the join_function with the LazyJoinType + join_field_collector: List[ast.FieldType | ast.PropertyType] = [] + self.stack_of_fields.append(join_field_collector) + super().visit(join_to_add) + self.stack_of_fields.pop() + field_collector.extend(join_field_collector) + # Assign all types on the fields we collected earlier for field_or_property in field_collector: if isinstance(field_or_property, ast.FieldType): @@ -385,7 +403,11 @@ def create_override(table_name: str, field_chain: List[str | int]) -> None: raise ResolutionError("Should not be reachable") table_name = get_long_table_name(select_type, table_type) - table_type = select_type.tables[table_name] + try: + table_type = select_type.tables[table_name] + except KeyError: + # If the table is not found, then it's likely that it'll need to be resolved on a second pass of lazy_tables + continue if isinstance(field_or_property, ast.FieldType): field_or_property.table_type = table_type diff --git a/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr b/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr index 0f20b0df0bd44..ca2923fa1eb85 100644 --- a/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr +++ b/posthog/hogql/transforms/test/__snapshots__/test_lazy_tables.ambr @@ -92,6 +92,44 @@ LIMIT 10 ''' # --- +# name: TestLazyJoins.test_resolve_lazy_table_indirect_duplicate_references + ''' + + SELECT ifNull(nullIf(events__override.override_person_id, %(hogql_val_1)s), events.person_id) AS person_id, events__person.properties AS properties + FROM events INNER JOIN ( + SELECT argMax(person.properties, person.version) AS properties, person.id AS id + FROM person + WHERE equals(person.team_id, 420) + GROUP BY person.id + HAVING ifNull(equals(argMax(person.is_deleted, person.version), 0), 0) + SETTINGS optimize_aggregation_in_order=1) AS events__person ON equals(ifNull(nullIf(events__override.override_person_id, %(hogql_val_0)s), events.person_id), events__person.id) LEFT OUTER JOIN ( + SELECT argMax(person_overrides.override_person_id, person_overrides.version) AS override_person_id, person_overrides.old_person_id AS old_person_id + FROM person_overrides + WHERE equals(person_overrides.team_id, 420) + GROUP BY person_overrides.old_person_id) AS events__override ON equals(events.person_id, events__override.old_person_id) + WHERE equals(events.team_id, 420) + LIMIT 10000 + ''' +# --- +# name: TestLazyJoins.test_resolve_lazy_table_indirectly_referenced + ''' + + SELECT events__person.id AS id + FROM events LEFT OUTER JOIN ( + SELECT argMax(person_overrides.override_person_id, person_overrides.version) AS override_person_id, person_overrides.old_person_id AS old_person_id + FROM person_overrides + WHERE equals(person_overrides.team_id, 420) + GROUP BY person_overrides.old_person_id) AS events__override ON equals(events.person_id, events__override.old_person_id) INNER JOIN ( + SELECT person.id AS id + FROM person + WHERE equals(person.team_id, 420) + GROUP BY person.id + HAVING ifNull(equals(argMax(person.is_deleted, person.version), 0), 0) + SETTINGS optimize_aggregation_in_order=1) AS events__person ON equals(ifNull(nullIf(events__override.override_person_id, %(hogql_val_0)s), events.person_id), events__person.id) + WHERE equals(events.team_id, 420) + LIMIT 10000 + ''' +# --- # name: TestLazyJoins.test_resolve_lazy_tables ''' diff --git a/posthog/hogql/transforms/test/test_lazy_tables.py b/posthog/hogql/transforms/test/test_lazy_tables.py index 8e93e16df1470..3ea762b786983 100644 --- a/posthog/hogql/transforms/test/test_lazy_tables.py +++ b/posthog/hogql/transforms/test/test_lazy_tables.py @@ -7,6 +7,7 @@ from posthog.hogql.parser import parse_select from posthog.hogql.printer import print_ast from posthog.hogql.test.utils import pretty_print_in_tests +from posthog.schema import HogQLQueryModifiers, PersonsOnEventsMode from posthog.test.base import BaseTest from posthog.warehouse.models.join import DataWarehouseJoin @@ -79,11 +80,15 @@ def test_select_count_from_lazy_table(self): printed = self._print_select("select count() from persons") assert printed == self.snapshot - def _print_select(self, select: str): + def _print_select(self, select: str, modifiers: HogQLQueryModifiers | None = None): expr = parse_select(select) query = print_ast( expr, - HogQLContext(team_id=self.team.pk, enable_select_queries=True), + HogQLContext( + team_id=self.team.pk, + enable_select_queries=True, + modifiers=modifiers if modifiers is not None else HogQLQueryModifiers(), + ), "clickhouse", ) return pretty_print_in_tests(query, self.team.pk) @@ -129,3 +134,24 @@ def test_lazy_join_on_lazy_table_with_person_properties(self): printed = self._print_select("select events.event from persons") assert printed == self.snapshot + + @pytest.mark.usefixtures("unittest_snapshot") + def test_resolve_lazy_table_indirectly_referenced(self): + # Ensures that the override table is added as a join, even when it is + # only indirectly referenced in the query as part of the join constraint + # of a lazy join. + printed = self._print_select( + "select person.id from events", + HogQLQueryModifiers(personsOnEventsMode=PersonsOnEventsMode.person_id_override_properties_joined), + ) + assert printed == self.snapshot + + @pytest.mark.usefixtures("unittest_snapshot") + def test_resolve_lazy_table_indirect_duplicate_references(self): + # Ensures that the override table is only joined one time, even when it + # is referenced via two different selected columns. + printed = self._print_select( + "select person_id, person.properties from events", + HogQLQueryModifiers(personsOnEventsMode=PersonsOnEventsMode.person_id_override_properties_joined), + ) + assert printed == self.snapshot diff --git a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel.ambr b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel.ambr index cdedde60af058..60adaa8480c7c 100644 --- a/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel.ambr +++ b/posthog/hogql_queries/insights/funnels/test/__snapshots__/test_funnel.ambr @@ -357,9 +357,7 @@ if(and(equals(e.event, 'user signed up'), ifNull(in(e__pdi.person_id, (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0)), 1, 0) AS step_0, + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0)), 1, 0) AS step_0, if(ifNull(equals(step_0, 1), 0), timestamp, NULL) AS latest_0, if(equals(e.event, 'paid'), 1, 0) AS step_1, if(ifNull(equals(step_1, 1), 0), timestamp, NULL) AS latest_1 diff --git a/posthog/hogql_queries/insights/test/__snapshots__/test_lifecycle_query_runner.ambr b/posthog/hogql_queries/insights/test/__snapshots__/test_lifecycle_query_runner.ambr index cc062aa3bb227..52d5bd0fa78a0 100644 --- a/posthog/hogql_queries/insights/test/__snapshots__/test_lifecycle_query_runner.ambr +++ b/posthog/hogql_queries/insights/test/__snapshots__/test_lifecycle_query_runner.ambr @@ -80,9 +80,7 @@ WHERE and(equals(events.team_id, 2), greaterOrEquals(toTimeZone(events.timestamp, 'UTC'), minus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-12 00:00:00', 6, 'UTC'))), toIntervalDay(1))), less(toTimeZone(events.timestamp, 'UTC'), plus(toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-19 23:59:59', 6, 'UTC'))), toIntervalDay(1))), ifNull(in(person_id, (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0), equals(events.event, '$pageview')) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0), equals(events.event, '$pageview')) GROUP BY person_id) GROUP BY start_of_period, status) diff --git a/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr b/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr index fbee3bfdbd06b..8df3bf49e48db 100644 --- a/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr +++ b/posthog/hogql_queries/insights/trends/test/__snapshots__/test_trends.ambr @@ -86,9 +86,7 @@ WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-01 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-07 23:59:59', 6, 'UTC'))), ifNull(equals(e__pdi__person.`properties___$bool_prop`, 'x'), 0), and(equals(e.event, 'sign up'), ifNull(in(e__pdi.person_id, (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0))) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 2)))), 0))) GROUP BY day_start) GROUP BY day_start ORDER BY day_start ASC) @@ -173,9 +171,7 @@ WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-01 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-07 23:59:59', 6, 'UTC'))), ifNull(equals(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(e.person_properties, '$bool_prop'), ''), 'null'), '^"|"$', ''), 'x'), 0), and(equals(e.event, 'sign up'), ifNull(in(ifNull(nullIf(e__override.override_person_id, '00000000-0000-0000-0000-000000000000'), e.person_id), (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0))) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 2)))), 0))) GROUP BY day_start) GROUP BY day_start ORDER BY day_start ASC) @@ -626,9 +622,7 @@ WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-01 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-12 23:59:59', 6, 'UTC')))), and(equals(e.event, '$pageview'), and(or(ifNull(equals(e__pdi__person.properties___name, 'p1'), 0), ifNull(equals(e__pdi__person.properties___name, 'p2'), 0), ifNull(equals(e__pdi__person.properties___name, 'p3'), 0)), ifNull(in(e__pdi.person_id, (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0)))) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0)))) GROUP BY value ORDER BY count DESC, value DESC LIMIT 26 SETTINGS readonly=2, @@ -695,9 +689,7 @@ WHERE and(equals(e.team_id, 2), and(and(equals(e.event, '$pageview'), and(or(ifNull(equals(e__pdi__person.properties___name, 'p1'), 0), ifNull(equals(e__pdi__person.properties___name, 'p2'), 0), ifNull(equals(e__pdi__person.properties___name, 'p3'), 0)), ifNull(in(e__pdi.person_id, (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0))), true), ifNull(greaterOrEquals(timestamp, minus(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-01 00:00:00', 6, 'UTC')), toIntervalDay(7))), 0), ifNull(lessOrEquals(timestamp, assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-12 23:59:59', 6, 'UTC'))), 0)) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0))), true), ifNull(greaterOrEquals(timestamp, minus(assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-01 00:00:00', 6, 'UTC')), toIntervalDay(7))), 0), ifNull(lessOrEquals(timestamp, assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-12 23:59:59', 6, 'UTC'))), 0)) GROUP BY timestamp, actor_id, breakdown_value) AS e WHERE and(ifNull(lessOrEquals(e.timestamp, plus(d.timestamp, toIntervalDay(1))), 0), ifNull(greater(e.timestamp, minus(d.timestamp, toIntervalDay(6))), 0)) @@ -1514,9 +1506,7 @@ WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC')))), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), and(equals(e.event, 'sign up'), ifNull(in(e__pdi.person_id, (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0)))) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0)))) GROUP BY value ORDER BY count DESC, value DESC LIMIT 26 SETTINGS readonly=2, @@ -1561,9 +1551,7 @@ WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), and(equals(e.event, 'sign up'), ifNull(in(e__pdi.person_id, (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0)), true) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0)), true) GROUP BY day_start, breakdown_value) GROUP BY day_start, @@ -1611,9 +1599,7 @@ WHERE and(equals(e.team_id, 2), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC')))), and(greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), and(equals(e.event, 'sign up'), ifNull(in(ifNull(nullIf(e__override.override_person_id, '00000000-0000-0000-0000-000000000000'), e.person_id), (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0)))) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0)))) GROUP BY value ORDER BY count DESC, value DESC LIMIT 26 SETTINGS readonly=2, @@ -1657,9 +1643,7 @@ WHERE and(equals(e.team_id, 2), greaterOrEquals(toTimeZone(e.timestamp, 'UTC'), toStartOfDay(assumeNotNull(parseDateTime64BestEffortOrNull('2019-12-28 00:00:00', 6, 'UTC')))), lessOrEquals(toTimeZone(e.timestamp, 'UTC'), assumeNotNull(parseDateTime64BestEffortOrNull('2020-01-04 23:59:59', 6, 'UTC'))), and(equals(e.event, 'sign up'), ifNull(in(ifNull(nullIf(e__override.override_person_id, '00000000-0000-0000-0000-000000000000'), e.person_id), (SELECT cohortpeople.person_id AS person_id FROM cohortpeople - WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2)) - GROUP BY cohortpeople.person_id, cohortpeople.cohort_id, cohortpeople.version - HAVING ifNull(greater(sum(cohortpeople.sign), 0), 0))), 0)), true) + WHERE and(equals(cohortpeople.team_id, 2), equals(cohortpeople.cohort_id, 2), equals(cohortpeople.version, 0)))), 0)), true) GROUP BY day_start, breakdown_value) GROUP BY day_start, diff --git a/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py b/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py index 653e8987658c3..89ba0dd47a72a 100644 --- a/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py +++ b/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py @@ -32,7 +32,6 @@ PropertyMathType, TrendsFilter, TrendsQuery, - AggregationAxisFormat, ) from posthog.schema import Series as InsightActorsQuerySeries @@ -218,7 +217,7 @@ def _run_trends_query( limit_context=limit_context, ).calculate() - def test_trends_query_label(self): + def test_trends_label(self): self._create_test_events() response = self._run_trends_query( @@ -232,7 +231,7 @@ def test_trends_query_label(self): self.assertEqual("$pageview", response.results[0]["label"]) - def test_trends_query_count(self): + def test_trends_count(self): self._create_test_events() response = self._run_trends_query( @@ -246,7 +245,7 @@ def test_trends_query_count(self): self.assertEqual(10, response.results[0]["count"]) - def test_trends_query_data(self): + def test_trends_data(self): self._create_test_events() response = self._run_trends_query( @@ -260,7 +259,7 @@ def test_trends_query_data(self): self.assertEqual([1, 0, 1, 3, 1, 0, 2, 0, 1, 0, 1], response.results[0]["data"]) - def test_trends_query_days(self): + def test_trends_days(self): self._create_test_events() response = self._run_trends_query( @@ -289,7 +288,7 @@ def test_trends_query_days(self): response.results[0]["days"], ) - def test_trends_query_labels(self): + def test_trends_labels(self): self._create_test_events() response = self._run_trends_query( @@ -318,7 +317,7 @@ def test_trends_query_labels(self): response.results[0]["labels"], ) - def test_trends_query_labels_hour(self): + def test_trends_labels_hour(self): self._create_test_events() response = self._run_trends_query( @@ -336,7 +335,7 @@ def test_trends_query_labels_hour(self): response.results[0]["labels"], ) - def test_trends_query_multiple_series(self): + def test_trends_multiple_series(self): self._create_test_events() response = self._run_trends_query( @@ -357,7 +356,7 @@ def test_trends_query_multiple_series(self): self.assertEqual([1, 0, 1, 3, 1, 0, 2, 0, 1, 0, 1], response.results[0]["data"]) self.assertEqual([0, 0, 1, 1, 3, 0, 0, 1, 0, 0, 0], response.results[1]["data"]) - def test_trends_query_formula(self): + def test_formula(self): self._create_test_events() response = self._run_trends_query( @@ -365,69 +364,300 @@ def test_trends_query_formula(self): self.default_date_to, IntervalType.day, [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], - TrendsFilter(formula="A+B"), + TrendsFilter(formula="A+2*B"), ) self.assertEqual(1, len(response.results)) - self.assertEqual(16, response.results[0]["count"]) - self.assertEqual("Formula (A+B)", response.results[0]["label"]) - self.assertEqual([1, 0, 2, 4, 4, 0, 2, 1, 1, 0, 1], response.results[0]["data"]) + self.assertEqual(22, response.results[0]["count"]) + self.assertEqual("Formula (A+2*B)", response.results[0]["label"]) + self.assertEqual([1, 0, 3, 5, 7, 0, 2, 2, 1, 0, 1], response.results[0]["data"]) - def test_trends_query_formula_breakdown_no_data(self): + def test_formula_total_value(self): self._create_test_events() response = self._run_trends_query( self.default_date_from, self.default_date_to, IntervalType.day, - [EventsNode(event="$pageviewxxx"), EventsNode(event="$pageleavexxx")], - TrendsFilter(formula="A+B"), - BreakdownFilter(breakdown_type=BreakdownType.person, breakdown="$browser"), + [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], + TrendsFilter( + formula="A+2*B", + display=ChartDisplayType.BoldNumber, # total value + ), ) - self.assertEqual([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], response.results[0]["data"]) + self.assertEqual(1, len(response.results)) + self.assertEqual(22, response.results[0]["aggregated_value"]) + self.assertEqual(0, response.results[0]["count"]) # it has always been so :shrug: + self.assertEqual("Formula (A+2*B)", response.results[0]["label"]) + self.assertEqual(None, response.results[0].get("data")) - def test_trends_query_formula_aggregate(self): + def test_formula_with_compare(self): self._create_test_events() response = self._run_trends_query( - self.default_date_from, - self.default_date_to, + "2020-01-15", + "2020-01-19", + IntervalType.day, + [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], + TrendsFilter(formula="A+2*B", compare=True), + ) + + # one for current, one for previous + self.assertEqual(2, len(response.results)) + + # current + self.assertEqual("current", response.results[0]["compare_label"]) + self.assertEqual(6, response.results[0]["count"]) + self.assertEqual([2, 2, 1, 0, 1], response.results[0]["data"]) + + # previous + self.assertEqual("previous", response.results[1]["compare_label"]) + self.assertEqual(15, response.results[1]["count"]) + self.assertEqual([0, 3, 5, 7, 0], response.results[1]["data"]) + + # response shape + self.assertEqual("Formula (A+2*B)", response.results[0]["label"]) + self.assertEqual(True, response.results[0]["compare"]) + + def test_formula_with_compare_total_value(self): + self._create_test_events() + + response = self._run_trends_query( + "2020-01-15", + "2020-01-19", IntervalType.day, [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], TrendsFilter( - formula="A+B", - display=ChartDisplayType.BoldNumber, - aggregationAxisFormat=AggregationAxisFormat.percentage_scaled, + formula="A+2*B", + display=ChartDisplayType.BoldNumber, # total value + compare=True, ), ) - self.assertEqual(1, len(response.results)) - self.assertEqual(16, response.results[0]["aggregated_value"]) + + # one for current, one for previous + self.assertEqual(2, len(response.results)) + + # current + self.assertEqual("current", response.results[0]["compare_label"]) + self.assertEqual(6, response.results[0]["aggregated_value"]) + + # previous + self.assertEqual("previous", response.results[1]["compare_label"]) + self.assertEqual(15, response.results[1]["aggregated_value"]) + + # response shape + self.assertEqual("Formula (A+2*B)", response.results[0]["label"]) self.assertEqual(0, response.results[0]["count"]) # it has always been so :shrug: - self.assertEqual("Formula (A+B)", response.results[0]["label"]) self.assertEqual(None, response.results[0].get("data")) - def test_trends_query_formula_aggregate_compare(self): + def test_formula_with_breakdown(self): self._create_test_events() response = self._run_trends_query( - self.default_date_from, - self.default_date_to, + "2020-01-09", + "2020-01-20", + IntervalType.day, + [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], + TrendsFilter(formula="A+2*B"), + BreakdownFilter(breakdown_type=BreakdownType.event, breakdown="$browser"), + ) + + # one for each breakdown value + assert len(response.results) == 4 + + # chrome + assert response.results[0]["breakdown_value"] == "Chrome" + assert response.results[0]["count"] == 12 + assert response.results[0]["data"] == [0, 0, 3, 3, 3, 0, 1, 0, 1, 0, 1, 0] + + # firefox + assert response.results[1]["breakdown_value"] == "Firefox" + assert response.results[1]["count"] == 4 + + # response shape + assert response.results[0]["label"] == "Formula (A+2*B)" + assert response.results[0]["action"] is None # action needs to be unset to display custom label + + def test_formula_with_breakdown_and_compare(self): + self._create_test_events() + + response = self._run_trends_query( + "2020-01-15", + "2020-01-19", + IntervalType.day, + [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], + TrendsFilter(formula="A+2*B", compare=True), + BreakdownFilter(breakdown_type=BreakdownType.event, breakdown="$browser"), + ) + + # chrome, ff and edge for previous, and chrome and safari for current + assert len(response.results) == 5 + + assert response.results[0]["compare_label"] == "current" + assert response.results[0]["breakdown_value"] == "Chrome" + assert response.results[0]["label"] == "Formula (A+2*B)" + assert response.results[0]["count"] == 3 + assert response.results[0]["data"] == [1, 0, 1, 0, 1] + + assert response.results[1]["compare_label"] == "current" + assert response.results[1]["breakdown_value"] == "Safari" + assert response.results[0]["count"] == 3 + + assert response.results[2]["compare_label"] == "previous" + assert response.results[2]["label"] == "Formula (A+2*B)" + assert response.results[2]["breakdown_value"] == "Chrome" + assert response.results[2]["count"] == 9 + + def test_formula_with_breakdown_and_compare_total_value(self): + self._create_test_events() + + response = self._run_trends_query( + "2020-01-15", + "2020-01-19", IntervalType.day, [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], TrendsFilter( - formula="A+B", - display=ChartDisplayType.BoldNumber, - aggregationAxisFormat=AggregationAxisFormat.percentage_scaled, + formula="A+2*B", + display=ChartDisplayType.BoldNumber, # total value compare=True, ), + BreakdownFilter(breakdown_type=BreakdownType.event, breakdown="$browser"), ) - self.assertEqual(2, len(response.results)) - self.assertEqual(16, response.results[0]["aggregated_value"]) - self.assertEqual(0, response.results[0]["count"]) # it has always been so :shrug: - self.assertEqual("Formula (A+B)", response.results[0]["label"]) - self.assertEqual(None, response.results[0].get("data")) - def test_trends_query_compare(self): + # chrome, ff and edge for previous, and chrome and safari for current + assert len(response.results) == 5 + + assert response.results[0]["compare_label"] == "current" + assert response.results[0]["breakdown_value"] == "Chrome" + assert response.results[0]["label"] == "Formula (A+2*B)" + assert response.results[0]["aggregated_value"] == 3 + assert response.results[0]["count"] == 0 + assert response.results[0].get("data") is None + + assert response.results[1]["compare_label"] == "current" + assert response.results[1]["breakdown_value"] == "Safari" + assert response.results[0]["aggregated_value"] == 3 + + assert response.results[2]["compare_label"] == "previous" + assert response.results[2]["label"] == "Formula (A+2*B)" + assert response.results[2]["breakdown_value"] == "Chrome" + assert response.results[2]["aggregated_value"] == 9 + + def test_formula_with_multi_cohort_breakdown(self): + self._create_test_events() + cohort1 = Cohort.objects.create( + team=self.team, + groups=[ + { + "properties": [ + { + "key": "name", + "value": "p1", + "type": "person", + } + ] + } + ], + name="cohort p1", + ) + cohort1.calculate_people_ch(pending_version=0) + cohort2 = Cohort.objects.create( + team=self.team, + groups=[ + { + "properties": [ + { + "key": "name", + "value": "p2", + "type": "person", + } + ] + } + ], + name="cohort p2", + ) + cohort2.calculate_people_ch(pending_version=0) + + response = self._run_trends_query( + "2020-01-09", + "2020-01-20", + IntervalType.day, + [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], + TrendsFilter(formula="A+B"), + BreakdownFilter(breakdown_type=BreakdownType.cohort, breakdown=[cohort1.pk, cohort2.pk]), + ) + + assert len(response.results) == 2 + + assert response.results[0]["label"] == "Formula (A+B)" + assert response.results[0]["breakdown_value"] == cohort1.pk + assert response.results[0]["count"] == 9 + assert response.results[0]["data"] == [0, 0, 2, 2, 2, 0, 1, 0, 1, 0, 1, 0] + + assert response.results[1]["label"] == "Formula (A+B)" + assert response.results[1]["breakdown_value"] == cohort2.pk + assert response.results[1]["count"] == 3 + + # action needs to be unset to display custom label + assert response.results[0]["action"] is None + + def test_formula_with_multi_cohort_all_breakdown(self): + self._create_test_events() + cohort1 = Cohort.objects.create( + team=self.team, + groups=[ + { + "properties": [ + { + "key": "name", + "value": "p1", + "type": "person", + } + ] + } + ], + name="cohort p1", + ) + cohort1.calculate_people_ch(pending_version=0) + + response = self._run_trends_query( + "2020-01-09", + "2020-01-20", + IntervalType.day, + [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], + TrendsFilter(formula="A+B"), + BreakdownFilter(breakdown_type=BreakdownType.cohort, breakdown=[cohort1.pk, "all"]), + ) + + print(response) # noqa: T201 + assert len(response.results) == 2 + + assert response.results[0]["label"] == "Formula (A+B)" + assert response.results[0]["breakdown_value"] == "all" + assert response.results[0]["count"] == 16 + + assert response.results[1]["label"] == "Formula (A+B)" + assert response.results[1]["breakdown_value"] == cohort1.pk + assert response.results[1]["count"] == 9 + assert response.results[1]["data"] == [0, 0, 2, 2, 2, 0, 1, 0, 1, 0, 1, 0] + + # action needs to be unset to display custom label + assert response.results[0]["action"] is None + + def test_formula_with_breakdown_and_no_data(self): + self._create_test_events() + + response = self._run_trends_query( + self.default_date_from, + self.default_date_to, + IntervalType.day, + [EventsNode(event="$pageviewxxx"), EventsNode(event="$pageleavexxx")], + TrendsFilter(formula="A+2*B"), + BreakdownFilter(breakdown_type=BreakdownType.person, breakdown="$browser"), + ) + self.assertEqual([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], response.results[0]["data"]) + + def test_trends_compare(self): self._create_test_events() response = self._run_trends_query( @@ -470,7 +700,7 @@ def test_trends_query_compare(self): self.assertEqual(["day 0", "day 1", "day 2", "day 3", "day 4"], response.results[0]["labels"]) self.assertEqual(["day 0", "day 1", "day 2", "day 3", "day 4"], response.results[1]["labels"]) - def test_trends_query_compare_weeks(self): + def test_trends_compare_weeks(self): self._create_test_events() with freeze_time("2020-01-24"): @@ -524,31 +754,6 @@ def test_trends_query_compare_weeks(self): ["day 0", "day 1", "day 2", "day 3", "day 4", "day 5", "day 6", "day 7"], response.results[1]["labels"] ) - def test_trends_query_formula_with_compare(self): - self._create_test_events() - - response = self._run_trends_query( - "2020-01-15", - "2020-01-19", - IntervalType.day, - [EventsNode(event="$pageview"), EventsNode(event="$pageleave")], - TrendsFilter(formula="A+B", compare=True), - ) - - self.assertEqual(2, len(response.results)) - - self.assertEqual(5, response.results[0]["count"]) - self.assertEqual(10, response.results[1]["count"]) - - self.assertEqual(True, response.results[0]["compare"]) - self.assertEqual(True, response.results[1]["compare"]) - - self.assertEqual("current", response.results[0]["compare_label"]) - self.assertEqual("previous", response.results[1]["compare_label"]) - - self.assertEqual("Formula (A+B)", response.results[0]["label"]) - self.assertEqual("Formula (A+B)", response.results[1]["label"]) - def test_trends_breakdowns(self): self._create_test_events() @@ -1200,7 +1405,7 @@ def test_previous_period_with_number_display(self): assert len(response.results) == 2 - def test_trends_query_formula_rounding(self): + def test_formula_rounding(self): _create_event( team=self.team, event="$pageleave", diff --git a/posthog/hogql_queries/insights/trends/trends_query_runner.py b/posthog/hogql_queries/insights/trends/trends_query_runner.py index 1a43231a88234..eebe5202f2d7c 100644 --- a/posthog/hogql_queries/insights/trends/trends_query_runner.py +++ b/posthog/hogql_queries/insights/trends/trends_query_runner.py @@ -1,3 +1,5 @@ +import copy +from natsort import natsorted, ns from typing import Union from copy import deepcopy from datetime import timedelta @@ -62,7 +64,7 @@ DataWarehouseEventsModifier, ) from posthog.warehouse.models import DataWarehouseTable -from posthog.utils import format_label_date +from posthog.utils import format_label_date, multisort class TrendsQueryRunner(QueryRunner): @@ -384,14 +386,18 @@ def get_value(name: str, val: Any): if series.aggregate_values: series_object = { "data": [], - "days": [ - item.strftime( - "%Y-%m-%d{}".format(" %H:%M:%S" if self.query_date_range.interval_name == "hour" else "") - ) - for item in get_value("date", val) - ] - if response.columns and "date" in response.columns - else [], + "days": ( + [ + item.strftime( + "%Y-%m-%d{}".format( + " %H:%M:%S" if self.query_date_range.interval_name == "hour" else "" + ) + ) + for item in get_value("date", val) + ] + if response.columns and "date" in response.columns + else [] + ), "count": 0, "aggregated_value": get_value("total", val), "label": "All events" if series_label is None else series_label, @@ -630,54 +636,79 @@ def setup_series(self) -> List[SeriesWithExtras]: return series_with_extras def apply_formula(self, formula: str, results: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - if self.query.trendsFilter is not None and self.query.trendsFilter.compare: - sorted_results = sorted(results, key=itemgetter("compare_label")) - res = [] - for _, group in groupby(sorted_results, key=itemgetter("compare_label")): - group_list = list(group) - - if self._trends_display.should_aggregate_values(): - series_data = [[s["aggregated_value"]] for s in group_list] - new_series_data = FormulaAST(series_data).call(formula) - - new_result = group_list[0] - new_result["aggregated_value"] = float(sum(new_series_data)) - new_result["data"] = None - new_result["count"] = 0 - new_result["label"] = f"Formula ({formula})" - res.append(new_result) - else: - series_data = [s["data"] for s in group_list] - new_series_data = FormulaAST(series_data).call(formula) - - new_result = group_list[0] - new_result["data"] = new_series_data - new_result["count"] = float(sum(new_series_data)) - new_result["label"] = f"Formula ({formula})" - res.append(new_result) - return res - - if len(results) > 0: - if self._trends_display.should_aggregate_values(): - series_data = [[s["aggregated_value"]] for s in results] - new_series_data = FormulaAST(series_data).call(formula) - - new_result = results[0] - new_result["aggregated_value"] = float(sum(new_series_data)) - new_result["data"] = None - new_result["count"] = 0 - new_result["label"] = f"Formula ({formula})" - else: - series_data = [s["data"] for s in results] - new_series_data = FormulaAST(series_data).call(formula) + has_compare = bool(self.query.trendsFilter and self.query.trendsFilter.compare) + has_breakdown = bool(self.query.breakdownFilter and self.query.breakdownFilter.breakdown) + is_total_value = self._trends_display.should_aggregate_values() + + if len(results) == 0: + return [] - new_result = results[0] - new_result["data"] = new_series_data - new_result["count"] = float(sum(new_series_data)) - new_result["label"] = f"Formula ({formula})" + # we need to apply the formula to a group of results when we have a breakdown or the compare option is enabled + if has_compare or has_breakdown: + keys = [*(["compare_label"] if has_compare else []), *(["breakdown_value"] if has_breakdown else [])] + try: + sorted_results = natsorted( + results, key=lambda x: tuple(str(itemgetter(k)(x)) for k in keys), alg=ns.IGNORECASE + ) + except Exception: + sorted_results = results + + computed_results = [] + for _key, group in groupby(sorted_results, key=itemgetter(*keys)): + results_group = list(group) + # compare queries are executed separately and some breakdown values might be missing in a group + # we need to fill them up so that series are correctly attributed to formula letters + if has_compare: + for idx in range(0, len(self.query.series)): + if any(result["action"]["order"] == idx for result in results_group): + continue + + # add the missing result + base_result = copy.deepcopy(results_group[0]) + base_result["label"] = f"filler for {idx} - {base_result['breakdown_value']}" + if is_total_value: + base_result["aggregated_value"] = 0 + else: + base_result["data"] = [0] * len(base_result["data"]) + base_result["count"] = 0 + base_result["action"]["order"] = idx + results_group.append(base_result) + + results_group = sorted(results_group, key=lambda x: x["action"]["order"]) + + computed_results.append(self.apply_formula_to_results_group(results_group, formula, is_total_value)) + + if has_compare: + return multisort(computed_results, (("compare_label", False), ("count", True))) + + return sorted(computed_results, key=itemgetter("count"), reverse=True) + else: + return [self.apply_formula_to_results_group(results, formula, aggregate_values=is_total_value)] + + @staticmethod + def apply_formula_to_results_group( + results_group: List[Dict[str, Any]], formula: str, aggregate_values: Optional[bool] = False + ) -> Dict[str, Any]: + """ + Applies the formula to a list of results, resulting in a single, computed result. + """ + base_result = results_group[0] + base_result["label"] = f"Formula ({formula})" + base_result["action"] = None + + if aggregate_values: + series_data = [[s["aggregated_value"]] for s in results_group] + new_series_data = FormulaAST(series_data).call(formula) + base_result["aggregated_value"] = float(sum(new_series_data)) + base_result["data"] = None + base_result["count"] = 0 + else: + series_data = [s["data"] for s in results_group] + new_series_data = FormulaAST(series_data).call(formula) + base_result["data"] = new_series_data + base_result["count"] = float(sum(new_series_data)) - return [new_result] - return [] + return base_result def _is_breakdown_field_boolean(self): if not self.query.breakdownFilter or not self.query.breakdownFilter.breakdown_type: diff --git a/posthog/hogql_queries/legacy_compatibility/clean_properties.py b/posthog/hogql_queries/legacy_compatibility/clean_properties.py index 27e400d8c99e3..a6e8e8663bb44 100644 --- a/posthog/hogql_queries/legacy_compatibility/clean_properties.py +++ b/posthog/hogql_queries/legacy_compatibility/clean_properties.py @@ -60,7 +60,8 @@ def clean_property_group_filter(properties: dict): def clean_property_group_filter_values(properties: list[dict]): - return [clean_property_group_filter_value(property) for property in properties] + cleaned = [clean_property_group_filter_value(property) for property in properties if property] + return cleaned def clean_property_group_filter_value(property: dict): diff --git a/posthog/hogql_queries/legacy_compatibility/test/test_filter_to_query.py b/posthog/hogql_queries/legacy_compatibility/test/test_filter_to_query.py index 39a06c3e13807..589cee60a19b2 100644 --- a/posthog/hogql_queries/legacy_compatibility/test/test_filter_to_query.py +++ b/posthog/hogql_queries/legacy_compatibility/test/test_filter_to_query.py @@ -1230,7 +1230,7 @@ def test_series_properties(self): EventsNode( event="$pageview", name="$pageview", - properties=[SessionPropertyFilter(value=1, operator=PropertyOperator.gt)], + properties=[SessionPropertyFilter(key="$session_duration", value=1, operator=PropertyOperator.gt)], ), EventsNode( event="$pageview", diff --git a/posthog/models/dashboard_tile.py b/posthog/models/dashboard_tile.py index 7cc6b2601cb62..50af2868abf5b 100644 --- a/posthog/models/dashboard_tile.py +++ b/posthog/models/dashboard_tile.py @@ -109,6 +109,9 @@ def save(self, *args, **kwargs) -> None: if has_no_filters_hash and self.insight.filters != {}: self.filters_hash = generate_insight_cache_key(self.insight, self.dashboard) + if "update_fields" in kwargs: + kwargs["update_fields"].append("filters_hash") + super(DashboardTile, self).save(*args, **kwargs) def copy_to_dashboard(self, dashboard: Dashboard) -> None: diff --git a/posthog/models/event/util.py b/posthog/models/event/util.py index a5cb4be15c9e5..1d8357b855b71 100644 --- a/posthog/models/event/util.py +++ b/posthog/models/event/util.py @@ -1,9 +1,9 @@ import datetime as dt import json import uuid -from typing import Any, Dict, List, Optional, Set, Union - +from typing import Any, Dict, List, Literal, Optional, Set, Union from zoneinfo import ZoneInfo + from dateutil.parser import isoparse from django.utils import timezone from rest_framework import serializers @@ -46,6 +46,7 @@ def create_event( group2_created_at: Optional[Union[timezone.datetime, str]] = None, group3_created_at: Optional[Union[timezone.datetime, str]] = None, group4_created_at: Optional[Union[timezone.datetime, str]] = None, + person_mode: Literal["full", "propertyless"] = "full", ) -> str: if not timestamp: timestamp = timezone.now() @@ -79,7 +80,7 @@ def create_event( "group2_created_at": format_clickhouse_timestamp(group2_created_at, ZERO_DATE), "group3_created_at": format_clickhouse_timestamp(group3_created_at, ZERO_DATE), "group4_created_at": format_clickhouse_timestamp(group4_created_at, ZERO_DATE), - "person_mode": "full", + "person_mode": person_mode, } p = ClickhouseProducer() p.produce(topic=KAFKA_EVENTS_JSON, sql=INSERT_EVENT_SQL(), data=data) @@ -101,7 +102,10 @@ def format_clickhouse_timestamp( return parsed_datetime.strftime("%Y-%m-%d %H:%M:%S.%f") -def bulk_create_events(events: List[Dict[str, Any]], person_mapping: Optional[Dict[str, Person]] = None) -> None: +def bulk_create_events( + events: List[Dict[str, Any]], + person_mapping: Optional[Dict[str, Person]] = None, +) -> None: """ TEST ONLY Insert events in bulk. List of dicts: @@ -163,6 +167,7 @@ def bulk_create_events(events: List[Dict[str, Any]], person_mapping: Optional[Di #  use person properties mapping to populate person properties in given event team_id = event["team"].pk + person_mode = event.get("person_mode", "full") if person_mapping and person_mapping.get(event["distinct_id"]): person = person_mapping[event["distinct_id"]] person_properties = person.properties @@ -228,30 +233,30 @@ def bulk_create_events(events: List[Dict[str, Any]], person_mapping: Optional[Di "created_at": timestamp, "person_id": event["person_id"] if event.get("person_id") else str(uuid.uuid4()), "person_properties": json.dumps(event["person_properties"]) if event.get("person_properties") else "{}", - "person_created_at": event["person_created_at"] - if event.get("person_created_at") - else datetime64_default_timestamp, + "person_created_at": ( + event["person_created_at"] if event.get("person_created_at") else datetime64_default_timestamp + ), "group0_properties": json.dumps(event["group0_properties"]) if event.get("group0_properties") else "{}", "group1_properties": json.dumps(event["group1_properties"]) if event.get("group1_properties") else "{}", "group2_properties": json.dumps(event["group2_properties"]) if event.get("group2_properties") else "{}", "group3_properties": json.dumps(event["group3_properties"]) if event.get("group3_properties") else "{}", "group4_properties": json.dumps(event["group4_properties"]) if event.get("group4_properties") else "{}", - "group0_created_at": event["group0_created_at"] - if event.get("group0_created_at") - else datetime64_default_timestamp, - "group1_created_at": event["group1_created_at"] - if event.get("group1_created_at") - else datetime64_default_timestamp, - "group2_created_at": event["group2_created_at"] - if event.get("group2_created_at") - else datetime64_default_timestamp, - "group3_created_at": event["group3_created_at"] - if event.get("group3_created_at") - else datetime64_default_timestamp, - "group4_created_at": event["group4_created_at"] - if event.get("group4_created_at") - else datetime64_default_timestamp, - "person_mode": "full", + "group0_created_at": ( + event["group0_created_at"] if event.get("group0_created_at") else datetime64_default_timestamp + ), + "group1_created_at": ( + event["group1_created_at"] if event.get("group1_created_at") else datetime64_default_timestamp + ), + "group2_created_at": ( + event["group2_created_at"] if event.get("group2_created_at") else datetime64_default_timestamp + ), + "group3_created_at": ( + event["group3_created_at"] if event.get("group3_created_at") else datetime64_default_timestamp + ), + "group4_created_at": ( + event["group4_created_at"] if event.get("group4_created_at") else datetime64_default_timestamp + ), + "person_mode": person_mode, } params = { diff --git a/posthog/models/feature_flag/flag_matching.py b/posthog/models/feature_flag/flag_matching.py index 6efb943d3f6fb..50f0a5d848149 100644 --- a/posthog/models/feature_flag/flag_matching.py +++ b/posthog/models/feature_flag/flag_matching.py @@ -790,7 +790,8 @@ def get_all_feature_flags( distinct_ids = [distinct_id, str(hash_key_override)] query = """ WITH target_person_ids AS ( - SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = %(team_id)s AND distinct_id IN %(distinct_ids)s + SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = %(team_id)s AND + distinct_id = ANY(%(distinct_ids)s) ), existing_overrides AS ( SELECT team_id, person_id, feature_flag_key, hash_key FROM posthog_featureflaghashkeyoverride @@ -801,7 +802,7 @@ def get_all_feature_flags( """ cursor.execute( query, - {"team_id": team_id, "distinct_ids": tuple(distinct_ids)}, # type: ignore + {"team_id": team_id, "distinct_ids": distinct_ids}, # type: ignore ) flags_with_no_overrides = [row[0] for row in cursor.fetchall()] should_write_hash_key_override = len(flags_with_no_overrides) > 0 @@ -902,7 +903,8 @@ def set_feature_flag_hash_key_overrides(team_id: int, distinct_ids: List[str], h with execute_with_timeout(FLAG_MATCHING_QUERY_TIMEOUT_MS) as cursor: query = """ WITH target_person_ids AS ( - SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = %(team_id)s AND distinct_id IN %(distinct_ids)s + SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = %(team_id)s AND + distinct_id = ANY(%(distinct_ids)s) ), existing_overrides AS ( SELECT team_id, person_id, feature_flag_key, hash_key FROM posthog_featureflaghashkeyoverride @@ -931,7 +933,7 @@ def set_feature_flag_hash_key_overrides(team_id: int, distinct_ids: List[str], h query, { "team_id": team_id, - "distinct_ids": tuple(distinct_ids), # type: ignore + "distinct_ids": distinct_ids, # type: ignore "hash_key_override": hash_key_override, }, ) diff --git a/posthog/models/filters/test/__snapshots__/test_filter.ambr b/posthog/models/filters/test/__snapshots__/test_filter.ambr index 1bd4315507dde..6fd1a58ba6a05 100644 --- a/posthog/models/filters/test/__snapshots__/test_filter.ambr +++ b/posthog/models/filters/test/__snapshots__/test_filter.ambr @@ -314,7 +314,7 @@ FROM "posthog_person" WHERE (UPPER(("posthog_person"."properties" ->> 'urls')::text) LIKE UPPER('%["abcd"]%') AND "posthog_person"."properties" ? 'urls' - AND NOT (("posthog_person"."properties" -> 'urls') = 'null') + AND NOT (("posthog_person"."properties" -> 'urls') = 'null'::jsonb) AND "posthog_person"."team_id" = 2) ''' # --- @@ -333,7 +333,7 @@ FROM "posthog_person" WHERE (UPPER(("posthog_person"."properties" ->> '$key')::text) LIKE UPPER('%[''red'']%') AND "posthog_person"."properties" ? '$key' - AND NOT (("posthog_person"."properties" -> '$key') = 'null') + AND NOT (("posthog_person"."properties" -> '$key') = 'null'::jsonb) AND "posthog_person"."team_id" = 2) ''' # --- @@ -343,7 +343,7 @@ FROM "posthog_person" WHERE (UPPER(("posthog_person"."properties" ->> '$key')::text) LIKE UPPER('%red%') AND "posthog_person"."properties" ? '$key' - AND NOT (("posthog_person"."properties" -> '$key') = 'null') + AND NOT (("posthog_person"."properties" -> '$key') = 'null'::jsonb) AND "posthog_person"."team_id" = 2) ''' # --- @@ -351,9 +351,9 @@ ''' SELECT "posthog_person"."uuid" FROM "posthog_person" - WHERE (("posthog_person"."properties" -> '$key') > '["2"]' + WHERE (("posthog_person"."properties" -> '$key') > '["2"]'::jsonb AND "posthog_person"."properties" ? '$key' - AND NOT (("posthog_person"."properties" -> '$key') = 'null') + AND NOT (("posthog_person"."properties" -> '$key') = 'null'::jsonb) AND "posthog_person"."team_id" = 2) ''' # --- @@ -364,7 +364,7 @@ INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = 'example_id' AND "posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'created_at') > '["2m", "3d"]') + AND ("posthog_person"."properties" -> 'created_at') > '["2m", "3d"]'::jsonb) LIMIT 1 ''' # --- @@ -375,7 +375,7 @@ INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = 'example_id' AND "posthog_person"."team_id" = 2 - AND ("posthog_person"."properties" -> 'created_at') > '"bazinga"') + AND ("posthog_person"."properties" -> 'created_at') > '"bazinga"'::jsonb) LIMIT 1 ''' # --- @@ -419,21 +419,21 @@ "posthog_person"."uuid", "posthog_person"."version" FROM "posthog_person" - WHERE (((("posthog_person"."properties" -> 'url') = '"https://whatever.com"' + WHERE (((("posthog_person"."properties" -> 'url') = '"https://whatever.com"'::jsonb AND "posthog_person"."properties" ? 'url' - AND NOT (("posthog_person"."properties" -> 'url') = 'null') - AND ("posthog_person"."properties" -> 'bla') = '1' + AND NOT (("posthog_person"."properties" -> 'url') = 'null'::jsonb) + AND ("posthog_person"."properties" -> 'bla') = '1'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null') - AND ((("posthog_person"."properties" -> 'bla') = '1' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb) + AND ((("posthog_person"."properties" -> 'bla') = '1'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null')) - OR (("posthog_person"."properties" -> 'bla') = '2' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'bla') = '2'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null')))) - OR (("posthog_person"."properties" -> 'bla') = '3' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb)))) + OR (("posthog_person"."properties" -> 'bla') = '3'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null'))) + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb))) AND "posthog_person"."team_id" = 2) ''' # --- @@ -495,21 +495,21 @@ "posthog_person"."uuid", "posthog_person"."version" FROM "posthog_person" - WHERE (((("posthog_person"."properties" -> 'url') = '"https://whatever.com"' + WHERE (((("posthog_person"."properties" -> 'url') = '"https://whatever.com"'::jsonb AND "posthog_person"."properties" ? 'url' - AND NOT (("posthog_person"."properties" -> 'url') = 'null') - AND ("posthog_person"."properties" -> 'bla') = '1' + AND NOT (("posthog_person"."properties" -> 'url') = 'null'::jsonb) + AND ("posthog_person"."properties" -> 'bla') = '1'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null') - AND ("posthog_person"."properties" -> 'bla') = '1' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb) + AND ("posthog_person"."properties" -> 'bla') = '1'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null') - AND ("posthog_person"."properties" -> 'bla') = '2' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb) + AND ("posthog_person"."properties" -> 'bla') = '2'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null')) - OR (("posthog_person"."properties" -> 'bla') = '3' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'bla') = '3'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null'))) + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb))) AND "posthog_person"."team_id" = 2) ''' # --- @@ -643,21 +643,21 @@ "posthog_person"."uuid", "posthog_person"."version" FROM "posthog_person" - WHERE (NOT (((("posthog_person"."properties" -> 'bla') = '1' - AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null')) - OR (("posthog_person"."properties" -> 'bla') = '2' + WHERE (NOT ((("posthog_person"."properties" -> 'bla') = '1'::jsonb + AND "posthog_person"."properties" ? 'bla' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'bla') = '2'::jsonb + AND "posthog_person"."properties" ? 'bla' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb))) + AND NOT ((("posthog_person"."properties" -> 'bla') = '3'::jsonb AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null')))) - AND NOT (((("posthog_person"."properties" -> 'bla') = '3' - AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null')) - OR (("posthog_person"."properties" -> 'bla') = '4' - AND "posthog_person"."properties" ? 'bla' - AND NOT (("posthog_person"."properties" -> 'bla') = 'null')))) - AND ("posthog_person"."properties" -> 'other') = '1' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb)) + OR (("posthog_person"."properties" -> 'bla') = '4'::jsonb + AND "posthog_person"."properties" ? 'bla' + AND NOT (("posthog_person"."properties" -> 'bla') = 'null'::jsonb))) + AND ("posthog_person"."properties" -> 'other') = '1'::jsonb AND "posthog_person"."properties" ? 'other' - AND NOT (("posthog_person"."properties" -> 'other') = 'null') + AND NOT (("posthog_person"."properties" -> 'other') = 'null'::jsonb) AND "posthog_person"."team_id" = 2) ''' # --- diff --git a/posthog/models/property/property.py b/posthog/models/property/property.py index cf5402f5afbdb..defd098cd7ef7 100644 --- a/posthog/models/property/property.py +++ b/posthog/models/property/property.py @@ -103,20 +103,28 @@ class BehavioralPropertyType(str, Enum): "hogql": ["key"], } +VALIDATE_CONDITIONAL_BEHAVIORAL_PROP_TYPES = { + BehavioralPropertyType.PERFORMED_EVENT: [ + {"time_value", "time_interval"}, + {"explicit_datetime"}, + ], + BehavioralPropertyType.PERFORMED_EVENT_MULTIPLE: [ + {"time_value", "time_interval"}, + {"explicit_datetime"}, + ], +} + + VALIDATE_BEHAVIORAL_PROP_TYPES = { BehavioralPropertyType.PERFORMED_EVENT: [ "key", "value", "event_type", - "time_value", - "time_interval", ], BehavioralPropertyType.PERFORMED_EVENT_MULTIPLE: [ "key", "value", "event_type", - "time_value", - "time_interval", "operator_value", ], BehavioralPropertyType.PERFORMED_EVENT_FIRST_TIME: [ @@ -175,8 +183,11 @@ class Property: type: PropertyType group_type_index: Optional[GroupTypeIndex] + # All these property keys are used in cohorts. # Type of `key` event_type: Optional[Literal["events", "actions"]] + # Any extra filters on the event + event_filters: Optional[List["Property"]] # Query people who did event '$pageview' 20 times in the last 30 days # translates into: # key = '$pageview', value = 'performed_event_multiple' @@ -185,6 +196,8 @@ class Property: operator_value: Optional[int] time_value: Optional[int] time_interval: Optional[OperatorInterval] + # Alternative to time_value & time_interval, for explicit date bound rather than relative + explicit_datetime: Optional[str] # Query people who did event '$pageview' in last week, but not in the previous 30 days # translates into: # key = '$pageview', value = 'restarted_performing_event' @@ -218,6 +231,7 @@ def __init__( operator_value: Optional[int] = None, time_value: Optional[int] = None, time_interval: Optional[OperatorInterval] = None, + explicit_datetime: Optional[str] = None, total_periods: Optional[int] = None, min_periods: Optional[int] = None, seq_event_type: Optional[str] = None, @@ -225,6 +239,7 @@ def __init__( seq_time_value: Optional[int] = None, seq_time_interval: Optional[OperatorInterval] = None, negation: Optional[bool] = None, + event_filters: Optional[List["Property"]] = None, **kwargs, ) -> None: self.key = key @@ -235,6 +250,7 @@ def __init__( self.operator_value = operator_value self.time_value = time_value self.time_interval = time_interval + self.explicit_datetime = explicit_datetime self.total_periods = total_periods self.min_periods = min_periods self.seq_event_type = seq_event_type @@ -242,6 +258,7 @@ def __init__( self.seq_time_value = seq_time_value self.seq_time_interval = seq_time_interval self.negation = None if negation is None else str_to_bool(negation) + self.event_filters = event_filters if value is None and self.operator in ["is_set", "is_not_set"]: self.value = self.operator @@ -264,6 +281,19 @@ def __init__( if getattr(self, attr, None) is None: raise ValueError(f"Missing required attr {attr} for property type {self.type}::{self.value}") + if cast(BehavioralPropertyType, self.value) in VALIDATE_CONDITIONAL_BEHAVIORAL_PROP_TYPES: + matches_attr_list = False + condition_list = VALIDATE_CONDITIONAL_BEHAVIORAL_PROP_TYPES[cast(BehavioralPropertyType, self.value)] + for attr_list in condition_list: + if all(getattr(self, attr, None) is not None for attr in attr_list): + matches_attr_list = True + break + + if not matches_attr_list: + raise ValueError( + f"Missing required parameters, atleast one of values ({'), ('.join([' & '.join(condition) for condition in condition_list])}) for property type {self.type}::{self.value}" + ) + def __repr__(self): params_repr = ", ".join(f"{key}={repr(value)}" for key, value in self.to_dict().items()) return f"Property({params_repr})" diff --git a/posthog/models/team/team.py b/posthog/models/team/team.py index fd317a9dbb617..c199c6bcc1d56 100644 --- a/posthog/models/team/team.py +++ b/posthog/models/team/team.py @@ -57,7 +57,7 @@ # keep in sync with posthog/frontend/src/scenes/project/Settings/ExtraTeamSettings.tsx class AvailableExtraSettings: - poe_v2_enabled = "poe_v2_enabled" + pass class TeamManager(models.Manager): @@ -290,18 +290,24 @@ def aggregate_users_by_distinct_id(self) -> bool: @property def person_on_events_mode(self) -> PersonOnEventsMode: - # Persons on Events V2 always takes priority over Persons on Events V1 - if self._person_on_events_v2_querying_enabled: - tag_queries(person_on_events_mode=PersonOnEventsMode.V2_ENABLED) - return PersonOnEventsMode.V2_ENABLED + if self._person_on_events_person_id_override_properties_on_events: + tag_queries(person_on_events_mode=PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS) + return PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS - if self._person_on_events_querying_enabled: + if self._person_on_events_person_id_no_override_properties_on_events: # also tag person_on_events_enabled for legacy compatibility tag_queries( person_on_events_enabled=True, - person_on_events_mode=PersonOnEventsMode.V1_ENABLED, + person_on_events_mode=PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS, ) - return PersonOnEventsMode.V1_ENABLED + return PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS + + if self._person_on_events_person_id_override_properties_joined: + tag_queries( + person_on_events_enabled=True, + person_on_events_mode=PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_JOINED, + ) + return PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_JOINED return PersonOnEventsMode.DISABLED @@ -312,25 +318,17 @@ def person_on_events_querying_enabled(self) -> bool: return self.person_on_events_mode != PersonOnEventsMode.DISABLED @property - def _person_on_events_querying_enabled(self) -> bool: + def _person_on_events_person_id_no_override_properties_on_events(self) -> bool: if settings.PERSON_ON_EVENTS_OVERRIDE is not None: return settings.PERSON_ON_EVENTS_OVERRIDE # on PostHog Cloud, use the feature flag if is_cloud(): - # users can override our feature flag via extra_settings - if self.extra_settings and AvailableExtraSettings.poe_v2_enabled in self.extra_settings: - return self.extra_settings["poe_v2_enabled"] return posthoganalytics.feature_enabled( - "person-on-events-enabled", + "persons-on-events-person-id-no-override-properties-on-events", str(self.uuid), - groups={"organization": str(self.organization_id)}, - group_properties={ - "organization": { - "id": str(self.organization_id), - "created_at": self.organization.created_at, - } - }, + groups={"project": str(self.id)}, + group_properties={"project": {"id": str(self.id), "created_at": self.created_at, "uuid": self.uuid}}, only_evaluate_locally=True, send_feature_flag_events=False, ) @@ -339,7 +337,7 @@ def _person_on_events_querying_enabled(self) -> bool: return get_instance_setting("PERSON_ON_EVENTS_ENABLED") @property - def _person_on_events_v2_querying_enabled(self) -> bool: + def _person_on_events_person_id_override_properties_on_events(self) -> bool: if settings.PERSON_ON_EVENTS_V2_OVERRIDE is not None: return settings.PERSON_ON_EVENTS_V2_OVERRIDE @@ -362,23 +360,24 @@ def _person_on_events_v2_querying_enabled(self) -> bool: return get_instance_setting("PERSON_ON_EVENTS_V2_ENABLED") @property - def person_on_events_v3_querying_enabled(self) -> bool: - if settings.PERSON_ON_EVENTS_V3_OVERRIDE is not None: - return settings.PERSON_ON_EVENTS_V3_OVERRIDE - - return posthoganalytics.feature_enabled( - "persons-on-events-v3-reads-enabled", - str(self.uuid), - groups={"organization": str(self.organization_id)}, - group_properties={ - "organization": { - "id": str(self.organization_id), - "created_at": self.organization.created_at, - } - }, - only_evaluate_locally=True, - send_feature_flag_events=False, - ) + def _person_on_events_person_id_override_properties_joined(self) -> bool: + # on PostHog Cloud, use the feature flag + if is_cloud(): + return posthoganalytics.feature_enabled( + "persons-on-events-person-id-override-properties-joined", + str(self.uuid), + groups={"organization": str(self.organization_id)}, + group_properties={ + "organization": { + "id": str(self.organization_id), + "created_at": self.organization.created_at, + } + }, + only_evaluate_locally=True, + send_feature_flag_events=False, + ) + + return False @property def strict_caching_enabled(self) -> bool: diff --git a/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr b/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr index bdc1861fb8605..10d960e13eb3a 100644 --- a/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr +++ b/posthog/queries/app_metrics/test/__snapshots__/test_historical_exports.ambr @@ -68,10 +68,8 @@ WHERE ("posthog_activitylog"."activity" IN ('job_triggered', 'export_success', 'export_fail') - AND ("posthog_activitylog"."detail" #> ARRAY['trigger', - 'job_id']) = '"1234"' - AND ("posthog_activitylog"."detail" #> ARRAY['trigger', - 'job_type']) = '"Export historical events V2"' + AND ("posthog_activitylog"."detail" #> '{trigger,job_id}') = '"1234"'::jsonb + AND ("posthog_activitylog"."detail" #> '{trigger,job_type}') = '"Export historical events V2"'::jsonb AND "posthog_activitylog"."item_id" = '3' AND "posthog_activitylog"."scope" = 'PluginConfig' AND "posthog_activitylog"."team_id" = 2) @@ -126,8 +124,7 @@ WHERE ("posthog_activitylog"."activity" IN ('job_triggered', 'export_success', 'export_fail') - AND ("posthog_activitylog"."detail" #> ARRAY['trigger', - 'job_type']) = '"Export historical events V2"' + AND ("posthog_activitylog"."detail" #> '{trigger,job_type}') = '"Export historical events V2"'::jsonb AND "posthog_activitylog"."item_id" = '3' AND "posthog_activitylog"."scope" = 'PluginConfig' AND "posthog_activitylog"."team_id" = 2) @@ -182,8 +179,7 @@ WHERE ("posthog_activitylog"."activity" IN ('job_triggered', 'export_success', 'export_fail') - AND ("posthog_activitylog"."detail" #> ARRAY['trigger', - 'job_type']) = '"Export historical events V2"' + AND ("posthog_activitylog"."detail" #> '{trigger,job_type}') = '"Export historical events V2"'::jsonb AND "posthog_activitylog"."item_id" = '3' AND "posthog_activitylog"."scope" = 'PluginConfig' AND "posthog_activitylog"."team_id" = 2) @@ -238,8 +234,7 @@ WHERE ("posthog_activitylog"."activity" IN ('job_triggered', 'export_success', 'export_fail') - AND ("posthog_activitylog"."detail" #> ARRAY['trigger', - 'job_type']) = '"Export historical events V2"' + AND ("posthog_activitylog"."detail" #> '{trigger,job_type}') = '"Export historical events V2"'::jsonb AND "posthog_activitylog"."item_id" = '3' AND "posthog_activitylog"."scope" = 'PluginConfig' AND "posthog_activitylog"."team_id" = 2) diff --git a/posthog/queries/event_query/event_query.py b/posthog/queries/event_query/event_query.py index 862e6d8f03495..aa292e7ee44e4 100644 --- a/posthog/queries/event_query/event_query.py +++ b/posthog/queries/event_query/event_query.py @@ -120,9 +120,9 @@ def _determine_should_join_distinct_ids(self) -> None: pass def _get_person_id_alias(self, person_on_events_mode) -> str: - if person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: return f"if(notEmpty({self.PERSON_ID_OVERRIDES_TABLE_ALIAS}.person_id), {self.PERSON_ID_OVERRIDES_TABLE_ALIAS}.person_id, {self.EVENT_TABLE_ALIAS}.person_id)" - elif person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + elif person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: return f"{self.EVENT_TABLE_ALIAS}.person_id" return f"{self.DISTINCT_ID_TABLE_ALIAS}.person_id" @@ -131,7 +131,7 @@ def _get_person_ids_query(self, *, relevant_events_conditions: str = "") -> str: if not self._should_join_distinct_ids: return "" - if self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: return PERSON_OVERRIDES_JOIN_SQL.format( person_overrides_table_alias=self.PERSON_ID_OVERRIDES_TABLE_ALIAS, event_table_alias=self.EVENT_TABLE_ALIAS, diff --git a/posthog/queries/foss_cohort_query.py b/posthog/queries/foss_cohort_query.py index e6005abab632a..34300757f58d8 100644 --- a/posthog/queries/foss_cohort_query.py +++ b/posthog/queries/foss_cohort_query.py @@ -18,10 +18,10 @@ PropertyGroup, PropertyName, ) -from posthog.models.property.util import prop_filter_json_extract +from posthog.models.property.util import prop_filter_json_extract, parse_prop_grouped_clauses from posthog.queries.event_query import EventQuery from posthog.queries.util import PersonPropertiesMode -from posthog.utils import PersonOnEventsMode +from posthog.utils import PersonOnEventsMode, relative_date_parse Relative_Date = Tuple[int, OperatorInterval] Event = Tuple[str, Union[str, int]] @@ -297,7 +297,7 @@ def _build_sources(self, subq: List[Tuple[str, str]]) -> Tuple[str, str]: fields = f"{subq_alias}.person_id" elif prev_alias: # can't join without a previous alias if subq_alias == self.PERSON_TABLE_ALIAS and self.should_pushdown_persons: - if self._person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: # when using person-on-events, instead of inner join, we filter inside # the event query itself continue @@ -458,24 +458,57 @@ def get_static_cohort_condition(self, prop: Property, prepend: str, idx: int) -> query, params = format_static_cohort_query(cohort, idx, prepend) return f"id {'NOT' if prop.negation else ''} IN ({query})", params + def _get_entity_event_filters(self, prop: Property, prepend: str, idx: int) -> Tuple[str, Dict[str, Any]]: + params: Dict[str, Any] = {} + + if prop.event_filters: + prop_query, prop_params = parse_prop_grouped_clauses( + team_id=self._team_id, + property_group=Filter(data={"properties": prop.event_filters}).property_groups, + prepend=f"{prepend}_{idx}_event_filters", + # should be no person properties in these filters, but if there are, use + # the inefficient person subquery default mode + person_properties_mode=PersonPropertiesMode.USING_SUBQUERY, + hogql_context=self._filter.hogql_context, + ) + params.update(prop_params) + return prop_query, params + else: + return "AND 1=1", {} + + def _get_entity_datetime_filters(self, prop: Property, prepend: str, idx: int) -> Tuple[str, Dict[str, Any]]: + if prop.explicit_datetime: + # Explicit datetime filter, can be a relative or absolute date, follows same convention + # as all analytics datetime filters + # TODO: Confirm if we need to validate the datetime + date_param = f"{prepend}_explicit_date_{idx}" + target_datetime = relative_date_parse(prop.explicit_datetime, self._team.timezone_info) + return f"timestamp > %({date_param})s", {f"{date_param}": target_datetime} + else: + date_value = parse_and_validate_positive_integer(prop.time_value, "time_value") + date_interval = validate_interval(prop.time_interval) + date_param = f"{prepend}_date_{idx}" + + self._check_earliest_date((date_value, date_interval)) + + return f"timestamp > now() - INTERVAL %({date_param})s {date_interval}", {f"{date_param}": date_value} + def get_performed_event_condition(self, prop: Property, prepend: str, idx: int) -> Tuple[str, Dict[str, Any]]: event = (prop.event_type, prop.key) column_name = f"performed_event_condition_{prepend}_{idx}" entity_query, entity_params = self._get_entity(event, prepend, idx) - date_value = parse_and_validate_positive_integer(prop.time_value, "time_value") - date_interval = validate_interval(prop.time_interval) - date_param = f"{prepend}_date_{idx}" - - self._check_earliest_date((date_value, date_interval)) + entity_filters, entity_filters_params = self._get_entity_event_filters(prop, prepend, idx) + date_filter, date_params = self._get_entity_datetime_filters(prop, prepend, idx) - field = f"countIf(timestamp > now() - INTERVAL %({date_param})s {date_interval} AND timestamp < now() AND {entity_query}) > 0 AS {column_name}" + field = f"countIf({date_filter} AND timestamp < now() AND {entity_query} {entity_filters}) > 0 AS {column_name}" self._fields.append(field) # Negation is handled in the where clause to ensure the right result if a full join occurs where the joined person did not perform the event return f"{'NOT' if prop.negation else ''} {column_name}", { - f"{date_param}": date_value, + **date_params, **entity_params, + **entity_filters_params, } def get_performed_event_multiple(self, prop: Property, prepend: str, idx: int) -> Tuple[str, Dict[str, Any]]: @@ -483,15 +516,13 @@ def get_performed_event_multiple(self, prop: Property, prepend: str, idx: int) - column_name = f"performed_event_multiple_condition_{prepend}_{idx}" entity_query, entity_params = self._get_entity(event, prepend, idx) + entity_filters, entity_filters_params = self._get_entity_event_filters(prop, prepend, idx) + date_filter, date_params = self._get_entity_datetime_filters(prop, prepend, idx) + count = parse_and_validate_positive_integer(prop.operator_value, "operator_value") - date_value = parse_and_validate_positive_integer(prop.time_value, "time_value") - date_interval = validate_interval(prop.time_interval) - date_param = f"{prepend}_date_{idx}" operator_value_param = f"{prepend}_operator_value_{idx}" - self._check_earliest_date((date_value, date_interval)) - - field = f"countIf(timestamp > now() - INTERVAL %({date_param})s {date_interval} AND timestamp < now() AND {entity_query}) {get_count_operator(prop.operator)} %({operator_value_param})s AS {column_name}" + field = f"countIf({date_filter} AND timestamp < now() AND {entity_query} {entity_filters}) {get_count_operator(prop.operator)} %({operator_value_param})s AS {column_name}" self._fields.append(field) # Negation is handled in the where clause to ensure the right result if a full join occurs where the joined person did not perform the event @@ -499,13 +530,16 @@ def get_performed_event_multiple(self, prop: Property, prepend: str, idx: int) - f"{'NOT' if prop.negation else ''} {column_name}", { f"{operator_value_param}": count, - f"{date_param}": date_value, + **date_params, **entity_params, + **entity_filters_params, }, ) def _determine_should_join_distinct_ids(self) -> None: - self._should_join_distinct_ids = self._person_on_events_mode != PersonOnEventsMode.V1_ENABLED + self._should_join_distinct_ids = ( + self._person_on_events_mode != PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS + ) def _determine_should_join_persons(self) -> None: # :TRICKY: This doesn't apply to joining inside events query, but to the diff --git a/posthog/queries/funnels/funnel_event_query.py b/posthog/queries/funnels/funnel_event_query.py index 01c2f6af00497..d2393f77b5d21 100644 --- a/posthog/queries/funnels/funnel_event_query.py +++ b/posthog/queries/funnels/funnel_event_query.py @@ -131,9 +131,9 @@ def _determine_should_join_distinct_ids(self) -> None: ) is_using_cohort_propertes = self._column_optimizer.is_using_cohort_propertes - if self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: self._should_join_distinct_ids = True - elif self._person_on_events_mode == PersonOnEventsMode.V1_ENABLED or ( + elif self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS or ( non_person_id_aggregation and not is_using_cohort_propertes ): self._should_join_distinct_ids = False diff --git a/posthog/queries/paths/paths_event_query.py b/posthog/queries/paths/paths_event_query.py index 134b61f5be66a..5c222558973a2 100644 --- a/posthog/queries/paths/paths_event_query.py +++ b/posthog/queries/paths/paths_event_query.py @@ -141,7 +141,7 @@ def get_query(self) -> Tuple[str, Dict[str, Any]]: return query, self.params def _determine_should_join_distinct_ids(self) -> None: - if self._person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: self._should_join_distinct_ids = False else: self._should_join_distinct_ids = True diff --git a/posthog/queries/retention/retention_events_query.py b/posthog/queries/retention/retention_events_query.py index 46ac34df48f61..871d9dbb3e033 100644 --- a/posthog/queries/retention/retention_events_query.py +++ b/posthog/queries/retention/retention_events_query.py @@ -197,7 +197,7 @@ def _determine_should_join_distinct_ids(self) -> None: self._filter.aggregation_group_type_index is not None or self._aggregate_users_by_distinct_id ) is_using_cohort_propertes = self._column_optimizer.is_using_cohort_propertes - if self._person_on_events_mode == PersonOnEventsMode.V1_ENABLED or ( + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS or ( non_person_id_aggregation and not is_using_cohort_propertes ): self._should_join_distinct_ids = False diff --git a/posthog/queries/stickiness/stickiness_event_query.py b/posthog/queries/stickiness/stickiness_event_query.py index 755f04a0bc335..ce76b2d17ce5c 100644 --- a/posthog/queries/stickiness/stickiness_event_query.py +++ b/posthog/queries/stickiness/stickiness_event_query.py @@ -82,7 +82,7 @@ def _person_query(self): ) def _determine_should_join_distinct_ids(self) -> None: - if self._person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: self._should_join_distinct_ids = False else: self._should_join_distinct_ids = True diff --git a/posthog/queries/trends/breakdown.py b/posthog/queries/trends/breakdown.py index 84b304ff99b28..de8665a549610 100644 --- a/posthog/queries/trends/breakdown.py +++ b/posthog/queries/trends/breakdown.py @@ -111,9 +111,9 @@ def __init__( self.column_optimizer = column_optimizer or ColumnOptimizer(self.filter, self.team_id) self.add_person_urls = add_person_urls self.person_on_events_mode = person_on_events_mode - if person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: self._person_id_alias = f"if(notEmpty({self.PERSON_ID_OVERRIDES_TABLE_ALIAS}.person_id), {self.PERSON_ID_OVERRIDES_TABLE_ALIAS}.person_id, {self.EVENT_TABLE_ALIAS}.person_id)" - elif person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + elif person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: self._person_id_alias = f"{self.EVENT_TABLE_ALIAS}.person_id" else: self._person_id_alias = f"{self.DISTINCT_ID_TABLE_ALIAS}.person_id" @@ -163,7 +163,7 @@ def get_query(self) -> Tuple[str, Dict, Callable]: filter=self.filter, event_table_alias=self.EVENT_TABLE_ALIAS, person_id_alias=f"person_id" - if self.person_on_events_mode == PersonOnEventsMode.V1_ENABLED + if self.person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS else self._person_id_alias, ) @@ -748,10 +748,10 @@ def _determine_breakdown_label( return str(value) or BREAKDOWN_NULL_DISPLAY def _person_join_condition(self) -> Tuple[str, Dict]: - if self.person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + if self.person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: return "", {} - if self.person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if self.person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: return ( PERSON_OVERRIDES_JOIN_SQL.format( person_overrides_table_alias=self.PERSON_ID_OVERRIDES_TABLE_ALIAS, diff --git a/posthog/queries/trends/lifecycle.py b/posthog/queries/trends/lifecycle.py index 4821d5295a363..6397439d8922b 100644 --- a/posthog/queries/trends/lifecycle.py +++ b/posthog/queries/trends/lifecycle.py @@ -188,7 +188,9 @@ def _get_date_filter(self): ) def _determine_should_join_distinct_ids(self) -> None: - self._should_join_distinct_ids = self._person_on_events_mode != PersonOnEventsMode.V1_ENABLED + self._should_join_distinct_ids = ( + self._person_on_events_mode != PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS + ) def _determine_should_join_persons(self) -> None: self._should_join_persons = self._person_on_events_mode == PersonOnEventsMode.DISABLED diff --git a/posthog/queries/trends/total_volume.py b/posthog/queries/trends/total_volume.py index 31f5d83b4c15c..9c7977ca02592 100644 --- a/posthog/queries/trends/total_volume.py +++ b/posthog/queries/trends/total_volume.py @@ -59,9 +59,9 @@ def _total_volume_query(self, entity: Entity, filter: Filter, team: Team) -> Tup interval_func = get_interval_func_ch(filter.interval) person_id_alias = f"{self.DISTINCT_ID_TABLE_ALIAS}.person_id" - if team.person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if team.person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: person_id_alias = f"if(notEmpty({self.PERSON_ID_OVERRIDES_TABLE_ALIAS}.person_id), {self.PERSON_ID_OVERRIDES_TABLE_ALIAS}.person_id, {self.EVENT_TABLE_ALIAS}.person_id)" - elif team.person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + elif team.person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: person_id_alias = f"{self.EVENT_TABLE_ALIAS}.person_id" aggregate_operation, join_condition, math_params = process_math( diff --git a/posthog/queries/trends/trends_actors.py b/posthog/queries/trends/trends_actors.py index 228eac4f799e3..1648e7575e7b2 100644 --- a/posthog/queries/trends/trends_actors.py +++ b/posthog/queries/trends/trends_actors.py @@ -104,7 +104,7 @@ def actor_query(self, limit_actors: Optional[bool] = True) -> Tuple[str, Dict]: team=self._team, entity=self.entity, should_join_distinct_ids=not self.is_aggregating_by_groups - and self._team.person_on_events_mode != PersonOnEventsMode.V1_ENABLED, + and self._team.person_on_events_mode != PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS, extra_event_properties=["$window_id", "$session_id"] if self._filter.include_recordings else [], extra_fields=extra_fields, person_on_events_mode=self._team.person_on_events_mode, diff --git a/posthog/queries/trends/trends_event_query.py b/posthog/queries/trends/trends_event_query.py index 6ef5cf009dafc..d3bcc9f381290 100644 --- a/posthog/queries/trends/trends_event_query.py +++ b/posthog/queries/trends/trends_event_query.py @@ -10,7 +10,7 @@ def get_query(self) -> Tuple[str, Dict[str, Any]]: person_id_field = "" if self._should_join_distinct_ids: person_id_field = f", {self._person_id_alias} as person_id" - elif self._person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + elif self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: person_id_field = f", {self.EVENT_TABLE_ALIAS}.person_id as person_id" _fields = ( diff --git a/posthog/queries/trends/trends_event_query_base.py b/posthog/queries/trends/trends_event_query_base.py index 16f742febc52b..082aed8e556a0 100644 --- a/posthog/queries/trends/trends_event_query_base.py +++ b/posthog/queries/trends/trends_event_query_base.py @@ -80,7 +80,7 @@ def get_query_base(self) -> Tuple[str, Dict[str, Any]]: return query, self.params def _determine_should_join_distinct_ids(self) -> None: - if self._person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: self._should_join_distinct_ids = False is_entity_per_user = self._entity.math in ( diff --git a/posthog/queries/trends/util.py b/posthog/queries/trends/util.py index 382201a9e0203..b91e4d6ac185d 100644 --- a/posthog/queries/trends/util.py +++ b/posthog/queries/trends/util.py @@ -174,9 +174,9 @@ def determine_aggregator(entity: Entity, team: Team) -> str: return f'"$group_{entity.math_group_type_index}"' elif team.aggregate_users_by_distinct_id: return "e.distinct_id" - elif team.person_on_events_mode == PersonOnEventsMode.V1_ENABLED: + elif team.person_on_events_mode == PersonOnEventsMode.PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS: return "e.person_id" - elif team.person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + elif team.person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: return f"if(notEmpty(overrides.person_id), overrides.person_id, e.person_id)" else: return "pdi.person_id" diff --git a/posthog/queries/util.py b/posthog/queries/util.py index adf37193f6c29..be08fb732c8ce 100644 --- a/posthog/queries/util.py +++ b/posthog/queries/util.py @@ -178,7 +178,7 @@ def get_person_properties_mode(team: Team) -> PersonPropertiesMode: if team.person_on_events_mode == PersonOnEventsMode.DISABLED: return PersonPropertiesMode.USING_PERSON_PROPERTIES_COLUMN - if team.person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if team.person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: return PersonPropertiesMode.DIRECT_ON_EVENTS_WITH_POE_V2 return PersonPropertiesMode.DIRECT_ON_EVENTS diff --git a/posthog/schema.py b/posthog/schema.py index aa9976ddd1e84..d86343b88fee0 100644 --- a/posthog/schema.py +++ b/posthog/schema.py @@ -423,10 +423,9 @@ class PersonsArgMaxVersion(str, Enum): class PersonsOnEventsMode(str, Enum): disabled = "disabled" - v1_enabled = "v1_enabled" - v1_mixed = "v1_mixed" - v2_enabled = "v2_enabled" - v3_enabled = "v3_enabled" + person_id_no_override_properties_on_events = "person_id_no_override_properties_on_events" + person_id_override_properties_on_events = "person_id_override_properties_on_events" + person_id_override_properties_joined = "person_id_override_properties_joined" class HogQLQueryModifiers(BaseModel): @@ -819,7 +818,7 @@ class SessionPropertyFilter(BaseModel): model_config = ConfigDict( extra="forbid", ) - key: Literal["$session_duration"] = "$session_duration" + key: str label: Optional[str] = None operator: PropertyOperator type: Literal["session"] = "session" diff --git a/posthog/session_recordings/queries/session_recording_list_from_replay_summary.py b/posthog/session_recordings/queries/session_recording_list_from_replay_summary.py index 1b6ed593abaa5..4ff24160ae3e6 100644 --- a/posthog/session_recordings/queries/session_recording_list_from_replay_summary.py +++ b/posthog/session_recordings/queries/session_recording_list_from_replay_summary.py @@ -197,7 +197,7 @@ def _data_to_return(self, results: List[Any]) -> List[Dict[str, Any]]: def get_query(self) -> Tuple[str, Dict[str, Any]]: # we don't support PoE V1 - hopefully that's ok - if self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: return "", {} prop_query, prop_params = self._get_prop_groups( @@ -302,7 +302,7 @@ def _determine_should_join_events(self): ) has_poe_filters = ( - self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED + self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS and len( [ pg @@ -314,7 +314,8 @@ def _determine_should_join_events(self): ) has_poe_person_filter = ( - self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED and self._filter.person_uuid + self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS + and self._filter.person_uuid ) return filters_by_event_or_action or has_event_property_filters or has_poe_filters or has_poe_person_filter @@ -370,7 +371,7 @@ def format_event_filter(self, entity: Entity, prepend: str, team_id: int) -> Tup allow_denormalized_props=True, has_person_id_joined=True, person_properties_mode=PersonPropertiesMode.DIRECT_ON_EVENTS_WITH_POE_V2 - if self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS else PersonPropertiesMode.USING_PERSON_PROPERTIES_COLUMN, hogql_context=self._filter.hogql_context, ) @@ -415,7 +416,7 @@ def build_event_filters(self) -> SummaryEventFiltersSQL: -- select the unique events in this session to support filtering sessions by presence of an event groupUniqArray(event) as event_names,""" - if self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED: + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS: person_id_clause, person_id_params = self._get_person_id_clause condition_sql += person_id_clause params = {**params, **person_id_params} @@ -491,7 +492,10 @@ def get_query(self, select_event_ids: bool = False) -> Tuple[str, Dict[str, Any] values=[ g for g in self._filter.property_groups.flat - if (self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED and g.type == "person") + if ( + self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS + and g.type == "person" + ) or ( (g.type == "hogql" and "person.properties" not in g.key) or (g.type != "hogql" and "cohort" not in g.type and g.type != "person") @@ -505,7 +509,7 @@ def get_query(self, select_event_ids: bool = False) -> Tuple[str, Dict[str, Any] # but would need careful monitoring allow_denormalized_props=settings.ALLOW_DENORMALIZED_PROPS_IN_LISTING, person_properties_mode=PersonPropertiesMode.DIRECT_ON_EVENTS_WITH_POE_V2 - if self._person_on_events_mode == PersonOnEventsMode.V2_ENABLED + if self._person_on_events_mode == PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS else PersonPropertiesMode.USING_PERSON_PROPERTIES_COLUMN, ) diff --git a/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr b/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr index 58e44aaccd47f..002cb37519f7f 100644 --- a/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr +++ b/posthog/session_recordings/test/__snapshots__/test_session_recordings.ambr @@ -327,7 +327,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.14 @@ -380,7 +380,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.15 @@ -412,7 +412,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.16 @@ -423,7 +423,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.17 @@ -434,7 +434,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.18 @@ -445,7 +445,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.19 @@ -456,7 +456,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.2 @@ -527,7 +527,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.21 @@ -538,7 +538,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.22 @@ -549,7 +549,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.23 @@ -560,7 +560,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.24 @@ -571,7 +571,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.25 @@ -582,7 +582,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.26 @@ -593,7 +593,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.27 @@ -604,7 +604,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.28 @@ -615,7 +615,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.29 @@ -626,7 +626,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.3 @@ -697,7 +697,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.31 @@ -708,7 +708,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.32 @@ -719,7 +719,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_get_session_recordings.33 @@ -747,7 +747,7 @@ FROM "posthog_sessionrecording" WHERE ("posthog_sessionrecording"."session_id" IN ('test_get_session_recordings-1', 'test_get_session_recordings-2') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_get_session_recordings.34 @@ -755,7 +755,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_get_session_recordings.35 @@ -779,7 +779,7 @@ INNER JOIN "posthog_person" ON ("posthog_persondistinctid"."person_id" = "posthog_person"."id") WHERE ("posthog_persondistinctid"."distinct_id" IN ('user2', 'user_one_0') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_get_session_recordings.36 @@ -1194,7 +1194,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.1 @@ -1247,7 +1247,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.10 @@ -1258,7 +1258,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.100 @@ -1269,7 +1269,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.101 @@ -1280,7 +1280,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.102 @@ -1291,7 +1291,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.103 @@ -1302,7 +1302,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.104 @@ -1313,7 +1313,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.105 @@ -1324,7 +1324,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.106 @@ -1335,7 +1335,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.107 @@ -1346,7 +1346,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.108 @@ -1357,7 +1357,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.109 @@ -1368,7 +1368,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.11 @@ -1379,7 +1379,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.110 @@ -1409,7 +1409,7 @@ '2', '3', '4') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.111 @@ -1417,7 +1417,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.112 @@ -1443,7 +1443,7 @@ 'user2', 'user3', 'user4') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.113 @@ -1534,7 +1534,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.115 @@ -1587,7 +1587,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.116 @@ -1619,7 +1619,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.117 @@ -1630,7 +1630,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.118 @@ -1641,7 +1641,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.119 @@ -1652,7 +1652,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.12 @@ -1663,7 +1663,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.120 @@ -1674,7 +1674,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.121 @@ -1685,7 +1685,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.122 @@ -1696,7 +1696,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.123 @@ -1707,7 +1707,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.124 @@ -1718,7 +1718,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.125 @@ -1729,7 +1729,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.126 @@ -1740,7 +1740,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.127 @@ -1751,7 +1751,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.128 @@ -1762,7 +1762,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.129 @@ -1773,7 +1773,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.13 @@ -1784,7 +1784,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.130 @@ -1795,7 +1795,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.131 @@ -1806,7 +1806,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.132 @@ -1817,7 +1817,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.133 @@ -1848,7 +1848,7 @@ '3', '4', '5') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.134 @@ -1856,7 +1856,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.135 @@ -1883,7 +1883,7 @@ 'user3', 'user4', 'user5') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.136 @@ -1974,7 +1974,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.138 @@ -2027,7 +2027,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.139 @@ -2059,7 +2059,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.14 @@ -2070,7 +2070,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.140 @@ -2081,7 +2081,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.141 @@ -2092,7 +2092,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.142 @@ -2103,7 +2103,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.143 @@ -2114,7 +2114,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.144 @@ -2125,7 +2125,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.145 @@ -2136,7 +2136,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.146 @@ -2147,7 +2147,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.147 @@ -2158,7 +2158,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.148 @@ -2169,7 +2169,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.149 @@ -2180,7 +2180,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.15 @@ -2191,7 +2191,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.150 @@ -2202,7 +2202,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.151 @@ -2213,7 +2213,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.152 @@ -2224,7 +2224,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.153 @@ -2235,7 +2235,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.154 @@ -2246,7 +2246,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.155 @@ -2257,7 +2257,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.156 @@ -2289,7 +2289,7 @@ '4', '5', '6') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.157 @@ -2297,7 +2297,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.158 @@ -2325,7 +2325,7 @@ 'user4', 'user5', 'user6') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.159 @@ -2396,7 +2396,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.160 @@ -2427,7 +2427,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.161 @@ -2480,7 +2480,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.162 @@ -2512,7 +2512,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.163 @@ -2523,7 +2523,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.164 @@ -2534,7 +2534,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.165 @@ -2545,7 +2545,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.166 @@ -2556,7 +2556,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.167 @@ -2567,7 +2567,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.168 @@ -2578,7 +2578,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.169 @@ -2589,7 +2589,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.17 @@ -2600,7 +2600,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.170 @@ -2611,7 +2611,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.171 @@ -2622,7 +2622,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.172 @@ -2633,7 +2633,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.173 @@ -2644,7 +2644,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.174 @@ -2655,7 +2655,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.175 @@ -2666,7 +2666,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.176 @@ -2677,7 +2677,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.177 @@ -2688,7 +2688,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.178 @@ -2699,7 +2699,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.179 @@ -2732,7 +2732,7 @@ '5', '6', '7') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.18 @@ -2743,7 +2743,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.180 @@ -2751,7 +2751,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.181 @@ -2780,7 +2780,7 @@ 'user5', 'user6', 'user7') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.182 @@ -2871,7 +2871,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.184 @@ -2924,7 +2924,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.185 @@ -2956,7 +2956,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.186 @@ -2967,7 +2967,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.187 @@ -2978,7 +2978,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.188 @@ -2989,7 +2989,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.189 @@ -3000,7 +3000,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.19 @@ -3011,7 +3011,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.190 @@ -3022,7 +3022,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.191 @@ -3033,7 +3033,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.192 @@ -3044,7 +3044,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.193 @@ -3055,7 +3055,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.194 @@ -3066,7 +3066,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.195 @@ -3077,7 +3077,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.196 @@ -3088,7 +3088,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.197 @@ -3099,7 +3099,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.198 @@ -3110,7 +3110,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.199 @@ -3121,7 +3121,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.2 @@ -3153,7 +3153,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.20 @@ -3161,7 +3161,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.200 @@ -3172,7 +3172,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.201 @@ -3183,7 +3183,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.202 @@ -3217,7 +3217,7 @@ '6', '7', '8') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.203 @@ -3225,7 +3225,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.204 @@ -3255,7 +3255,7 @@ 'user6', 'user7', 'user8') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.205 @@ -3346,7 +3346,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.207 @@ -3399,7 +3399,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.208 @@ -3431,7 +3431,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.209 @@ -3442,7 +3442,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.21 @@ -3513,7 +3513,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.211 @@ -3524,7 +3524,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.212 @@ -3535,7 +3535,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.213 @@ -3546,7 +3546,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.214 @@ -3557,7 +3557,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.215 @@ -3568,7 +3568,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.216 @@ -3579,7 +3579,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.217 @@ -3590,7 +3590,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.218 @@ -3601,7 +3601,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.219 @@ -3612,7 +3612,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.22 @@ -3643,7 +3643,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.220 @@ -3654,7 +3654,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.221 @@ -3665,7 +3665,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.222 @@ -3676,7 +3676,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.223 @@ -3687,7 +3687,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.224 @@ -3698,7 +3698,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.225 @@ -3733,7 +3733,7 @@ '7', '8', '9') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.226 @@ -3741,7 +3741,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.227 @@ -3772,7 +3772,7 @@ 'user7', 'user8', 'user9') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.228 @@ -3863,7 +3863,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.23 @@ -3916,7 +3916,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.230 @@ -3969,7 +3969,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.231 @@ -4001,7 +4001,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.232 @@ -4012,7 +4012,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.233 @@ -4023,7 +4023,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.234 @@ -4034,7 +4034,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.235 @@ -4045,7 +4045,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.236 @@ -4056,7 +4056,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.237 @@ -4067,7 +4067,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.238 @@ -4078,7 +4078,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.239 @@ -4089,7 +4089,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.24 @@ -4121,7 +4121,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.240 @@ -4132,7 +4132,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.241 @@ -4143,7 +4143,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.242 @@ -4154,7 +4154,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.243 @@ -4165,7 +4165,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.244 @@ -4176,7 +4176,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.245 @@ -4187,7 +4187,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.246 @@ -4198,7 +4198,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.247 @@ -4209,7 +4209,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.248 @@ -4245,7 +4245,7 @@ '7', '8', '9') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.249 @@ -4253,7 +4253,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.25 @@ -4264,7 +4264,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.250 @@ -4296,7 +4296,7 @@ 'user7', 'user8', 'user9') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.251 @@ -4431,7 +4431,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.260 @@ -4482,7 +4482,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.28 @@ -4493,7 +4493,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.29 @@ -4504,7 +4504,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.3 @@ -4515,7 +4515,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RATE_LIMIT_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.30 @@ -4526,7 +4526,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.31 @@ -4537,7 +4537,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.32 @@ -4548,7 +4548,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.33 @@ -4559,7 +4559,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.34 @@ -4570,7 +4570,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.35 @@ -4581,7 +4581,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.36 @@ -4592,7 +4592,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.37 @@ -4603,7 +4603,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.38 @@ -4614,7 +4614,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.39 @@ -4625,7 +4625,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.4 @@ -4636,7 +4636,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.40 @@ -4647,7 +4647,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.41 @@ -4674,7 +4674,7 @@ "posthog_sessionrecording"."storage_version" FROM "posthog_sessionrecording" WHERE ("posthog_sessionrecording"."session_id" IN ('1') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.42 @@ -4682,7 +4682,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.43 @@ -4705,7 +4705,7 @@ FROM "posthog_persondistinctid" INNER JOIN "posthog_person" ON ("posthog_persondistinctid"."person_id" = "posthog_person"."id") WHERE ("posthog_persondistinctid"."distinct_id" IN ('user1') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.44 @@ -4796,7 +4796,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.46 @@ -4849,7 +4849,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.47 @@ -4881,7 +4881,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.48 @@ -4892,7 +4892,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.49 @@ -4903,7 +4903,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.5 @@ -4914,7 +4914,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.50 @@ -4925,7 +4925,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.51 @@ -4936,7 +4936,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.52 @@ -4947,7 +4947,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.53 @@ -4958,7 +4958,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.54 @@ -4969,7 +4969,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.55 @@ -4980,7 +4980,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.56 @@ -4991,7 +4991,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.57 @@ -5002,7 +5002,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.58 @@ -5013,7 +5013,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.59 @@ -5024,7 +5024,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.6 @@ -5035,7 +5035,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.60 @@ -5046,7 +5046,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.61 @@ -5057,7 +5057,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.62 @@ -5068,7 +5068,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.63 @@ -5079,7 +5079,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.64 @@ -5107,7 +5107,7 @@ FROM "posthog_sessionrecording" WHERE ("posthog_sessionrecording"."session_id" IN ('1', '2') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.65 @@ -5115,7 +5115,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.66 @@ -5139,7 +5139,7 @@ INNER JOIN "posthog_person" ON ("posthog_persondistinctid"."person_id" = "posthog_person"."id") WHERE ("posthog_persondistinctid"."distinct_id" IN ('user1', 'user2') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.67 @@ -5230,7 +5230,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.69 @@ -5283,7 +5283,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.7 @@ -5294,7 +5294,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.70 @@ -5326,7 +5326,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.71 @@ -5337,7 +5337,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.72 @@ -5348,7 +5348,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.73 @@ -5359,7 +5359,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.74 @@ -5370,7 +5370,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.75 @@ -5381,7 +5381,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.76 @@ -5392,7 +5392,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.77 @@ -5403,7 +5403,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.78 @@ -5414,7 +5414,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.79 @@ -5425,7 +5425,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.8 @@ -5436,7 +5436,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.80 @@ -5447,7 +5447,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:RECORDINGS_TTL_WEEKS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.81 @@ -5458,7 +5458,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.82 @@ -5469,7 +5469,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.83 @@ -5480,7 +5480,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.84 @@ -5491,7 +5491,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.85 @@ -5502,7 +5502,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.86 @@ -5513,7 +5513,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:AGGREGATE_BY_DISTINCT_IDS_TEAMS' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.87 @@ -5542,7 +5542,7 @@ WHERE ("posthog_sessionrecording"."session_id" IN ('1', '2', '3') - AND "posthog_sessionrecording"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecording"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.88 @@ -5550,7 +5550,7 @@ SELECT "posthog_sessionrecordingviewed"."session_id" FROM "posthog_sessionrecordingviewed" WHERE ("posthog_sessionrecordingviewed"."team_id" = 2 - AND "posthog_sessionrecordingviewed"."user_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_sessionrecordingviewed"."user_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.89 @@ -5575,7 +5575,7 @@ WHERE ("posthog_persondistinctid"."distinct_id" IN ('user1', 'user2', 'user3') - AND "posthog_persondistinctid"."team_id" = 2) /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + AND "posthog_persondistinctid"."team_id" = 2) ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.9 @@ -5586,7 +5586,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.90 @@ -5677,7 +5677,7 @@ "posthog_user"."events_column_config" FROM "posthog_user" WHERE "posthog_user"."id" = 2 - LIMIT 21 /**/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.92 @@ -5730,7 +5730,7 @@ "posthog_team"."external_data_workspace_last_synced_at" FROM "posthog_team" WHERE "posthog_team"."id" = 2 - LIMIT 21 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 21 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.93 @@ -5762,7 +5762,7 @@ "posthog_organization"."available_features" FROM "posthog_organizationmembership" INNER JOIN "posthog_organization" ON ("posthog_organizationmembership"."organization_id" = "posthog_organization"."id") - WHERE "posthog_organizationmembership"."user_id" = 2 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + WHERE "posthog_organizationmembership"."user_id" = 2 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.94 @@ -5773,7 +5773,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.95 @@ -5784,7 +5784,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.96 @@ -5795,7 +5795,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.97 @@ -5806,7 +5806,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.98 @@ -5817,7 +5817,7 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_V2_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- # name: TestSessionRecordings.test_listing_recordings_is_not_nplus1_for_persons.99 @@ -5828,6 +5828,6 @@ FROM "posthog_instancesetting" WHERE "posthog_instancesetting"."key" = 'constance:posthog:PERSON_ON_EVENTS_ENABLED' ORDER BY "posthog_instancesetting"."id" ASC - LIMIT 1 /*controller='project_session_recordings-list',route='api/projects/%28%3FP%3Cparent_lookup_team_id%3E%5B%5E/.%5D%2B%29/session_recordings/%3F%24'*/ + LIMIT 1 ''' # --- diff --git a/posthog/settings/__init__.py b/posthog/settings/__init__.py index dd72e63bcc92a..455b7e8dc34a1 100644 --- a/posthog/settings/__init__.py +++ b/posthog/settings/__init__.py @@ -96,7 +96,6 @@ # Only written in specific scripts - do not use outside of them. PERSON_ON_EVENTS_V2_OVERRIDE = get_from_env("PERSON_ON_EVENTS_V2_OVERRIDE", optional=True, type_cast=str_to_bool) -PERSON_ON_EVENTS_V3_OVERRIDE = get_from_env("PERSON_ON_EVENTS_V3_OVERRIDE", optional=True, type_cast=str_to_bool) # Wether to use insight queries converted to HogQL. HOGQL_INSIGHTS_OVERRIDE = get_from_env("HOGQL_INSIGHTS_OVERRIDE", optional=True, type_cast=str_to_bool) diff --git a/posthog/settings/sentry.py b/posthog/settings/sentry.py index d6c5fae52b7eb..225e6dc61f51a 100644 --- a/posthog/settings/sentry.py +++ b/posthog/settings/sentry.py @@ -9,7 +9,6 @@ from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.logging import LoggingIntegration from sentry_sdk.integrations.redis import RedisIntegration -from sentry_sdk.integrations.clickhouse_driver import ClickhouseDriverIntegration from posthog.git import get_git_commit_full from posthog.settings import get_from_env @@ -136,6 +135,8 @@ def traces_sampler(sampling_context: dict) -> float: def sentry_init() -> None: if not TEST and os.getenv("SENTRY_DSN"): + sentry_sdk.utils.MAX_STRING_LENGTH = 10_000_000 + # Setting this on enables more visibility, at the risk of capturing personal information we should not: # - standard sentry "client IP" field, through send_default_pii # - django access logs (info level) @@ -144,6 +145,7 @@ def sentry_init() -> None: send_pii = get_from_env("SENTRY_SEND_PII", type_cast=bool, default=False) sentry_logging_level = logging.INFO if send_pii else logging.ERROR + sentry_logging = LoggingIntegration(level=sentry_logging_level, event_level=None) profiles_sample_rate = get_from_env("SENTRY_PROFILES_SAMPLE_RATE", type_cast=float, default=0.0) release = get_git_commit_full() @@ -156,11 +158,9 @@ def sentry_init() -> None: DjangoIntegration(), CeleryIntegration(), RedisIntegration(), - ClickhouseDriverIntegration(), - LoggingIntegration(level=sentry_logging_level, event_level=None), + sentry_logging, ], - max_request_body_size="always" if send_pii else "never", - max_value_length=8192, # Increased from the default of 1024 to capture SQL statements in full + request_bodies="always" if send_pii else "never", sample_rate=1.0, # Configures the sample rate for error events, in the range of 0.0 to 1.0 (default). # If set to 0.1 only 10% of error events will be sent. Events are picked randomly. diff --git a/posthog/settings/web.py b/posthog/settings/web.py index 9c4a277471ed0..f54c2e32fc28c 100644 --- a/posthog/settings/web.py +++ b/posthog/settings/web.py @@ -90,7 +90,6 @@ "posthog.health.healthcheck_middleware", "posthog.middleware.ShortCircuitMiddleware", "posthog.middleware.AllowIPMiddleware", - "google.cloud.sqlcommenter.django.middleware.SqlCommenter", "django.contrib.sessions.middleware.SessionMiddleware", "corsheaders.middleware.CorsMiddleware", "django.middleware.common.CommonMiddleware", diff --git a/posthog/tasks/scheduled.py b/posthog/tasks/scheduled.py index e7b29070db18a..537a1a49bbe20 100644 --- a/posthog/tasks/scheduled.py +++ b/posthog/tasks/scheduled.py @@ -10,6 +10,7 @@ from posthog.tasks.tasks import ( calculate_cohort, calculate_decide_usage, + calculate_replay_embeddings, check_async_migration_health, check_data_import_row_limits, check_flags_to_rollback, @@ -45,7 +46,6 @@ update_event_partitions, update_quota_limiting, verify_persons_data_in_sync, - calculate_replay_embeddings, ) from posthog.utils import get_crontab @@ -96,12 +96,12 @@ def setup_periodic_tasks(sender: Celery, **kwargs: Any) -> None: # Send all instance usage to the Billing service # Sends later on Sunday due to clickhouse things that happen on Sunday at ~00:00 UTC sender.add_periodic_task( - crontab(hour="2", minute="15", day_of_week="mon"), + crontab(hour="3", minute="15", day_of_week="mon"), send_org_usage_reports.s(), name="send instance usage report, monday", ) sender.add_periodic_task( - crontab(hour="0", minute="15", day_of_week="tue,wed,thu,fri,sat,sun"), + crontab(hour="2", minute="15", day_of_week="tue,wed,thu,fri,sat,sun"), send_org_usage_reports.s(), name="send instance usage report", ) diff --git a/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr b/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr index d4ed303a0dda1..dcf75cb638fac 100644 --- a/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr +++ b/posthog/tasks/test/__snapshots__/test_process_scheduled_changes.ambr @@ -37,7 +37,7 @@ "posthog_scheduledchange"."updated_at" FROM "posthog_scheduledchange" WHERE ("posthog_scheduledchange"."executed_at" IS NULL - AND "posthog_scheduledchange"."scheduled_at" <= '2023-12-21T09:00:00+00:00'::timestamptz) + AND "posthog_scheduledchange"."scheduled_at" <= '2023-12-21 09:00:00+00:00'::timestamptz) ORDER BY "posthog_scheduledchange"."scheduled_at" ASC LIMIT 10000 FOR diff --git a/posthog/tasks/test/__snapshots__/test_usage_report.ambr b/posthog/tasks/test/__snapshots__/test_usage_report.ambr index e2038e3de9f89..81a832aad0398 100644 --- a/posthog/tasks/test/__snapshots__/test_usage_report.ambr +++ b/posthog/tasks/test/__snapshots__/test_usage_report.ambr @@ -199,6 +199,7 @@ AND event NOT IN ('survey sent', 'survey shown', 'survey dismissed') + AND person_mode = 'full' GROUP BY team_id ''' # --- diff --git a/posthog/tasks/test/test_usage_report.py b/posthog/tasks/test/test_usage_report.py index 75e13fc845a70..055629bf055ca 100644 --- a/posthog/tasks/test/test_usage_report.py +++ b/posthog/tasks/test/test_usage_report.py @@ -312,6 +312,15 @@ def _create_sample_usage_data(self) -> None: timestamp=now() - relativedelta(hours=12), team=self.org_2_team_3, ) + _create_event( + event_uuid=uuid4(), + distinct_id=distinct_id, + event="$propertyless_event", + properties={"$lib": "$web"}, + timestamp=now() - relativedelta(hours=12), + team=self.org_1_team_1, + person_mode="propertyless", + ) flush_persons_and_events() @@ -367,11 +376,10 @@ def _test_usage_report(self) -> List[dict]: }, "plugins_enabled": {"Installed and enabled": 1}, "instance_tag": "none", - "event_count_lifetime": 55, - "event_count_in_period": 22, - # TODO: enhanced_persons: modify this test so that there are fewer of these events than the base + "event_count_lifetime": 56, + "event_count_in_period": 23, "enhanced_persons_event_count_in_period": 22, - "event_count_in_month": 42, + "event_count_in_month": 43, "event_count_with_groups_in_period": 2, "recording_count_in_period": 5, "recording_count_total": 16, @@ -411,10 +419,10 @@ def _test_usage_report(self) -> List[dict]: "team_count": 2, "teams": { str(self.org_1_team_1.id): { - "event_count_lifetime": 44, - "event_count_in_period": 12, + "event_count_lifetime": 45, + "event_count_in_period": 13, "enhanced_persons_event_count_in_period": 12, - "event_count_in_month": 32, + "event_count_in_month": 33, "event_count_with_groups_in_period": 2, "recording_count_in_period": 0, "recording_count_total": 0, diff --git a/posthog/tasks/usage_report.py b/posthog/tasks/usage_report.py index 5eba745608004..958601d1ec3ca 100644 --- a/posthog/tasks/usage_report.py +++ b/posthog/tasks/usage_report.py @@ -23,7 +23,7 @@ from django.db import connection from django.db.models import Count, Q from posthoganalytics.client import Client -from psycopg2 import sql +from psycopg import sql from retry import retry from sentry_sdk import capture_exception @@ -432,12 +432,11 @@ def get_teams_with_billable_enhanced_persons_event_count_in_period( else: distinct_expression = "1" - # TODO: enhanced_persons: update this query to filter on enhanced_persons column result = sync_execute( f""" SELECT team_id, count({distinct_expression}) as count FROM events - WHERE timestamp between %(begin)s AND %(end)s AND event != '$feature_flag_called' AND event NOT IN ('survey sent', 'survey shown', 'survey dismissed') + WHERE timestamp between %(begin)s AND %(end)s AND event != '$feature_flag_called' AND event NOT IN ('survey sent', 'survey shown', 'survey dismissed') AND person_mode = 'full' GROUP BY team_id """, {"begin": begin, "end": end}, diff --git a/posthog/tasks/warehouse.py b/posthog/tasks/warehouse.py index 46040b58a96a9..f9c526ac19616 100644 --- a/posthog/tasks/warehouse.py +++ b/posthog/tasks/warehouse.py @@ -12,7 +12,7 @@ logger = structlog.get_logger(__name__) -MONTHLY_LIMIT = 5_000_000 +MONTHLY_LIMIT = 100_000_000 def check_synced_row_limits() -> None: diff --git a/posthog/temporal/data_imports/external_data_job.py b/posthog/temporal/data_imports/external_data_job.py index b88dc44759ece..82e48a18e05c6 100644 --- a/posthog/temporal/data_imports/external_data_job.py +++ b/posthog/temporal/data_imports/external_data_job.py @@ -30,9 +30,11 @@ ) from posthog.warehouse.models.external_data_schema import get_postgres_schemas from posthog.temporal.common.logger import bind_temporal_worker_logger +from posthog.utils import get_instance_region from typing import Dict, Tuple import asyncio from django.conf import settings +from django.utils import timezone @dataclasses.dataclass @@ -188,12 +190,25 @@ async def run_external_data_job(inputs: ExternalDataJobInputs) -> Tuple[TSchemaT # until we require re update of account_ids in stripe so they're all store if not stripe_secret_key: raise ValueError(f"Stripe secret key not found for job {model.id}") + + # Hacky just for specific user + region = get_instance_region() + if region == "EU" and inputs.team_id == 11870: + prev_day = timezone.now() - dt.timedelta(days=1) + start_date = prev_day.replace(hour=0, minute=0, second=0, microsecond=0) + end_date = start_date + dt.timedelta(1) + else: + start_date = None + end_date = None + source = stripe_source( api_key=stripe_secret_key, account_id=account_id, endpoints=tuple(endpoints), team_id=inputs.team_id, job_id=inputs.run_id, + start_date=start_date, + end_date=end_date, ) elif model.pipeline.source_type == ExternalDataSource.Type.HUBSPOT: from posthog.temporal.data_imports.pipelines.hubspot.auth import refresh_access_token diff --git a/posthog/temporal/data_imports/pipelines/stripe/helpers.py b/posthog/temporal/data_imports/pipelines/stripe/helpers.py index 0a811e0811266..0646b28238a9e 100644 --- a/posthog/temporal/data_imports/pipelines/stripe/helpers.py +++ b/posthog/temporal/data_imports/pipelines/stripe/helpers.py @@ -61,6 +61,8 @@ async def stripe_pagination( team_id: int, job_id: str, starting_after: Optional[str] = None, + start_date: Optional[Any] = None, + end_date: Optional[Any] = None, ): """ Retrieves data from an endpoint with pagination. @@ -88,6 +90,8 @@ async def stripe_pagination( account_id, endpoint, starting_after=starting_after, + start_date=start_date, + end_date=end_date, ) if len(response["data"]) > 0: @@ -106,7 +110,14 @@ async def stripe_pagination( @dlt.source(max_table_nesting=0) def stripe_source( - api_key: str, account_id: str, endpoints: Tuple[str, ...], team_id, job_id, starting_after: Optional[str] = None + api_key: str, + account_id: str, + endpoints: Tuple[str, ...], + team_id, + job_id, + starting_after: Optional[str] = None, + start_date: Optional[Any] = None, + end_date: Optional[Any] = None, ) -> Iterable[DltResource]: for endpoint in endpoints: yield dlt.resource( @@ -120,4 +131,6 @@ def stripe_source( team_id=team_id, job_id=job_id, starting_after=starting_after, + start_date=start_date, + end_date=end_date, ) diff --git a/posthog/test/__snapshots__/test_feature_flag.ambr b/posthog/test/__snapshots__/test_feature_flag.ambr index 5a857e986a79d..84cd8f1298878 100644 --- a/posthog/test/__snapshots__/test_feature_flag.ambr +++ b/posthog/test/__snapshots__/test_feature_flag.ambr @@ -1,42 +1,42 @@ # serializer version: 1 # name: TestFeatureFlagMatcher.test_coercion_of_booleans_with_is_not_operator ''' - SELECT NOT ((("posthog_person"."properties" -> 'disabled') = 'false' - OR ("posthog_person"."properties" -> 'disabled') = '"false"') + SELECT NOT ((("posthog_person"."properties" -> 'disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'disabled' - AND NOT (("posthog_person"."properties" -> 'disabled') = 'null')) AS "flag_X_condition_0", - NOT ((("posthog_person"."properties" -> 'disabled') = 'false' - OR ("posthog_person"."properties" -> 'disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'disabled') = 'null'::jsonb)) AS "flag_X_condition_0", + NOT ((("posthog_person"."properties" -> 'disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'disabled' - AND NOT (("posthog_person"."properties" -> 'disabled') = 'null')) AS "flag_X_condition_1", - NOT ((("posthog_person"."properties" -> 'disabled') = 'false' - OR ("posthog_person"."properties" -> 'disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'disabled') = 'null'::jsonb)) AS "flag_X_condition_1", + NOT ((("posthog_person"."properties" -> 'disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'disabled' - AND NOT (("posthog_person"."properties" -> 'disabled') = 'null')) AS "flag_X_condition_2", - NOT ((("posthog_person"."properties" -> 'disabled') = 'false' - OR ("posthog_person"."properties" -> 'disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'disabled') = 'null'::jsonb)) AS "flag_X_condition_2", + NOT ((("posthog_person"."properties" -> 'disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'disabled' - AND NOT (("posthog_person"."properties" -> 'disabled') = 'null')) AS "flag_X_condition_3", - NOT ((("posthog_person"."properties" -> 'disabled') = 'false' - OR ("posthog_person"."properties" -> 'disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'disabled') = 'null'::jsonb)) AS "flag_X_condition_3", + NOT ((("posthog_person"."properties" -> 'disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'disabled' - AND NOT (("posthog_person"."properties" -> 'disabled') = 'null')) AS "flag_X_condition_4", - NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false' - OR ("posthog_person"."properties" -> 'string_disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'disabled') = 'null'::jsonb)) AS "flag_X_condition_4", + NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'string_disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'string_disabled' - AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null')) AS "flag_X_condition_5", - NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false' - OR ("posthog_person"."properties" -> 'string_disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null'::jsonb)) AS "flag_X_condition_5", + NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'string_disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'string_disabled' - AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null')) AS "flag_X_condition_6", - NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false' - OR ("posthog_person"."properties" -> 'string_disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null'::jsonb)) AS "flag_X_condition_6", + NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'string_disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'string_disabled' - AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null')) AS "flag_X_condition_7", - NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false' - OR ("posthog_person"."properties" -> 'string_disabled') = '"false"') + AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null'::jsonb)) AS "flag_X_condition_7", + NOT ((("posthog_person"."properties" -> 'string_disabled') = 'false'::jsonb + OR ("posthog_person"."properties" -> 'string_disabled') = '"false"'::jsonb) AND "posthog_person"."properties" ? 'string_disabled' - AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null')) AS "flag_X_condition_8" + AND NOT (("posthog_person"."properties" -> 'string_disabled') = 'null'::jsonb)) AS "flag_X_condition_8" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -46,20 +46,20 @@ # --- # name: TestFeatureFlagMatcher.test_coercion_of_strings_and_numbers_with_is_not_operator ''' - SELECT (NOT ((("posthog_person"."properties" -> 'Organizer Id') IN ('"307"') - OR ("posthog_person"."properties" -> 'Organizer Id') IN ('307')) + SELECT (NOT ((("posthog_person"."properties" -> 'Organizer Id') IN ('"307"'::jsonb) + OR ("posthog_person"."properties" -> 'Organizer Id') IN ('307'::jsonb)) AND "posthog_person"."properties" ? 'Organizer Id' - AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null')) - AND NOT (("posthog_person"."properties" -> 'Organizer Id') IN ('307') + AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null'::jsonb)) + AND NOT (("posthog_person"."properties" -> 'Organizer Id') IN ('307'::jsonb) AND "posthog_person"."properties" ? 'Organizer Id' - AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null')) - AND NOT ((("posthog_person"."properties" -> 'Organizer Id') = '"307"' - OR ("posthog_person"."properties" -> 'Organizer Id') = '307') + AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null'::jsonb)) + AND NOT ((("posthog_person"."properties" -> 'Organizer Id') = '"307"'::jsonb + OR ("posthog_person"."properties" -> 'Organizer Id') = '307'::jsonb) AND "posthog_person"."properties" ? 'Organizer Id' - AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null')) - AND NOT (("posthog_person"."properties" -> 'Organizer Id') = '307' + AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null'::jsonb)) + AND NOT (("posthog_person"."properties" -> 'Organizer Id') = '307'::jsonb AND "posthog_person"."properties" ? 'Organizer Id' - AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null'))) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'Organizer Id') = 'null'::jsonb))) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -69,20 +69,20 @@ # --- # name: TestFeatureFlagMatcher.test_coercion_of_strings_and_numbers_with_is_not_operator.1 ''' - SELECT NOT ((("posthog_person"."properties" -> 'Distinct Id') IN ('"307"') - OR ("posthog_person"."properties" -> 'Distinct Id') IN ('307')) + SELECT NOT ((("posthog_person"."properties" -> 'Distinct Id') IN ('"307"'::jsonb) + OR ("posthog_person"."properties" -> 'Distinct Id') IN ('307'::jsonb)) AND "posthog_person"."properties" ? 'Distinct Id' - AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null')) AS "flag_X_condition_0", - NOT (("posthog_person"."properties" -> 'Distinct Id') IN ('307') + AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null'::jsonb)) AS "flag_X_condition_0", + NOT (("posthog_person"."properties" -> 'Distinct Id') IN ('307'::jsonb) AND "posthog_person"."properties" ? 'Distinct Id' - AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null')) AS "flag_X_condition_1", - NOT ((("posthog_person"."properties" -> 'Distinct Id') = '"307"' - OR ("posthog_person"."properties" -> 'Distinct Id') = '307') + AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null'::jsonb)) AS "flag_X_condition_1", + NOT ((("posthog_person"."properties" -> 'Distinct Id') = '"307"'::jsonb + OR ("posthog_person"."properties" -> 'Distinct Id') = '307'::jsonb) AND "posthog_person"."properties" ? 'Distinct Id' - AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null')) AS "flag_X_condition_2", - NOT (("posthog_person"."properties" -> 'Distinct Id') = '307' + AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null'::jsonb)) AS "flag_X_condition_2", + NOT (("posthog_person"."properties" -> 'Distinct Id') = '307'::jsonb AND "posthog_person"."properties" ? 'Distinct Id' - AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null')) AS "flag_X_condition_3" + AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null'::jsonb)) AS "flag_X_condition_3" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -221,10 +221,10 @@ # --- # name: TestFeatureFlagMatcher.test_db_matches_independent_of_string_or_number_type.4 ''' - SELECT ((("posthog_person"."properties" -> 'Distinct Id') IN ('"307"') - OR ("posthog_person"."properties" -> 'Distinct Id') IN ('307')) + SELECT ((("posthog_person"."properties" -> 'Distinct Id') IN ('"307"'::jsonb) + OR ("posthog_person"."properties" -> 'Distinct Id') IN ('307'::jsonb)) AND "posthog_person"."properties" ? 'Distinct Id' - AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -234,9 +234,9 @@ # --- # name: TestFeatureFlagMatcher.test_db_matches_independent_of_string_or_number_type.5 ''' - SELECT (("posthog_person"."properties" -> 'Distinct Id') IN ('307') + SELECT (("posthog_person"."properties" -> 'Distinct Id') IN ('307'::jsonb) AND "posthog_person"."properties" ? 'Distinct Id' - AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -246,9 +246,9 @@ # --- # name: TestFeatureFlagMatcher.test_db_matches_independent_of_string_or_number_type.6 ''' - SELECT (("posthog_person"."properties" -> 'Distinct Id') = '307' + SELECT (("posthog_person"."properties" -> 'Distinct Id') = '307'::jsonb AND "posthog_person"."properties" ? 'Distinct Id' - AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'Distinct Id') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -343,7 +343,7 @@ ''' SELECT (("posthog_person"."properties" ->> 'email')::text ~ '["neil@x.com"]' AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -355,7 +355,7 @@ ''' SELECT (("posthog_person"."properties" ->> 'email')::text ~ '["neil@x.com"]' AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = 'another_id' @@ -377,9 +377,9 @@ # --- # name: TestFeatureFlagMatcher.test_multiple_flags.1 ''' - SELECT (("posthog_person"."properties" -> 'email') = '"test@posthog.com"' + SELECT (("posthog_person"."properties" -> 'email') = '"test@posthog.com"'::jsonb AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0", + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0", (true) AS "flag_X_condition_1", (true) AS "flag_X_condition_0", (true) AS "flag_X_condition_0", @@ -403,12 +403,12 @@ # --- # name: TestFeatureFlagMatcher.test_multiple_flags.3 ''' - SELECT (("posthog_group"."group_properties" -> 'name') IN ('"foo.inc"') + SELECT (("posthog_group"."group_properties" -> 'name') IN ('"foo.inc"'::jsonb) AND "posthog_group"."group_properties" ? 'name' - AND NOT (("posthog_group"."group_properties" -> 'name') = 'null')) AS "flag_X_condition_0", - (("posthog_group"."group_properties" -> 'name') IN ('"foo2.inc"') + AND NOT (("posthog_group"."group_properties" -> 'name') = 'null'::jsonb)) AS "flag_X_condition_0", + (("posthog_group"."group_properties" -> 'name') IN ('"foo2.inc"'::jsonb) AND "posthog_group"."group_properties" ? 'name' - AND NOT (("posthog_group"."group_properties" -> 'name') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_group"."group_properties" -> 'name') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_group" WHERE ("posthog_group"."team_id" = 2 AND "posthog_group"."group_key" = 'foo' @@ -429,9 +429,9 @@ # --- # name: TestFeatureFlagMatcher.test_multiple_flags.5 ''' - SELECT (("posthog_person"."properties" -> 'email') = '"test@posthog.com"' + SELECT (("posthog_person"."properties" -> 'email') = '"test@posthog.com"'::jsonb AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0", + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0", (true) AS "flag_X_condition_1", (true) AS "flag_X_condition_0", (true) AS "flag_X_condition_0", @@ -445,12 +445,12 @@ # --- # name: TestFeatureFlagMatcher.test_multiple_flags.6 ''' - SELECT (("posthog_group"."group_properties" -> 'name') IN ('"foo.inc"') + SELECT (("posthog_group"."group_properties" -> 'name') IN ('"foo.inc"'::jsonb) AND "posthog_group"."group_properties" ? 'name' - AND NOT (("posthog_group"."group_properties" -> 'name') = 'null')) AS "flag_X_condition_0", - (("posthog_group"."group_properties" -> 'name') IN ('"foo2.inc"') + AND NOT (("posthog_group"."group_properties" -> 'name') = 'null'::jsonb)) AS "flag_X_condition_0", + (("posthog_group"."group_properties" -> 'name') IN ('"foo2.inc"'::jsonb) AND "posthog_group"."group_properties" ? 'name' - AND NOT (("posthog_group"."group_properties" -> 'name') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_group"."group_properties" -> 'name') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_group" WHERE ("posthog_group"."team_id" = 2 AND "posthog_group"."group_key" = 'foo2' @@ -483,30 +483,30 @@ # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_cohorts_and_nested_cohorts.1 ''' - SELECT (((("posthog_person"."properties" -> 'number') > '"100"' + SELECT (((("posthog_person"."properties" -> 'number') > '"100"'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number')) = ('string')) - OR (("posthog_person"."properties" -> 'number') > '100.0' + OR (("posthog_person"."properties" -> 'number') > '100.0'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number')) = ('number'))) AND "posthog_person"."properties" ? 'number' - AND NOT (("posthog_person"."properties" -> 'number') = 'null')) AS "flag_X_condition_0", - (((("posthog_person"."properties" -> 'version') > '"1.05"' + AND NOT (("posthog_person"."properties" -> 'number') = 'null'::jsonb)) AS "flag_X_condition_0", + (((("posthog_person"."properties" -> 'version') > '"1.05"'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'version')) = ('string')) - OR (("posthog_person"."properties" -> 'version') > '1.05' + OR (("posthog_person"."properties" -> 'version') > '1.05'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'version')) = ('number'))) AND "posthog_person"."properties" ? 'version' - AND NOT (("posthog_person"."properties" -> 'version') = 'null')) AS "flag_X_condition_0", - (((("posthog_person"."properties" -> 'number') < '"31"' + AND NOT (("posthog_person"."properties" -> 'version') = 'null'::jsonb)) AS "flag_X_condition_0", + (((("posthog_person"."properties" -> 'number') < '"31"'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number')) = ('string')) - OR (("posthog_person"."properties" -> 'number') < '31.0' + OR (("posthog_person"."properties" -> 'number') < '31.0'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number')) = ('number'))) AND "posthog_person"."properties" ? 'number' - AND NOT (("posthog_person"."properties" -> 'number') = 'null') - AND ((("posthog_person"."properties" -> 'nested_prop') > '"20"' + AND NOT (("posthog_person"."properties" -> 'number') = 'null'::jsonb) + AND ((("posthog_person"."properties" -> 'nested_prop') > '"20"'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'nested_prop')) = ('string')) - OR (("posthog_person"."properties" -> 'nested_prop') > '20.0' + OR (("posthog_person"."properties" -> 'nested_prop') > '20.0'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'nested_prop')) = ('number'))) AND "posthog_person"."properties" ? 'nested_prop' - AND NOT (("posthog_person"."properties" -> 'nested_prop') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'nested_prop') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -561,12 +561,12 @@ # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_groups_and_person_flags.1 ''' - SELECT (((("posthog_person"."properties" -> 'number') >= '"20"' + SELECT (((("posthog_person"."properties" -> 'number') >= '"20"'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number')) = ('string')) - OR (("posthog_person"."properties" -> 'number') >= '20.0' + OR (("posthog_person"."properties" -> 'number') >= '20.0'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number')) = ('number'))) AND "posthog_person"."properties" ? 'number' - AND NOT (("posthog_person"."properties" -> 'number') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_person"."properties" -> 'number') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -576,12 +576,12 @@ # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_groups_and_person_flags.2 ''' - SELECT (((("posthog_group"."group_properties" -> 'number') > '"100"' + SELECT (((("posthog_group"."group_properties" -> 'number') > '"100"'::jsonb AND JSONB_TYPEOF(("posthog_group"."group_properties" -> 'number')) = ('string')) - OR (("posthog_group"."group_properties" -> 'number') > '100.0' + OR (("posthog_group"."group_properties" -> 'number') > '100.0'::jsonb AND JSONB_TYPEOF(("posthog_group"."group_properties" -> 'number')) = ('number'))) AND "posthog_group"."group_properties" ? 'number' - AND NOT (("posthog_group"."group_properties" -> 'number') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_group"."group_properties" -> 'number') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_group" WHERE ("posthog_group"."team_id" = 2 AND "posthog_group"."group_key" = 'foo' @@ -590,9 +590,9 @@ # --- # name: TestFeatureFlagMatcher.test_numeric_operator_with_groups_and_person_flags.3 ''' - SELECT (("posthog_group"."group_properties" -> 'number') > '"100b2c"' + SELECT (("posthog_group"."group_properties" -> 'number') > '"100b2c"'::jsonb AND "posthog_group"."group_properties" ? 'number' - AND NOT (("posthog_group"."group_properties" -> 'number') = 'null')) AS "flag_X_condition_0" + AND NOT (("posthog_group"."group_properties" -> 'number') = 'null'::jsonb)) AS "flag_X_condition_0" FROM "posthog_group" WHERE ("posthog_group"."team_id" = 2 AND "posthog_group"."group_key" = 'foo-project' @@ -601,17 +601,17 @@ # --- # name: TestFeatureFlagMatcher.test_super_condition_matches_string ''' - SELECT ((("posthog_person"."properties" -> 'is_enabled') = 'true' - OR ("posthog_person"."properties" -> 'is_enabled') = '"true"') + SELECT ((("posthog_person"."properties" -> 'is_enabled') = 'true'::jsonb + OR ("posthog_person"."properties" -> 'is_enabled') = '"true"'::jsonb) AND "posthog_person"."properties" ? 'is_enabled' - AND NOT (("posthog_person"."properties" -> 'is_enabled') = 'null')) AS "flag_X_super_condition", ("posthog_person"."properties" -> 'is_enabled') IS NOT NULL AS "flag_X_super_condition_is_set", - (("posthog_person"."properties" -> 'email') = '"fake@posthog.com"' - AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_0", - (("posthog_person"."properties" -> 'email') = '"test@posthog.com"' - AND "posthog_person"."properties" ? 'email' - AND NOT (("posthog_person"."properties" -> 'email') = 'null')) AS "flag_X_condition_1", - (true) AS "flag_X_condition_2" + AND NOT (("posthog_person"."properties" -> 'is_enabled') = 'null'::jsonb)) AS "flag_X_super_condition", ("posthog_person"."properties" -> 'is_enabled') IS NOT NULL AS "flag_X_super_condition_is_set", + (("posthog_person"."properties" -> 'email') = '"fake@posthog.com"'::jsonb + AND "posthog_person"."properties" ? 'email' + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_0", + (("posthog_person"."properties" -> 'email') = '"test@posthog.com"'::jsonb + AND "posthog_person"."properties" ? 'email' + AND NOT (("posthog_person"."properties" -> 'email') = 'null'::jsonb)) AS "flag_X_condition_1", + (true) AS "flag_X_condition_2" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = 'test_id' @@ -748,34 +748,34 @@ # --- # name: TestFeatureFlagMatcher.test_with_sql_injection_properties_and_other_aliases.3 ''' - SELECT (((("posthog_person"."properties" -> 'number space') > '"100"' + SELECT (((("posthog_person"."properties" -> 'number space') > '"100"'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number space')) = ('string')) - OR (("posthog_person"."properties" -> 'number space') > '100.0' + OR (("posthog_person"."properties" -> 'number space') > '100.0'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'number space')) = ('number'))) AND "posthog_person"."properties" ? 'number space' - AND NOT (("posthog_person"."properties" -> 'number space') = 'null') + AND NOT (("posthog_person"."properties" -> 'number space') = 'null'::jsonb) AND ((JSONB_TYPEOF(("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;')) = ('string') - AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '"100"') + AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '"100"'::jsonb) OR (JSONB_TYPEOF(("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;')) = ('number') - AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '100.0')) + AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '100.0'::jsonb)) AND "posthog_person"."properties" ? ';''" SELECT 1; DROP TABLE posthog_featureflag;' - AND NOT (("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') = 'null')) AS "flag_X_condition_0", + AND NOT (("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') = 'null'::jsonb)) AS "flag_X_condition_0", (((JSONB_TYPEOF(("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;')) = ('string') - AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '"100"') + AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '"100"'::jsonb) OR (JSONB_TYPEOF(("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;')) = ('number') - AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '100.0')) + AND ("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') > '100.0'::jsonb)) AND "posthog_person"."properties" ? ';''" SELECT 1; DROP TABLE posthog_featureflag;' - AND NOT (("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') = 'null')) AS "flag_X_condition_1", - (((("posthog_person"."properties" -> 'version!!!') > '"1.05"' + AND NOT (("posthog_person"."properties" -> ';''" SELECT 1; DROP TABLE posthog_featureflag;') = 'null'::jsonb)) AS "flag_X_condition_1", + (((("posthog_person"."properties" -> 'version!!!') > '"1.05"'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'version!!!')) = ('string')) - OR (("posthog_person"."properties" -> 'version!!!') > '1.05' + OR (("posthog_person"."properties" -> 'version!!!') > '1.05'::jsonb AND JSONB_TYPEOF(("posthog_person"."properties" -> 'version!!!')) = ('number'))) AND "posthog_person"."properties" ? 'version!!!' - AND NOT (("posthog_person"."properties" -> 'version!!!') = 'null')) AS "flag_X_condition_2", - ((("posthog_person"."properties" -> 'nested_prop --random #comment //test') = '"21"' - OR ("posthog_person"."properties" -> 'nested_prop --random #comment //test') = '21') + AND NOT (("posthog_person"."properties" -> 'version!!!') = 'null'::jsonb)) AS "flag_X_condition_2", + ((("posthog_person"."properties" -> 'nested_prop --random #comment //test') = '"21"'::jsonb + OR ("posthog_person"."properties" -> 'nested_prop --random #comment //test') = '21'::jsonb) AND "posthog_person"."properties" ? 'nested_prop --random #comment //test' - AND NOT (("posthog_person"."properties" -> 'nested_prop --random #comment //test') = 'null')) AS "flag_X_condition_3" + AND NOT (("posthog_person"."properties" -> 'nested_prop --random #comment //test') = 'null'::jsonb)) AS "flag_X_condition_3" FROM "posthog_person" INNER JOIN "posthog_persondistinctid" ON ("posthog_person"."id" = "posthog_persondistinctid"."person_id") WHERE ("posthog_persondistinctid"."distinct_id" = '307' @@ -821,20 +821,103 @@ ''' # --- # name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.1 ''' SET LOCAL statement_timeout = 2 ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.1 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.10 + ''' + WITH target_person_ids AS + (SELECT team_id, + person_id + FROM posthog_persondistinctid + WHERE team_id = 2 + AND distinct_id = ANY('{other_id,example_id}') ), + existing_overrides AS + (SELECT team_id, + person_id, + feature_flag_key, + hash_key + FROM posthog_featureflaghashkeyoverride + WHERE team_id = 2 + AND person_id IN + (SELECT person_id + FROM target_person_ids) ), + flags_to_override AS + (SELECT key + FROM posthog_featureflag + WHERE team_id = 2 + AND ensure_experience_continuity = TRUE + AND active = TRUE + AND deleted = FALSE + AND key NOT IN + (SELECT feature_flag_key + FROM existing_overrides) ) + INSERT INTO posthog_featureflaghashkeyoverride (team_id, person_id, feature_flag_key, hash_key) + SELECT team_id, + person_id, + key, + 'example_id' + FROM flags_to_override, + target_person_ids + WHERE EXISTS + (SELECT 1 + FROM posthog_person + WHERE id = person_id + AND team_id = 2) ON CONFLICT DO NOTHING + ''' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.11 + 'ROLLBACK' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.12 + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.13 + ''' + + SET LOCAL statement_timeout = 2 + ''' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.14 + ''' + SELECT "posthog_persondistinctid"."person_id", + "posthog_persondistinctid"."distinct_id" + FROM "posthog_persondistinctid" + WHERE ("posthog_persondistinctid"."distinct_id" IN ('other_id', + 'example_id') + AND "posthog_persondistinctid"."team_id" = 2) + ''' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.15 + ''' + SELECT "posthog_featureflaghashkeyoverride"."feature_flag_key", + "posthog_featureflaghashkeyoverride"."hash_key", + "posthog_featureflaghashkeyoverride"."person_id" + FROM "posthog_featureflaghashkeyoverride" + WHERE ("posthog_featureflaghashkeyoverride"."person_id" IN (1, + 2, + 3, + 4, + 5 /* ... */) + AND "posthog_featureflaghashkeyoverride"."team_id" = 2) + ''' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.16 + 'COMMIT' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.2 ''' WITH target_person_ids AS (SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('other_id', - 'example_id') ), + AND distinct_id = ANY('{other_id,example_id}') ), existing_overrides AS (SELECT team_id, person_id, @@ -856,21 +939,26 @@ FROM existing_overrides) ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.2 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.3 + 'COMMIT' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.4 + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.5 ''' SET LOCAL statement_timeout = 2 ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.3 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.6 ''' WITH target_person_ids AS (SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('other_id', - 'example_id') ), + AND distinct_id = ANY('{other_id,example_id}') ), existing_overrides AS (SELECT team_id, person_id, @@ -905,21 +993,35 @@ AND team_id = 2) ON CONFLICT DO NOTHING ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.4 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.7 + 'ROLLBACK' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.8 + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.9 ''' SET LOCAL statement_timeout = 2 ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.5 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.1 + ''' + + SET LOCAL statement_timeout = 2 + ''' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.10 ''' WITH target_person_ids AS (SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('other_id', - 'example_id') ), + AND distinct_id = ANY('{other_id,example_id}') ), existing_overrides AS (SELECT team_id, person_id, @@ -954,13 +1056,19 @@ AND team_id = 2) ON CONFLICT DO NOTHING ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.6 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.11 + 'COMMIT' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.12 + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.13 ''' SET LOCAL statement_timeout = 2 ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.7 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.14 ''' SELECT "posthog_persondistinctid"."person_id", "posthog_persondistinctid"."distinct_id" @@ -970,7 +1078,7 @@ AND "posthog_persondistinctid"."team_id" = 2) ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_error_race_conditions_on_person_merging.8 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.15 ''' SELECT "posthog_featureflaghashkeyoverride"."feature_flag_key", "posthog_featureflaghashkeyoverride"."hash_key", @@ -984,21 +1092,17 @@ AND "posthog_featureflaghashkeyoverride"."team_id" = 2) ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging - ''' - - SET LOCAL statement_timeout = 2 - ''' +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.16 + 'COMMIT' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.1 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.2 ''' WITH target_person_ids AS (SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('other_id', - 'example_id') ), + AND distinct_id = ANY('{other_id,example_id}') ), existing_overrides AS (SELECT team_id, person_id, @@ -1020,70 +1124,26 @@ FROM existing_overrides) ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.2 - ''' - - SET LOCAL statement_timeout = 2 - ''' -# --- # name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.3 - ''' - WITH target_person_ids AS - (SELECT team_id, - person_id - FROM posthog_persondistinctid - WHERE team_id = 2 - AND distinct_id IN ('other_id', - 'example_id') ), - existing_overrides AS - (SELECT team_id, - person_id, - feature_flag_key, - hash_key - FROM posthog_featureflaghashkeyoverride - WHERE team_id = 2 - AND person_id IN - (SELECT person_id - FROM target_person_ids) ), - flags_to_override AS - (SELECT key - FROM posthog_featureflag - WHERE team_id = 2 - AND ensure_experience_continuity = TRUE - AND active = TRUE - AND deleted = FALSE - AND key NOT IN - (SELECT feature_flag_key - FROM existing_overrides) ) - INSERT INTO posthog_featureflaghashkeyoverride (team_id, person_id, feature_flag_key, hash_key) - SELECT team_id, - person_id, - key, - 'example_id' - FROM flags_to_override, - target_person_ids - WHERE EXISTS - (SELECT 1 - FROM posthog_person - WHERE id = person_id - AND team_id = 2) ON CONFLICT DO NOTHING - ''' + 'COMMIT' # --- # name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.4 + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.5 ''' SET LOCAL statement_timeout = 2 ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.5 +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.6 ''' WITH target_person_ids AS (SELECT team_id, person_id FROM posthog_persondistinctid WHERE team_id = 2 - AND distinct_id IN ('other_id', - 'example_id') ), + AND distinct_id = ANY('{other_id,example_id}') ), existing_overrides AS (SELECT team_id, person_id, @@ -1118,33 +1178,15 @@ AND team_id = 2) ON CONFLICT DO NOTHING ''' # --- -# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.6 - ''' - - SET LOCAL statement_timeout = 2 - ''' -# --- # name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.7 - ''' - SELECT "posthog_persondistinctid"."person_id", - "posthog_persondistinctid"."distinct_id" - FROM "posthog_persondistinctid" - WHERE ("posthog_persondistinctid"."distinct_id" IN ('other_id', - 'example_id') - AND "posthog_persondistinctid"."team_id" = 2) - ''' + 'ROLLBACK' # --- # name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.8 + 'BEGIN' +# --- +# name: TestHashKeyOverridesRaceConditions.test_hash_key_overrides_with_simulated_race_conditions_on_person_merging.9 ''' - SELECT "posthog_featureflaghashkeyoverride"."feature_flag_key", - "posthog_featureflaghashkeyoverride"."hash_key", - "posthog_featureflaghashkeyoverride"."person_id" - FROM "posthog_featureflaghashkeyoverride" - WHERE ("posthog_featureflaghashkeyoverride"."person_id" IN (1, - 2, - 3, - 4, - 5 /* ... */) - AND "posthog_featureflaghashkeyoverride"."team_id" = 2) + + SET LOCAL statement_timeout = 2 ''' # --- diff --git a/posthog/test/test_team.py b/posthog/test/test_team.py index 25f73dcfa87a9..c6e9a681b4839 100644 --- a/posthog/test/test_team.py +++ b/posthog/test/test_team.py @@ -138,7 +138,7 @@ def test_team_on_cloud_uses_feature_flag_to_determine_person_on_events(self, moc with self.is_cloud(True): with override_instance_config("PERSON_ON_EVENTS_ENABLED", False): team = Team.objects.create_with_data(organization=self.organization) - self.assertEqual(team.person_on_events_mode, PersonOnEventsMode.V2_ENABLED) + self.assertEqual(team.person_on_events_mode, PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS) # called more than once when evaluating hogql mock_feature_enabled.assert_called_with( "persons-on-events-v2-reads-enabled", @@ -159,7 +159,7 @@ def test_team_on_self_hosted_uses_instance_setting_to_determine_person_on_events with self.is_cloud(False): with override_instance_config("PERSON_ON_EVENTS_V2_ENABLED", True): team = Team.objects.create_with_data(organization=self.organization) - self.assertEqual(team.person_on_events_mode, PersonOnEventsMode.V2_ENABLED) + self.assertEqual(team.person_on_events_mode, PersonOnEventsMode.PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS) mock_feature_enabled.assert_not_called() with override_instance_config("PERSON_ON_EVENTS_V2_ENABLED", False): diff --git a/posthog/utils.py b/posthog/utils.py index baa85c2c6d614..72c8d73d988fd 100644 --- a/posthog/utils.py +++ b/posthog/utils.py @@ -6,6 +6,7 @@ import gzip import hashlib import json +from operator import itemgetter import os import re import secrets @@ -1305,8 +1306,9 @@ def patch(wrapper): class PersonOnEventsMode(str, Enum): DISABLED = "disabled" - V1_ENABLED = "v1_enabled" - V2_ENABLED = "v2_enabled" + PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS = "person_id_no_override_properties_on_events" + PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS = "person_id_override_properties_on_events" + PERSON_ID_OVERRIDE_PROPERTIES_JOINED = "person_id_override_properties_joined" def label_for_team_id_to_track(team_id: int) -> str: @@ -1334,3 +1336,18 @@ def label_for_team_id_to_track(team_id: int) -> str: def camel_to_snake_case(name: str) -> str: return re.sub(r"(?