diff --git a/.dockerignore b/.dockerignore
index 2c26fc9cb0041..79a794a0401f7 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -33,4 +33,4 @@
!plugin-server/.prettierrc
!share/GeoLite2-City.mmdb
!hogvm/python
-!unit.json
\ No newline at end of file
+!unit.json
diff --git a/.github/actions/run-backend-tests/action.yml b/.github/actions/run-backend-tests/action.yml
index 48812f4caf992..87038a52189ad 100644
--- a/.github/actions/run-backend-tests/action.yml
+++ b/.github/actions/run-backend-tests/action.yml
@@ -49,11 +49,17 @@ runs:
python-version: ${{ inputs.python-version }}
token: ${{ inputs.token }}
+ - name: Determine if hogql-parser has changed compared to master
+ shell: bash
+ id: hogql-parser-diff
+ run: |
+ changed=$(git diff --quiet HEAD master -- hogql_parser/ && echo "false" || echo "true")
+ echo "::set-output name=changed::$changed"
+
- name: Install SAML (python3-saml) dependencies
shell: bash
run: |
- sudo apt-get update
- sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
+ sudo apt-get update && sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
- uses: syphar/restore-virtualenv@v1
id: cache-backend-tests
@@ -63,12 +69,37 @@ runs:
- uses: syphar/restore-pip-download-cache@v1
if: steps.cache-backend-tests.outputs.cache-hit != 'true'
- - name: Install python dependencies
+ - name: Install Python dependencies
if: steps.cache-backend-tests.outputs.cache-hit != 'true'
shell: bash
run: |
- python -m pip install -r requirements-dev.txt
- python -m pip install -r requirements.txt
+ pip install -r requirements.txt -r requirements-dev.txt
+
+ - name: Install the working version of hogql-parser
+ if: steps.hogql-parser-diff.outputs.changed == 'true'
+ shell: bash
+ # This is not cached currently, as it's important to build the current HEAD version of hogql-parser if it has
+ # changed (requirements.txt has the already-published version)
+ run: |
+ sudo apt-get install libboost-all-dev unzip cmake curl uuid pkg-config
+ curl https://www.antlr.org/download/antlr4-cpp-runtime-4.13.0-source.zip --output antlr4-source.zip
+ # Check that the downloaded archive is the expected runtime - a security measure
+ anltr_known_md5sum="ff214b65fb02e150b4f515d7983bca92"
+ antlr_found_ms5sum="$(md5sum antlr4-source.zip | cut -d' ' -f1)"
+ if [[ "$anltr_known_md5sum" != "$antlr_found_ms5sum" ]]; then
+ echo "Unexpected MD5 sum of antlr4-source.zip!"
+ echo "Known: $anltr_known_md5sum"
+ echo "Found: $antlr_found_ms5sum"
+ exit 64
+ fi
+ unzip antlr4-source.zip -d antlr4-source && cd antlr4-source
+ cmake .
+ DESTDIR=out make install
+ sudo cp -r out/usr/local/include/antlr4-runtime /usr/include/
+ sudo cp out/usr/local/lib/libantlr4-runtime.so* /usr/lib/
+ sudo ldconfig
+ cd ..
+ pip install ./hogql_parser
- name: Set up needed files
shell: bash
diff --git a/.github/workflows/build-hogql-parser.yml b/.github/workflows/build-hogql-parser.yml
new file mode 100644
index 0000000000000..97cc24fa59abf
--- /dev/null
+++ b/.github/workflows/build-hogql-parser.yml
@@ -0,0 +1,130 @@
+name: Release hogql-parser
+
+on:
+ push:
+ branches:
+ - master
+ paths:
+ - hogql_parser/**
+ - .github/workflows/build-hogql-parser.yml
+ pull_request:
+ paths:
+ - hogql_parser/**
+ - .github/workflows/build-hogql-parser.yml
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ check-version:
+ name: Check version legitimacy
+ runs-on: ubuntu-22.04
+ outputs:
+ parser_any_changed: ${{ steps.changed-files-yaml.outputs.parser_any_changed }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Fetching all for comparison since last push (not just last commit)
+
+ - name: Check if hogql_parser/ has changed
+ id: changed-files-yaml
+ uses: tj-actions/changed-files@v39
+ with:
+ since_last_remote_commit: true
+ files_yaml: |
+ parser:
+ - hogql_parser/**
+
+ - name: Notify about release needed
+ if: steps.changed-files-yaml.outputs.parser_any_changed == 'true'
+ shell: bash
+ run: |
+ published=$(curl -fSsl https://pypi.org/pypi/hogql-parser/json | jq -r '.info.version')
+ local=$(python hogql_parser/setup.py --version)
+ # TODO: Only comment if no comment alraedy exists for $local
+ if [[ "$published" == "$local" ]]; then
+ MESSAGE_BODY="It looks like the code of `hogql-parser` has changed since last push, but its version stayed the same at $local. 👀\nMake sure to resolve this in `hogql_parser/setup.py` before merging!"
+ curl -s -u posthog-bot:${{ secrets.POSTHOG_BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} -X POST -d "{ \"body\": \"$MESSAGE_BODY\" }" "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments"
+ fi
+
+ build-wheels:
+ name: Build wheels on ${{ matrix.os }}
+ needs: check-version
+ runs-on: ${{ matrix.os }}
+ timeout-minutes: 30
+ if: ${{ needs.check-version.outputs.parser_any_changed == 'true' }}
+ strategy:
+ matrix:
+ # As of October 2023, GitHub doesn't have ARM Actions runners… and ARM emulation is insanely slow
+ # (20x longer) on the Linux runners (while being reasonable on the macOS runners). Hence, we use
+ # BuildJet as a provider of ARM runners - this solution saves a lot of time and consequently some money.
+ os: [ubuntu-22.04, buildjet-2vcpu-ubuntu-2204-arm, macos-12]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - if: ${{ !endsWith(matrix.os, '-arm') }}
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.11'
+
+ - if: ${{ endsWith(matrix.os, '-arm') }}
+ uses: deadsnakes/action@v3.0.1 # Unfortunately actions/setup-python@v4 just doesn't work on ARM! This does
+ with:
+ python-version: '3.11'
+
+ - name: Build sdist
+ if: matrix.os == 'ubuntu-22.04' # Only build the sdist once
+ run: cd hogql_parser && python setup.py sdist
+
+ - name: Install cibuildwheel
+ run: python -m pip install cibuildwheel==2.16.*
+
+ - name: Build wheels
+ run: cd hogql_parser && python -m cibuildwheel --output-dir dist
+ env:
+ MACOSX_DEPLOYMENT_TARGET: '12' # A modern target allows us to use C++20
+
+ - uses: actions/upload-artifact@v3
+ with:
+ path: |
+ hogql_parser/dist/*.whl
+ hogql_parser/dist/*.tar.gz
+ if-no-files-found: error
+
+ publish:
+ name: Publish on PyPI
+ needs: build-wheels
+ environment: pypi-hogql-parser
+ permissions:
+ id-token: write
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Fetch wheels
+ uses: actions/download-artifact@v3
+ with:
+ name: artifact
+ path: dist/
+
+ - name: Publish package to PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+
+ - uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
+ ref: ${{ github.event.pull_request.head.ref }}
+
+ - name: Update hogql-parser in requirements
+ shell: bash
+ run: |
+ local=$(python hogql_parser/setup.py --version)
+ sed -i "s/hogql-parser==.*/hogql-parser==${local}/g" requirements.in
+ sed -i "s/hogql-parser==.*/hogql-parser==${local}/g" requirements.txt
+
+ - uses: EndBug/add-and-commit@v9
+ with:
+ add: '["requirements.in", "requirements.txt"]'
+ message: 'Use new hogql-parser version'
+ default_author: github_actions
+ github_token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
diff --git a/.github/workflows/ci-backend.yml b/.github/workflows/ci-backend.yml
index 5a74f81d849d0..198d41c25c117 100644
--- a/.github/workflows/ci-backend.yml
+++ b/.github/workflows/ci-backend.yml
@@ -98,7 +98,6 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 1
- path: 'current/'
- name: Set up Python
uses: actions/setup-python@v4
@@ -119,38 +118,30 @@ jobs:
sudo apt-get update
sudo apt-get install libxml2-dev libxmlsec1 libxmlsec1-dev libxmlsec1-openssl
- - name: Install python dependencies
+ - name: Install Python dependencies
if: steps.cache-backend-tests.outputs.cache-hit != 'true'
run: |
- cd current
python -m pip install -r requirements.txt -r requirements-dev.txt
- name: Check for syntax errors, import sort, and code style violations
run: |
- cd current
ruff .
- name: Check formatting
run: |
- cd current
black --exclude posthog/hogql/grammar --check .
- name: Check static typing
run: |
- cd current
mypy -p posthog --exclude bin/migrate_kafka_data.py --exclude posthog/hogql/grammar/HogQLParser.py --exclude gunicorn.config.py --enable-recursive-aliases
- name: Check if "schema.py" is up to date
run: |
- cd current
npm run schema:build:python && git diff --exit-code
- - name: Check if antlr definitions are up to date
+ - name: Check if ANTLR definitions are up to date
run: |
- # Installing a version of ant compatible with what we use in development from homebrew (4.13)
- # "apt-get install antlr" would install 4.7 which is incompatible with our grammar.
- export ANTLR_VERSION=4.13.0
- # java version doesn't matter
+ cd ..
sudo apt-get install default-jre
mkdir antlr
cd antlr
@@ -162,9 +153,13 @@ jobs:
export CLASSPATH=".:$PWD/antlr.jar:$CLASSPATH"
export PATH="$PWD:$PATH"
- cd ../current
+ cd ../posthog
antlr | grep "Version"
npm run grammar:build && git diff --exit-code
+ env:
+ # Installing a version of ANTLR compatible with what's in Homebrew as of October 2023 (version 4.13),
+ # as apt-get is quite out of date. The same version must be set in hogql_parser/pyproject.toml
+ ANTLR_VERSION: '4.13.0'
check-migrations:
needs: changes
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6282e516bf862..497b5f7fca0bf 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -96,6 +96,31 @@
"console": "integratedTerminal",
"python": "${workspaceFolder}/env/bin/python",
"cwd": "${workspaceFolder}"
+ },
+ {
+ "name": "Pytest: Current File",
+ "type": "python",
+ "request": "launch",
+ "module": "pytest",
+ "args": ["${file}", "-vvv"],
+ "console": "integratedTerminal",
+ "justMyCode": true
+ },
+ {
+ "name": "(lldb) Attach",
+ "type": "cppdbg",
+ "request": "attach",
+ "program": "/Users/twixes/.pyenv/versions/3.10.10/envs/posthog-3.10/bin/python",
+ "MIMode": "lldb"
+ },
+ {
+ "name": "Python C++ Debugger: Current File",
+ "type": "pythoncpp",
+ "request": "launch",
+ "pythonConfig": "custom",
+ "pythonLaunchName": "Pytest: Current File",
+ "cppConfig": "custom",
+ "cppAttachName": "(lldb) Attach"
}
],
"compounds": [
diff --git a/cypress/e2e/early-access-management.cy.ts b/cypress/e2e/early-access-management.cy.ts
new file mode 100644
index 0000000000000..9a594d8d1c34c
--- /dev/null
+++ b/cypress/e2e/early-access-management.cy.ts
@@ -0,0 +1,55 @@
+describe('Early Access Management', () => {
+ beforeEach(() => {
+ cy.visit('/early_access_features')
+ })
+
+ it('Early access feature new and list', () => {
+ // load an empty early access feature page
+ cy.get('h1').should('contain', 'Early Access Management')
+ cy.title().should('equal', 'Early Access Management • PostHog')
+ cy.get('h2').should('contain', 'Create your first feature')
+ cy.get('[data-attr="product-introduction-docs-link"]').should(
+ 'contain',
+ 'Learn more about Early access features'
+ )
+
+ // go to create a new feature
+ cy.get('[data-attr="create-feature"]').click()
+
+ // New Feature Release page
+ cy.get('h1').should('contain', 'New Feature Release')
+
+ // cancel new feature
+ cy.get('[data-attr="cancel-feature"]').click()
+ cy.get('h1').should('contain', 'Early Access Management')
+
+ // set feature name & description
+ cy.get('[data-attr="create-feature"]').click()
+ cy.get('[data-attr="feature-name"]').type('Test Feature')
+ cy.get('[data-attr="save-feature').should('contain.text', 'Save as draft')
+
+ // save
+ cy.get('[data-attr="save-feature"]').click()
+ cy.get('[data-attr=success-toast]').contains('Early Access Feature saved').should('exist')
+
+ // back to features
+ cy.visit('/early_access_features')
+ cy.get('tbody').contains('Test Feature')
+ cy.get('h2').should('not.have.text', 'Create your first feature')
+
+ // edit feature
+ cy.get('a.Link').contains('.row-name', 'Test Feature').click()
+ cy.get('[data-attr="edit-feature"]').click()
+ cy.get('h1').should('contain', 'Test Feature')
+ cy.get('[data-attr="save-feature"]').should('contain.text', 'Save')
+
+ // delete feature
+ cy.get('[data-attr="save-feature"]').click()
+ cy.get('[data-attr="delete-feature"]').click()
+ cy.get('h3').should('contain', 'Permanently delete feature?')
+ cy.get('[data-attr="confirm-delete-feature"]').click()
+ cy.get('[data-attr=info-toast]')
+ .contains('Early access feature deleted. Remember to delete corresponding feature flag if necessary')
+ .should('exist')
+ })
+})
diff --git a/cypress/e2e/insights-unsaved-confirmation.cy.ts b/cypress/e2e/insights-unsaved-confirmation.cy.ts
index 023b2a7ef7f74..6257fc264e20f 100644
--- a/cypress/e2e/insights-unsaved-confirmation.cy.ts
+++ b/cypress/e2e/insights-unsaved-confirmation.cy.ts
@@ -1,4 +1,3 @@
-import { urls } from 'scenes/urls'
import { randomString } from '../support/random'
import { decideResponse } from '../fixtures/api/decide'
import { insight } from '../productAnalytics'
@@ -20,7 +19,10 @@ describe('Insights', () => {
return true
})
- cy.visit(urls.insightNew())
+ cy.visit('/insights')
+ cy.wait('@getInsights').then(() => {
+ cy.get('.saved-insights tr').should('exist')
+ })
})
describe('unsaved insights confirmation', () => {
diff --git a/cypress/e2e/surveys.cy.ts b/cypress/e2e/surveys.cy.ts
new file mode 100644
index 0000000000000..ad6e45ff3201a
--- /dev/null
+++ b/cypress/e2e/surveys.cy.ts
@@ -0,0 +1,192 @@
+describe('Surveys', () => {
+ let name
+
+ beforeEach(() => {
+ name = 'survey-' + Math.floor(Math.random() * 10000000)
+ cy.clickNavMenu('surveys')
+ })
+
+ it('shows get started state on first load', () => {
+ // load an empty page
+ cy.get('h1').should('contain', 'Surveys')
+ cy.title().should('equal', 'Surveys • PostHog')
+
+ cy.get('h2').should('contain', 'Create your first survey')
+
+ // go to create a new survey
+ cy.get('[data-attr="create-survey"]').click()
+
+ cy.get('[data-attr="survey-name"]').type(name)
+
+ // save
+ cy.get('[data-attr="save-survey"]').click()
+ cy.get('[data-attr=success-toast]').contains('created').should('exist')
+
+ // back to surveys
+ cy.clickNavMenu('surveys')
+ cy.get('[data-attr=surveys-table]').should('contain', name)
+ cy.get('h2').should('not.have.text', 'Create your first survey')
+
+ // back into survey
+ cy.get(`[data-row-key="${name}"]`).contains(name).click()
+
+ // delete survey
+ cy.get('[data-attr="more-button"]').click()
+ cy.get('.Popover__content').contains('Delete').click()
+ cy.clickNavMenu('surveys')
+
+ cy.get('tbody').should('not.exist')
+ })
+
+ it('shows survey disabled banner when surveys disabled', () => {
+ cy.get('div.LemonBanner.LemonBanner--warning.mb-2').should(
+ 'contain',
+ 'Survey popups are currently disabled for this project'
+ )
+ cy.get('div.LemonBanner.LemonBanner--warning.mb-2').contains('Configure').click()
+
+ cy.contains('Surveys settings').should('exist').should('be.visible')
+
+ cy.get('[data-attr="opt-in-surveys-switch"]').click()
+
+ cy.get('[data-attr=success-toast]').contains('Surveys opt in').should('exist')
+
+ cy.contains('Done').click()
+
+ // now lemon banner should be gone
+ cy.get('div.LemonBanner.LemonBanner--warning.mb-2').should('not.exist')
+
+ // get it back
+ cy.contains('Configure').click()
+ cy.get('[data-attr="opt-in-surveys-switch"]').click()
+ cy.get('[data-attr=success-toast]').contains('Surveys opt in').should('exist')
+ cy.contains('Done').click()
+
+ // now lemon banner should be back
+ cy.get('div.LemonBanner.LemonBanner--warning.mb-2').should(
+ 'contain',
+ 'Survey popups are currently disabled for this project'
+ )
+ })
+
+ it('creates a new survey', () => {
+ // load an empty page
+ cy.get('h1').should('contain', 'Surveys')
+ cy.title().should('equal', 'Surveys • PostHog')
+
+ // click via top right button
+ cy.get('[data-attr="new-survey"]').click()
+
+ // select "add filter" and "property"
+ cy.get('[data-attr="survey-name"]').type(name)
+ cy.get('[data-attr="survey-question-type-0"]').click()
+ cy.contains('Rating').click()
+
+ // should pre-fill the question based on template
+ cy.get('[id="scenes.surveys.surveyLogic.new.survey.questions.0.question"]').should(
+ 'include.value',
+ 'How likely are you to recommend'
+ )
+
+ cy.get('[id="scenes.surveys.surveyLogic.new.survey.questions.0.scale"]')
+ .invoke('html')
+ .should('include', '1 - 10')
+
+ cy.get('[id="scenes.surveys.surveyLogic.new.survey.questions.0.upperBoundLabel"]').should(
+ 'have.value',
+ 'Very likely'
+ )
+
+ // change the scale
+ cy.get('[id="scenes.surveys.surveyLogic.new.survey.questions.0.scale"]').click()
+ cy.contains('1 - 5').click()
+
+ cy.get('[id="scenes.surveys.surveyLogic.new.survey.questions.0.scale"]')
+ .invoke('html')
+ .should('include', '1 - 5')
+
+ // make sure the preview is updated
+ cy.get('[data-attr="survey-preview"]')
+ .find('form')
+ .should('contain', 'How likely are you to recommend us to a friend?')
+ .should('contain', 'Unlikely')
+ .should('contain', 'Very likely')
+ cy.get('[data-attr="survey-preview"]').find('form').find('.ratings-number').should('have.length', 5)
+
+ // add targeting filters
+ cy.contains('Add user targeting').click()
+
+ // select the first property
+ cy.get('[data-attr="property-select-toggle-0"]').click()
+ cy.get('[data-attr="prop-filter-person_properties-0"]').click()
+ cy.get('[data-attr=prop-val] .ant-select-selector').click({ force: true })
+ cy.get('[data-attr=prop-val-0]').click({ force: true })
+
+ cy.get('.ant-input-number-input-wrap>input').type('{backspace}')
+
+ // save
+ cy.get('[data-attr="save-survey"]').click()
+ cy.get('[data-attr=success-toast]').contains('created').should('exist')
+
+ // check preview release conditions
+ cy.contains('Release conditions summary').should('exist')
+ cy.get('.FeatureConditionCard').should('exist').should('contain.text', 'is_demo equals true')
+ cy.get('.FeatureConditionCard').should('contain.text', 'Rolled out to 100% of users in this set.')
+
+ // launch survey
+ cy.get('[data-attr="launch-survey"]').click()
+
+ // refresh, see survey show up on page
+ cy.reload()
+
+ cy.contains('Unique users viewed').should('exist')
+
+ // stop survey
+ cy.contains('Stop').click()
+
+ // back to surveys
+ cy.clickNavMenu('surveys')
+ cy.get('[data-attr=surveys-table]').should('contain', name)
+
+ // back into survey
+ cy.get(`[data-row-key="${name}"]`).contains(name).click()
+
+ // edit
+ cy.get('[data-attr="more-button"]').click()
+ cy.get('.Popover__content').contains('Edit').click()
+
+ // remove user targeting properties
+ cy.contains('Remove all user properties').click()
+
+ // save
+ cy.get('[data-attr="save-survey"]').click()
+
+ // check preview release conditions
+ cy.get('.LemonTabs').contains('Overview').click()
+ cy.contains('Release conditions summary').should('exist')
+ cy.get('.FeatureConditionCard').should('not.exist')
+
+ // delete survey
+ cy.get('[data-attr="more-button"]').click()
+ cy.get('.Popover__content').contains('Delete').click()
+ cy.clickNavMenu('surveys')
+ cy.get('tbody').should('not.exist')
+ })
+
+ it('Delete survey', () => {
+ cy.get('h1').should('contain', 'Surveys')
+ cy.get('[data-attr=new-survey]').click()
+ cy.get('[data-attr=survey-name]').focus().type(name).should('have.value', name)
+ cy.get('[data-attr=save-survey]').first().click()
+
+ // after save there should be a launch button
+ cy.get('button[data-attr="launch-survey"]').should('have.text', 'Launch')
+
+ cy.clickNavMenu('surveys')
+ cy.get('[data-attr=surveys-table]').should('contain', name)
+ cy.get(`[data-row-key=${name}]`).contains(name).click()
+ cy.get('[data-attr=more-button]').click()
+ cy.get('[data-attr=delete-survey]').click()
+ cy.get('.Toastify__toast-body').contains('Survey deleted').should('be.visible')
+ })
+})
diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts
index 02170cf711177..f3de742cdb817 100644
--- a/cypress/support/e2e.ts
+++ b/cypress/support/e2e.ts
@@ -30,6 +30,7 @@ beforeEach(() => {
decideResponse({
// set feature flags here e.g.
// 'toolbar-launch-side-action': true,
+ 'surveys-results-visualizations': true,
'auto-redirect': true,
notebooks: true,
})
diff --git a/ee/clickhouse/queries/test/__snapshots__/test_lifecycle.ambr b/ee/clickhouse/queries/test/__snapshots__/test_lifecycle.ambr
index 249b940160578..29eb93b4ae929 100644
--- a/ee/clickhouse/queries/test/__snapshots__/test_lifecycle.ambr
+++ b/ee/clickhouse/queries/test/__snapshots__/test_lifecycle.ambr
@@ -501,7 +501,7 @@
AND event = '$pageview'
AND timestamp >= toDateTime(dateTrunc('day', toDateTime('2021-04-28 00:00:00', 'UTC'))) - INTERVAL 1 day
AND timestamp < toDateTime(dateTrunc('day', toDateTime('2021-05-05 23:59:59', 'UTC'))) + INTERVAL 1 day
- AND (like(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person_props, 'email'), ''), 'null'), '^"|"$', ''), '%test.com'))
+ AND (like(replaceRegexpAll(nullIf(nullIf(JSONExtractRaw(person_properties, 'email'), ''), 'null'), '^"|"$', ''), '%test.com'))
GROUP BY pdi.person_id)
GROUP BY start_of_period,
status)
@@ -576,7 +576,7 @@
AND event = '$pageview'
AND timestamp >= toDateTime(dateTrunc('day', toDateTime('2021-04-28 00:00:00', 'UTC'))) - INTERVAL 1 day
AND timestamp < toDateTime(dateTrunc('day', toDateTime('2021-05-05 23:59:59', 'UTC'))) + INTERVAL 1 day
- AND (like(nullIf(nullIf(pmat_email, ''), 'null'), '%test.com'))
+ AND (like(nullIf(nullIf(mat_pp_email, ''), 'null'), '%test.com'))
GROUP BY pdi.person_id)
GROUP BY start_of_period,
status)
diff --git a/frontend/__snapshots__/components-not-found--not-found.png b/frontend/__snapshots__/components-not-found--not-found.png
index f456cf74ed622..21dff8ace1435 100644
Binary files a/frontend/__snapshots__/components-not-found--not-found.png and b/frontend/__snapshots__/components-not-found--not-found.png differ
diff --git a/frontend/__snapshots__/filters-action-filter--bordered.png b/frontend/__snapshots__/filters-action-filter--bordered.png
index 8c563c33a451b..1db6d879c8ff4 100644
Binary files a/frontend/__snapshots__/filters-action-filter--bordered.png and b/frontend/__snapshots__/filters-action-filter--bordered.png differ
diff --git a/frontend/__snapshots__/filters-action-filter--funnel-like.png b/frontend/__snapshots__/filters-action-filter--funnel-like.png
index 7dc3c323eea7b..e24f6e531e276 100644
Binary files a/frontend/__snapshots__/filters-action-filter--funnel-like.png and b/frontend/__snapshots__/filters-action-filter--funnel-like.png differ
diff --git a/frontend/__snapshots__/filters-action-filter--property-filters-with-popover.png b/frontend/__snapshots__/filters-action-filter--property-filters-with-popover.png
index 5b009d401dda5..6c2032bab9115 100644
Binary files a/frontend/__snapshots__/filters-action-filter--property-filters-with-popover.png and b/frontend/__snapshots__/filters-action-filter--property-filters-with-popover.png differ
diff --git a/frontend/__snapshots__/filters-action-filter--single-filter.png b/frontend/__snapshots__/filters-action-filter--single-filter.png
index e59fed9c418b9..40f774a796548 100644
Binary files a/frontend/__snapshots__/filters-action-filter--single-filter.png and b/frontend/__snapshots__/filters-action-filter--single-filter.png differ
diff --git a/frontend/__snapshots__/filters-action-filter--sortable.png b/frontend/__snapshots__/filters-action-filter--sortable.png
index 5b009d401dda5..6c2032bab9115 100644
Binary files a/frontend/__snapshots__/filters-action-filter--sortable.png and b/frontend/__snapshots__/filters-action-filter--sortable.png differ
diff --git a/frontend/__snapshots__/filters-action-filter--standard.png b/frontend/__snapshots__/filters-action-filter--standard.png
index 5b009d401dda5..6c2032bab9115 100644
Binary files a/frontend/__snapshots__/filters-action-filter--standard.png and b/frontend/__snapshots__/filters-action-filter--standard.png differ
diff --git a/frontend/__snapshots__/lemon-ui-icons--shelf-n.png b/frontend/__snapshots__/lemon-ui-icons--shelf-n.png
index 9a82995334fba..f8c31c3cf2ee5 100644
Binary files a/frontend/__snapshots__/lemon-ui-icons--shelf-n.png and b/frontend/__snapshots__/lemon-ui-icons--shelf-n.png differ
diff --git a/frontend/__snapshots__/scenes-app-experiments--experiment-not-found.png b/frontend/__snapshots__/scenes-app-experiments--experiment-not-found.png
index 770fd04035f09..3332b4e9b583f 100644
Binary files a/frontend/__snapshots__/scenes-app-experiments--experiment-not-found.png and b/frontend/__snapshots__/scenes-app-experiments--experiment-not-found.png differ
diff --git a/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png b/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png
index 7e96b5125fdab..36ad5c81084e2 100644
Binary files a/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png and b/frontend/__snapshots__/scenes-app-experiments--experiments-list-pay-gate.png differ
diff --git a/frontend/__snapshots__/scenes-app-experiments--experiments-list.png b/frontend/__snapshots__/scenes-app-experiments--experiments-list.png
index 5a3d3dd285231..35578f8df9b47 100644
Binary files a/frontend/__snapshots__/scenes-app-experiments--experiments-list.png and b/frontend/__snapshots__/scenes-app-experiments--experiments-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-experiments--view-experiment-pay-gate.png b/frontend/__snapshots__/scenes-app-experiments--view-experiment-pay-gate.png
index 520840cd0f18a..dbfa94be817be 100644
Binary files a/frontend/__snapshots__/scenes-app-experiments--view-experiment-pay-gate.png and b/frontend/__snapshots__/scenes-app-experiments--view-experiment-pay-gate.png differ
diff --git a/frontend/__snapshots__/scenes-app-feature-flags--feature-flag-not-found.png b/frontend/__snapshots__/scenes-app-feature-flags--feature-flag-not-found.png
index 4455d9ad6aa26..3848b31fa78a8 100644
Binary files a/frontend/__snapshots__/scenes-app-feature-flags--feature-flag-not-found.png and b/frontend/__snapshots__/scenes-app-feature-flags--feature-flag-not-found.png differ
diff --git a/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png b/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png
index a30dc1ed64cb0..6231ed9ab28e7 100644
Binary files a/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png and b/frontend/__snapshots__/scenes-app-feature-flags--feature-flags-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-feature-flags--new-feature-flag.png b/frontend/__snapshots__/scenes-app-feature-flags--new-feature-flag.png
index ea0fcd95872d9..c640e778e8505 100644
Binary files a/frontend/__snapshots__/scenes-app-feature-flags--new-feature-flag.png and b/frontend/__snapshots__/scenes-app-feature-flags--new-feature-flag.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-historical-trends.png b/frontend/__snapshots__/scenes-app-insights--funnel-historical-trends.png
index a0bef56dc2724..e7ae0a9602d9c 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--funnel-historical-trends.png and b/frontend/__snapshots__/scenes-app-insights--funnel-historical-trends.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--funnel-time-to-convert.png b/frontend/__snapshots__/scenes-app-insights--funnel-time-to-convert.png
index 97187756246b5..d3c5a1c7e9457 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--funnel-time-to-convert.png and b/frontend/__snapshots__/scenes-app-insights--funnel-time-to-convert.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--lifecycle.png b/frontend/__snapshots__/scenes-app-insights--lifecycle.png
index 0f5f19aac9013..738d5ec8994c5 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--lifecycle.png and b/frontend/__snapshots__/scenes-app-insights--lifecycle.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--stickiness.png b/frontend/__snapshots__/scenes-app-insights--stickiness.png
index 1f58fbc9b518b..8a6be5ba22fdc 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--stickiness.png and b/frontend/__snapshots__/scenes-app-insights--stickiness.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--trends-number.png b/frontend/__snapshots__/scenes-app-insights--trends-number.png
index 5e11ddb074351..932161c2835e5 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--trends-number.png and b/frontend/__snapshots__/scenes-app-insights--trends-number.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png b/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png
index 60eb90e01d46e..fb9e049372866 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png and b/frontend/__snapshots__/scenes-app-insights--trends-table-breakdown.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--trends-table-edit.png b/frontend/__snapshots__/scenes-app-insights--trends-table-edit.png
index 35e186b20d96c..b7e8cedbda6c6 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--trends-table-edit.png and b/frontend/__snapshots__/scenes-app-insights--trends-table-edit.png differ
diff --git a/frontend/__snapshots__/scenes-app-insights--trends-table.png b/frontend/__snapshots__/scenes-app-insights--trends-table.png
index 1e44c590b7ab1..53b2b12ca2cf5 100644
Binary files a/frontend/__snapshots__/scenes-app-insights--trends-table.png and b/frontend/__snapshots__/scenes-app-insights--trends-table.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--bullet-list.png b/frontend/__snapshots__/scenes-app-notebooks--bullet-list.png
index 815c9affb5153..34247b0185eb5 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--bullet-list.png and b/frontend/__snapshots__/scenes-app-notebooks--bullet-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--empty-notebook.png b/frontend/__snapshots__/scenes-app-notebooks--empty-notebook.png
index c14e260cd137b..f87bfdaef347b 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--empty-notebook.png and b/frontend/__snapshots__/scenes-app-notebooks--empty-notebook.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--headings.png b/frontend/__snapshots__/scenes-app-notebooks--headings.png
index eb890f7ef2025..9ff9e7d7d0bfc 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--headings.png and b/frontend/__snapshots__/scenes-app-notebooks--headings.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png b/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png
index 41cd092223d0b..2f437cf858fb4 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png and b/frontend/__snapshots__/scenes-app-notebooks--notebook-not-found.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png b/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png
index 29840a3cd8ae5..d5a4c1ace9fd6 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png and b/frontend/__snapshots__/scenes-app-notebooks--notebooks-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--numbered-list.png b/frontend/__snapshots__/scenes-app-notebooks--numbered-list.png
index 070e8df9913bc..1346ab080a48f 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--numbered-list.png and b/frontend/__snapshots__/scenes-app-notebooks--numbered-list.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png b/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png
index 7d63a60ab61a0..73e674b602ceb 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png and b/frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--text-formats.png b/frontend/__snapshots__/scenes-app-notebooks--text-formats.png
index bd3592454d431..3c2128dd71e8c 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--text-formats.png and b/frontend/__snapshots__/scenes-app-notebooks--text-formats.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks--text-only-notebook.png b/frontend/__snapshots__/scenes-app-notebooks--text-only-notebook.png
index 940a069cdde81..74e3f0f71f7f3 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks--text-only-notebook.png and b/frontend/__snapshots__/scenes-app-notebooks--text-only-notebook.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--default.png b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--default.png
index ca05fd2fff918..1de7efd118dc3 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--default.png and b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--default.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks.png b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks.png
index 17c750c0c42d7..28b598fae1d26 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks.png and b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-existing-containing-notebooks.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-notebooks.png b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-notebooks.png
index ca05fd2fff918..1de7efd118dc3 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-notebooks.png and b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-no-notebooks.png differ
diff --git a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-slow-network-response.png b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-slow-network-response.png
index 2e25a8113f1d1..b1029c69736a8 100644
Binary files a/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-slow-network-response.png and b/frontend/__snapshots__/scenes-app-notebooks-components-notebook-select-button--with-slow-network-response.png differ
diff --git a/frontend/__snapshots__/scenes-app-surveys--new-survey.png b/frontend/__snapshots__/scenes-app-surveys--new-survey.png
index 9033d58fe25e7..95162d2315a21 100644
Binary files a/frontend/__snapshots__/scenes-app-surveys--new-survey.png and b/frontend/__snapshots__/scenes-app-surveys--new-survey.png differ
diff --git a/frontend/__snapshots__/scenes-app-surveys--survey-not-found.png b/frontend/__snapshots__/scenes-app-surveys--survey-not-found.png
index f0a3188f10cbd..a19faf8440760 100644
Binary files a/frontend/__snapshots__/scenes-app-surveys--survey-not-found.png and b/frontend/__snapshots__/scenes-app-surveys--survey-not-found.png differ
diff --git a/frontend/__snapshots__/scenes-app-surveys--survey-view.png b/frontend/__snapshots__/scenes-app-surveys--survey-view.png
index 4fd6630f9ddd5..ed047d62e2ddd 100644
Binary files a/frontend/__snapshots__/scenes-app-surveys--survey-view.png and b/frontend/__snapshots__/scenes-app-surveys--survey-view.png differ
diff --git a/frontend/__snapshots__/scenes-app-surveys--surveys-list.png b/frontend/__snapshots__/scenes-app-surveys--surveys-list.png
index 40a6821eca9ba..f39a5614cf0dd 100644
Binary files a/frontend/__snapshots__/scenes-app-surveys--surveys-list.png and b/frontend/__snapshots__/scenes-app-surveys--surveys-list.png differ
diff --git a/frontend/src/lib/components/NotFound/NotFound.scss b/frontend/src/lib/components/NotFound/NotFound.scss
index 0b5494fce1ba8..d9a3d97ced82f 100644
--- a/frontend/src/lib/components/NotFound/NotFound.scss
+++ b/frontend/src/lib/components/NotFound/NotFound.scss
@@ -9,4 +9,16 @@
height: 270px;
width: 100%;
}
+
+ .NotebookNode & {
+ background-color: var(--danger-highlight);
+ margin: 0;
+ max-width: 100%;
+ padding: 2rem;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ }
}
diff --git a/frontend/src/lib/components/NotFound/index.tsx b/frontend/src/lib/components/NotFound/index.tsx
index 5156adc4812fe..1c1a20c595925 100644
--- a/frontend/src/lib/components/NotFound/index.tsx
+++ b/frontend/src/lib/components/NotFound/index.tsx
@@ -4,6 +4,8 @@ import './NotFound.scss'
import { useActions, useValues } from 'kea'
import { supportLogic } from '../Support/supportLogic'
import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic'
+import { useNotebookNode } from 'scenes/notebooks/Nodes/notebookNodeLogic'
+import { LemonButton } from '@posthog/lemon-ui'
interface NotFoundProps {
object: string // Type of object that was not found (e.g. `dashboard`, `insight`, `action`, ...)
@@ -14,13 +16,18 @@ export function NotFound({ object, caption }: NotFoundProps): JSX.Element {
const { preflight } = useValues(preflightLogic)
const { openSupportForm } = useActions(supportLogic)
+ const nodeLogic = useNotebookNode()
+
return (
-
+ {!nodeLogic ?
: null}
{capitalizeFirstLetter(object)} not found
-
- It seems this page may have been lost in space.
-
+ {!nodeLogic ? (
+
+ It seems this {object} may have been lost in space.
+
+ ) : null}
+
{caption || (
<>
@@ -36,6 +43,13 @@ export function NotFound({ object, caption }: NotFoundProps): JSX.Element {
>
)}
+
+ {nodeLogic && (
+ nodeLogic.actions.deleteNode()}>
+ Remove from Notebook
+
+ )}
+
)
}
diff --git a/frontend/src/lib/lemon-ui/LemonWidget/LemonWidget.tsx b/frontend/src/lib/lemon-ui/LemonWidget/LemonWidget.tsx
index 290e6717c1971..232a68b23fd12 100644
--- a/frontend/src/lib/lemon-ui/LemonWidget/LemonWidget.tsx
+++ b/frontend/src/lib/lemon-ui/LemonWidget/LemonWidget.tsx
@@ -15,7 +15,7 @@ export function LemonWidget({ title, onClose, actions, children, className }: Le
return (
- {title}
+ {title}
{actions}
{onClose && } />}
diff --git a/frontend/src/lib/utils.tsx b/frontend/src/lib/utils.tsx
index adaddb869ecdd..1df911788009a 100644
--- a/frontend/src/lib/utils.tsx
+++ b/frontend/src/lib/utils.tsx
@@ -1583,6 +1583,26 @@ export function isNumeric(x: any): boolean {
return !isNaN(Number(x)) && !isNaN(parseFloat(x))
}
+/**
+ * Check if the argument is nullish (null or undefined).
+ *
+ * Useful as a typeguard, e.g. when passed to Array.filter()
+ *
+ * @example
+ * const myList = [1, 2, null]; // type is (number | null)[]
+ *
+ * // using isNotNil
+ * const myFilteredList1 = myList.filter(isNotNil) // type is number[]
+ * const squaredList1 = myFilteredList1.map(x => x * x) // not a type error!
+ *
+ * // compared to:
+ * const myFilteredList2 = myList.filter(x => x != null) // type is (number | null)[]
+ * const squaredList2 = myFilteredList2.map(x => x * x) // Type Error: TS18047: x is possibly null
+ */
+export function isNotNil(arg: T): arg is Exclude {
+ return arg !== null && arg !== undefined
+}
+
export function calculateDays(timeValue: number, timeUnit: TimeUnitType): number {
if (timeUnit === TimeUnitType.Year) {
return timeValue * 365
diff --git a/frontend/src/queries/nodes/DataTable/renderColumn.tsx b/frontend/src/queries/nodes/DataTable/renderColumn.tsx
index f502ec138cd74..422fc0934da03 100644
--- a/frontend/src/queries/nodes/DataTable/renderColumn.tsx
+++ b/frontend/src/queries/nodes/DataTable/renderColumn.tsx
@@ -227,8 +227,9 @@ export function renderColumn(
const personRecord = record as PersonType
return
} else if (key.startsWith('context.columns.')) {
- const Component = context?.columns?.[trimQuotes(key.substring(16))]?.render
- return Component ? : ''
+ const columnName = trimQuotes(key.substring(16)) // 16 = "context.columns.".length
+ const Component = context?.columns?.[columnName]?.render
+ return Component ? : ''
} else if (key === 'id' && (isPersonsNode(query.source) || isPersonsQuery(query.source))) {
return (
}
+/** HogQL Query Options are automatically set per team. However, they can be overriden in the query. */
+export interface HogQLQueryModifiers {
+ personsOnEventsMode?: 'disabled' | 'v1_enabled' | 'v2_enabled'
+ personsArgMaxVersion?: 'auto' | 'v1' | 'v2'
+}
+
export interface HogQLQueryResponse {
query?: string
hogql?: string
@@ -136,6 +144,7 @@ export interface HogQLQueryResponse {
types?: any[]
columns?: any[]
timings?: QueryTiming[]
+ modifiers?: HogQLQueryModifiers
}
/** Filters object that will be converted to a HogQL {filters} placeholder */
@@ -150,6 +159,7 @@ export interface HogQLQuery extends DataNode {
filters?: HogQLFilters
/** Constant values that can be referenced with the {placeholder} syntax in the query */
values?: Record
+ modifiers?: HogQLQueryModifiers
response?: HogQLQueryResponse
}
@@ -534,7 +544,7 @@ export interface PersonsQuery extends DataNode {
response?: PersonsQueryResponse
}
-export type WebAnalyticsFilters = any
+export type WebAnalyticsPropertyFilters = EventPropertyFilter[]
export interface WebAnalyticsQueryBase {
dateRange?: DateRange
@@ -542,7 +552,7 @@ export interface WebAnalyticsQueryBase {
export interface WebOverviewStatsQuery extends WebAnalyticsQueryBase {
kind: NodeKind.WebOverviewStatsQuery
- filters: WebAnalyticsFilters
+ properties: WebAnalyticsPropertyFilters
response?: WebOverviewStatsQueryResponse
}
@@ -553,7 +563,7 @@ export interface WebOverviewStatsQueryResponse extends QueryResponse {
}
export interface WebTopSourcesQuery extends WebAnalyticsQueryBase {
kind: NodeKind.WebTopSourcesQuery
- filters: WebAnalyticsFilters
+ properties: WebAnalyticsPropertyFilters
response?: WebTopSourcesQueryResponse
}
export interface WebTopSourcesQueryResponse extends QueryResponse {
@@ -564,7 +574,7 @@ export interface WebTopSourcesQueryResponse extends QueryResponse {
export interface WebTopClicksQuery extends WebAnalyticsQueryBase {
kind: NodeKind.WebTopClicksQuery
- filters: WebAnalyticsFilters
+ properties: WebAnalyticsPropertyFilters
response?: WebTopClicksQueryResponse
}
export interface WebTopClicksQueryResponse extends QueryResponse {
@@ -575,7 +585,7 @@ export interface WebTopClicksQueryResponse extends QueryResponse {
export interface WebTopPagesQuery extends WebAnalyticsQueryBase {
kind: NodeKind.WebTopPagesQuery
- filters: WebAnalyticsFilters
+ properties: WebAnalyticsPropertyFilters
response?: WebTopPagesQueryResponse
}
export interface WebTopPagesQueryResponse extends QueryResponse {
@@ -703,7 +713,9 @@ export interface QueryContext {
emptyStateDetail?: string
}
+export type QueryContextColumnComponent = ComponentType<{ record: any; columnName: string; value: any }>
+
interface QueryContextColumn {
title?: string
- render?: (props: { record: any }) => JSX.Element
+ render?: QueryContextColumnComponent
}
diff --git a/frontend/src/scenes/cohorts/Cohort.tsx b/frontend/src/scenes/cohorts/Cohort.tsx
index 72481de9acefe..d597f2a93964a 100644
--- a/frontend/src/scenes/cohorts/Cohort.tsx
+++ b/frontend/src/scenes/cohorts/Cohort.tsx
@@ -1,12 +1,13 @@
-import { cohortLogic, CohortLogicProps } from './cohortLogic'
+import { cohortSceneLogic } from './cohortSceneLogic'
import 'antd/lib/dropdown/style/index.css'
import { SceneExport } from 'scenes/sceneTypes'
import { CohortEdit } from 'scenes/cohorts/CohortEdit'
+import { CohortLogicProps } from './cohortEditLogic'
export const scene: SceneExport = {
component: Cohort,
- logic: cohortLogic,
- paramsToProps: ({ params: { id } }): (typeof cohortLogic)['props'] => ({
+ logic: cohortSceneLogic,
+ paramsToProps: ({ params: { id } }): (typeof cohortSceneLogic)['props'] => ({
id: id && id !== 'new' ? parseInt(id) : 'new',
}),
}
diff --git a/frontend/src/scenes/cohorts/CohortEdit.tsx b/frontend/src/scenes/cohorts/CohortEdit.tsx
index 878104df2349d..ed5f3767cbfd2 100644
--- a/frontend/src/scenes/cohorts/CohortEdit.tsx
+++ b/frontend/src/scenes/cohorts/CohortEdit.tsx
@@ -1,7 +1,6 @@
-import { cohortEditLogic } from 'scenes/cohorts/cohortEditLogic'
+import { CohortLogicProps, cohortEditLogic } from 'scenes/cohorts/cohortEditLogic'
import { useActions, useValues } from 'kea'
import { userLogic } from 'scenes/userLogic'
-import { CohortLogicProps } from 'scenes/cohorts/cohortLogic'
import { PageHeader } from 'lib/components/PageHeader'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { router } from 'kea-router'
@@ -12,7 +11,7 @@ import { LemonInput } from 'lib/lemon-ui/LemonInput/LemonInput'
import { LemonSelect } from 'lib/lemon-ui/LemonSelect'
import { COHORT_TYPE_OPTIONS } from 'scenes/cohorts/CohortFilters/constants'
import { CohortTypeEnum } from 'lib/constants'
-import { AvailableFeature } from '~/types'
+import { AvailableFeature, NotebookNodeType } from '~/types'
import { LemonTextArea } from 'lib/lemon-ui/LemonTextArea/LemonTextArea'
import Dragger from 'antd/lib/upload/Dragger'
import { UploadFile } from 'antd/es/upload/interface'
@@ -27,6 +26,7 @@ import { pluralize } from 'lib/utils'
import { LemonDivider } from '@posthog/lemon-ui'
import { AndOrFilterSelect } from '~/queries/nodes/InsightViz/PropertyGroupFilters/AndOrFilterSelect'
import { More } from 'lib/lemon-ui/LemonButton/More'
+import { NotebookSelectButton } from 'scenes/notebooks/NotebookSelectButton/NotebookSelectButton'
export function CohortEdit({ id }: CohortLogicProps): JSX.Element {
const logicProps = { id }
@@ -105,6 +105,17 @@ export function CohortEdit({ id }: CohortLogicProps): JSX.Element {
/>
)}
+ {!isNewCohort && (
+
+ )}
{
let logic: ReturnType
diff --git a/frontend/src/scenes/cohorts/cohortEditLogic.ts b/frontend/src/scenes/cohorts/cohortEditLogic.ts
index 6e30a5e34b19d..0b53d5ce25e6a 100644
--- a/frontend/src/scenes/cohorts/cohortEditLogic.ts
+++ b/frontend/src/scenes/cohorts/cohortEditLogic.ts
@@ -27,12 +27,15 @@ import {
} from 'scenes/cohorts/cohortUtils'
import { NEW_COHORT, NEW_CRITERIA, NEW_CRITERIA_GROUP } from 'scenes/cohorts/CohortFilters/constants'
import type { cohortEditLogicType } from './cohortEditLogicType'
-import { CohortLogicProps } from 'scenes/cohorts/cohortLogic'
import { processCohort } from 'lib/utils'
import { DataTableNode, Node, NodeKind } from '~/queries/schema'
import { isDataTableNode } from '~/queries/utils'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
+export type CohortLogicProps = {
+ id?: CohortType['id']
+}
+
export const cohortEditLogic = kea([
props({} as CohortLogicProps),
key((props) => props.id || 'new'),
diff --git a/frontend/src/scenes/cohorts/cohortLogic.ts b/frontend/src/scenes/cohorts/cohortSceneLogic.ts
similarity index 78%
rename from frontend/src/scenes/cohorts/cohortLogic.ts
rename to frontend/src/scenes/cohorts/cohortSceneLogic.ts
index af1aa108c7d8d..52ea69b500b72 100644
--- a/frontend/src/scenes/cohorts/cohortLogic.ts
+++ b/frontend/src/scenes/cohorts/cohortSceneLogic.ts
@@ -1,14 +1,12 @@
import { kea, key, path, props, selectors } from 'kea'
-import type { cohortLogicType } from './cohortLogicType'
-import { Breadcrumb, CohortType } from '~/types'
+import { Breadcrumb } from '~/types'
import { urls } from 'scenes/urls'
import { cohortsModel } from '~/models/cohortsModel'
+import { CohortLogicProps } from './cohortEditLogic'
-export interface CohortLogicProps {
- id?: CohortType['id']
-}
+import type { cohortSceneLogicType } from './cohortSceneLogicType'
-export const cohortLogic = kea([
+export const cohortSceneLogic = kea([
props({} as CohortLogicProps),
key((props) => props.id || 'new'),
path(['scenes', 'cohorts', 'cohortLogic']),
diff --git a/frontend/src/scenes/debug/DebugScene.tsx b/frontend/src/scenes/debug/DebugScene.tsx
index c69aa492dd33f..723a132162b6d 100644
--- a/frontend/src/scenes/debug/DebugScene.tsx
+++ b/frontend/src/scenes/debug/DebugScene.tsx
@@ -10,23 +10,46 @@ import { LemonButton } from 'lib/lemon-ui/LemonButton'
import { HogQLQuery } from '~/queries/schema'
import { HogQLDebug } from 'scenes/debug/HogQLDebug'
-export function DebugScene(): JSX.Element {
- const { query } = useValues(debugSceneLogic)
- const { setQuery } = useActions(debugSceneLogic)
-
+interface QueryDebugProps {
+ queryKey: string
+ query: string
+ setQuery: (query: string) => void
+}
+function QueryDebug({ query, setQuery, queryKey }: QueryDebugProps): JSX.Element {
let parsed: Record | undefined
try {
parsed = JSON.parse(query)
} catch (e) {
// do nothing
}
-
- const showQueryEditor = !(
- parsed &&
- parsed.kind == 'DataTableNode' &&
- parsed.source.kind == 'HogQLQuery' &&
- (parsed.full || parsed.showHogQLEditor)
+ return (
+ <>
+ {parsed && parsed?.kind === 'HogQLQuery' ? (
+ setQuery(JSON.stringify(query, null, 2))}
+ />
+ ) : (
+ setQuery(JSON.stringify(query, null, 2))}
+ context={{
+ showQueryEditor:
+ parsed &&
+ parsed.kind == 'DataTableNode' &&
+ parsed.source.kind == 'HogQLQuery' &&
+ (parsed.full || parsed.showHogQLEditor),
+ }}
+ />
+ )}
+ >
)
+}
+
+export function DebugScene(): JSX.Element {
+ const { query1, query2 } = useValues(debugSceneLogic)
+ const { setQuery1, setQuery2 } = useActions(debugSceneLogic)
return (
@@ -34,21 +57,24 @@ export function DebugScene(): JSX.Element {
title="Query Debugger"
buttons={
<>
+
(query2 ? setQuery2('') : setQuery2(query1))}>
+ Split
+
setQuery(stringifiedExamples.HogQLRaw)}
+ active={query1 === stringifiedExamples.HogQLRaw}
+ onClick={() => setQuery1(stringifiedExamples.HogQLRaw)}
>
HogQL Debug
setQuery(stringifiedExamples.HogQLTable)}
+ active={query1 === stringifiedExamples.HogQLTable}
+ onClick={() => setQuery1(stringifiedExamples.HogQLTable)}
>
HogQL Table
setQuery(stringifiedExamples.Events)}
+ active={query1 === stringifiedExamples.Events}
+ onClick={() => setQuery1(stringifiedExamples.Events)}
>
Any Query
@@ -62,7 +88,7 @@ export function DebugScene(): JSX.Element {
})}
onChange={(v) => {
if (v) {
- setQuery(v)
+ setQuery1(v)
}
}}
/>
@@ -70,20 +96,16 @@ export function DebugScene(): JSX.Element {
>
}
/>
- {parsed && parsed?.kind === 'HogQLQuery' ? (
-
setQuery(JSON.stringify(query, null, 2))}
- />
- ) : (
- setQuery(JSON.stringify(query, null, 2))}
- context={{
- showQueryEditor: showQueryEditor,
- }}
- />
- )}
+
+
+
+
+ {query2 ? (
+
+
+
+ ) : null}
+
)
}
diff --git a/frontend/src/scenes/debug/HogQLDebug.tsx b/frontend/src/scenes/debug/HogQLDebug.tsx
index 62b495947c04f..6c047d967fbbb 100644
--- a/frontend/src/scenes/debug/HogQLDebug.tsx
+++ b/frontend/src/scenes/debug/HogQLDebug.tsx
@@ -7,22 +7,62 @@ import { dataNodeLogic, DataNodeLogicProps } from '~/queries/nodes/DataNode/data
import { ElapsedTime, Timings } from '~/queries/nodes/DataNode/ElapsedTime'
import { CodeSnippet, Language } from 'lib/components/CodeSnippet'
import { CodeEditor } from 'lib/components/CodeEditors'
+import { LemonSelect } from 'lib/lemon-ui/LemonSelect'
+import { LemonLabel } from 'lib/lemon-ui/LemonLabel'
+import { Reload } from '~/queries/nodes/DataNode/Reload'
interface HogQLDebugProps {
+ queryKey: string
query: HogQLQuery
setQuery: (query: DataNode) => void
}
-export function HogQLDebug({ query, setQuery }: HogQLDebugProps): JSX.Element {
- const dataNodeLogicProps: DataNodeLogicProps = { query, key: 'debug-scene' }
+export function HogQLDebug({ query, setQuery, queryKey }: HogQLDebugProps): JSX.Element {
+ const dataNodeLogicProps: DataNodeLogicProps = { query, key: queryKey }
const { dataLoading, response, responseErrorObject, elapsedTime } = useValues(dataNodeLogic(dataNodeLogicProps))
return (
+
+
+
+ POE Version:
+
+ setQuery({
+ ...query,
+ modifiers: { ...query.modifiers, personsOnEventsMode: value },
+ } as HogQLQuery)
+ }
+ value={query.modifiers?.personsOnEventsMode ?? response?.modifiers?.personsOnEventsMode}
+ />
+
+
+ Persons ArgMax Version
+
+ setQuery({
+ ...query,
+ modifiers: { ...query.modifiers, personsArgMaxVersion: value },
+ } as HogQLQuery)
+ }
+ value={query.modifiers?.personsArgMaxVersion ?? response?.modifiers?.personsArgMaxVersion}
+ />
+
+
{dataLoading ? (
<>
Running query...
diff --git a/frontend/src/scenes/debug/debugSceneLogic.ts b/frontend/src/scenes/debug/debugSceneLogic.ts
index aaf975c26ee85..912474eac6907 100644
--- a/frontend/src/scenes/debug/debugSceneLogic.ts
+++ b/frontend/src/scenes/debug/debugSceneLogic.ts
@@ -10,20 +10,33 @@ const DEFAULT_QUERY: string = stringifiedExamples['HogQLRaw']
export const debugSceneLogic = kea
([
path(['scenes', 'query', 'debugSceneLogic']),
actions({
- setQuery: (query: string) => ({ query: query }),
+ setQuery1: (query: string) => ({ query: query }),
+ setQuery2: (query: string) => ({ query: query }),
}),
reducers({
- query: [DEFAULT_QUERY, { setQuery: (_, { query }) => query }],
+ query1: [DEFAULT_QUERY, { setQuery1: (_, { query }) => query }],
+ query2: [DEFAULT_QUERY, { setQuery2: (_, { query }) => query }],
}),
- actionToUrl({
- setQuery: ({ query }) => {
- return [urls.debugQuery(), {}, { q: query }, { replace: true }]
+ actionToUrl(({ values }) => ({
+ setQuery1: ({ query }) => {
+ return [
+ urls.debugQuery(),
+ {},
+ { ...{ q: query }, ...(values.query2 ? { q2: values.query2 } : {}) },
+ { replace: true },
+ ]
},
- }),
+ setQuery2: () => {
+ return [urls.debugQuery(), {}, { q: values.query1, q2: values.query2 }, { replace: true }]
+ },
+ })),
urlToAction(({ actions, values }) => ({
- [urls.debugQuery()]: (_, __, { q }) => {
- if (q && q !== values.query) {
- actions.setQuery(q)
+ [urls.debugQuery()]: (_, __, { q, q2 }) => {
+ if (q && q !== values.query1) {
+ actions.setQuery1(q)
+ }
+ if ((q2 ?? '') !== (values.query2 ?? '')) {
+ actions.setQuery2(q2 ?? '')
}
},
})),
diff --git a/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx b/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx
index 2677d3fb1ccec..a894b964432cf 100644
--- a/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx
+++ b/frontend/src/scenes/early-access-features/EarlyAccessFeature.tsx
@@ -48,8 +48,13 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element {
isEditingFeature,
earlyAccessFeatureMissing,
} = useValues(earlyAccessFeatureLogic)
- const { submitEarlyAccessFeatureRequest, cancel, editFeature, updateStage, deleteEarlyAccessFeature } =
- useActions(earlyAccessFeatureLogic)
+ const {
+ submitEarlyAccessFeatureRequest,
+ loadEarlyAccessFeature,
+ editFeature,
+ updateStage,
+ deleteEarlyAccessFeature,
+ } = useActions(earlyAccessFeatureLogic)
const isNewEarlyAccessFeature = id === 'new' || id === undefined
@@ -72,7 +77,15 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element {
<>
cancel()}
+ data-attr="cancel-feature"
+ onClick={() => {
+ if (isEditingFeature) {
+ editFeature(false)
+ loadEarlyAccessFeature()
+ } else {
+ router.actions.push(urls.earlyAccessFeatures())
+ }
+ }}
disabledReason={isEarlyAccessFeatureSubmitting ? 'Saving…' : undefined}
>
Cancel
@@ -80,6 +93,7 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element {
{
submitEarlyAccessFeatureRequest(earlyAccessFeature)
}}
@@ -103,6 +117,7 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element {
children: 'Delete',
type: 'primary',
status: 'danger',
+ 'data-attr': 'confirm-delete-feature',
onClick: () => {
// conditional above ensures earlyAccessFeature is not NewEarlyAccessFeature
deleteEarlyAccessFeature(
@@ -148,7 +163,12 @@ export function EarlyAccessFeature({ id }: { id?: string } = {}): JSX.Element {
)}
{earlyAccessFeature.stage != EarlyAccessFeatureStage.GeneralAvailability && (
- editFeature(true)} loading={false}>
+ editFeature(true)}
+ loading={false}
+ data-attr="edit-feature"
+ >
Edit
)}
diff --git a/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx b/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx
index c6dc0c2c83cf0..594a986400042 100644
--- a/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx
+++ b/frontend/src/scenes/early-access-features/EarlyAccessFeatures.tsx
@@ -60,7 +60,7 @@ export function EarlyAccessFeatures(): JSX.Element {
}
buttons={
- New public beta
+ Create feature
}
delimited
diff --git a/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts b/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts
index 96ce8ab5eac2d..df5aabcc583b9 100644
--- a/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts
+++ b/frontend/src/scenes/early-access-features/earlyAccessFeatureLogic.ts
@@ -40,7 +40,6 @@ export const earlyAccessFeatureLogic = kea([
actions({
setEarlyAccessFeatureMissing: true,
toggleImplementOptInInstructionsModal: true,
- cancel: true,
editFeature: (editing: boolean) => ({ editing }),
updateStage: (stage: EarlyAccessFeatureStage) => ({ stage }),
deleteEarlyAccessFeature: (earlyAccessFeatureId: EarlyAccessFeatureType['id']) => ({ earlyAccessFeatureId }),
@@ -130,12 +129,6 @@ export const earlyAccessFeatureLogic = kea([
],
}),
listeners(({ actions, values, props }) => ({
- cancel: () => {
- if ('id' in values.earlyAccessFeature) {
- actions.loadEarlyAccessFeature()
- }
- actions.editFeature(false)
- },
updateStage: async ({ stage }) => {
'id' in values.earlyAccessFeature &&
(await api.earlyAccessFeatures.update(props.id, {
diff --git a/frontend/src/scenes/feature-flags/featureFlagLogic.test.ts b/frontend/src/scenes/feature-flags/featureFlagLogic.test.ts
index f0516fe9956e1..db6df537e3eac 100644
--- a/frontend/src/scenes/feature-flags/featureFlagLogic.test.ts
+++ b/frontend/src/scenes/feature-flags/featureFlagLogic.test.ts
@@ -317,7 +317,8 @@ describe('the feature flag logic', () => {
logic.actions.setTotalUsers(100)
expect(logic.values.computeBlastRadiusPercentage(67, 0)).toBeCloseTo(67, 2)
// total users is defined but affected users is not. UI side should handle not showing the result in this case
- expect(logic.values.computeBlastRadiusPercentage(75, 1)).toEqual(NaN)
+ // and computation resolves to rollout percentage
+ expect(logic.values.computeBlastRadiusPercentage(75, 1)).toEqual(75)
expect(logic.values.computeBlastRadiusPercentage(100, 2)).toBeCloseTo(25, 2)
})
diff --git a/frontend/src/scenes/feature-flags/featureFlagLogic.ts b/frontend/src/scenes/feature-flags/featureFlagLogic.ts
index 5f33ae64bd556..0ea7e1154bbcf 100644
--- a/frontend/src/scenes/feature-flags/featureFlagLogic.ts
+++ b/frontend/src/scenes/feature-flags/featureFlagLogic.ts
@@ -446,7 +446,7 @@ export const featureFlagLogic = kea([
},
],
affectedUsers: [
- {},
+ { 0: -1 },
{
setAffectedUsers: (state, { index, count }) => ({
...state,
@@ -801,7 +801,12 @@ export const featureFlagLogic = kea([
effectiveRolloutPercentage = 100
}
- if (affectedUsers[index] === -1 || totalUsers === -1 || !totalUsers) {
+ if (
+ affectedUsers[index] === -1 ||
+ totalUsers === -1 ||
+ !totalUsers ||
+ affectedUsers[index] === undefined
+ ) {
return effectiveRolloutPercentage
}
diff --git a/frontend/src/scenes/groups/Group.tsx b/frontend/src/scenes/groups/Group.tsx
index ed84536cf0953..f3ed2116c2aed 100644
--- a/frontend/src/scenes/groups/Group.tsx
+++ b/frontend/src/scenes/groups/Group.tsx
@@ -1,11 +1,11 @@
import { useActions, useValues } from 'kea'
import { PropertiesTable } from 'lib/components/PropertiesTable'
import { TZLabel } from 'lib/components/TZLabel'
-import { groupLogic } from 'scenes/groups/groupLogic'
+import { GroupLogicProps, groupLogic } from 'scenes/groups/groupLogic'
import { RelatedGroups } from 'scenes/groups/RelatedGroups'
import { SceneExport } from 'scenes/sceneTypes'
import { groupDisplayId } from 'scenes/persons/GroupActorDisplay'
-import { Group as IGroup, PersonsTabType, PropertyDefinitionType } from '~/types'
+import { Group as IGroup, NotebookNodeType, PersonsTabType, PropertyDefinitionType } from '~/types'
import { PageHeader } from 'lib/components/PageHeader'
import { CopyToClipboardInline } from 'lib/components/CopyToClipboard'
import { Spinner, SpinnerOverlay } from 'lib/lemon-ui/Spinner/Spinner'
@@ -14,13 +14,24 @@ import { RelatedFeatureFlags } from 'scenes/persons/RelatedFeatureFlags'
import { Query } from '~/queries/Query/Query'
import { LemonTabs } from 'lib/lemon-ui/LemonTabs'
import { GroupDashboard } from 'scenes/groups/GroupDashboard'
+import { router } from 'kea-router'
+import { urls } from 'scenes/urls'
+import { NotebookSelectButton } from 'scenes/notebooks/NotebookSelectButton/NotebookSelectButton'
+interface GroupSceneProps {
+ groupTypeIndex?: string
+ groupKey?: string
+}
export const scene: SceneExport = {
component: Group,
logic: groupLogic,
+ paramsToProps: ({ params: { groupTypeIndex, groupKey } }: { params: GroupSceneProps }): GroupLogicProps => ({
+ groupTypeIndex: parseInt(groupTypeIndex ?? '0'),
+ groupKey: decodeURIComponent(groupKey ?? ''),
+ }),
}
-function GroupCaption({ groupData, groupTypeName }: { groupData: IGroup; groupTypeName: string }): JSX.Element {
+export function GroupCaption({ groupData, groupTypeName }: { groupData: IGroup; groupTypeName: string }): JSX.Element {
return (
@@ -46,17 +57,17 @@ function GroupCaption({ groupData, groupTypeName }: { groupData: IGroup; groupTy
export function Group(): JSX.Element {
const {
+ logicProps,
groupData,
groupDataLoading,
groupTypeName,
- groupKey,
- groupTypeIndex,
groupType,
groupTab,
groupEventsQuery,
showCustomerSuccessDashboards,
} = useValues(groupLogic)
- const { setGroupTab, setGroupEventsQuery } = useActions(groupLogic)
+ const { groupKey, groupTypeIndex } = logicProps
+ const { setGroupEventsQuery } = useActions(groupLogic)
if (!groupData) {
return groupDataLoading ?
:
@@ -67,10 +78,22 @@ export function Group(): JSX.Element {
}
+ buttons={
+
+ }
/>
setGroupTab(tab)}
+ onChange={(tab) => router.actions.push(urls.group(String(groupTypeIndex), groupKey, true, tab))}
tabs={[
{
key: PersonsTabType.PROPERTIES,
diff --git a/frontend/src/scenes/groups/groupLogic.ts b/frontend/src/scenes/groups/groupLogic.ts
index 42fe4904c4867..0800a07890f14 100644
--- a/frontend/src/scenes/groups/groupLogic.ts
+++ b/frontend/src/scenes/groups/groupLogic.ts
@@ -1,4 +1,4 @@
-import { kea } from 'kea'
+import { actions, afterMount, connect, kea, key, path, props, reducers, selectors } from 'kea'
import api from 'lib/api'
import { toParams } from 'lib/utils'
import { teamLogic } from 'scenes/teamLogic'
@@ -13,6 +13,8 @@ import { defaultDataTableColumns } from '~/queries/nodes/DataTable/utils'
import { isDataTableNode } from '~/queries/utils'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS } from 'lib/constants'
+import { loaders } from 'kea-loaders'
+import { urlToAction } from 'kea-router'
function getGroupEventsQuery(groupTypeIndex: number, groupKey: string): DataTableNode {
return {
@@ -34,9 +36,16 @@ function getGroupEventsQuery(groupTypeIndex: number, groupKey: string): DataTabl
}
}
-export const groupLogic = kea({
- path: ['groups', 'groupLogic'],
- connect: {
+export type GroupLogicProps = {
+ groupTypeIndex: number
+ groupKey: string
+}
+
+export const groupLogic = kea([
+ props({} as GroupLogicProps),
+ key((props) => `${props.groupTypeIndex}-${props.groupKey}`),
+ path((key) => ['scenes', 'groups', 'groupLogic', key]),
+ connect({
values: [
teamLogic,
['currentTeamId'],
@@ -45,71 +54,54 @@ export const groupLogic = kea({
featureFlagLogic,
['featureFlags'],
],
- },
- actions: () => ({
- setGroup: (groupTypeIndex: number, groupKey: string, groupTab?: string | null) => ({
- groupTypeIndex,
- groupKey,
- groupTab,
- }),
+ }),
+ actions(() => ({
setGroupTab: (groupTab: string | null) => ({ groupTab }),
setGroupEventsQuery: (query: Node) => ({ query }),
- }),
- loaders: ({ values }) => ({
+ })),
+ loaders(({ values, props }) => ({
groupData: [
null as Group | null,
{
loadGroup: async () => {
- const params = { group_type_index: values.groupTypeIndex, group_key: values.groupKey }
+ const params = { group_type_index: props.groupTypeIndex, group_key: props.groupKey }
const url = `api/projects/${values.currentTeamId}/groups/find?${toParams(params)}`
return await api.get(url)
},
},
],
- }),
- reducers: {
- groupTypeIndex: [
- 0,
- {
- setGroup: (_, { groupTypeIndex }) => groupTypeIndex,
- },
- ],
- groupKey: [
- '',
- {
- setGroup: (_, { groupKey }) => groupKey,
- },
- ],
+ })),
+ reducers({
groupTab: [
null as string | null,
{
- setGroup: (_, { groupTab }) => groupTab ?? null,
setGroupTab: (_, { groupTab }) => groupTab,
},
],
groupEventsQuery: [
null as DataTableNode | null,
{
- setGroup: (_, { groupTypeIndex, groupKey }) => getGroupEventsQuery(groupTypeIndex, groupKey),
setGroupEventsQuery: (_, { query }) => (isDataTableNode(query) ? query : null),
},
],
- },
- selectors: {
+ }),
+ selectors({
+ logicProps: [() => [(_, props) => props], (props): GroupLogicProps => props],
+
showCustomerSuccessDashboards: [
(s) => [s.featureFlags],
(featureFlags) => featureFlags[FEATURE_FLAGS.CS_DASHBOARDS],
],
groupTypeName: [
- (s) => [s.aggregationLabel, s.groupTypeIndex],
+ (s, p) => [s.aggregationLabel, p.groupTypeIndex],
(aggregationLabel, index): string => aggregationLabel(index).singular,
],
groupType: [
- (s) => [s.groupTypes, s.groupTypeIndex],
+ (s, p) => [s.groupTypes, p.groupTypeIndex],
(groupTypes, index): string => groupTypes[index]?.group_type,
],
breadcrumbs: [
- (s) => [s.groupTypeName, s.groupTypeIndex, s.groupKey, s.groupData],
+ (s, p) => [s.groupTypeName, p.groupTypeIndex, p.groupKey, s.groupData],
(groupTypeName, groupTypeIndex, groupKey, groupData): Breadcrumb[] => [
{
name: capitalizeFirstLetter(groupTypeName),
@@ -121,36 +113,15 @@ export const groupLogic = kea({
},
],
],
- },
- actionToUrl: ({ values }) => ({
- setGroup: () => {
- const { groupTypeIndex, groupKey, groupTab } = values
- return urls.group(String(groupTypeIndex), groupKey, true, groupTab)
- },
- setGroupTab: () => {
- const { groupTypeIndex, groupKey, groupTab } = values
- return urls.group(String(groupTypeIndex), groupKey, true, groupTab)
- },
- }),
- urlToAction: ({ actions, values }) => ({
- '/groups/:groupTypeIndex/:groupKey(/:groupTab)': ({ groupTypeIndex, groupKey, groupTab }) => {
- if (groupTypeIndex && groupKey) {
- if (+groupTypeIndex === values.groupTypeIndex && groupKey === values.groupKey) {
- actions.setGroupTab(groupTab || null)
- } else {
- actions.setGroup(+groupTypeIndex, decodeURIComponent(groupKey), groupTab)
- }
- }
- },
}),
- listeners: ({ actions, selectors, values }) => ({
- setGroup: (_, __, ___, previousState) => {
- if (
- selectors.groupTypeIndex(previousState) !== values.groupTypeIndex ||
- selectors.groupKey(previousState) !== values.groupKey
- ) {
- actions.loadGroup()
- }
+ urlToAction(({ actions }) => ({
+ '/groups/:groupTypeIndex/:groupKey(/:groupTab)': ({ groupTab }) => {
+ actions.setGroupTab(groupTab || null)
},
+ })),
+
+ afterMount(({ actions, props }) => {
+ actions.loadGroup()
+ actions.setGroupEventsQuery(getGroupEventsQuery(props.groupTypeIndex, props.groupKey))
}),
-})
+])
diff --git a/frontend/src/scenes/insights/filters/ActionFilter/ActionFilterRow/ActionFilterRow.scss b/frontend/src/scenes/insights/filters/ActionFilter/ActionFilterRow/ActionFilterRow.scss
index cd25fb8ed77f1..854c50ea3469f 100644
--- a/frontend/src/scenes/insights/filters/ActionFilter/ActionFilterRow/ActionFilterRow.scss
+++ b/frontend/src/scenes/insights/filters/ActionFilter/ActionFilterRow/ActionFilterRow.scss
@@ -1,6 +1,4 @@
.ActionFilterRow {
- background: var(--bg-3000);
-
.ActionFilterRow-content {
display: flex;
align-items: flex-start;
diff --git a/frontend/src/scenes/insights/views/WorldMap/countryVectors.tsx b/frontend/src/scenes/insights/views/WorldMap/countryVectors.tsx
index a56171683da74..5acfa5a1ee1de 100644
--- a/frontend/src/scenes/insights/views/WorldMap/countryVectors.tsx
+++ b/frontend/src/scenes/insights/views/WorldMap/countryVectors.tsx
@@ -7888,6 +7888,42 @@ export const countryVectors: Record = {
/>
),
+ GF: (
+
+
+
+ ),
+ GP: (
+
+
+
+
+
+
+
+ ),
+ YT: (
+
+
+
+ ),
FR: (
@@ -7917,34 +7953,6 @@ export const countryVectors: Record = {
d="m 1367.17,332.118 c 0.41,-0.415 0.49,-1.257 1.04,-1.534 1.1,-0.55 2.35,-0.692 3.39,-1.385 0.93,-0.619 0.27,-2.364 1.54,-2.266 0.15,2.196 1.2,5.361 0.68,7.488 -0.55,2.244 -1.65,4.389 -2.62,6.479 -0.38,-0.593 -3.91,-1.882 -2.02,-2.664 -0.51,-0.119 -0.99,-0.311 -1.44,-0.575 0.49,-0.312 0.84,-0.833 0.79,-1.44 -1.01,0.237 -1.15,-0.887 -0.57,-1.439 -0.86,-0.216 -1.4,-1.342 -0.22,-1.584 -0.25,-0.332 -0.44,-0.691 -0.57,-1.08"
/>
-
-
-
-
-
-
-
-
-
-
-
),
MQ: (
diff --git a/frontend/src/scenes/notebooks/Nodes/NodeWrapper.scss b/frontend/src/scenes/notebooks/Nodes/NodeWrapper.scss
index f60af4fa98878..58572fec9bd99 100644
--- a/frontend/src/scenes/notebooks/Nodes/NodeWrapper.scss
+++ b/frontend/src/scenes/notebooks/Nodes/NodeWrapper.scss
@@ -4,7 +4,7 @@
--border-color: var(--border);
transform: translate3d(0, 0, 0);
- margin: 0px 0px 1rem 0px;
+ margin: 0.65rem 0px 0.35rem 0px;
.NotebookNode__box {
transform: translate3d(0, 0, 0);
@@ -96,3 +96,18 @@
object-fit: contain;
}
}
+
+.NotebookNodeTitle {
+ padding: 0.25rem;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ &--editable {
+ border-radius: var(--radius);
+ transition: background-color 150ms linear;
+ &:hover {
+ background-color: var(--border);
+ }
+ }
+}
diff --git a/frontend/src/scenes/notebooks/Nodes/NodeWrapper.tsx b/frontend/src/scenes/notebooks/Nodes/NodeWrapper.tsx
index 8a032e899e1be..c9ddb93f4137b 100644
--- a/frontend/src/scenes/notebooks/Nodes/NodeWrapper.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NodeWrapper.tsx
@@ -36,13 +36,14 @@ import {
NotebookNodeSettings,
} from '../Notebook/utils'
import { useWhyDidIRender } from 'lib/hooks/useWhyDidIRender'
+import { NotebookNodeTitle } from './components/NotebookNodeTitle'
export interface NodeWrapperProps {
nodeType: NotebookNodeType
Component: (props: NotebookNodeProps) => JSX.Element | null
// Meta properties - these should never be too advanced - more advanced should be done via updateAttributes in the component
- defaultTitle: string
+ titlePlaceholder: string
href?: string | ((attributes: NotebookNodeAttributes) => string | undefined)
// Sizing
@@ -62,7 +63,7 @@ function NodeWrapper(
props: NodeWrapperProps & NotebookNodeProps & Omit
): JSX.Element {
const {
- defaultTitle,
+ titlePlaceholder,
nodeType,
Component,
selected,
@@ -100,7 +101,7 @@ function NodeWrapper(
resizeable: resizeableOrGenerator,
settings,
startExpanded,
- defaultTitle,
+ titlePlaceholder,
}
const nodeLogic = useMountedLogic(notebookNodeLogic(nodeLogicProps))
const { resizeable, expanded, actions } = useValues(nodeLogic)
@@ -142,8 +143,6 @@ function NodeWrapper(
}, [resizeable, updateAttributes])
const parsedHref = typeof href === 'function' ? href(attributes) : href
- // If a title is set on the attrs we use it. Otherwise we use the base component title.
- const title = attributes.title ? attributes.title : defaultTitle
// Element is resizable if resizable is set to true. If expandable is set to true then is is only resizable if expanded is true
const isResizeable = resizeable && (!expandable || expanded)
@@ -172,11 +171,11 @@ function NodeWrapper(
) : (
<>
-
+
{isEditable && (
)}
- {title}
+
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeCohort.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeCohort.tsx
new file mode 100644
index 0000000000000..60fa028e0814a
--- /dev/null
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeCohort.tsx
@@ -0,0 +1,176 @@
+import { createPostHogWidgetNode } from 'scenes/notebooks/Nodes/NodeWrapper'
+import { NotebookNodeType, PropertyFilterType } from '~/types'
+import { useActions, useValues } from 'kea'
+import { urls } from 'scenes/urls'
+import { LemonSkeleton } from 'lib/lemon-ui/LemonSkeleton'
+import { notebookNodeLogic } from './notebookNodeLogic'
+import { NotebookNodeProps } from '../Notebook/utils'
+import { useEffect, useMemo } from 'react'
+import clsx from 'clsx'
+import { NotFound } from 'lib/components/NotFound'
+import { cohortEditLogic } from 'scenes/cohorts/cohortEditLogic'
+import { IconCohort, IconPerson, InsightsTrendsIcon } from 'lib/lemon-ui/icons'
+import { Query } from '~/queries/Query/Query'
+import { LemonDivider, LemonTag } from '@posthog/lemon-ui'
+import { DataTableNode, NodeKind } from '~/queries/schema'
+
+const Component = ({ attributes }: NotebookNodeProps
): JSX.Element => {
+ const { id } = attributes
+
+ const { expanded } = useValues(notebookNodeLogic)
+ const { setExpanded, setActions, insertAfter, setTitlePlaceholder } = useActions(notebookNodeLogic)
+
+ const { cohort, cohortLoading, cohortMissing, query } = useValues(cohortEditLogic({ id }))
+ const { setQuery } = useActions(cohortEditLogic({ id }))
+
+ const modifiedQuery = useMemo(() => {
+ return {
+ ...query,
+ embedded: true,
+ // TODO: Add back in controls in a way that actually works - maybe sync with NotebookNodeQuery
+ full: false,
+ showElapsedTime: false,
+ showTimings: false,
+ showOpenEditorButton: false,
+ }
+ }, [query])
+
+ useEffect(() => {
+ const title = cohort ? `Cohort: ${cohort.name}` : 'Cohort'
+
+ setTitlePlaceholder(title)
+ setActions(
+ !cohortMissing
+ ? [
+ {
+ text: 'People in cohort',
+ icon: ,
+ onClick: () => {
+ setExpanded(false)
+ insertAfter({
+ type: NotebookNodeType.Query,
+ attrs: {
+ query: {
+ kind: NodeKind.DataTableNode,
+ source: {
+ kind: NodeKind.PersonsQuery,
+ properties: [
+ {
+ type: PropertyFilterType.Cohort,
+ key: 'id',
+ value: id,
+ },
+ ],
+ },
+ full: true,
+ },
+ },
+ })
+ },
+ },
+
+ {
+ text: 'Cohort trends',
+ icon: ,
+ onClick: () => {
+ setExpanded(false)
+ insertAfter({
+ type: NotebookNodeType.Query,
+ attrs: {
+ query: {
+ kind: 'InsightVizNode',
+ source: {
+ kind: 'TrendsQuery',
+ filterTestAccounts: true,
+ series: [
+ {
+ kind: 'EventsNode',
+ event: '$pageview',
+ name: '$pageview',
+ math: 'total',
+ },
+ ],
+ interval: 'day',
+ trendsFilter: {
+ display: 'ActionsLineGraph',
+ },
+ properties: {
+ type: 'AND',
+ values: [
+ {
+ type: 'AND',
+ values: [
+ {
+ key: 'id',
+ value: id,
+ type: 'cohort',
+ },
+ ],
+ },
+ ],
+ },
+ },
+ },
+ },
+ })
+ },
+ },
+ ]
+ : []
+ )
+ }, [cohort, cohortMissing])
+
+ if (cohortMissing) {
+ return
+ }
+ return (
+
+
+ {cohortLoading ? (
+
+ ) : (
+
+
+ {cohort.name}
+ ({cohort.count} persons)
+ {cohort.is_static ? 'Static' : 'Dynamic'}
+
+ )}
+
+
+ {expanded ? (
+ <>
+
+
+ >
+ ) : null}
+
+ )
+}
+
+type NotebookNodeCohortAttributes = {
+ id: number
+}
+
+export const NotebookNodeCohort = createPostHogWidgetNode({
+ nodeType: NotebookNodeType.Cohort,
+ titlePlaceholder: 'Cohort',
+ Component,
+ heightEstimate: 300,
+ minHeight: 100,
+ href: (attrs) => urls.cohort(attrs.id),
+ attributes: {
+ id: {},
+ },
+ pasteOptions: {
+ find: urls.cohort('(.+)'),
+ getAttributes: async (match) => {
+ return { id: parseInt(match[1]) }
+ },
+ },
+ serializedText: (attrs) => {
+ const title = attrs?.title || ''
+ const id = attrs?.id || ''
+ return `${title} ${id}`.trim()
+ },
+})
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeEarlyAccessFeature.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeEarlyAccessFeature.tsx
index 78396e4b5f06e..94304f7f7e2f4 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeEarlyAccessFeature.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeEarlyAccessFeature.tsx
@@ -14,15 +14,15 @@ import {
import { PersonList } from 'scenes/early-access-features/EarlyAccessFeature'
import { buildFlagContent } from './NotebookNodeFlag'
import { useEffect } from 'react'
+import { NotFound } from 'lib/components/NotFound'
-const Component = ({
- attributes,
- updateAttributes,
-}: NotebookNodeProps): JSX.Element => {
+const Component = ({ attributes }: NotebookNodeProps): JSX.Element => {
const { id } = attributes
- const { earlyAccessFeature, earlyAccessFeatureLoading } = useValues(earlyAccessFeatureLogic({ id }))
+ const { earlyAccessFeature, earlyAccessFeatureLoading, earlyAccessFeatureMissing } = useValues(
+ earlyAccessFeatureLogic({ id })
+ )
const { expanded } = useValues(notebookNodeLogic)
- const { insertAfter, setActions } = useActions(notebookNodeLogic)
+ const { insertAfter, setActions, setTitlePlaceholder } = useActions(notebookNodeLogic)
useEffect(() => {
const flagId = (earlyAccessFeature as EarlyAccessFeatureType).feature_flag?.id
@@ -41,13 +41,15 @@ const Component = ({
}, [earlyAccessFeature])
useEffect(() => {
- updateAttributes({
- title: earlyAccessFeature.name
- ? `Early Access Management: ${earlyAccessFeature.name}`
- : 'Early Access Management',
- })
+ setTitlePlaceholder(
+ earlyAccessFeature.name ? `Early Access Management: ${earlyAccessFeature.name}` : 'Early Access Management'
+ )
}, [earlyAccessFeature?.name])
+ if (earlyAccessFeatureMissing) {
+ return
+ }
+
return (
@@ -118,7 +120,7 @@ type NotebookNodeEarlyAccessAttributes = {
export const NotebookNodeEarlyAccessFeature = createPostHogWidgetNode({
nodeType: NotebookNodeType.EarlyAccessFeature,
- defaultTitle: 'Early Access Management',
+ titlePlaceholder: 'Early Access Management',
Component,
heightEstimate: '3rem',
href: (attrs) => urls.earlyAccessFeature(attrs.id),
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeExperiment.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeExperiment.tsx
index 643ad00c20e29..28801d7c356a7 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeExperiment.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeExperiment.tsx
@@ -17,10 +17,13 @@ import { funnelDataLogic } from 'scenes/funnels/funnelDataLogic'
import { trendsDataLogic } from 'scenes/trends/trendsDataLogic'
import { ExperimentResult } from 'scenes/experiments/ExperimentResult'
import { ResultsTag, StatusTag } from 'scenes/experiments/Experiment'
+import { NotFound } from 'lib/components/NotFound'
const Component = ({ attributes }: NotebookNodeProps): JSX.Element => {
const { id } = attributes
- const { experiment, experimentLoading, isExperimentRunning } = useValues(experimentLogic({ experimentId: id }))
+ const { experiment, experimentLoading, experimentMissing, isExperimentRunning } = useValues(
+ experimentLogic({ experimentId: id })
+ )
const { loadExperiment } = useActions(experimentLogic({ experimentId: id }))
const { expanded, nextNode } = useValues(notebookNodeLogic)
const { insertAfter } = useActions(notebookNodeLogic)
@@ -40,6 +43,10 @@ const Component = ({ attributes }: NotebookNodeProps
+ }
+
return (
@@ -122,7 +129,7 @@ type NotebookNodeExperimentAttributes = {
export const NotebookNodeExperiment = createPostHogWidgetNode({
nodeType: NotebookNodeType.Experiment,
- defaultTitle: 'Experiment',
+ titlePlaceholder: 'Experiment',
Component,
heightEstimate: '3rem',
href: (attrs) => urls.experiment(attrs.id),
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlag.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlag.tsx
index 92a5646dce29e..28941e0ccec11 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlag.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlag.tsx
@@ -16,27 +16,29 @@ import { buildEarlyAccessFeatureContent } from './NotebookNodeEarlyAccessFeature
import { notebookNodeFlagLogic } from './NotebookNodeFlagLogic'
import { buildSurveyContent } from './NotebookNodeSurvey'
import { useEffect } from 'react'
+import { NotFound } from 'lib/components/NotFound'
-const Component = ({ attributes, updateAttributes }: NotebookNodeProps): JSX.Element => {
+const Component = ({ attributes }: NotebookNodeProps): JSX.Element => {
const { id } = attributes
const {
featureFlag,
featureFlagLoading,
recordingFilterForFlag,
+ featureFlagMissing,
hasEarlyAccessFeatures,
canCreateEarlyAccessFeature,
hasSurveys,
} = useValues(featureFlagLogic({ id }))
const { createEarlyAccessFeature, createSurvey } = useActions(featureFlagLogic({ id }))
const { expanded, nextNode } = useValues(notebookNodeLogic)
- const { insertAfter, setActions } = useActions(notebookNodeLogic)
+ const { insertAfter, setActions, setTitlePlaceholder } = useActions(notebookNodeLogic)
const { shouldDisableInsertEarlyAccessFeature, shouldDisableInsertSurvey } = useValues(
notebookNodeFlagLogic({ id, insertAfter })
)
useEffect(() => {
- updateAttributes({ title: featureFlag.key ? `Feature flag: ${featureFlag.key}` : 'Feature flag' })
+ setTitlePlaceholder(featureFlag.key ? `Feature flag: ${featureFlag.key}` : 'Feature flag')
setActions([
{
@@ -93,6 +95,10 @@ const Component = ({ attributes, updateAttributes }: NotebookNodeProps
+ }
+
return (
@@ -134,7 +140,7 @@ type NotebookNodeFlagAttributes = {
export const NotebookNodeFlag = createPostHogWidgetNode({
nodeType: NotebookNodeType.FeatureFlag,
- defaultTitle: 'Feature flag',
+ titlePlaceholder: 'Feature flag',
Component,
heightEstimate: '3rem',
href: (attrs) => urls.featureFlag(attrs.id),
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlagCodeExample.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlagCodeExample.tsx
index 621ba8f1f7ba8..deb1dac4eb25f 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlagCodeExample.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeFlagCodeExample.tsx
@@ -1,27 +1,30 @@
import { createPostHogWidgetNode } from 'scenes/notebooks/Nodes/NodeWrapper'
import { NotebookNodeType } from '~/types'
-import { useValues } from 'kea'
+import { useActions, useValues } from 'kea'
import { FeatureFlagLogicProps, featureFlagLogic } from 'scenes/feature-flags/featureFlagLogic'
import { FeatureFlagCodeExample } from 'scenes/feature-flags/FeatureFlagCodeExample'
import { urls } from 'scenes/urls'
import { JSONContent, NotebookNodeProps } from '../Notebook/utils'
import { notebookNodeLogic } from './notebookNodeLogic'
import { useEffect } from 'react'
+import { NotFound } from 'lib/components/NotFound'
-const Component = ({
- attributes,
- updateAttributes,
-}: NotebookNodeProps): JSX.Element => {
+const Component = ({ attributes }: NotebookNodeProps): JSX.Element => {
const { id } = attributes
- const { featureFlag } = useValues(featureFlagLogic({ id }))
+ const { featureFlag, featureFlagMissing } = useValues(featureFlagLogic({ id }))
const { expanded } = useValues(notebookNodeLogic)
+ const { setTitlePlaceholder } = useActions(notebookNodeLogic)
useEffect(() => {
- updateAttributes({
- title: featureFlag.key ? `Feature flag code example: ${featureFlag.key}` : 'Feature flag code example',
- })
+ setTitlePlaceholder(
+ featureFlag.key ? `Feature flag code example: ${featureFlag.key}` : 'Feature flag code example'
+ )
}, [featureFlag?.key])
+ if (!featureFlagMissing) {
+ return
+ }
+
return {expanded && }
}
@@ -31,7 +34,7 @@ type NotebookNodeFlagCodeExampleAttributes = {
export const NotebookNodeFlagCodeExample = createPostHogWidgetNode({
nodeType: NotebookNodeType.FeatureFlagCodeExample,
- defaultTitle: 'Feature flag code example',
+ titlePlaceholder: 'Feature flag code example',
Component,
heightEstimate: '3rem',
startExpanded: true,
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeGroup.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeGroup.tsx
new file mode 100644
index 0000000000000..af0df8cd9699b
--- /dev/null
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeGroup.tsx
@@ -0,0 +1,111 @@
+import { createPostHogWidgetNode } from 'scenes/notebooks/Nodes/NodeWrapper'
+import { NotebookNodeType, PropertyFilterType, PropertyOperator } from '~/types'
+import { useActions, useValues } from 'kea'
+import { urls } from 'scenes/urls'
+import { LemonSkeleton } from 'lib/lemon-ui/LemonSkeleton'
+import { notebookNodeLogic } from './notebookNodeLogic'
+import { NotebookNodeProps } from '../Notebook/utils'
+import { useEffect } from 'react'
+import clsx from 'clsx'
+import { NotFound } from 'lib/components/NotFound'
+import { groupLogic } from 'scenes/groups/groupLogic'
+import { groupDisplayId } from 'scenes/persons/GroupActorDisplay'
+import { GroupCaption } from 'scenes/groups/Group'
+import { NodeKind } from '~/queries/schema'
+import { defaultDataTableColumns } from '~/queries/nodes/DataTable/utils'
+
+const Component = ({ attributes }: NotebookNodeProps): JSX.Element => {
+ const { id, groupTypeIndex } = attributes
+
+ const logic = groupLogic({ groupKey: id, groupTypeIndex: groupTypeIndex })
+ const { groupData, groupDataLoading, groupTypeName } = useValues(logic)
+ const { setActions, insertAfter, setTitlePlaceholder } = useActions(notebookNodeLogic)
+
+ const groupDisplay = groupData ? groupDisplayId(groupData.group_key, groupData.group_properties) : 'Group'
+
+ useEffect(() => {
+ const title = groupData ? `${groupTypeName}: ${groupDisplay}` : 'Group'
+ setTitlePlaceholder(title)
+ setActions([
+ {
+ text: 'Events for this group',
+ onClick: () => {
+ insertAfter({
+ type: NotebookNodeType.Query,
+ attrs: {
+ title: `Events for ${title}`,
+ query: {
+ kind: NodeKind.DataTableNode,
+ full: true,
+ source: {
+ kind: NodeKind.EventsQuery,
+ select: defaultDataTableColumns(NodeKind.EventsQuery),
+ after: '-24h',
+ properties: [
+ {
+ key: `$group_${groupTypeIndex}`,
+ value: id,
+ type: PropertyFilterType.Event,
+ operator: PropertyOperator.Exact,
+ },
+ ],
+ },
+ },
+ },
+ })
+ },
+ },
+ ])
+ }, [groupData])
+
+ if (!groupData && !groupDataLoading) {
+ return
+ }
+
+ return (
+
+
+ {groupDataLoading ? (
+
+ ) : groupData ? (
+ <>
+
{groupDisplay}
+
+ >
+ ) : null}
+
+
+ )
+}
+
+type NotebookNodeGroupAttributes = {
+ id: string
+ groupTypeIndex: number
+}
+
+export const NotebookNodeGroup = createPostHogWidgetNode({
+ nodeType: NotebookNodeType.Group,
+ titlePlaceholder: 'Group',
+ Component,
+ heightEstimate: 300,
+ minHeight: 100,
+ href: (attrs) => urls.group(attrs.groupTypeIndex, attrs.id),
+ resizeable: false,
+ expandable: false,
+ attributes: {
+ id: {},
+ groupTypeIndex: {},
+ },
+ pasteOptions: {
+ find: urls.groups('(.+)'),
+ getAttributes: async (match) => {
+ const [groupTypeIndex, id] = match[1].split('/')
+ return { id: decodeURIComponent(id), groupTypeIndex: parseInt(groupTypeIndex) }
+ },
+ },
+ serializedText: (attrs) => {
+ const title = attrs?.title || ''
+ const id = attrs?.id || ''
+ return `${title} ${id}`.trim()
+ },
+})
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeImage.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeImage.tsx
index d2b8cdb051d23..7af4f1e7e956f 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeImage.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeImage.tsx
@@ -77,7 +77,7 @@ type NotebookNodeImageAttributes = {
export const NotebookNodeImage = createPostHogWidgetNode({
nodeType: NotebookNodeType.Image,
- defaultTitle: 'Image',
+ titlePlaceholder: 'Image',
Component,
serializedText: (attrs) => {
// TODO file is null when this runs... should it be?
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodePerson.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodePerson.tsx
index fcd23e8bdf11f..56d31294ccc07 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodePerson.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodePerson.tsx
@@ -14,21 +14,20 @@ import { useEffect } from 'react'
import { PropertyIcon } from 'lib/components/PropertyIcon'
import clsx from 'clsx'
import { NodeKind } from '~/queries/schema'
+import { NotFound } from 'lib/components/NotFound'
-const Component = ({ attributes, updateAttributes }: NotebookNodeProps): JSX.Element => {
+const Component = ({ attributes }: NotebookNodeProps): JSX.Element => {
const { id } = attributes
const logic = personLogic({ id })
const { person, personLoading } = useValues(logic)
const { expanded } = useValues(notebookNodeLogic)
const { setExpanded, setActions, insertAfter } = useActions(notebookNodeLogic)
-
- const title = person ? `Person: ${asDisplay(person)}` : 'Person'
+ const { setTitlePlaceholder } = useActions(notebookNodeLogic)
useEffect(() => {
- updateAttributes({
- title,
- })
+ const title = person ? `Person: ${asDisplay(person)}` : 'Person'
+ setTitlePlaceholder(title)
setActions([
{
text: 'Events',
@@ -98,6 +97,10 @@ const Component = ({ attributes, updateAttributes }: NotebookNodeProps
)
+ if (!person && !personLoading) {
+ return
+ }
+
return (
@@ -146,7 +149,7 @@ type NotebookNodePersonAttributes = {
export const NotebookNodePerson = createPostHogWidgetNode
({
nodeType: NotebookNodeType.Person,
- defaultTitle: 'Person',
+ titlePlaceholder: 'Person',
Component,
heightEstimate: 300,
minHeight: 100,
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodePlaylist.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodePlaylist.tsx
index d648dfef3bce8..06f018a156c3d 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodePlaylist.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodePlaylist.tsx
@@ -137,7 +137,7 @@ type NotebookNodePlaylistAttributes = {
export const NotebookNodePlaylist = createPostHogWidgetNode({
nodeType: NotebookNodeType.RecordingPlaylist,
- defaultTitle: 'Session replays',
+ titlePlaceholder: 'Session replays',
Component,
heightEstimate: 'calc(100vh - 20rem)',
href: (attrs) => {
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeQuery.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeQuery.tsx
index 10bc6ee836332..738a8fdb18b4c 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeQuery.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeQuery.tsx
@@ -2,7 +2,7 @@ import { Query } from '~/queries/Query/Query'
import { DataTableNode, InsightVizNode, NodeKind, QuerySchema } from '~/queries/schema'
import { createPostHogWidgetNode } from 'scenes/notebooks/Nodes/NodeWrapper'
import { InsightLogicProps, InsightShortId, NotebookNodeType } from '~/types'
-import { useMountedLogic, useValues } from 'kea'
+import { useActions, useMountedLogic, useValues } from 'kea'
import { useEffect, useMemo } from 'react'
import { notebookNodeLogic } from './notebookNodeLogic'
import { NotebookNodeProps, NotebookNodeAttributeProperties } from '../Notebook/utils'
@@ -26,13 +26,11 @@ const DEFAULT_QUERY: QuerySchema = {
},
}
-const Component = ({
- attributes,
- updateAttributes,
-}: NotebookNodeProps): JSX.Element | null => {
+const Component = ({ attributes }: NotebookNodeProps): JSX.Element | null => {
const { query, nodeId } = attributes
const nodeLogic = useMountedLogic(notebookNodeLogic)
const { expanded } = useValues(nodeLogic)
+ const { setTitlePlaceholder } = useActions(nodeLogic)
useEffect(() => {
let title = 'Query'
@@ -56,7 +54,7 @@ const Component = ({
title = (logic?.values.insight.name || logic?.values.insight.derived_name) ?? 'Saved Insight'
}
- updateAttributes({ title: title })
+ setTitlePlaceholder(title)
}, [query])
const modifiedQuery = useMemo(() => {
@@ -195,7 +193,7 @@ export const Settings = ({
export const NotebookNodeQuery = createPostHogWidgetNode({
nodeType: NotebookNodeType.Query,
- defaultTitle: 'Query',
+ titlePlaceholder: 'Query',
Component,
heightEstimate: 500,
minHeight: 200,
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeRecording.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeRecording.tsx
index 448679a1def8a..245a52e07dfd5 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeRecording.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeRecording.tsx
@@ -22,6 +22,7 @@ import { LemonSwitch } from '@posthog/lemon-ui'
import { JSONContent, NotebookNodeProps, NotebookNodeAttributeProperties } from '../Notebook/utils'
import { asDisplay } from 'scenes/persons/person-utils'
import { IconComment, IconPerson } from 'lib/lemon-ui/icons'
+import { NotFound } from 'lib/components/NotFound'
const HEIGHT = 500
const MIN_HEIGHT = 400
@@ -47,7 +48,9 @@ const Component = ({ attributes }: NotebookNodeProps
+ }
+
return !expanded ? (
{sessionPlayerMetaData ? (
@@ -135,7 +142,7 @@ type NotebookNodeRecordingAttributes = {
export const NotebookNodeRecording = createPostHogWidgetNode
({
nodeType: NotebookNodeType.Recording,
- defaultTitle: 'Session replay',
+ titlePlaceholder: 'Session replay',
Component,
heightEstimate: HEIGHT,
minHeight: MIN_HEIGHT,
diff --git a/frontend/src/scenes/notebooks/Nodes/NotebookNodeSurvey.tsx b/frontend/src/scenes/notebooks/Nodes/NotebookNodeSurvey.tsx
index 6120a20a31412..0899fb415c3f6 100644
--- a/frontend/src/scenes/notebooks/Nodes/NotebookNodeSurvey.tsx
+++ b/frontend/src/scenes/notebooks/Nodes/NotebookNodeSurvey.tsx
@@ -15,12 +15,13 @@ import { SurveyResult } from 'scenes/surveys/SurveyView'
import { SurveyAppearance } from 'scenes/surveys/SurveyAppearance'
import { SurveyReleaseSummary } from 'scenes/surveys/Survey'
import { useEffect } from 'react'
+import { NotFound } from 'lib/components/NotFound'
-const Component = ({ attributes, updateAttributes }: NotebookNodeProps): JSX.Element => {
+const Component = ({ attributes }: NotebookNodeProps): JSX.Element => {
const { id } = attributes
- const { survey, surveyLoading, hasTargetingFlag } = useValues(surveyLogic({ id }))
+ const { survey, surveyLoading, hasTargetingFlag, surveyMissing } = useValues(surveyLogic({ id }))
const { expanded, nextNode } = useValues(notebookNodeLogic)
- const { insertAfter, setActions } = useActions(notebookNodeLogic)
+ const { insertAfter, setActions, setTitlePlaceholder } = useActions(notebookNodeLogic)
useEffect(() => {
setActions([
@@ -38,9 +39,13 @@ const Component = ({ attributes, updateAttributes }: NotebookNodeProps {
- updateAttributes({ title: survey.name ? `Survey: ${survey.name}` : 'Survey' })
+ setTitlePlaceholder(survey.name ? `Survey: ${survey.name}` : 'Survey')
}, [survey.name])
+ if (surveyMissing) {
+ return
+ }
+
return (
@@ -135,7 +140,7 @@ type NotebookNodeSurveyAttributes = {
export const NotebookNodeSurvey = createPostHogWidgetNode({
nodeType: NotebookNodeType.Survey,
- defaultTitle: 'Survey',
+ titlePlaceholder: 'Survey',
Component,
heightEstimate: '3rem',
href: (attrs) => urls.survey(attrs.id),
diff --git a/frontend/src/scenes/notebooks/Nodes/components/NotebookNodeTitle.tsx b/frontend/src/scenes/notebooks/Nodes/components/NotebookNodeTitle.tsx
new file mode 100644
index 0000000000000..4e7f6e2a2b045
--- /dev/null
+++ b/frontend/src/scenes/notebooks/Nodes/components/NotebookNodeTitle.tsx
@@ -0,0 +1,63 @@
+import { KeyboardEvent } from 'react'
+import { useActions, useValues } from 'kea'
+import { notebookNodeLogic } from '../notebookNodeLogic'
+import { useEffect, useState } from 'react'
+import { LemonInput, Tooltip } from '@posthog/lemon-ui'
+import { notebookLogic } from 'scenes/notebooks/Notebook/notebookLogic'
+
+export function NotebookNodeTitle(): JSX.Element {
+ const { isEditable } = useValues(notebookLogic)
+ const { nodeAttributes, title, titlePlaceholder } = useValues(notebookNodeLogic)
+ const { updateAttributes } = useActions(notebookNodeLogic)
+ const [editing, setEditing] = useState(false)
+ const [newValue, setNewValue] = useState('')
+
+ useEffect(() => {
+ setNewValue(nodeAttributes.title ?? '')
+ }, [editing])
+
+ const commitEdit = (): void => {
+ updateAttributes({
+ title: newValue ?? undefined,
+ })
+
+ setEditing(false)
+ }
+
+ const onKeyUp = (e: KeyboardEvent): void => {
+ // Esc cancels, enter commits
+ if (e.key === 'Escape') {
+ setEditing(false)
+ } else if (e.key === 'Enter') {
+ commitEdit()
+ }
+ }
+
+ return !isEditable ? (
+
+ {title}
+
+ ) : !editing ? (
+
+ setEditing(true)}
+ >
+ {title}
+
+
+ ) : (
+ setNewValue(e)}
+ onBlur={commitEdit}
+ onKeyUp={onKeyUp}
+ onFocus={(e) => e.target.select()}
+ />
+ )
+}
diff --git a/frontend/src/scenes/notebooks/Nodes/notebookNodeLogic.ts b/frontend/src/scenes/notebooks/Nodes/notebookNodeLogic.ts
index af8b15202d970..22701188b98ec 100644
--- a/frontend/src/scenes/notebooks/Nodes/notebookNodeLogic.ts
+++ b/frontend/src/scenes/notebooks/Nodes/notebookNodeLogic.ts
@@ -39,7 +39,7 @@ export type NotebookNodeLogicProps = {
settings: NotebookNodeSettings
messageListeners?: NotebookNodeMessagesListeners
startExpanded: boolean
- defaultTitle: string
+ titlePlaceholder: string
} & NotebookNodeAttributeProperties
const computeResizeable = (
@@ -69,6 +69,7 @@ export const notebookNodeLogic = kea([
toggleEditing: true,
scrollIntoView: true,
setMessageListeners: (listeners: NotebookNodeMessagesListeners) => ({ listeners }),
+ setTitlePlaceholder: (titlePlaceholder: string) => ({ titlePlaceholder }),
}),
connect((props: NotebookNodeLogicProps) => ({
@@ -113,13 +114,23 @@ export const notebookNodeLogic = kea([
setMessageListeners: (_, { listeners }) => listeners,
},
],
+
+ titlePlaceholder: [
+ props.titlePlaceholder,
+ {
+ setTitlePlaceholder: (_, { titlePlaceholder }) => titlePlaceholder,
+ },
+ ],
})),
selectors({
notebookLogic: [(_, p) => [p.notebookLogic], (notebookLogic) => notebookLogic],
nodeAttributes: [(_, p) => [p.attributes], (nodeAttributes) => nodeAttributes],
settings: [(_, p) => [p.settings], (settings) => settings],
- defaultTitle: [(_, p) => [p.defaultTitle], (title) => title],
+ title: [
+ (s) => [s.titlePlaceholder, s.nodeAttributes],
+ (titlePlaceholder, nodeAttributes) => nodeAttributes.title || titlePlaceholder,
+ ],
sendMessage: [
(s) => [s.messageListeners],
diff --git a/frontend/src/scenes/notebooks/Notebook/Editor.tsx b/frontend/src/scenes/notebooks/Notebook/Editor.tsx
index c05cf3c31cb42..39c6c29115958 100644
--- a/frontend/src/scenes/notebooks/Notebook/Editor.tsx
+++ b/frontend/src/scenes/notebooks/Notebook/Editor.tsx
@@ -34,6 +34,8 @@ import { InlineMenu } from './InlineMenu'
import NodeGapInsertionExtension from './Extensions/NodeGapInsertion'
import { notebookLogic } from './notebookLogic'
import { sampleOne } from 'lib/utils'
+import { NotebookNodeGroup } from '../Nodes/NotebookNodeGroup'
+import { NotebookNodeCohort } from '../Nodes/NotebookNodeCohort'
const CustomDocument = ExtensionDocument.extend({
content: 'heading block*',
@@ -99,6 +101,8 @@ export function Editor(): JSX.Element {
NotebookNodeReplayTimestamp,
NotebookNodePlaylist,
NotebookNodePerson,
+ NotebookNodeCohort,
+ NotebookNodeGroup,
NotebookNodeFlagCodeExample,
NotebookNodeFlag,
NotebookNodeExperiment,
diff --git a/frontend/src/scenes/notebooks/Notebook/Notebook.scss b/frontend/src/scenes/notebooks/Notebook/Notebook.scss
index e56aab45a21ce..a1437dc89ed8e 100644
--- a/frontend/src/scenes/notebooks/Notebook/Notebook.scss
+++ b/frontend/src/scenes/notebooks/Notebook/Notebook.scss
@@ -199,6 +199,7 @@
.NotebookRecordingTimestamp {
display: inline-flex;
+ max-height: 22px;
}
// overriding ::selection is necessary here because
diff --git a/frontend/src/scenes/notebooks/Notebook/Notebook.tsx b/frontend/src/scenes/notebooks/Notebook/Notebook.tsx
index f6fc4be7a1ae5..43146b75b270f 100644
--- a/frontend/src/scenes/notebooks/Notebook/Notebook.tsx
+++ b/frontend/src/scenes/notebooks/Notebook/Notebook.tsx
@@ -79,7 +79,7 @@ export function Notebook({ shortId, editable = false, initialAutofocus = 'start'
className="my-4"
action={{
onClick: duplicateNotebook,
- children: 'Create notebook',
+ children: 'Create copy',
}}
>
This is a template. You can create a copy of it to edit and use as your own.
diff --git a/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx b/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx
index e573eecd30c3f..8adeb7f4236c9 100644
--- a/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx
+++ b/frontend/src/scenes/notebooks/Notebook/NotebookListMini.tsx
@@ -24,7 +24,7 @@ export function NotebookListMini({ selectedNotebookId }: NotebookListMiniProps):
return (
} status="primary-alt" sideIcon={null}>
- {selectedTitle || 'Notebooks'}
+ {selectedTitle || 'Notebooks'}
)
diff --git a/frontend/src/scenes/notebooks/Notebook/NotebookPopover.tsx b/frontend/src/scenes/notebooks/Notebook/NotebookPopover.tsx
index 37015d2dbb177..1af1ba7e7c282 100644
--- a/frontend/src/scenes/notebooks/Notebook/NotebookPopover.tsx
+++ b/frontend/src/scenes/notebooks/Notebook/NotebookPopover.tsx
@@ -4,7 +4,7 @@ import './NotebookPopover.scss'
import { Notebook } from './Notebook'
import { notebookPopoverLogic } from 'scenes/notebooks/Notebook/notebookPopoverLogic'
import { LemonButton } from '@posthog/lemon-ui'
-import { IconFullScreen, IconChevronRight, IconLink } from 'lib/lemon-ui/icons'
+import { IconFullScreen, IconChevronRight, IconOpenInNew, IconShare } from 'lib/lemon-ui/icons'
import { useEffect, useMemo, useRef } from 'react'
import { useKeyboardHotkeys } from 'lib/hooks/useKeyboardHotkeys'
import { NotebookListMini } from './NotebookListMini'
@@ -14,6 +14,7 @@ import { notebookLogic } from './notebookLogic'
import { urls } from 'scenes/urls'
import { NotebookPopoverDropzone } from './NotebookPopoverDropzone'
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver'
+import { openNotebookShareDialog } from './NotebookShare'
export function NotebookPopoverCard(): JSX.Element | null {
const { visibility, shownAtLeastOnce, fullScreen, selectedNotebook, initialAutofocus, droppedResource } =
@@ -38,7 +39,7 @@ export function NotebookPopoverCard(): JSX.Element | null {
return (
-
+
selectNotebook(notebook.short_id)}
@@ -53,8 +54,16 @@ export function NotebookPopoverCard(): JSX.Element | null {
to={urls.notebook(selectedNotebook)}
onClick={() => setVisibility('hidden')}
status="primary-alt"
- icon={}
- tooltip="Go to Notebook"
+ icon={}
+ tooltip="View notebook outside of popover"
+ tooltipPlacement="left"
+ />
+ openNotebookShareDialog({ shortId: selectedNotebook })}
+ status="primary-alt"
+ icon={}
+ tooltip="Share notebook"
tooltipPlacement="left"
/>
diff --git a/frontend/src/scenes/notebooks/Notebook/NotebookShare.tsx b/frontend/src/scenes/notebooks/Notebook/NotebookShare.tsx
new file mode 100644
index 0000000000000..c40031ad20dfc
--- /dev/null
+++ b/frontend/src/scenes/notebooks/Notebook/NotebookShare.tsx
@@ -0,0 +1,72 @@
+import { LemonBanner, LemonButton, LemonDivider } from '@posthog/lemon-ui'
+import { combineUrl } from 'kea-router'
+import { IconCopy } from 'lib/lemon-ui/icons'
+import { LemonDialog } from 'lib/lemon-ui/LemonDialog'
+import { copyToClipboard } from 'lib/utils'
+import posthog from 'posthog-js'
+import { useState } from 'react'
+import { urls } from 'scenes/urls'
+
+export type NotebookShareProps = {
+ shortId: string
+}
+export function NotebookShare({ shortId }: NotebookShareProps): JSX.Element {
+ const url = combineUrl(`${window.location.origin}${urls.notebook(shortId)}`).url
+
+ const [interestTracked, setInterestTracked] = useState(false)
+
+ const trackInterest = (): void => {
+ posthog.capture('pressed interested in notebook sharing', { url })
+ }
+
+ return (
+
+
Internal Link
+
+ Click the button below to copy a direct link to this Notebook. Make sure the person you share it
+ with has access to this PostHog project.
+
+
}
+ onClick={async () => await copyToClipboard(url, 'notebook link')}
+ title={url}
+ >
+
{url}
+
+
+
+
+
External Sharing
+
+
{
+ if (!interestTracked) {
+ trackInterest()
+ setInterestTracked(true)
+ }
+ },
+ }}
+ >
+ We don’t currently support sharing notebooks externally, but it’s on our roadmap!
+
+
+ )
+}
+
+export function openNotebookShareDialog({ shortId }: NotebookShareProps): void {
+ LemonDialog.open({
+ title: 'Share notebook',
+ content: ,
+ width: 600,
+ primaryButton: {
+ children: 'Close',
+ type: 'secondary',
+ },
+ })
+}
diff --git a/frontend/src/scenes/notebooks/Notebook/NotebookSidebar.tsx b/frontend/src/scenes/notebooks/Notebook/NotebookSidebar.tsx
index b909c5c340da0..93b03871338b7 100644
--- a/frontend/src/scenes/notebooks/Notebook/NotebookSidebar.tsx
+++ b/frontend/src/scenes/notebooks/Notebook/NotebookSidebar.tsx
@@ -31,12 +31,12 @@ export const NotebookSidebar = (): JSX.Element | null => {
const Widgets = ({ logic }: { logic: BuiltLogic }): JSX.Element => {
const { setEditingNodeId } = useActions(notebookLogic)
- const { settings: Settings, nodeAttributes, defaultTitle } = useValues(logic)
+ const { settings: Settings, nodeAttributes, title } = useValues(logic)
const { updateAttributes, selectNode } = useActions(logic)
return (
diff --git a/frontend/src/scenes/notebooks/Notebook/SlashCommands.tsx b/frontend/src/scenes/notebooks/Notebook/SlashCommands.tsx
index 87d5ee8c1e5c2..04a27423ee2b8 100644
--- a/frontend/src/scenes/notebooks/Notebook/SlashCommands.tsx
+++ b/frontend/src/scenes/notebooks/Notebook/SlashCommands.tsx
@@ -19,13 +19,14 @@ import {
import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react'
import { EditorCommands, EditorRange } from './utils'
import { NotebookNodeType } from '~/types'
-import { examples } from '~/queries/examples'
import { Popover } from 'lib/lemon-ui/Popover'
import { KeyboardShortcut } from '~/layout/navigation-3000/components/KeyboardShortcut'
import Fuse from 'fuse.js'
import { useValues } from 'kea'
import { notebookLogic } from './notebookLogic'
import { selectFile } from '../Nodes/utils'
+import { NodeKind } from '~/queries/schema'
+import { defaultDataTableColumns } from '~/queries/nodes/DataTable/utils'
type SlashCommandsProps = {
mode: 'slash' | 'add'
@@ -243,21 +244,77 @@ const SLASH_COMMANDS: SlashCommandsItem[] = [
search: 'sql',
icon: ,
command: (chain) =>
- chain.insertContent({ type: NotebookNodeType.Query, attrs: { query: examples['HogQLTable'] } }),
+ chain.insertContent({
+ type: NotebookNodeType.Query,
+ attrs: {
+ query: {
+ kind: NodeKind.DataTableNode,
+ full: true,
+ source: {
+ kind: NodeKind.HogQLQuery,
+ query: `select event,
+ person.properties.email,
+ properties.$browser,
+ count()
+ from events
+ where {filters} -- replaced with global date and property filters
+ and person.properties.email is not null
+ group by event,
+ properties.$browser,
+ person.properties.email
+ order by count() desc
+ limit 100`,
+ filters: {
+ dateRange: {
+ date_from: '-24h',
+ },
+ },
+ },
+ },
+ },
+ }),
},
{
title: 'Events',
search: 'data explore',
icon: ,
command: (chain) =>
- chain.insertContent({ type: NotebookNodeType.Query, attrs: { query: examples['EventsTableFull'] } }),
+ chain.insertContent({
+ type: NotebookNodeType.Query,
+ attrs: {
+ query: {
+ kind: NodeKind.DataTableNode,
+ full: true,
+ source: {
+ kind: NodeKind.EventsQuery,
+ select: defaultDataTableColumns(NodeKind.EventsQuery),
+ properties: [],
+ after: '-24h',
+ limit: 100,
+ },
+ },
+ },
+ }),
},
{
title: 'Persons',
search: 'people users',
icon: ,
command: (chain) =>
- chain.insertContent({ type: NotebookNodeType.Query, attrs: { query: examples['PersonsTableFull'] } }),
+ chain.insertContent({
+ type: NotebookNodeType.Query,
+ attrs: {
+ query: {
+ kind: NodeKind.DataTableNode,
+ full: true,
+ columns: defaultDataTableColumns(NodeKind.PersonsNode),
+ source: {
+ kind: NodeKind.PersonsNode,
+ properties: [],
+ },
+ },
+ },
+ }),
},
{
title: 'Session Replays',
diff --git a/frontend/src/scenes/notebooks/Notebook/utils.ts b/frontend/src/scenes/notebooks/Notebook/utils.ts
index 6fb341763b37b..62fd0387c54e2 100644
--- a/frontend/src/scenes/notebooks/Notebook/utils.ts
+++ b/frontend/src/scenes/notebooks/Notebook/utils.ts
@@ -26,7 +26,7 @@ export type CustomNotebookNodeAttributes = Record
export type NotebookNodeAttributes = T & {
nodeId: string
height?: string | number
- title: string
+ title?: string
}
// NOTE: Pushes users to use the parsed "attributes" instead
@@ -117,6 +117,8 @@ export const textContent = (node: any): string => {
'ph-recording-playlist': customOrTitleSerializer,
'ph-replay-timestamp': customOrTitleSerializer,
'ph-survey': customOrTitleSerializer,
+ 'ph-group': customOrTitleSerializer,
+ 'ph-cohort': customOrTitleSerializer,
}
return getText(node, {
diff --git a/frontend/src/scenes/notebooks/NotebookScene.tsx b/frontend/src/scenes/notebooks/NotebookScene.tsx
index a69e66f2ce483..805a1186f9039 100644
--- a/frontend/src/scenes/notebooks/NotebookScene.tsx
+++ b/frontend/src/scenes/notebooks/NotebookScene.tsx
@@ -15,6 +15,7 @@ import {
IconExport,
IconHelpOutline,
IconNotification,
+ IconShare,
} from 'lib/lemon-ui/icons'
import { LemonMenu } from 'lib/lemon-ui/LemonMenu'
import { notebooksModel } from '~/models/notebooksModel'
@@ -25,6 +26,7 @@ import './NotebookScene.scss'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS } from 'lib/constants'
import { NotebookLoadingState } from './Notebook/NotebookLoadingState'
+import { openNotebookShareDialog } from './Notebook/NotebookShare'
interface NotebookSceneProps {
shortId?: string
@@ -102,6 +104,11 @@ export function NotebookScene(): JSX.Element {
icon: ,
onClick: () => setShowHistory(!showHistory),
},
+ {
+ label: 'Share',
+ icon: ,
+ onClick: () => openNotebookShareDialog({ shortId: notebookId }),
+ },
!isTemplate && {
label: 'Delete',
icon: ,
@@ -140,13 +147,13 @@ export function NotebookScene(): JSX.Element {
}}
tooltip={
<>
- Pins the notebook to the right, allowing you to view it while navigating the rest of
- PostHog. This is great for dragging and dropping elements like Insights, Recordings or
- even Feature Flags into your active Notebook.
+ Opens the notebook in a popover, that can be accessed from anywhere in the PostHog app.
+ This is great for dragging and dropping elements like Insights, Recordings or even
+ Feature Flags into your active Notebook.
>
}
>
- Pin to side
+ Open in popover
diff --git a/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.stories.tsx b/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.stories.tsx
index 64e6fadadb513..1baff1b2871f6 100644
--- a/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.stories.tsx
+++ b/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.stories.tsx
@@ -13,9 +13,27 @@ const allNotebooks = [
{
title: 'my amazing notebook',
short_id: 'abc',
+ created_by: {
+ first_name: 'Ben',
+ email: 'ben@posthog.com',
+ },
+ },
+ {
+ title: 'and another amazing notebook',
+ short_id: 'def',
+ created_by: {
+ first_name: 'Paul',
+ email: 'paul@posthog.com',
+ },
+ },
+ {
+ title: 'an empty notebook',
+ short_id: 'ghi',
+ created_by: {
+ first_name: 'David',
+ email: 'david@posthog.com',
+ },
},
- { title: 'and another amazing notebook', short_id: 'def' },
- { title: 'an empty notebook', short_id: 'ghi' },
]
const Template: StoryFn = (props) => {
diff --git a/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx b/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx
index edc4a3a3173b7..8aec2c9ffc917 100644
--- a/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx
+++ b/frontend/src/scenes/notebooks/NotebookSelectButton/NotebookSelectButton.tsx
@@ -17,7 +17,7 @@ import { notebookNodeLogicType } from '../Nodes/notebookNodeLogicType'
import { FlaggedFeature } from 'lib/components/FlaggedFeature'
import { FEATURE_FLAGS } from 'lib/constants'
import { ReactChild, useEffect } from 'react'
-import { LemonDivider } from '@posthog/lemon-ui'
+import { LemonDivider, ProfilePicture } from '@posthog/lemon-ui'
export type NotebookSelectProps = NotebookSelectButtonLogicProps & {
newNotebookTitle?: string
@@ -50,8 +50,22 @@ function NotebooksChoiceList(props: {
) : (
props.notebooks.map((notebook, i) => {
return (
- props.onClick(notebook.short_id)}>
- {notebook.title || `Untitled (${notebook.short_id})`}
+ `}
+ />
+ ) : null
+ }
+ fullWidth
+ onClick={() => props.onClick(notebook.short_id)}
+ >
+ {notebook.title || `Untitled (${notebook.short_id})`}
)
})
diff --git a/frontend/src/scenes/notebooks/NotebooksTable/ContainsTypeFilter.tsx b/frontend/src/scenes/notebooks/NotebooksTable/ContainsTypeFilter.tsx
index ac8f58010de68..5437da52bc4c1 100644
--- a/frontend/src/scenes/notebooks/NotebooksTable/ContainsTypeFilter.tsx
+++ b/frontend/src/scenes/notebooks/NotebooksTable/ContainsTypeFilter.tsx
@@ -15,6 +15,8 @@ export const fromNodeTypeToLabel: Omit, Noteboo
[NotebookNodeType.Recording]: 'Session recordings',
[NotebookNodeType.RecordingPlaylist]: 'Session replay playlists',
[NotebookNodeType.ReplayTimestamp]: 'Session recording comments',
+ [NotebookNodeType.Cohort]: 'Cohorts',
+ [NotebookNodeType.Group]: 'Groups',
}
export function ContainsTypeFilters({
diff --git a/frontend/src/scenes/notebooks/NotebooksTable/NotebooksTable.tsx b/frontend/src/scenes/notebooks/NotebooksTable/NotebooksTable.tsx
index 2ce18eba28801..6f57e08427f01 100644
--- a/frontend/src/scenes/notebooks/NotebooksTable/NotebooksTable.tsx
+++ b/frontend/src/scenes/notebooks/NotebooksTable/NotebooksTable.tsx
@@ -91,6 +91,7 @@ export function NotebooksTable(): JSX.Element {
},
children: 'Get started',
}}
+ dismissKey="notebooks-preview-banner"
>
Welcome to the preview of Notebooks - a great way to bring Insights, Replays, Feature Flags and
many more PostHog prodcuts together into one place.
diff --git a/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.ts b/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.ts
index d5edf19da253a..8d4d1ebe5c878 100644
--- a/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.ts
+++ b/frontend/src/scenes/session-recordings/file-playback/sessionRecordingFilePlaybackLogic.ts
@@ -138,7 +138,7 @@ export const sessionRecordingFilePlaybackLogic = kea
diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts
index 2e0c2cb130a3b..5dbf59b3015fe 100644
--- a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts
+++ b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.test.ts
@@ -217,8 +217,8 @@ describe('sessionRecordingDataLogic', () => {
logic.actions.loadRecordingSnapshots()
})
.toDispatchActionsInAnyOrder([
- 'loadRecordingSnapshotsV2',
- 'loadRecordingSnapshotsV2Success',
+ 'loadRecordingSnapshots',
+ 'loadRecordingSnapshotsSuccess',
'loadEvents',
'loadEventsSuccess',
])
diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts
index e989e3a8bf863..2a28edac17964 100644
--- a/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts
+++ b/frontend/src/scenes/session-recordings/player/sessionRecordingDataLogic.ts
@@ -20,8 +20,6 @@ import { eventUsageLogic } from 'lib/utils/eventUsageLogic'
import { eventWithTime } from '@rrweb/types'
import { Dayjs, dayjs } from 'lib/dayjs'
import type { sessionRecordingDataLogicType } from './sessionRecordingDataLogicType'
-import { teamLogic } from 'scenes/teamLogic'
-import { userLogic } from 'scenes/userLogic'
import { chainToElements } from 'lib/utils/elements-chain'
import { captureException } from '@sentry/react'
import { createSegments, mapSnapshotsToWindowId } from './utils/segmenter'
@@ -135,7 +133,6 @@ export const sessionRecordingDataLogic = kea([
key(({ sessionRecordingId }) => sessionRecordingId || 'no-session-recording-id'),
connect({
logic: [eventUsageLogic],
- values: [teamLogic, ['currentTeamId'], userLogic, ['hasAvailableFeature']],
}),
defaults({
sessionPlayerMetaData: null as SessionRecordingType | null,
@@ -144,10 +141,7 @@ export const sessionRecordingDataLogic = kea([
setFilters: (filters: Partial) => ({ filters }),
loadRecordingMeta: true,
maybeLoadRecordingMeta: true,
- loadRecordingSnapshotsV2: (source?: SessionRecordingSnapshotSource) => ({ source }),
- loadRecordingSnapshots: true,
- loadRecordingSnapshotsSuccess: true,
- loadRecordingSnapshotsFailure: true,
+ loadRecordingSnapshots: (source?: SessionRecordingSnapshotSource) => ({ source }),
loadEvents: true,
loadFullEventData: (event: RecordingEventType) => ({ event }),
reportViewed: true,
@@ -185,15 +179,9 @@ export const sessionRecordingDataLogic = kea([
}
},
loadRecordingSnapshots: () => {
- if (values.sessionPlayerSnapshotDataLoading) {
- return
- }
- if (!values.sessionPlayerSnapshotData?.snapshots) {
- actions.loadRecordingSnapshotsV2()
- }
actions.loadEvents()
},
- loadRecordingSnapshotsV2Success: () => {
+ loadRecordingSnapshotsSuccess: () => {
const { snapshots, sources } = values.sessionPlayerSnapshotData ?? {}
if (snapshots && !snapshots.length && sources?.length === 1) {
// We got only a snapshot response for realtime, and it was empty
@@ -204,15 +192,6 @@ export const sessionRecordingDataLogic = kea([
return
}
- actions.loadRecordingSnapshotsSuccess()
-
- const nextSourceToLoad = sources?.find((s) => !s.loaded)
-
- if (nextSourceToLoad) {
- actions.loadRecordingSnapshotsV2(nextSourceToLoad)
- }
- },
- loadRecordingSnapshotsSuccess: () => {
cache.firstPaintDurationRow = {
size: (values.sessionPlayerSnapshotData?.snapshots ?? []).length,
duration: Math.round(performance.now() - cache.snapshotsStartTime),
@@ -220,9 +199,12 @@ export const sessionRecordingDataLogic = kea([
actions.reportViewed()
actions.reportUsageIfFullyLoaded()
- },
- loadRecordingSnapshotsV2Failure: () => {
- actions.loadRecordingSnapshotsFailure()
+
+ const nextSourceToLoad = sources?.find((s) => !s.loaded)
+
+ if (nextSourceToLoad) {
+ actions.loadRecordingSnapshots(nextSourceToLoad)
+ }
},
loadEventsSuccess: () => {
actions.reportUsageIfFullyLoaded()
@@ -303,7 +285,7 @@ export const sessionRecordingDataLogic = kea([
sessionPlayerSnapshotData: [
null as SessionPlayerSnapshotData | null,
{
- loadRecordingSnapshotsV2: async ({ source }, breakpoint): Promise => {
+ loadRecordingSnapshots: async ({ source }, breakpoint): Promise => {
if (!props.sessionRecordingId) {
return values.sessionPlayerSnapshotData
}
@@ -514,7 +496,6 @@ export const sessionRecordingDataLogic = kea([
s.sessionPlayerMetaDataLoading,
s.sessionPlayerSnapshotDataLoading,
s.sessionEventsDataLoading,
- s.hasAvailableFeature,
],
(
sessionPlayerSnapshotData,
diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts
index 02bde3f747399..8b4526d450338 100644
--- a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts
+++ b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.test.ts
@@ -18,8 +18,11 @@ import { urls } from 'scenes/urls'
describe('sessionRecordingPlayerLogic', () => {
let logic: ReturnType
+ const mockWarn = jest.fn()
beforeEach(() => {
+ console.warn = mockWarn
+ mockWarn.mockClear()
useMocks({
get: {
'/api/projects/:team/session_recordings/:id/snapshots/': (req, res, ctx) => {
@@ -99,11 +102,10 @@ describe('sessionRecordingPlayerLogic', () => {
expect(logic.values.sessionPlayerData).toMatchSnapshot()
await expectLogic(logic).toDispatchActions([
- sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshots,
// once to gather sources
- sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshotsV2,
+ sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshots,
// once to load source from that
- sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshotsV2,
+ sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshots,
sessionRecordingDataLogic({ sessionRecordingId: '2' }).actionTypes.loadRecordingSnapshotsSuccess,
])
@@ -325,5 +327,32 @@ describe('sessionRecordingPlayerLogic', () => {
}),
})
})
+
+ it('captures replayer warnings', async () => {
+ jest.useFakeTimers()
+ logic = sessionRecordingPlayerLogic({
+ sessionRecordingId: '4',
+ playerKey: 'test',
+ matchingEventsMatchType: {
+ matchType: 'uuid',
+ eventUUIDs: listOfMatchingEvents.map((event) => event.uuid),
+ },
+ })
+ logic.mount()
+
+ console.warn('[replayer]', 'test')
+ console.warn('[replayer]', 'test2')
+
+ expect(mockWarn).not.toHaveBeenCalled()
+
+ expect((window as any).__posthog_player_warnings).toEqual([
+ ['[replayer]', 'test'],
+ ['[replayer]', 'test2'],
+ ])
+ jest.runOnlyPendingTimers()
+ expect(mockWarn).toHaveBeenCalledWith(
+ '[PostHog Replayer] 2 warnings (window.__posthog_player_warnings to safely log them)'
+ )
+ })
})
})
diff --git a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts
index cfa711c3b4445..d5df80dd1fda5 100644
--- a/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts
+++ b/frontend/src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts
@@ -108,7 +108,7 @@ export const sessionRecordingPlayerLogic = kea(
playerSettingsLogic,
['speed', 'skipInactivitySetting'],
userLogic,
- ['hasAvailableFeature'],
+ ['user', 'hasAvailableFeature'],
preflightLogic,
['preflight'],
featureFlagLogic,
@@ -762,15 +762,8 @@ export const sessionRecordingPlayerLogic = kea(
},
togglePlayPause: () => {
- // If buffering, toggle is a noop
- if (values.currentPlayerState === SessionPlayerState.BUFFER) {
- return
- }
// If paused, start playing
- if (
- values.currentPlayerState === SessionPlayerState.PAUSE ||
- values.currentPlayerState === SessionPlayerState.READY
- ) {
+ if (values.playingState === SessionPlayerState.PAUSE) {
actions.setPlay()
}
// If playing, pause
@@ -873,7 +866,7 @@ export const sessionRecordingPlayerLogic = kea(
return
}
- if (!values.hasAvailableFeature(AvailableFeature.RECORDINGS_FILE_EXPORT)) {
+ if (!values.user?.is_impersonated && !values.hasAvailableFeature(AvailableFeature.RECORDINGS_FILE_EXPORT)) {
openBillingPopupModal({
title: 'Unlock recording exports',
description:
@@ -896,7 +889,7 @@ export const sessionRecordingPlayerLogic = kea(
const payload = createExportedSessionRecording(sessionRecordingDataLogic(props))
const recordingFile = new File(
- [JSON.stringify(payload)],
+ [JSON.stringify(payload, null, 2)],
`export-${props.sessionRecordingId}.ph-recording.json`,
{ type: 'application/json' }
)
@@ -965,13 +958,13 @@ export const sessionRecordingPlayerLogic = kea(
delete (window as any).__debug_player
actions.stopAnimation()
- cache.resetConsoleWarn?.()
+
cache.hasInitialized = false
- clearTimeout(cache.consoleWarnDebounceTimer)
document.removeEventListener('fullscreenchange', cache.fullScreenListener)
cache.pausedMediaElements = []
values.player?.replayer?.pause()
actions.setPlayer(null)
+ cache.unmountConsoleWarns?.()
const playTimeMs = values.playingTimeTracking.watchTime || 0
const summaryAnalytics: RecordingViewedSummaryAnalytics = {
@@ -1024,29 +1017,7 @@ export const sessionRecordingPlayerLogic = kea(
cache.openTime = performance.now()
- // NOTE: RRWeb can log _alot_ of warnings, so we debounce the count otherwise we just end up making the performance worse
- let warningCount = 0
- cache.consoleWarnDebounceTimer = null
-
- const debouncedCounter = (): void => {
- warningCount += 1
-
- if (!cache.consoleWarnDebounceTimer) {
- cache.consoleWarnDebounceTimer = setTimeout(() => {
- cache.consoleWarnDebounceTimer = null
- actions.incrementWarningCount(warningCount)
- warningCount = 0
- }, 1000)
- }
- }
-
- cache.resetConsoleWarn = wrapConsole('warn', (args) => {
- if (typeof args[0] === 'string' && args[0].includes('[replayer]')) {
- debouncedCounter()
- }
-
- return true
- })
+ cache.unmountConsoleWarns = manageConsoleWarns(cache, actions.incrementWarningCount)
}),
])
@@ -1055,3 +1026,48 @@ export const getCurrentPlayerTime = (logicProps: SessionRecordingPlayerLogicProp
const playerTime = sessionRecordingPlayerLogic.findMounted(logicProps)?.values.currentPlayerTime || 0
return Math.floor(playerTime / 1000)
}
+
+export const manageConsoleWarns = (cache: any, onIncrement: (count: number) => void): (() => void) => {
+ // NOTE: RRWeb can log _alot_ of warnings, so we debounce the count otherwise we just end up making the performance worse
+ // We also don't log the warnings directly. Sometimes the sheer size of messages and warnings can cause the browser to crash deserializing it all
+ ;(window as any).__posthog_player_warnings = []
+ const warnings: any[][] = (window as any).__posthog_player_warnings
+
+ let counter = 0
+
+ let consoleWarnDebounceTimer: NodeJS.Timeout | null = null
+
+ const actualConsoleWarn = console.warn
+
+ const debouncedCounter = (args: any[]): void => {
+ warnings.push(args)
+ counter += 1
+
+ if (!consoleWarnDebounceTimer) {
+ consoleWarnDebounceTimer = setTimeout(() => {
+ consoleWarnDebounceTimer = null
+ onIncrement(warnings.length)
+
+ actualConsoleWarn(
+ `[PostHog Replayer] ${counter} warnings (window.__posthog_player_warnings to safely log them)`
+ )
+ counter = 0
+ }, 1000)
+ }
+ }
+
+ const resetConsoleWarn = wrapConsole('warn', (args) => {
+ if (typeof args[0] === 'string' && args[0].includes('[replayer]')) {
+ debouncedCounter(args)
+ // WARNING: Logging these out can cause the browser to completely crash, so we want to delay it and
+ return false
+ }
+
+ return true
+ })
+
+ return () => {
+ resetConsoleWarn()
+ clearTimeout(cache.consoleWarnDebounceTimer)
+ }
+}
diff --git a/frontend/src/scenes/session-recordings/player/view-explorer/SessionRecordingPlayerExplorer.scss b/frontend/src/scenes/session-recordings/player/view-explorer/SessionRecordingPlayerExplorer.scss
index 2ecc3d9890d10..c7ef3432dab58 100644
--- a/frontend/src/scenes/session-recordings/player/view-explorer/SessionRecordingPlayerExplorer.scss
+++ b/frontend/src/scenes/session-recordings/player/view-explorer/SessionRecordingPlayerExplorer.scss
@@ -2,7 +2,7 @@
display: flex;
flex-direction: column;
flex: 1;
- height: calc(100vh - 3.5rem - 2rem);
+ height: 100%;
padding: 0.5rem;
overflow: hidden;
diff --git a/frontend/src/scenes/surveys/Survey.tsx b/frontend/src/scenes/surveys/Survey.tsx
index 10a67d4e96aea..8363e5a22a00c 100644
--- a/frontend/src/scenes/surveys/Survey.tsx
+++ b/frontend/src/scenes/surveys/Survey.tsx
@@ -166,6 +166,7 @@ export function SurveyForm({ id }: { id: string }): JSX.Element {
{
const isEditingQuestion =
defaultSurveyFieldValues[question.type].questions[0]
diff --git a/frontend/src/scenes/surveys/SurveyAppearance.tsx b/frontend/src/scenes/surveys/SurveyAppearance.tsx
index 4ab57e95ed773..504536949f387 100644
--- a/frontend/src/scenes/surveys/SurveyAppearance.tsx
+++ b/frontend/src/scenes/surveys/SurveyAppearance.tsx
@@ -100,7 +100,7 @@ export function SurveyAppearance({
}, [showThankYou])
return (
- <>
+
Preview
{!hideSubmittedSurvey && (
<>
@@ -220,7 +220,7 @@ export function SurveyAppearance({
)}
- >
+
)
}
diff --git a/frontend/src/scenes/surveys/SurveyView.tsx b/frontend/src/scenes/surveys/SurveyView.tsx
index a3a2a9c5b7e86..9805fb361babc 100644
--- a/frontend/src/scenes/surveys/SurveyView.tsx
+++ b/frontend/src/scenes/surveys/SurveyView.tsx
@@ -71,7 +71,12 @@ export function SurveyView({ id }: { id: string }): JSX.Element {
Archive
)}
- deleteSurvey(id)}>
+ deleteSurvey(id)}
+ >
Delete survey
>
@@ -81,6 +86,7 @@ export function SurveyView({ id }: { id: string }): JSX.Element {
{!survey.start_date ? (
{
launchSurvey()
}}
diff --git a/frontend/src/scenes/surveys/Surveys.tsx b/frontend/src/scenes/surveys/Surveys.tsx
index c81a5216d3fa5..1d9899d10a64a 100644
--- a/frontend/src/scenes/surveys/Surveys.tsx
+++ b/frontend/src/scenes/surveys/Surveys.tsx
@@ -196,6 +196,7 @@ export function Surveys(): JSX.Element {
columnKey: 'created_at',
order: -1,
}}
+ rowKey="name"
nouns={['survey', 'surveys']}
data-attr="surveys-table"
emptyState={
diff --git a/frontend/src/scenes/web-analytics/WebDashboard.tsx b/frontend/src/scenes/web-analytics/WebDashboard.tsx
index 35485ad82b70e..b081446350627 100644
--- a/frontend/src/scenes/web-analytics/WebDashboard.tsx
+++ b/frontend/src/scenes/web-analytics/WebDashboard.tsx
@@ -1,21 +1,106 @@
import { Query } from '~/queries/Query/Query'
-import { useValues } from 'kea'
+import { useActions, useValues } from 'kea'
import { webAnalyticsLogic } from 'scenes/web-analytics/webAnalyticsLogic'
+import { PropertyFilters } from 'lib/components/PropertyFilters/PropertyFilters'
+import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types'
+import { isEventPropertyFilter } from 'lib/components/PropertyFilters/utils'
+import { QueryContext, QueryContextColumnComponent } from '~/queries/schema'
+import { useCallback } from 'react'
+
+const PercentageCell: QueryContextColumnComponent = ({ value }) => {
+ if (typeof value === 'number') {
+ return (
+
+ {`${(value * 100).toFixed(1)}%`}
+
+ )
+ } else {
+ return null
+ }
+}
+
+const NumericCell: QueryContextColumnComponent = ({ value }) => {
+ return (
+
+ {String(value)}
+
+ )
+}
+
+const ClickablePropertyCell: QueryContextColumnComponent = (props) => {
+ const { columnName, value } = props
+ const { togglePropertyFilter } = useActions(webAnalyticsLogic)
+ let propertyName: string
+ switch (columnName) {
+ case 'pathname':
+ propertyName = '$pathname'
+ break
+ default:
+ return null
+ }
+
+ const onClick = useCallback(() => {
+ togglePropertyFilter(propertyName, value)
+ }, [togglePropertyFilter, propertyName, value])
+
+ return {value}
+}
+
+const queryContext: QueryContext = {
+ columns: {
+ bounce_rate: {
+ title: 'Bounce Rate',
+ render: PercentageCell,
+ },
+ pathname: {
+ title: 'Path',
+ render: ClickablePropertyCell,
+ },
+ views: {
+ title: 'Views',
+ render: NumericCell,
+ },
+ visitors: {
+ title: 'Visitors',
+ render: NumericCell,
+ },
+ },
+}
export const WebAnalyticsDashboard = (): JSX.Element => {
- const { tiles } = useValues(webAnalyticsLogic)
+ const { tiles, webAnalyticsFilters } = useValues(webAnalyticsLogic)
+ const { setWebAnalyticsFilters } = useActions(webAnalyticsLogic)
return (
-
- {tiles.map(({ query, layout }, i) => (
-
-
-
- ))}
+
+
+
setWebAnalyticsFilters(filters.filter(isEventPropertyFilter))}
+ propertyFilters={webAnalyticsFilters}
+ pageKey={'web-analytics'}
+ />
+
+
+
+ {tiles.map((tile, i) => {
+ if ('query' in tile) {
+ const { query, title, layout } = tile
+ return (
+
+ {title &&
{title}
}
+
+
+ )
+ } else {
+ return null
+ }
+ })}
+
)
}
diff --git a/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts b/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts
index ff68b6cea6a50..8df1288047610 100644
--- a/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts
+++ b/frontend/src/scenes/web-analytics/webAnalyticsLogic.ts
@@ -1,26 +1,96 @@
import { actions, connect, kea, listeners, path, reducers, selectors, sharedListeners } from 'kea'
import type { webAnalyticsLogicType } from './webAnalyticsLogicType'
-import { NodeKind, QuerySchema } from '~/queries/schema'
-import { BaseMathType, ChartDisplayType } from '~/types'
+import { NodeKind, QuerySchema, WebAnalyticsPropertyFilters } from '~/queries/schema'
+import { BaseMathType, ChartDisplayType, EventPropertyFilter, PropertyFilterType, PropertyOperator } from '~/types'
+import { isNotNil } from 'lib/utils'
interface Layout {
colSpan?: number
rowSpan?: number
}
-export interface WebDashboardTile {
- query: QuerySchema
+
+interface BaseTile {
layout: Layout
}
+
+interface QueryTile extends BaseTile {
+ title?: string
+ query: QuerySchema
+}
+
+interface TabsTile extends BaseTile {
+ tabs: {
+ title: string
+ linkText: string
+ query: QuerySchema
+ }
+}
+
+export type WebDashboardTile = QueryTile | TabsTile
+
+export const initialWebAnalyticsFilter = [] as WebAnalyticsPropertyFilters
+
export const webAnalyticsLogic = kea
([
path(['scenes', 'webAnalytics', 'webAnalyticsSceneLogic']),
connect({}),
- actions({}),
- reducers({}),
+ actions({
+ setWebAnalyticsFilters: (webAnalyticsFilters: WebAnalyticsPropertyFilters) => ({ webAnalyticsFilters }),
+ togglePropertyFilter: (key: string, value: string) => ({ key, value }),
+ }),
+ reducers({
+ webAnalyticsFilters: [
+ initialWebAnalyticsFilter,
+ {
+ setWebAnalyticsFilters: (_, { webAnalyticsFilters }) => webAnalyticsFilters,
+ togglePropertyFilter: (oldPropertyFilters, { key, value }) => {
+ if (oldPropertyFilters.some((f) => f.key === key && f.operator === PropertyOperator.Exact)) {
+ return oldPropertyFilters
+ .map((f) => {
+ if (
+ f.type !== PropertyFilterType.Event ||
+ f.key !== key ||
+ f.operator !== PropertyOperator.Exact
+ ) {
+ return f
+ }
+ const oldValue = (Array.isArray(f.value) ? f.value : [f.value]).filter(isNotNil)
+ let newValue: (string | number)[]
+ if (oldValue.includes(value)) {
+ // If there are multiple values for this filter, reduce that to just the one being clicked
+ if (oldValue.length > 1) {
+ newValue = [value]
+ } else {
+ return null
+ }
+ } else {
+ newValue = [...oldValue, value]
+ }
+ return {
+ type: PropertyFilterType.Event,
+ key,
+ operator: PropertyOperator.Exact,
+ value: newValue,
+ } as const
+ })
+ .filter(isNotNil)
+ } else {
+ const newFilter: EventPropertyFilter = {
+ type: PropertyFilterType.Event,
+ key,
+ value,
+ operator: PropertyOperator.Exact,
+ }
+ return [...oldPropertyFilters, newFilter]
+ }
+ },
+ },
+ ],
+ }),
selectors({
tiles: [
- () => [],
- (): WebDashboardTile[] => [
+ (s) => [s.webAnalyticsFilters],
+ (webAnalyticsFilters): WebDashboardTile[] => [
{
layout: {
colSpan: 12,
@@ -30,11 +100,12 @@ export const webAnalyticsLogic = kea([
kind: NodeKind.DataTableNode,
source: {
kind: NodeKind.WebOverviewStatsQuery,
- filters: {},
+ properties: webAnalyticsFilters,
},
},
},
{
+ title: 'Pages',
layout: {
colSpan: 6,
},
@@ -43,11 +114,12 @@ export const webAnalyticsLogic = kea([
kind: NodeKind.DataTableNode,
source: {
kind: NodeKind.WebTopPagesQuery,
- filters: {},
+ properties: webAnalyticsFilters,
},
},
},
{
+ title: 'Traffic Sources',
layout: {
colSpan: 6,
},
@@ -56,11 +128,12 @@ export const webAnalyticsLogic = kea([
kind: NodeKind.DataTableNode,
source: {
kind: NodeKind.WebTopSourcesQuery,
- filters: {},
+ properties: webAnalyticsFilters,
},
},
},
{
+ title: 'Unique users',
layout: {
colSpan: 6,
},
@@ -86,10 +159,12 @@ export const webAnalyticsLogic = kea([
display: ChartDisplayType.ActionsLineGraph,
},
filterTestAccounts: true,
+ properties: webAnalyticsFilters,
},
},
},
{
+ title: 'User locations',
layout: {
colSpan: 6,
},
@@ -115,6 +190,7 @@ export const webAnalyticsLogic = kea([
display: ChartDisplayType.WorldMap,
},
filterTestAccounts: true,
+ properties: webAnalyticsFilters,
},
},
},
diff --git a/frontend/src/styles/utilities.scss b/frontend/src/styles/utilities.scss
index b564e26b9ae54..05cff33f5d4d3 100644
--- a/frontend/src/styles/utilities.scss
+++ b/frontend/src/styles/utilities.scss
@@ -129,6 +129,25 @@
}
}
+.w-px {
+ width: 1px;
+}
+.h-px {
+ height: 1px;
+}
+.min-w-px {
+ min-width: 1px;
+}
+.max-w-px {
+ max-width: 1px;
+}
+.min-h-px {
+ min-height: 1px;
+}
+.max-h-px {
+ max-height: 1px;
+}
+
@each $name, $size in $screens {
.w-#{$name} {
width: $size;
diff --git a/frontend/src/types.ts b/frontend/src/types.ts
index 35170c4eb8e6a..fe343947f81cd 100644
--- a/frontend/src/types.ts
+++ b/frontend/src/types.ts
@@ -3072,6 +3072,8 @@ export enum NotebookNodeType {
EarlyAccessFeature = 'ph-early-access-feature',
Survey = 'ph-survey',
Person = 'ph-person',
+ Group = 'ph-group',
+ Cohort = 'ph-cohort',
Backlink = 'ph-backlink',
ReplayTimestamp = 'ph-replay-timestamp',
Image = 'ph-image',
diff --git a/hogql_parser/.clang-format b/hogql_parser/.clang-format
new file mode 100644
index 0000000000000..583a666fe94e5
--- /dev/null
+++ b/hogql_parser/.clang-format
@@ -0,0 +1,3 @@
+BasedOnStyle: Chromium
+ColumnLimit: 120
+AlignAfterOpenBracket: BlockIndent
diff --git a/hogql_parser/.gitignore b/hogql_parser/.gitignore
new file mode 100644
index 0000000000000..2a5a44e877407
--- /dev/null
+++ b/hogql_parser/.gitignore
@@ -0,0 +1,5 @@
+# Build
+build/
+*.egg-info
+*.so
+dist/
diff --git a/hogql_parser/CONTRIBUTING.md b/hogql_parser/CONTRIBUTING.md
new file mode 100644
index 0000000000000..a8274e06c4732
--- /dev/null
+++ b/hogql_parser/CONTRIBUTING.md
@@ -0,0 +1,50 @@
+# Developing `hogql-parser`
+
+## Mandatory reading
+
+If you're new to Python C/C++ extensions, there are some things you must have in your mind.
+
+### [Objects, Types and Reference Counts in CPython](https://docs.python.org/3/c-api/intro.html#objects-types-and-reference-counts)
+
+ Key takeaways:
+
+ 1. `Py_INCREF()` and `Py_DECREF()` need to be used accurately, or there'll be memory leaks (or, less likely, segfaults).
+ 1. `Py_None`, `Py_True`, and `Py_False` are singletons, but they still need to be incref'd/decref'd - the best way to do create a new reference to them is wrapping them in `Py_NewRef()`.
+ 1. Pretty much only `PyList_SET_ITEM()` _steals_ references (i.e. assumes ownership of objects passed into it), if you pass an object into any other function and no longer need it after that - remember to `Py_DECREF` it!
+
+### [Building Values in CPython](https://docs.python.org/3/c-api/arg.html#building-values)
+
+ Key takeaways:
+
+ 1. Use `Py_BuildValue()` for building tuples, dicts, and lists of static size. Use type-specific functions (e.g. `PyUnicode_FromString()` or `PyList_New()`) otherwise.
+ 1. `str`-building with `s` involves `strlen`, while `s#` doesn't - it's better to use the latter with C++ strings.
+ 1. `object`-passing with `O` increments the object's refcount, while doing it with `N` doesn't - we should use `N` pretty much exclusively, because the parse tree converter is about creating new objects (not borrowing).
+
+## Conventions
+
+1. Use `snake_case`. ANTLR is `camelCase`-heavy because of its Java heritage, but both the C++ stdlib and CPython are snaky.
+2. Use the `auto` type for ANTLR and ANTLR-derived types, since they can be pretty verbose. Otherwise specify the type explictly.
+3. Stay out of Python land as long as possible. E.g. avoid using `PyObject*`s` for bools or strings.
+ Do use Python for parsing numbers though - that way we don't need to consider integer overflow.
+4. If any child rule results in an AST node, so must the parent rule - once in Python land, always in Python land.
+ E.g. it doesn't make sense to create a `vector`, that should just be a `PyObject*` of Python type `list`.
+
+## How to develop locally on macOS
+
+1. Install libraries:
+
+ ```bash
+ brew install boost antlr4-cpp-runtime
+ ```
+
+1. Install `hogql_parser` by building from local sources:
+
+ ```bash
+ pip install ./hogql_parser
+ ```
+
+1. If you now run tests, the locally-built version of `hogql_parser` will be used:
+
+ ```bash
+ pytest posthog/hogql/
+ ```
diff --git a/hogql_parser/HogQLLexer.cpp b/hogql_parser/HogQLLexer.cpp
new file mode 100644
index 0000000000000..d8ba1b07116fa
--- /dev/null
+++ b/hogql_parser/HogQLLexer.cpp
@@ -0,0 +1,1048 @@
+
+// Generated from HogQLLexer.g4 by ANTLR 4.13.0
+
+
+#include "HogQLLexer.h"
+
+
+using namespace antlr4;
+
+
+
+using namespace antlr4;
+
+namespace {
+
+struct HogQLLexerStaticData final {
+ HogQLLexerStaticData(std::vector ruleNames,
+ std::vector channelNames,
+ std::vector modeNames,
+ std::vector literalNames,
+ std::vector symbolicNames)
+ : ruleNames(std::move(ruleNames)), channelNames(std::move(channelNames)),
+ modeNames(std::move(modeNames)), literalNames(std::move(literalNames)),
+ symbolicNames(std::move(symbolicNames)),
+ vocabulary(this->literalNames, this->symbolicNames) {}
+
+ HogQLLexerStaticData(const HogQLLexerStaticData&) = delete;
+ HogQLLexerStaticData(HogQLLexerStaticData&&) = delete;
+ HogQLLexerStaticData& operator=(const HogQLLexerStaticData&) = delete;
+ HogQLLexerStaticData& operator=(HogQLLexerStaticData&&) = delete;
+
+ std::vector decisionToDFA;
+ antlr4::atn::PredictionContextCache sharedContextCache;
+ const std::vector ruleNames;
+ const std::vector channelNames;
+ const std::vector modeNames;
+ const std::vector literalNames;
+ const std::vector symbolicNames;
+ const antlr4::dfa::Vocabulary vocabulary;
+ antlr4::atn::SerializedATNView serializedATN;
+ std::unique_ptr atn;
+};
+
+::antlr4::internal::OnceFlag hogqllexerLexerOnceFlag;
+#if ANTLR4_USE_THREAD_LOCAL_CACHE
+static thread_local
+#endif
+HogQLLexerStaticData *hogqllexerLexerStaticData = nullptr;
+
+void hogqllexerLexerInitialize() {
+#if ANTLR4_USE_THREAD_LOCAL_CACHE
+ if (hogqllexerLexerStaticData != nullptr) {
+ return;
+ }
+#else
+ assert(hogqllexerLexerStaticData == nullptr);
+#endif
+ auto staticData = std::make_unique(
+ std::vector{
+ "ADD", "AFTER", "ALIAS", "ALL", "ALTER", "AND", "ANTI", "ANY", "ARRAY",
+ "AS", "ASCENDING", "ASOF", "AST", "ASYNC", "ATTACH", "BETWEEN", "BOTH",
+ "BY", "CASE", "CAST", "CHECK", "CLEAR", "CLUSTER", "CODEC", "COHORT",
+ "COLLATE", "COLUMN", "COMMENT", "CONSTRAINT", "CREATE", "CROSS", "CUBE",
+ "CURRENT", "DATABASE", "DATABASES", "DATE", "DAY", "DEDUPLICATE",
+ "DEFAULT", "DELAY", "DELETE", "DESC", "DESCENDING", "DESCRIBE", "DETACH",
+ "DICTIONARIES", "DICTIONARY", "DISK", "DISTINCT", "DISTRIBUTED", "DROP",
+ "ELSE", "END", "ENGINE", "EVENTS", "EXISTS", "EXPLAIN", "EXPRESSION",
+ "EXTRACT", "FETCHES", "FINAL", "FIRST", "FLUSH", "FOLLOWING", "FOR",
+ "FORMAT", "FREEZE", "FROM", "FULL", "FUNCTION", "GLOBAL", "GRANULARITY",
+ "GROUP", "HAVING", "HIERARCHICAL", "HOUR", "ID", "IF", "ILIKE", "IN",
+ "INDEX", "INF", "INJECTIVE", "INNER", "INSERT", "INTERVAL", "INTO",
+ "IS", "IS_OBJECT_ID", "JOIN", "KEY", "KILL", "LAST", "LAYOUT", "LEADING",
+ "LEFT", "LIFETIME", "LIKE", "LIMIT", "LIVE", "LOCAL", "LOGS", "MATERIALIZE",
+ "MATERIALIZED", "MAX", "MERGES", "MIN", "MINUTE", "MODIFY", "MONTH",
+ "MOVE", "MUTATION", "NAN_SQL", "NO", "NOT", "NULL_SQL", "NULLS", "OFFSET",
+ "ON", "OPTIMIZE", "OR", "ORDER", "OUTER", "OUTFILE", "OVER", "PARTITION",
+ "POPULATE", "PRECEDING", "PREWHERE", "PRIMARY", "PROJECTION", "QUARTER",
+ "RANGE", "RELOAD", "REMOVE", "RENAME", "REPLACE", "REPLICA", "REPLICATED",
+ "RIGHT", "ROLLUP", "ROW", "ROWS", "SAMPLE", "SECOND", "SELECT", "SEMI",
+ "SENDS", "SET", "SETTINGS", "SHOW", "SOURCE", "START", "STOP", "SUBSTRING",
+ "SYNC", "SYNTAX", "SYSTEM", "TABLE", "TABLES", "TEMPORARY", "TEST",
+ "THEN", "TIES", "TIMEOUT", "TIMESTAMP", "TO", "TOP", "TOTALS", "TRAILING",
+ "TRIM", "TRUNCATE", "TTL", "TYPE", "UNBOUNDED", "UNION", "UPDATE",
+ "USE", "USING", "UUID", "VALUES", "VIEW", "VOLUME", "WATCH", "WEEK",
+ "WHEN", "WHERE", "WINDOW", "WITH", "YEAR", "JSON_FALSE", "JSON_TRUE",
+ "ESCAPE_CHAR", "IDENTIFIER", "FLOATING_LITERAL", "OCTAL_LITERAL",
+ "DECIMAL_LITERAL", "HEXADECIMAL_LITERAL", "STRING_LITERAL", "PLACEHOLDER",
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
+ "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "LETTER",
+ "OCT_DIGIT", "DEC_DIGIT", "HEX_DIGIT", "ARROW", "ASTERISK", "BACKQUOTE",
+ "BACKSLASH", "COLON", "COMMA", "CONCAT", "DASH", "DOLLAR", "DOT",
+ "EQ_DOUBLE", "EQ_SINGLE", "GT_EQ", "GT", "HASH", "IREGEX_SINGLE",
+ "IREGEX_DOUBLE", "LBRACE", "LBRACKET", "LPAREN", "LT_EQ", "LT", "NOT_EQ",
+ "NOT_IREGEX", "NOT_REGEX", "NULLISH", "PERCENT", "PLUS", "QUERY",
+ "QUOTE_DOUBLE", "QUOTE_SINGLE", "REGEX_SINGLE", "REGEX_DOUBLE", "RBRACE",
+ "RBRACKET", "RPAREN", "SEMICOLON", "SLASH", "UNDERSCORE", "MULTI_LINE_COMMENT",
+ "SINGLE_LINE_COMMENT", "WHITESPACE"
+ },
+ std::vector{
+ "DEFAULT_TOKEN_CHANNEL", "HIDDEN"
+ },
+ std::vector{
+ "DEFAULT_MODE"
+ },
+ std::vector{
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "'false'", "'true'", "", "", "", "", "", "", "", "",
+ "'->'", "'*'", "'`'", "'\\'", "':'", "','", "'||'", "'-'", "'$'",
+ "'.'", "'=='", "'='", "'>='", "'>'", "'#'", "'~*'", "'=~*'", "'{'",
+ "'['", "'('", "'<='", "'<'", "", "'!~*'", "'!~'", "'\\u003F\\u003F'",
+ "'%'", "'+'", "'\\u003F'", "'\"'", "'''", "'~'", "'=~'", "'}'", "']'",
+ "')'", "';'", "'/'", "'_'"
+ },
+ std::vector{
+ "", "ADD", "AFTER", "ALIAS", "ALL", "ALTER", "AND", "ANTI", "ANY",
+ "ARRAY", "AS", "ASCENDING", "ASOF", "AST", "ASYNC", "ATTACH", "BETWEEN",
+ "BOTH", "BY", "CASE", "CAST", "CHECK", "CLEAR", "CLUSTER", "CODEC",
+ "COHORT", "COLLATE", "COLUMN", "COMMENT", "CONSTRAINT", "CREATE",
+ "CROSS", "CUBE", "CURRENT", "DATABASE", "DATABASES", "DATE", "DAY",
+ "DEDUPLICATE", "DEFAULT", "DELAY", "DELETE", "DESC", "DESCENDING",
+ "DESCRIBE", "DETACH", "DICTIONARIES", "DICTIONARY", "DISK", "DISTINCT",
+ "DISTRIBUTED", "DROP", "ELSE", "END", "ENGINE", "EVENTS", "EXISTS",
+ "EXPLAIN", "EXPRESSION", "EXTRACT", "FETCHES", "FINAL", "FIRST", "FLUSH",
+ "FOLLOWING", "FOR", "FORMAT", "FREEZE", "FROM", "FULL", "FUNCTION",
+ "GLOBAL", "GRANULARITY", "GROUP", "HAVING", "HIERARCHICAL", "HOUR",
+ "ID", "IF", "ILIKE", "IN", "INDEX", "INF", "INJECTIVE", "INNER", "INSERT",
+ "INTERVAL", "INTO", "IS", "IS_OBJECT_ID", "JOIN", "KEY", "KILL", "LAST",
+ "LAYOUT", "LEADING", "LEFT", "LIFETIME", "LIKE", "LIMIT", "LIVE",
+ "LOCAL", "LOGS", "MATERIALIZE", "MATERIALIZED", "MAX", "MERGES", "MIN",
+ "MINUTE", "MODIFY", "MONTH", "MOVE", "MUTATION", "NAN_SQL", "NO",
+ "NOT", "NULL_SQL", "NULLS", "OFFSET", "ON", "OPTIMIZE", "OR", "ORDER",
+ "OUTER", "OUTFILE", "OVER", "PARTITION", "POPULATE", "PRECEDING",
+ "PREWHERE", "PRIMARY", "PROJECTION", "QUARTER", "RANGE", "RELOAD",
+ "REMOVE", "RENAME", "REPLACE", "REPLICA", "REPLICATED", "RIGHT", "ROLLUP",
+ "ROW", "ROWS", "SAMPLE", "SECOND", "SELECT", "SEMI", "SENDS", "SET",
+ "SETTINGS", "SHOW", "SOURCE", "START", "STOP", "SUBSTRING", "SYNC",
+ "SYNTAX", "SYSTEM", "TABLE", "TABLES", "TEMPORARY", "TEST", "THEN",
+ "TIES", "TIMEOUT", "TIMESTAMP", "TO", "TOP", "TOTALS", "TRAILING",
+ "TRIM", "TRUNCATE", "TTL", "TYPE", "UNBOUNDED", "UNION", "UPDATE",
+ "USE", "USING", "UUID", "VALUES", "VIEW", "VOLUME", "WATCH", "WEEK",
+ "WHEN", "WHERE", "WINDOW", "WITH", "YEAR", "JSON_FALSE", "JSON_TRUE",
+ "ESCAPE_CHAR", "IDENTIFIER", "FLOATING_LITERAL", "OCTAL_LITERAL",
+ "DECIMAL_LITERAL", "HEXADECIMAL_LITERAL", "STRING_LITERAL", "PLACEHOLDER",
+ "ARROW", "ASTERISK", "BACKQUOTE", "BACKSLASH", "COLON", "COMMA", "CONCAT",
+ "DASH", "DOLLAR", "DOT", "EQ_DOUBLE", "EQ_SINGLE", "GT_EQ", "GT",
+ "HASH", "IREGEX_SINGLE", "IREGEX_DOUBLE", "LBRACE", "LBRACKET", "LPAREN",
+ "LT_EQ", "LT", "NOT_EQ", "NOT_IREGEX", "NOT_REGEX", "NULLISH", "PERCENT",
+ "PLUS", "QUERY", "QUOTE_DOUBLE", "QUOTE_SINGLE", "REGEX_SINGLE", "REGEX_DOUBLE",
+ "RBRACE", "RBRACKET", "RPAREN", "SEMICOLON", "SLASH", "UNDERSCORE",
+ "MULTI_LINE_COMMENT", "SINGLE_LINE_COMMENT", "WHITESPACE"
+ }
+ );
+ static const int32_t serializedATNSegment[] = {
+ 4,0,242,2222,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,
+ 7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,
+ 14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,
+ 21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,
+ 28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,
+ 35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,
+ 42,7,42,2,43,7,43,2,44,7,44,2,45,7,45,2,46,7,46,2,47,7,47,2,48,7,48,2,
+ 49,7,49,2,50,7,50,2,51,7,51,2,52,7,52,2,53,7,53,2,54,7,54,2,55,7,55,2,
+ 56,7,56,2,57,7,57,2,58,7,58,2,59,7,59,2,60,7,60,2,61,7,61,2,62,7,62,2,
+ 63,7,63,2,64,7,64,2,65,7,65,2,66,7,66,2,67,7,67,2,68,7,68,2,69,7,69,2,
+ 70,7,70,2,71,7,71,2,72,7,72,2,73,7,73,2,74,7,74,2,75,7,75,2,76,7,76,2,
+ 77,7,77,2,78,7,78,2,79,7,79,2,80,7,80,2,81,7,81,2,82,7,82,2,83,7,83,2,
+ 84,7,84,2,85,7,85,2,86,7,86,2,87,7,87,2,88,7,88,2,89,7,89,2,90,7,90,2,
+ 91,7,91,2,92,7,92,2,93,7,93,2,94,7,94,2,95,7,95,2,96,7,96,2,97,7,97,2,
+ 98,7,98,2,99,7,99,2,100,7,100,2,101,7,101,2,102,7,102,2,103,7,103,2,104,
+ 7,104,2,105,7,105,2,106,7,106,2,107,7,107,2,108,7,108,2,109,7,109,2,110,
+ 7,110,2,111,7,111,2,112,7,112,2,113,7,113,2,114,7,114,2,115,7,115,2,116,
+ 7,116,2,117,7,117,2,118,7,118,2,119,7,119,2,120,7,120,2,121,7,121,2,122,
+ 7,122,2,123,7,123,2,124,7,124,2,125,7,125,2,126,7,126,2,127,7,127,2,128,
+ 7,128,2,129,7,129,2,130,7,130,2,131,7,131,2,132,7,132,2,133,7,133,2,134,
+ 7,134,2,135,7,135,2,136,7,136,2,137,7,137,2,138,7,138,2,139,7,139,2,140,
+ 7,140,2,141,7,141,2,142,7,142,2,143,7,143,2,144,7,144,2,145,7,145,2,146,
+ 7,146,2,147,7,147,2,148,7,148,2,149,7,149,2,150,7,150,2,151,7,151,2,152,
+ 7,152,2,153,7,153,2,154,7,154,2,155,7,155,2,156,7,156,2,157,7,157,2,158,
+ 7,158,2,159,7,159,2,160,7,160,2,161,7,161,2,162,7,162,2,163,7,163,2,164,
+ 7,164,2,165,7,165,2,166,7,166,2,167,7,167,2,168,7,168,2,169,7,169,2,170,
+ 7,170,2,171,7,171,2,172,7,172,2,173,7,173,2,174,7,174,2,175,7,175,2,176,
+ 7,176,2,177,7,177,2,178,7,178,2,179,7,179,2,180,7,180,2,181,7,181,2,182,
+ 7,182,2,183,7,183,2,184,7,184,2,185,7,185,2,186,7,186,2,187,7,187,2,188,
+ 7,188,2,189,7,189,2,190,7,190,2,191,7,191,2,192,7,192,2,193,7,193,2,194,
+ 7,194,2,195,7,195,2,196,7,196,2,197,7,197,2,198,7,198,2,199,7,199,2,200,
+ 7,200,2,201,7,201,2,202,7,202,2,203,7,203,2,204,7,204,2,205,7,205,2,206,
+ 7,206,2,207,7,207,2,208,7,208,2,209,7,209,2,210,7,210,2,211,7,211,2,212,
+ 7,212,2,213,7,213,2,214,7,214,2,215,7,215,2,216,7,216,2,217,7,217,2,218,
+ 7,218,2,219,7,219,2,220,7,220,2,221,7,221,2,222,7,222,2,223,7,223,2,224,
+ 7,224,2,225,7,225,2,226,7,226,2,227,7,227,2,228,7,228,2,229,7,229,2,230,
+ 7,230,2,231,7,231,2,232,7,232,2,233,7,233,2,234,7,234,2,235,7,235,2,236,
+ 7,236,2,237,7,237,2,238,7,238,2,239,7,239,2,240,7,240,2,241,7,241,2,242,
+ 7,242,2,243,7,243,2,244,7,244,2,245,7,245,2,246,7,246,2,247,7,247,2,248,
+ 7,248,2,249,7,249,2,250,7,250,2,251,7,251,2,252,7,252,2,253,7,253,2,254,
+ 7,254,2,255,7,255,2,256,7,256,2,257,7,257,2,258,7,258,2,259,7,259,2,260,
+ 7,260,2,261,7,261,2,262,7,262,2,263,7,263,2,264,7,264,2,265,7,265,2,266,
+ 7,266,2,267,7,267,2,268,7,268,2,269,7,269,2,270,7,270,2,271,7,271,1,0,
+ 1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,
+ 3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,7,
+ 1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,
+ 10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,3,10,608,8,10,1,11,1,
+ 11,1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,13,1,13,1,
+ 14,1,14,1,14,1,14,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,
+ 15,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1,17,1,18,1,18,1,18,1,18,1,18,1,
+ 19,1,19,1,19,1,19,1,19,1,20,1,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,
+ 21,1,21,1,21,1,22,1,22,1,22,1,22,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,
+ 23,1,23,1,23,1,24,1,24,1,24,1,24,1,24,1,24,1,24,1,25,1,25,1,25,1,25,1,
+ 25,1,25,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,27,1,27,1,27,1,
+ 27,1,27,1,27,1,27,1,27,1,28,1,28,1,28,1,28,1,28,1,28,1,28,1,28,1,28,1,
+ 28,1,28,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,30,1,30,1,30,1,30,1,30,1,
+ 30,1,31,1,31,1,31,1,31,1,31,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,
+ 33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,34,1,34,1,34,1,34,1,34,1,
+ 34,1,34,1,34,1,34,1,34,1,35,1,35,1,35,1,35,1,35,1,36,1,36,1,36,1,36,1,
+ 37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,
+ 38,1,38,1,38,1,38,1,38,1,38,1,39,1,39,1,39,1,39,1,39,1,39,1,40,1,40,1,
+ 40,1,40,1,40,1,40,1,40,1,41,1,41,1,41,1,41,1,41,1,42,1,42,1,42,1,42,1,
+ 42,1,42,1,42,1,42,1,42,1,42,1,42,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,
+ 43,1,43,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,45,1,45,1,45,1,45,1,45,1,
+ 45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,46,1,46,1,46,1,46,1,46,1,46,1,
+ 46,1,46,1,46,1,46,1,46,1,47,1,47,1,47,1,47,1,47,1,48,1,48,1,48,1,48,1,
+ 48,1,48,1,48,1,48,1,48,1,49,1,49,1,49,1,49,1,49,1,49,1,49,1,49,1,49,1,
+ 49,1,49,1,49,1,50,1,50,1,50,1,50,1,50,1,51,1,51,1,51,1,51,1,51,1,52,1,
+ 52,1,52,1,52,1,53,1,53,1,53,1,53,1,53,1,53,1,53,1,54,1,54,1,54,1,54,1,
+ 54,1,54,1,54,1,55,1,55,1,55,1,55,1,55,1,55,1,55,1,56,1,56,1,56,1,56,1,
+ 56,1,56,1,56,1,56,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,57,1,
+ 57,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,58,1,59,1,59,1,59,1,59,1,59,1,
+ 59,1,59,1,59,1,60,1,60,1,60,1,60,1,60,1,60,1,61,1,61,1,61,1,61,1,61,1,
+ 61,1,62,1,62,1,62,1,62,1,62,1,62,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,
+ 63,1,63,1,63,1,64,1,64,1,64,1,64,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,
+ 66,1,66,1,66,1,66,1,66,1,66,1,66,1,67,1,67,1,67,1,67,1,67,1,68,1,68,1,
+ 68,1,68,1,68,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,70,1,70,1,
+ 70,1,70,1,70,1,70,1,70,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,
+ 71,1,71,1,71,1,72,1,72,1,72,1,72,1,72,1,72,1,73,1,73,1,73,1,73,1,73,1,
+ 73,1,73,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,
+ 74,1,75,1,75,1,75,1,75,1,75,1,76,1,76,1,76,1,77,1,77,1,77,1,78,1,78,1,
+ 78,1,78,1,78,1,78,1,79,1,79,1,79,1,80,1,80,1,80,1,80,1,80,1,80,1,81,1,
+ 81,1,81,1,81,1,81,1,81,1,81,1,81,1,81,1,81,1,81,1,81,1,81,3,81,1113,8,
+ 81,1,82,1,82,1,82,1,82,1,82,1,82,1,82,1,82,1,82,1,82,1,83,1,83,1,83,1,
+ 83,1,83,1,83,1,84,1,84,1,84,1,84,1,84,1,84,1,84,1,85,1,85,1,85,1,85,1,
+ 85,1,85,1,85,1,85,1,85,1,86,1,86,1,86,1,86,1,86,1,87,1,87,1,87,1,88,1,
+ 88,1,88,1,88,1,88,1,88,1,88,1,88,1,88,1,88,1,88,1,88,1,88,1,89,1,89,1,
+ 89,1,89,1,89,1,90,1,90,1,90,1,90,1,91,1,91,1,91,1,91,1,91,1,92,1,92,1,
+ 92,1,92,1,92,1,93,1,93,1,93,1,93,1,93,1,93,1,93,1,94,1,94,1,94,1,94,1,
+ 94,1,94,1,94,1,94,1,95,1,95,1,95,1,95,1,95,1,96,1,96,1,96,1,96,1,96,1,
+ 96,1,96,1,96,1,96,1,97,1,97,1,97,1,97,1,97,1,98,1,98,1,98,1,98,1,98,1,
+ 98,1,99,1,99,1,99,1,99,1,99,1,100,1,100,1,100,1,100,1,100,1,100,1,101,
+ 1,101,1,101,1,101,1,101,1,102,1,102,1,102,1,102,1,102,1,102,1,102,1,102,
+ 1,102,1,102,1,102,1,102,1,103,1,103,1,103,1,103,1,103,1,103,1,103,1,103,
+ 1,103,1,103,1,103,1,103,1,103,1,104,1,104,1,104,1,104,1,105,1,105,1,105,
+ 1,105,1,105,1,105,1,105,1,106,1,106,1,106,1,106,1,107,1,107,1,107,1,107,
+ 1,107,1,107,1,107,1,108,1,108,1,108,1,108,1,108,1,108,1,108,1,109,1,109,
+ 1,109,1,109,1,109,1,109,1,110,1,110,1,110,1,110,1,110,1,111,1,111,1,111,
+ 1,111,1,111,1,111,1,111,1,111,1,111,1,112,1,112,1,112,1,112,1,113,1,113,
+ 1,113,1,114,1,114,1,114,1,114,1,115,1,115,1,115,1,115,1,115,1,116,1,116,
+ 1,116,1,116,1,116,1,116,1,117,1,117,1,117,1,117,1,117,1,117,1,117,1,118,
+ 1,118,1,118,1,119,1,119,1,119,1,119,1,119,1,119,1,119,1,119,1,119,1,120,
+ 1,120,1,120,1,121,1,121,1,121,1,121,1,121,1,121,1,122,1,122,1,122,1,122,
+ 1,122,1,122,1,123,1,123,1,123,1,123,1,123,1,123,1,123,1,123,1,124,1,124,
+ 1,124,1,124,1,124,1,125,1,125,1,125,1,125,1,125,1,125,1,125,1,125,1,125,
+ 1,125,1,126,1,126,1,126,1,126,1,126,1,126,1,126,1,126,1,126,1,127,1,127,
+ 1,127,1,127,1,127,1,127,1,127,1,127,1,127,1,127,1,128,1,128,1,128,1,128,
+ 1,128,1,128,1,128,1,128,1,128,1,129,1,129,1,129,1,129,1,129,1,129,1,129,
+ 1,129,1,130,1,130,1,130,1,130,1,130,1,130,1,130,1,130,1,130,1,130,1,130,
+ 1,131,1,131,1,131,1,131,1,131,1,131,1,131,1,131,1,132,1,132,1,132,1,132,
+ 1,132,1,132,1,133,1,133,1,133,1,133,1,133,1,133,1,133,1,134,1,134,1,134,
+ 1,134,1,134,1,134,1,134,1,135,1,135,1,135,1,135,1,135,1,135,1,135,1,136,
+ 1,136,1,136,1,136,1,136,1,136,1,136,1,136,1,137,1,137,1,137,1,137,1,137,
+ 1,137,1,137,1,137,1,138,1,138,1,138,1,138,1,138,1,138,1,138,1,138,1,138,
+ 1,138,1,138,1,139,1,139,1,139,1,139,1,139,1,139,1,140,1,140,1,140,1,140,
+ 1,140,1,140,1,140,1,141,1,141,1,141,1,141,1,142,1,142,1,142,1,142,1,142,
+ 1,143,1,143,1,143,1,143,1,143,1,143,1,143,1,144,1,144,1,144,1,144,1,144,
+ 1,144,1,144,1,145,1,145,1,145,1,145,1,145,1,145,1,145,1,146,1,146,1,146,
+ 1,146,1,146,1,147,1,147,1,147,1,147,1,147,1,147,1,148,1,148,1,148,1,148,
+ 1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,150,1,150,1,150,
+ 1,150,1,150,1,151,1,151,1,151,1,151,1,151,1,151,1,151,1,152,1,152,1,152,
+ 1,152,1,152,1,152,1,153,1,153,1,153,1,153,1,153,1,154,1,154,1,154,1,154,
+ 1,154,1,154,1,154,1,154,1,154,1,154,1,155,1,155,1,155,1,155,1,155,1,156,
+ 1,156,1,156,1,156,1,156,1,156,1,156,1,157,1,157,1,157,1,157,1,157,1,157,
+ 1,157,1,158,1,158,1,158,1,158,1,158,1,158,1,159,1,159,1,159,1,159,1,159,
+ 1,159,1,159,1,160,1,160,1,160,1,160,1,160,1,160,1,160,1,160,1,160,1,160,
+ 1,161,1,161,1,161,1,161,1,161,1,162,1,162,1,162,1,162,1,162,1,163,1,163,
+ 1,163,1,163,1,163,1,164,1,164,1,164,1,164,1,164,1,164,1,164,1,164,1,165,
+ 1,165,1,165,1,165,1,165,1,165,1,165,1,165,1,165,1,165,1,166,1,166,1,166,
+ 1,167,1,167,1,167,1,167,1,168,1,168,1,168,1,168,1,168,1,168,1,168,1,169,
+ 1,169,1,169,1,169,1,169,1,169,1,169,1,169,1,169,1,170,1,170,1,170,1,170,
+ 1,170,1,171,1,171,1,171,1,171,1,171,1,171,1,171,1,171,1,171,1,172,1,172,
+ 1,172,1,172,1,173,1,173,1,173,1,173,1,173,1,174,1,174,1,174,1,174,1,174,
+ 1,174,1,174,1,174,1,174,1,174,1,175,1,175,1,175,1,175,1,175,1,175,1,176,
+ 1,176,1,176,1,176,1,176,1,176,1,176,1,177,1,177,1,177,1,177,1,178,1,178,
+ 1,178,1,178,1,178,1,178,1,179,1,179,1,179,1,179,1,179,1,180,1,180,1,180,
+ 1,180,1,180,1,180,1,180,1,181,1,181,1,181,1,181,1,181,1,182,1,182,1,182,
+ 1,182,1,182,1,182,1,182,1,183,1,183,1,183,1,183,1,183,1,183,1,184,1,184,
+ 1,184,1,184,1,184,1,185,1,185,1,185,1,185,1,185,1,186,1,186,1,186,1,186,
+ 1,186,1,186,1,187,1,187,1,187,1,187,1,187,1,187,1,187,1,188,1,188,1,188,
+ 1,188,1,188,1,189,1,189,1,189,1,189,1,189,1,189,1,189,1,189,1,189,1,189,
+ 3,189,1827,8,189,1,190,1,190,1,190,1,190,1,190,1,190,1,191,1,191,1,191,
+ 1,191,1,191,1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,
+ 1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,
+ 1,192,1,192,1,192,1,192,1,192,1,192,1,192,1,192,3,192,1870,8,192,1,193,
+ 1,193,1,193,3,193,1875,8,193,1,193,1,193,1,193,1,193,5,193,1881,8,193,
+ 10,193,12,193,1884,9,193,1,193,1,193,1,193,1,193,1,193,1,193,5,193,1892,
+ 8,193,10,193,12,193,1895,9,193,1,193,1,193,1,193,1,193,1,193,1,193,1,
+ 193,1,193,5,193,1905,8,193,10,193,12,193,1908,9,193,1,193,1,193,3,193,
+ 1912,8,193,1,194,1,194,1,194,5,194,1917,8,194,10,194,12,194,1920,9,194,
+ 1,194,1,194,3,194,1924,8,194,1,194,1,194,3,194,1928,8,194,1,194,4,194,
+ 1931,8,194,11,194,12,194,1932,1,194,1,194,1,194,3,194,1938,8,194,1,194,
+ 1,194,3,194,1942,8,194,1,194,4,194,1945,8,194,11,194,12,194,1946,1,194,
+ 1,194,1,194,5,194,1952,8,194,10,194,12,194,1955,9,194,1,194,1,194,1,194,
+ 3,194,1960,8,194,1,194,4,194,1963,8,194,11,194,12,194,1964,1,194,1,194,
+ 1,194,1,194,1,194,3,194,1972,8,194,1,194,4,194,1975,8,194,11,194,12,194,
+ 1976,1,194,1,194,1,194,1,194,3,194,1983,8,194,1,194,4,194,1986,8,194,
+ 11,194,12,194,1987,3,194,1990,8,194,1,195,1,195,4,195,1994,8,195,11,195,
+ 12,195,1995,1,196,4,196,1999,8,196,11,196,12,196,2000,1,197,1,197,1,197,
+ 4,197,2006,8,197,11,197,12,197,2007,1,198,1,198,1,198,1,198,1,198,1,198,
+ 5,198,2016,8,198,10,198,12,198,2019,9,198,1,198,1,198,1,199,1,199,1,199,
+ 1,199,1,199,1,199,5,199,2029,8,199,10,199,12,199,2032,9,199,1,199,1,199,
+ 1,200,1,200,1,201,1,201,1,202,1,202,1,203,1,203,1,204,1,204,1,205,1,205,
+ 1,206,1,206,1,207,1,207,1,208,1,208,1,209,1,209,1,210,1,210,1,211,1,211,
+ 1,212,1,212,1,213,1,213,1,214,1,214,1,215,1,215,1,216,1,216,1,217,1,217,
+ 1,218,1,218,1,219,1,219,1,220,1,220,1,221,1,221,1,222,1,222,1,223,1,223,
+ 1,224,1,224,1,225,1,225,1,226,1,226,1,227,1,227,1,228,1,228,1,229,1,229,
+ 1,230,1,230,1,230,1,231,1,231,1,232,1,232,1,233,1,233,1,234,1,234,1,235,
+ 1,235,1,236,1,236,1,236,1,237,1,237,1,238,1,238,1,239,1,239,1,240,1,240,
+ 1,240,1,241,1,241,1,242,1,242,1,242,1,243,1,243,1,244,1,244,1,245,1,245,
+ 1,245,1,246,1,246,1,246,1,246,1,247,1,247,1,248,1,248,1,249,1,249,1,250,
+ 1,250,1,250,1,251,1,251,1,252,1,252,1,252,1,252,3,252,2152,8,252,1,253,
+ 1,253,1,253,1,253,1,254,1,254,1,254,1,255,1,255,1,255,1,256,1,256,1,257,
+ 1,257,1,258,1,258,1,259,1,259,1,260,1,260,1,261,1,261,1,262,1,262,1,262,
+ 1,263,1,263,1,264,1,264,1,265,1,265,1,266,1,266,1,267,1,267,1,268,1,268,
+ 1,269,1,269,1,269,1,269,5,269,2195,8,269,10,269,12,269,2198,9,269,1,269,
+ 1,269,1,269,1,269,1,269,1,270,1,270,1,270,1,270,5,270,2209,8,270,10,270,
+ 12,270,2212,9,270,1,270,3,270,2215,8,270,1,270,1,270,1,271,1,271,1,271,
+ 1,271,1,2196,0,272,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,
+ 23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,
+ 23,47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,
+ 69,35,71,36,73,37,75,38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,
+ 46,93,47,95,48,97,49,99,50,101,51,103,52,105,53,107,54,109,55,111,56,
+ 113,57,115,58,117,59,119,60,121,61,123,62,125,63,127,64,129,65,131,66,
+ 133,67,135,68,137,69,139,70,141,71,143,72,145,73,147,74,149,75,151,76,
+ 153,77,155,78,157,79,159,80,161,81,163,82,165,83,167,84,169,85,171,86,
+ 173,87,175,88,177,89,179,90,181,91,183,92,185,93,187,94,189,95,191,96,
+ 193,97,195,98,197,99,199,100,201,101,203,102,205,103,207,104,209,105,
+ 211,106,213,107,215,108,217,109,219,110,221,111,223,112,225,113,227,114,
+ 229,115,231,116,233,117,235,118,237,119,239,120,241,121,243,122,245,123,
+ 247,124,249,125,251,126,253,127,255,128,257,129,259,130,261,131,263,132,
+ 265,133,267,134,269,135,271,136,273,137,275,138,277,139,279,140,281,141,
+ 283,142,285,143,287,144,289,145,291,146,293,147,295,148,297,149,299,150,
+ 301,151,303,152,305,153,307,154,309,155,311,156,313,157,315,158,317,159,
+ 319,160,321,161,323,162,325,163,327,164,329,165,331,166,333,167,335,168,
+ 337,169,339,170,341,171,343,172,345,173,347,174,349,175,351,176,353,177,
+ 355,178,357,179,359,180,361,181,363,182,365,183,367,184,369,185,371,186,
+ 373,187,375,188,377,189,379,190,381,191,383,192,385,193,387,194,389,195,
+ 391,196,393,197,395,198,397,199,399,200,401,0,403,0,405,0,407,0,409,0,
+ 411,0,413,0,415,0,417,0,419,0,421,0,423,0,425,0,427,0,429,0,431,0,433,
+ 0,435,0,437,0,439,0,441,0,443,0,445,0,447,0,449,0,451,0,453,0,455,0,457,
+ 0,459,0,461,201,463,202,465,203,467,204,469,205,471,206,473,207,475,208,
+ 477,209,479,210,481,211,483,212,485,213,487,214,489,215,491,216,493,217,
+ 495,218,497,219,499,220,501,221,503,222,505,223,507,224,509,225,511,226,
+ 513,227,515,228,517,229,519,230,521,231,523,232,525,233,527,234,529,235,
+ 531,236,533,237,535,238,537,239,539,240,541,241,543,242,1,0,37,2,0,92,
+ 92,96,96,2,0,34,34,92,92,2,0,39,39,92,92,2,0,92,92,125,125,2,0,65,65,
+ 97,97,2,0,66,66,98,98,2,0,67,67,99,99,2,0,68,68,100,100,2,0,69,69,101,
+ 101,2,0,70,70,102,102,2,0,71,71,103,103,2,0,72,72,104,104,2,0,73,73,105,
+ 105,2,0,74,74,106,106,2,0,75,75,107,107,2,0,76,76,108,108,2,0,77,77,109,
+ 109,2,0,78,78,110,110,2,0,79,79,111,111,2,0,80,80,112,112,2,0,81,81,113,
+ 113,2,0,82,82,114,114,2,0,83,83,115,115,2,0,84,84,116,116,2,0,85,85,117,
+ 117,2,0,86,86,118,118,2,0,87,87,119,119,2,0,88,88,120,120,2,0,89,89,121,
+ 121,2,0,90,90,122,122,2,0,65,90,97,122,1,0,48,55,1,0,48,57,3,0,48,57,
+ 65,70,97,102,2,0,10,10,13,13,2,1,10,10,13,13,2,0,9,13,32,32,2252,0,1,
+ 1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,
+ 0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,
+ 1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,
+ 0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,
+ 0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,
+ 1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,
+ 0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,
+ 0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,
+ 1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,
+ 0,0,0,99,1,0,0,0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0,107,1,0,
+ 0,0,0,109,1,0,0,0,0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0,0,117,1,0,
+ 0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0,0,0,0,125,1,0,0,0,0,127,1,0,
+ 0,0,0,129,1,0,0,0,0,131,1,0,0,0,0,133,1,0,0,0,0,135,1,0,0,0,0,137,1,0,
+ 0,0,0,139,1,0,0,0,0,141,1,0,0,0,0,143,1,0,0,0,0,145,1,0,0,0,0,147,1,0,
+ 0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0,155,1,0,0,0,0,157,1,0,
+ 0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0,0,0,0,165,1,0,0,0,0,167,1,0,
+ 0,0,0,169,1,0,0,0,0,171,1,0,0,0,0,173,1,0,0,0,0,175,1,0,0,0,0,177,1,0,
+ 0,0,0,179,1,0,0,0,0,181,1,0,0,0,0,183,1,0,0,0,0,185,1,0,0,0,0,187,1,0,
+ 0,0,0,189,1,0,0,0,0,191,1,0,0,0,0,193,1,0,0,0,0,195,1,0,0,0,0,197,1,0,
+ 0,0,0,199,1,0,0,0,0,201,1,0,0,0,0,203,1,0,0,0,0,205,1,0,0,0,0,207,1,0,
+ 0,0,0,209,1,0,0,0,0,211,1,0,0,0,0,213,1,0,0,0,0,215,1,0,0,0,0,217,1,0,
+ 0,0,0,219,1,0,0,0,0,221,1,0,0,0,0,223,1,0,0,0,0,225,1,0,0,0,0,227,1,0,
+ 0,0,0,229,1,0,0,0,0,231,1,0,0,0,0,233,1,0,0,0,0,235,1,0,0,0,0,237,1,0,
+ 0,0,0,239,1,0,0,0,0,241,1,0,0,0,0,243,1,0,0,0,0,245,1,0,0,0,0,247,1,0,
+ 0,0,0,249,1,0,0,0,0,251,1,0,0,0,0,253,1,0,0,0,0,255,1,0,0,0,0,257,1,0,
+ 0,0,0,259,1,0,0,0,0,261,1,0,0,0,0,263,1,0,0,0,0,265,1,0,0,0,0,267,1,0,
+ 0,0,0,269,1,0,0,0,0,271,1,0,0,0,0,273,1,0,0,0,0,275,1,0,0,0,0,277,1,0,
+ 0,0,0,279,1,0,0,0,0,281,1,0,0,0,0,283,1,0,0,0,0,285,1,0,0,0,0,287,1,0,
+ 0,0,0,289,1,0,0,0,0,291,1,0,0,0,0,293,1,0,0,0,0,295,1,0,0,0,0,297,1,0,
+ 0,0,0,299,1,0,0,0,0,301,1,0,0,0,0,303,1,0,0,0,0,305,1,0,0,0,0,307,1,0,
+ 0,0,0,309,1,0,0,0,0,311,1,0,0,0,0,313,1,0,0,0,0,315,1,0,0,0,0,317,1,0,
+ 0,0,0,319,1,0,0,0,0,321,1,0,0,0,0,323,1,0,0,0,0,325,1,0,0,0,0,327,1,0,
+ 0,0,0,329,1,0,0,0,0,331,1,0,0,0,0,333,1,0,0,0,0,335,1,0,0,0,0,337,1,0,
+ 0,0,0,339,1,0,0,0,0,341,1,0,0,0,0,343,1,0,0,0,0,345,1,0,0,0,0,347,1,0,
+ 0,0,0,349,1,0,0,0,0,351,1,0,0,0,0,353,1,0,0,0,0,355,1,0,0,0,0,357,1,0,
+ 0,0,0,359,1,0,0,0,0,361,1,0,0,0,0,363,1,0,0,0,0,365,1,0,0,0,0,367,1,0,
+ 0,0,0,369,1,0,0,0,0,371,1,0,0,0,0,373,1,0,0,0,0,375,1,0,0,0,0,377,1,0,
+ 0,0,0,379,1,0,0,0,0,381,1,0,0,0,0,383,1,0,0,0,0,385,1,0,0,0,0,387,1,0,
+ 0,0,0,389,1,0,0,0,0,391,1,0,0,0,0,393,1,0,0,0,0,395,1,0,0,0,0,397,1,0,
+ 0,0,0,399,1,0,0,0,0,461,1,0,0,0,0,463,1,0,0,0,0,465,1,0,0,0,0,467,1,0,
+ 0,0,0,469,1,0,0,0,0,471,1,0,0,0,0,473,1,0,0,0,0,475,1,0,0,0,0,477,1,0,
+ 0,0,0,479,1,0,0,0,0,481,1,0,0,0,0,483,1,0,0,0,0,485,1,0,0,0,0,487,1,0,
+ 0,0,0,489,1,0,0,0,0,491,1,0,0,0,0,493,1,0,0,0,0,495,1,0,0,0,0,497,1,0,
+ 0,0,0,499,1,0,0,0,0,501,1,0,0,0,0,503,1,0,0,0,0,505,1,0,0,0,0,507,1,0,
+ 0,0,0,509,1,0,0,0,0,511,1,0,0,0,0,513,1,0,0,0,0,515,1,0,0,0,0,517,1,0,
+ 0,0,0,519,1,0,0,0,0,521,1,0,0,0,0,523,1,0,0,0,0,525,1,0,0,0,0,527,1,0,
+ 0,0,0,529,1,0,0,0,0,531,1,0,0,0,0,533,1,0,0,0,0,535,1,0,0,0,0,537,1,0,
+ 0,0,0,539,1,0,0,0,0,541,1,0,0,0,0,543,1,0,0,0,1,545,1,0,0,0,3,549,1,0,
+ 0,0,5,555,1,0,0,0,7,561,1,0,0,0,9,565,1,0,0,0,11,571,1,0,0,0,13,575,1,
+ 0,0,0,15,580,1,0,0,0,17,584,1,0,0,0,19,590,1,0,0,0,21,607,1,0,0,0,23,
+ 609,1,0,0,0,25,614,1,0,0,0,27,618,1,0,0,0,29,624,1,0,0,0,31,631,1,0,0,
+ 0,33,639,1,0,0,0,35,644,1,0,0,0,37,647,1,0,0,0,39,652,1,0,0,0,41,657,
+ 1,0,0,0,43,663,1,0,0,0,45,669,1,0,0,0,47,677,1,0,0,0,49,683,1,0,0,0,51,
+ 690,1,0,0,0,53,698,1,0,0,0,55,705,1,0,0,0,57,713,1,0,0,0,59,724,1,0,0,
+ 0,61,731,1,0,0,0,63,737,1,0,0,0,65,742,1,0,0,0,67,750,1,0,0,0,69,759,
+ 1,0,0,0,71,769,1,0,0,0,73,774,1,0,0,0,75,778,1,0,0,0,77,790,1,0,0,0,79,
+ 798,1,0,0,0,81,804,1,0,0,0,83,811,1,0,0,0,85,816,1,0,0,0,87,827,1,0,0,
+ 0,89,836,1,0,0,0,91,843,1,0,0,0,93,856,1,0,0,0,95,867,1,0,0,0,97,872,
+ 1,0,0,0,99,881,1,0,0,0,101,893,1,0,0,0,103,898,1,0,0,0,105,903,1,0,0,
+ 0,107,907,1,0,0,0,109,914,1,0,0,0,111,921,1,0,0,0,113,928,1,0,0,0,115,
+ 936,1,0,0,0,117,947,1,0,0,0,119,955,1,0,0,0,121,963,1,0,0,0,123,969,1,
+ 0,0,0,125,975,1,0,0,0,127,981,1,0,0,0,129,991,1,0,0,0,131,995,1,0,0,0,
+ 133,1002,1,0,0,0,135,1009,1,0,0,0,137,1014,1,0,0,0,139,1019,1,0,0,0,141,
+ 1028,1,0,0,0,143,1035,1,0,0,0,145,1047,1,0,0,0,147,1053,1,0,0,0,149,1060,
+ 1,0,0,0,151,1073,1,0,0,0,153,1078,1,0,0,0,155,1081,1,0,0,0,157,1084,1,
+ 0,0,0,159,1090,1,0,0,0,161,1093,1,0,0,0,163,1112,1,0,0,0,165,1114,1,0,
+ 0,0,167,1124,1,0,0,0,169,1130,1,0,0,0,171,1137,1,0,0,0,173,1146,1,0,0,
+ 0,175,1151,1,0,0,0,177,1154,1,0,0,0,179,1167,1,0,0,0,181,1172,1,0,0,0,
+ 183,1176,1,0,0,0,185,1181,1,0,0,0,187,1186,1,0,0,0,189,1193,1,0,0,0,191,
+ 1201,1,0,0,0,193,1206,1,0,0,0,195,1215,1,0,0,0,197,1220,1,0,0,0,199,1226,
+ 1,0,0,0,201,1231,1,0,0,0,203,1237,1,0,0,0,205,1242,1,0,0,0,207,1254,1,
+ 0,0,0,209,1267,1,0,0,0,211,1271,1,0,0,0,213,1278,1,0,0,0,215,1282,1,0,
+ 0,0,217,1289,1,0,0,0,219,1296,1,0,0,0,221,1302,1,0,0,0,223,1307,1,0,0,
+ 0,225,1316,1,0,0,0,227,1320,1,0,0,0,229,1323,1,0,0,0,231,1327,1,0,0,0,
+ 233,1332,1,0,0,0,235,1338,1,0,0,0,237,1345,1,0,0,0,239,1348,1,0,0,0,241,
+ 1357,1,0,0,0,243,1360,1,0,0,0,245,1366,1,0,0,0,247,1372,1,0,0,0,249,1380,
+ 1,0,0,0,251,1385,1,0,0,0,253,1395,1,0,0,0,255,1404,1,0,0,0,257,1414,1,
+ 0,0,0,259,1423,1,0,0,0,261,1431,1,0,0,0,263,1442,1,0,0,0,265,1450,1,0,
+ 0,0,267,1456,1,0,0,0,269,1463,1,0,0,0,271,1470,1,0,0,0,273,1477,1,0,0,
+ 0,275,1485,1,0,0,0,277,1493,1,0,0,0,279,1504,1,0,0,0,281,1510,1,0,0,0,
+ 283,1517,1,0,0,0,285,1521,1,0,0,0,287,1526,1,0,0,0,289,1533,1,0,0,0,291,
+ 1540,1,0,0,0,293,1547,1,0,0,0,295,1552,1,0,0,0,297,1558,1,0,0,0,299,1562,
+ 1,0,0,0,301,1571,1,0,0,0,303,1576,1,0,0,0,305,1583,1,0,0,0,307,1589,1,
+ 0,0,0,309,1594,1,0,0,0,311,1604,1,0,0,0,313,1609,1,0,0,0,315,1616,1,0,
+ 0,0,317,1623,1,0,0,0,319,1629,1,0,0,0,321,1636,1,0,0,0,323,1646,1,0,0,
+ 0,325,1651,1,0,0,0,327,1656,1,0,0,0,329,1661,1,0,0,0,331,1669,1,0,0,0,
+ 333,1679,1,0,0,0,335,1682,1,0,0,0,337,1686,1,0,0,0,339,1693,1,0,0,0,341,
+ 1702,1,0,0,0,343,1707,1,0,0,0,345,1716,1,0,0,0,347,1720,1,0,0,0,349,1725,
+ 1,0,0,0,351,1735,1,0,0,0,353,1741,1,0,0,0,355,1748,1,0,0,0,357,1752,1,
+ 0,0,0,359,1758,1,0,0,0,361,1763,1,0,0,0,363,1770,1,0,0,0,365,1775,1,0,
+ 0,0,367,1782,1,0,0,0,369,1788,1,0,0,0,371,1793,1,0,0,0,373,1798,1,0,0,
+ 0,375,1804,1,0,0,0,377,1811,1,0,0,0,379,1826,1,0,0,0,381,1828,1,0,0,0,
+ 383,1834,1,0,0,0,385,1869,1,0,0,0,387,1911,1,0,0,0,389,1989,1,0,0,0,391,
+ 1991,1,0,0,0,393,1998,1,0,0,0,395,2002,1,0,0,0,397,2009,1,0,0,0,399,2022,
+ 1,0,0,0,401,2035,1,0,0,0,403,2037,1,0,0,0,405,2039,1,0,0,0,407,2041,1,
+ 0,0,0,409,2043,1,0,0,0,411,2045,1,0,0,0,413,2047,1,0,0,0,415,2049,1,0,
+ 0,0,417,2051,1,0,0,0,419,2053,1,0,0,0,421,2055,1,0,0,0,423,2057,1,0,0,
+ 0,425,2059,1,0,0,0,427,2061,1,0,0,0,429,2063,1,0,0,0,431,2065,1,0,0,0,
+ 433,2067,1,0,0,0,435,2069,1,0,0,0,437,2071,1,0,0,0,439,2073,1,0,0,0,441,
+ 2075,1,0,0,0,443,2077,1,0,0,0,445,2079,1,0,0,0,447,2081,1,0,0,0,449,2083,
+ 1,0,0,0,451,2085,1,0,0,0,453,2087,1,0,0,0,455,2089,1,0,0,0,457,2091,1,
+ 0,0,0,459,2093,1,0,0,0,461,2095,1,0,0,0,463,2098,1,0,0,0,465,2100,1,0,
+ 0,0,467,2102,1,0,0,0,469,2104,1,0,0,0,471,2106,1,0,0,0,473,2108,1,0,0,
+ 0,475,2111,1,0,0,0,477,2113,1,0,0,0,479,2115,1,0,0,0,481,2117,1,0,0,0,
+ 483,2120,1,0,0,0,485,2122,1,0,0,0,487,2125,1,0,0,0,489,2127,1,0,0,0,491,
+ 2129,1,0,0,0,493,2132,1,0,0,0,495,2136,1,0,0,0,497,2138,1,0,0,0,499,2140,
+ 1,0,0,0,501,2142,1,0,0,0,503,2145,1,0,0,0,505,2151,1,0,0,0,507,2153,1,
+ 0,0,0,509,2157,1,0,0,0,511,2160,1,0,0,0,513,2163,1,0,0,0,515,2165,1,0,
+ 0,0,517,2167,1,0,0,0,519,2169,1,0,0,0,521,2171,1,0,0,0,523,2173,1,0,0,
+ 0,525,2175,1,0,0,0,527,2178,1,0,0,0,529,2180,1,0,0,0,531,2182,1,0,0,0,
+ 533,2184,1,0,0,0,535,2186,1,0,0,0,537,2188,1,0,0,0,539,2190,1,0,0,0,541,
+ 2204,1,0,0,0,543,2218,1,0,0,0,545,546,3,401,200,0,546,547,3,407,203,0,
+ 547,548,3,407,203,0,548,2,1,0,0,0,549,550,3,401,200,0,550,551,3,411,205,
+ 0,551,552,3,439,219,0,552,553,3,409,204,0,553,554,3,435,217,0,554,4,1,
+ 0,0,0,555,556,3,401,200,0,556,557,3,423,211,0,557,558,3,417,208,0,558,
+ 559,3,401,200,0,559,560,3,437,218,0,560,6,1,0,0,0,561,562,3,401,200,0,
+ 562,563,3,423,211,0,563,564,3,423,211,0,564,8,1,0,0,0,565,566,3,401,200,
+ 0,566,567,3,423,211,0,567,568,3,439,219,0,568,569,3,409,204,0,569,570,
+ 3,435,217,0,570,10,1,0,0,0,571,572,3,401,200,0,572,573,3,427,213,0,573,
+ 574,3,407,203,0,574,12,1,0,0,0,575,576,3,401,200,0,576,577,3,427,213,
+ 0,577,578,3,439,219,0,578,579,3,417,208,0,579,14,1,0,0,0,580,581,3,401,
+ 200,0,581,582,3,427,213,0,582,583,3,449,224,0,583,16,1,0,0,0,584,585,
+ 3,401,200,0,585,586,3,435,217,0,586,587,3,435,217,0,587,588,3,401,200,
+ 0,588,589,3,449,224,0,589,18,1,0,0,0,590,591,3,401,200,0,591,592,3,437,
+ 218,0,592,20,1,0,0,0,593,594,3,401,200,0,594,595,3,437,218,0,595,596,
+ 3,405,202,0,596,608,1,0,0,0,597,598,3,401,200,0,598,599,3,437,218,0,599,
+ 600,3,405,202,0,600,601,3,409,204,0,601,602,3,427,213,0,602,603,3,407,
+ 203,0,603,604,3,417,208,0,604,605,3,427,213,0,605,606,3,413,206,0,606,
+ 608,1,0,0,0,607,593,1,0,0,0,607,597,1,0,0,0,608,22,1,0,0,0,609,610,3,
+ 401,200,0,610,611,3,437,218,0,611,612,3,429,214,0,612,613,3,411,205,0,
+ 613,24,1,0,0,0,614,615,3,401,200,0,615,616,3,437,218,0,616,617,3,439,
+ 219,0,617,26,1,0,0,0,618,619,3,401,200,0,619,620,3,437,218,0,620,621,
+ 3,449,224,0,621,622,3,427,213,0,622,623,3,405,202,0,623,28,1,0,0,0,624,
+ 625,3,401,200,0,625,626,3,439,219,0,626,627,3,439,219,0,627,628,3,401,
+ 200,0,628,629,3,405,202,0,629,630,3,415,207,0,630,30,1,0,0,0,631,632,
+ 3,403,201,0,632,633,3,409,204,0,633,634,3,439,219,0,634,635,3,445,222,
+ 0,635,636,3,409,204,0,636,637,3,409,204,0,637,638,3,427,213,0,638,32,
+ 1,0,0,0,639,640,3,403,201,0,640,641,3,429,214,0,641,642,3,439,219,0,642,
+ 643,3,415,207,0,643,34,1,0,0,0,644,645,3,403,201,0,645,646,3,449,224,
+ 0,646,36,1,0,0,0,647,648,3,405,202,0,648,649,3,401,200,0,649,650,3,437,
+ 218,0,650,651,3,409,204,0,651,38,1,0,0,0,652,653,3,405,202,0,653,654,
+ 3,401,200,0,654,655,3,437,218,0,655,656,3,439,219,0,656,40,1,0,0,0,657,
+ 658,3,405,202,0,658,659,3,415,207,0,659,660,3,409,204,0,660,661,3,405,
+ 202,0,661,662,3,421,210,0,662,42,1,0,0,0,663,664,3,405,202,0,664,665,
+ 3,423,211,0,665,666,3,409,204,0,666,667,3,401,200,0,667,668,3,435,217,
+ 0,668,44,1,0,0,0,669,670,3,405,202,0,670,671,3,423,211,0,671,672,3,441,
+ 220,0,672,673,3,437,218,0,673,674,3,439,219,0,674,675,3,409,204,0,675,
+ 676,3,435,217,0,676,46,1,0,0,0,677,678,3,405,202,0,678,679,3,429,214,
+ 0,679,680,3,407,203,0,680,681,3,409,204,0,681,682,3,405,202,0,682,48,
+ 1,0,0,0,683,684,3,405,202,0,684,685,3,429,214,0,685,686,3,415,207,0,686,
+ 687,3,429,214,0,687,688,3,435,217,0,688,689,3,439,219,0,689,50,1,0,0,
+ 0,690,691,3,405,202,0,691,692,3,429,214,0,692,693,3,423,211,0,693,694,
+ 3,423,211,0,694,695,3,401,200,0,695,696,3,439,219,0,696,697,3,409,204,
+ 0,697,52,1,0,0,0,698,699,3,405,202,0,699,700,3,429,214,0,700,701,3,423,
+ 211,0,701,702,3,441,220,0,702,703,3,425,212,0,703,704,3,427,213,0,704,
+ 54,1,0,0,0,705,706,3,405,202,0,706,707,3,429,214,0,707,708,3,425,212,
+ 0,708,709,3,425,212,0,709,710,3,409,204,0,710,711,3,427,213,0,711,712,
+ 3,439,219,0,712,56,1,0,0,0,713,714,3,405,202,0,714,715,3,429,214,0,715,
+ 716,3,427,213,0,716,717,3,437,218,0,717,718,3,439,219,0,718,719,3,435,
+ 217,0,719,720,3,401,200,0,720,721,3,417,208,0,721,722,3,427,213,0,722,
+ 723,3,439,219,0,723,58,1,0,0,0,724,725,3,405,202,0,725,726,3,435,217,
+ 0,726,727,3,409,204,0,727,728,3,401,200,0,728,729,3,439,219,0,729,730,
+ 3,409,204,0,730,60,1,0,0,0,731,732,3,405,202,0,732,733,3,435,217,0,733,
+ 734,3,429,214,0,734,735,3,437,218,0,735,736,3,437,218,0,736,62,1,0,0,
+ 0,737,738,3,405,202,0,738,739,3,441,220,0,739,740,3,403,201,0,740,741,
+ 3,409,204,0,741,64,1,0,0,0,742,743,3,405,202,0,743,744,3,441,220,0,744,
+ 745,3,435,217,0,745,746,3,435,217,0,746,747,3,409,204,0,747,748,3,427,
+ 213,0,748,749,3,439,219,0,749,66,1,0,0,0,750,751,3,407,203,0,751,752,
+ 3,401,200,0,752,753,3,439,219,0,753,754,3,401,200,0,754,755,3,403,201,
+ 0,755,756,3,401,200,0,756,757,3,437,218,0,757,758,3,409,204,0,758,68,
+ 1,0,0,0,759,760,3,407,203,0,760,761,3,401,200,0,761,762,3,439,219,0,762,
+ 763,3,401,200,0,763,764,3,403,201,0,764,765,3,401,200,0,765,766,3,437,
+ 218,0,766,767,3,409,204,0,767,768,3,437,218,0,768,70,1,0,0,0,769,770,
+ 3,407,203,0,770,771,3,401,200,0,771,772,3,439,219,0,772,773,3,409,204,
+ 0,773,72,1,0,0,0,774,775,3,407,203,0,775,776,3,401,200,0,776,777,3,449,
+ 224,0,777,74,1,0,0,0,778,779,3,407,203,0,779,780,3,409,204,0,780,781,
+ 3,407,203,0,781,782,3,441,220,0,782,783,3,431,215,0,783,784,3,423,211,
+ 0,784,785,3,417,208,0,785,786,3,405,202,0,786,787,3,401,200,0,787,788,
+ 3,439,219,0,788,789,3,409,204,0,789,76,1,0,0,0,790,791,3,407,203,0,791,
+ 792,3,409,204,0,792,793,3,411,205,0,793,794,3,401,200,0,794,795,3,441,
+ 220,0,795,796,3,423,211,0,796,797,3,439,219,0,797,78,1,0,0,0,798,799,
+ 3,407,203,0,799,800,3,409,204,0,800,801,3,423,211,0,801,802,3,401,200,
+ 0,802,803,3,449,224,0,803,80,1,0,0,0,804,805,3,407,203,0,805,806,3,409,
+ 204,0,806,807,3,423,211,0,807,808,3,409,204,0,808,809,3,439,219,0,809,
+ 810,3,409,204,0,810,82,1,0,0,0,811,812,3,407,203,0,812,813,3,409,204,
+ 0,813,814,3,437,218,0,814,815,3,405,202,0,815,84,1,0,0,0,816,817,3,407,
+ 203,0,817,818,3,409,204,0,818,819,3,437,218,0,819,820,3,405,202,0,820,
+ 821,3,409,204,0,821,822,3,427,213,0,822,823,3,407,203,0,823,824,3,417,
+ 208,0,824,825,3,427,213,0,825,826,3,413,206,0,826,86,1,0,0,0,827,828,
+ 3,407,203,0,828,829,3,409,204,0,829,830,3,437,218,0,830,831,3,405,202,
+ 0,831,832,3,435,217,0,832,833,3,417,208,0,833,834,3,403,201,0,834,835,
+ 3,409,204,0,835,88,1,0,0,0,836,837,3,407,203,0,837,838,3,409,204,0,838,
+ 839,3,439,219,0,839,840,3,401,200,0,840,841,3,405,202,0,841,842,3,415,
+ 207,0,842,90,1,0,0,0,843,844,3,407,203,0,844,845,3,417,208,0,845,846,
+ 3,405,202,0,846,847,3,439,219,0,847,848,3,417,208,0,848,849,3,429,214,
+ 0,849,850,3,427,213,0,850,851,3,401,200,0,851,852,3,435,217,0,852,853,
+ 3,417,208,0,853,854,3,409,204,0,854,855,3,437,218,0,855,92,1,0,0,0,856,
+ 857,3,407,203,0,857,858,3,417,208,0,858,859,3,405,202,0,859,860,3,439,
+ 219,0,860,861,3,417,208,0,861,862,3,429,214,0,862,863,3,427,213,0,863,
+ 864,3,401,200,0,864,865,3,435,217,0,865,866,3,449,224,0,866,94,1,0,0,
+ 0,867,868,3,407,203,0,868,869,3,417,208,0,869,870,3,437,218,0,870,871,
+ 3,421,210,0,871,96,1,0,0,0,872,873,3,407,203,0,873,874,3,417,208,0,874,
+ 875,3,437,218,0,875,876,3,439,219,0,876,877,3,417,208,0,877,878,3,427,
+ 213,0,878,879,3,405,202,0,879,880,3,439,219,0,880,98,1,0,0,0,881,882,
+ 3,407,203,0,882,883,3,417,208,0,883,884,3,437,218,0,884,885,3,439,219,
+ 0,885,886,3,435,217,0,886,887,3,417,208,0,887,888,3,403,201,0,888,889,
+ 3,441,220,0,889,890,3,439,219,0,890,891,3,409,204,0,891,892,3,407,203,
+ 0,892,100,1,0,0,0,893,894,3,407,203,0,894,895,3,435,217,0,895,896,3,429,
+ 214,0,896,897,3,431,215,0,897,102,1,0,0,0,898,899,3,409,204,0,899,900,
+ 3,423,211,0,900,901,3,437,218,0,901,902,3,409,204,0,902,104,1,0,0,0,903,
+ 904,3,409,204,0,904,905,3,427,213,0,905,906,3,407,203,0,906,106,1,0,0,
+ 0,907,908,3,409,204,0,908,909,3,427,213,0,909,910,3,413,206,0,910,911,
+ 3,417,208,0,911,912,3,427,213,0,912,913,3,409,204,0,913,108,1,0,0,0,914,
+ 915,3,409,204,0,915,916,3,443,221,0,916,917,3,409,204,0,917,918,3,427,
+ 213,0,918,919,3,439,219,0,919,920,3,437,218,0,920,110,1,0,0,0,921,922,
+ 3,409,204,0,922,923,3,447,223,0,923,924,3,417,208,0,924,925,3,437,218,
+ 0,925,926,3,439,219,0,926,927,3,437,218,0,927,112,1,0,0,0,928,929,3,409,
+ 204,0,929,930,3,447,223,0,930,931,3,431,215,0,931,932,3,423,211,0,932,
+ 933,3,401,200,0,933,934,3,417,208,0,934,935,3,427,213,0,935,114,1,0,0,
+ 0,936,937,3,409,204,0,937,938,3,447,223,0,938,939,3,431,215,0,939,940,
+ 3,435,217,0,940,941,3,409,204,0,941,942,3,437,218,0,942,943,3,437,218,
+ 0,943,944,3,417,208,0,944,945,3,429,214,0,945,946,3,427,213,0,946,116,
+ 1,0,0,0,947,948,3,409,204,0,948,949,3,447,223,0,949,950,3,439,219,0,950,
+ 951,3,435,217,0,951,952,3,401,200,0,952,953,3,405,202,0,953,954,3,439,
+ 219,0,954,118,1,0,0,0,955,956,3,411,205,0,956,957,3,409,204,0,957,958,
+ 3,439,219,0,958,959,3,405,202,0,959,960,3,415,207,0,960,961,3,409,204,
+ 0,961,962,3,437,218,0,962,120,1,0,0,0,963,964,3,411,205,0,964,965,3,417,
+ 208,0,965,966,3,427,213,0,966,967,3,401,200,0,967,968,3,423,211,0,968,
+ 122,1,0,0,0,969,970,3,411,205,0,970,971,3,417,208,0,971,972,3,435,217,
+ 0,972,973,3,437,218,0,973,974,3,439,219,0,974,124,1,0,0,0,975,976,3,411,
+ 205,0,976,977,3,423,211,0,977,978,3,441,220,0,978,979,3,437,218,0,979,
+ 980,3,415,207,0,980,126,1,0,0,0,981,982,3,411,205,0,982,983,3,429,214,
+ 0,983,984,3,423,211,0,984,985,3,423,211,0,985,986,3,429,214,0,986,987,
+ 3,445,222,0,987,988,3,417,208,0,988,989,3,427,213,0,989,990,3,413,206,
+ 0,990,128,1,0,0,0,991,992,3,411,205,0,992,993,3,429,214,0,993,994,3,435,
+ 217,0,994,130,1,0,0,0,995,996,3,411,205,0,996,997,3,429,214,0,997,998,
+ 3,435,217,0,998,999,3,425,212,0,999,1000,3,401,200,0,1000,1001,3,439,
+ 219,0,1001,132,1,0,0,0,1002,1003,3,411,205,0,1003,1004,3,435,217,0,1004,
+ 1005,3,409,204,0,1005,1006,3,409,204,0,1006,1007,3,451,225,0,1007,1008,
+ 3,409,204,0,1008,134,1,0,0,0,1009,1010,3,411,205,0,1010,1011,3,435,217,
+ 0,1011,1012,3,429,214,0,1012,1013,3,425,212,0,1013,136,1,0,0,0,1014,1015,
+ 3,411,205,0,1015,1016,3,441,220,0,1016,1017,3,423,211,0,1017,1018,3,423,
+ 211,0,1018,138,1,0,0,0,1019,1020,3,411,205,0,1020,1021,3,441,220,0,1021,
+ 1022,3,427,213,0,1022,1023,3,405,202,0,1023,1024,3,439,219,0,1024,1025,
+ 3,417,208,0,1025,1026,3,429,214,0,1026,1027,3,427,213,0,1027,140,1,0,
+ 0,0,1028,1029,3,413,206,0,1029,1030,3,423,211,0,1030,1031,3,429,214,0,
+ 1031,1032,3,403,201,0,1032,1033,3,401,200,0,1033,1034,3,423,211,0,1034,
+ 142,1,0,0,0,1035,1036,3,413,206,0,1036,1037,3,435,217,0,1037,1038,3,401,
+ 200,0,1038,1039,3,427,213,0,1039,1040,3,441,220,0,1040,1041,3,423,211,
+ 0,1041,1042,3,401,200,0,1042,1043,3,435,217,0,1043,1044,3,417,208,0,1044,
+ 1045,3,439,219,0,1045,1046,3,449,224,0,1046,144,1,0,0,0,1047,1048,3,413,
+ 206,0,1048,1049,3,435,217,0,1049,1050,3,429,214,0,1050,1051,3,441,220,
+ 0,1051,1052,3,431,215,0,1052,146,1,0,0,0,1053,1054,3,415,207,0,1054,1055,
+ 3,401,200,0,1055,1056,3,443,221,0,1056,1057,3,417,208,0,1057,1058,3,427,
+ 213,0,1058,1059,3,413,206,0,1059,148,1,0,0,0,1060,1061,3,415,207,0,1061,
+ 1062,3,417,208,0,1062,1063,3,409,204,0,1063,1064,3,435,217,0,1064,1065,
+ 3,401,200,0,1065,1066,3,435,217,0,1066,1067,3,405,202,0,1067,1068,3,415,
+ 207,0,1068,1069,3,417,208,0,1069,1070,3,405,202,0,1070,1071,3,401,200,
+ 0,1071,1072,3,423,211,0,1072,150,1,0,0,0,1073,1074,3,415,207,0,1074,1075,
+ 3,429,214,0,1075,1076,3,441,220,0,1076,1077,3,435,217,0,1077,152,1,0,
+ 0,0,1078,1079,3,417,208,0,1079,1080,3,407,203,0,1080,154,1,0,0,0,1081,
+ 1082,3,417,208,0,1082,1083,3,411,205,0,1083,156,1,0,0,0,1084,1085,3,417,
+ 208,0,1085,1086,3,423,211,0,1086,1087,3,417,208,0,1087,1088,3,421,210,
+ 0,1088,1089,3,409,204,0,1089,158,1,0,0,0,1090,1091,3,417,208,0,1091,1092,
+ 3,427,213,0,1092,160,1,0,0,0,1093,1094,3,417,208,0,1094,1095,3,427,213,
+ 0,1095,1096,3,407,203,0,1096,1097,3,409,204,0,1097,1098,3,447,223,0,1098,
+ 162,1,0,0,0,1099,1100,3,417,208,0,1100,1101,3,427,213,0,1101,1102,3,411,
+ 205,0,1102,1113,1,0,0,0,1103,1104,3,417,208,0,1104,1105,3,427,213,0,1105,
+ 1106,3,411,205,0,1106,1107,3,417,208,0,1107,1108,3,427,213,0,1108,1109,
+ 3,417,208,0,1109,1110,3,439,219,0,1110,1111,3,449,224,0,1111,1113,1,0,
+ 0,0,1112,1099,1,0,0,0,1112,1103,1,0,0,0,1113,164,1,0,0,0,1114,1115,3,
+ 417,208,0,1115,1116,3,427,213,0,1116,1117,3,419,209,0,1117,1118,3,409,
+ 204,0,1118,1119,3,405,202,0,1119,1120,3,439,219,0,1120,1121,3,417,208,
+ 0,1121,1122,3,443,221,0,1122,1123,3,409,204,0,1123,166,1,0,0,0,1124,1125,
+ 3,417,208,0,1125,1126,3,427,213,0,1126,1127,3,427,213,0,1127,1128,3,409,
+ 204,0,1128,1129,3,435,217,0,1129,168,1,0,0,0,1130,1131,3,417,208,0,1131,
+ 1132,3,427,213,0,1132,1133,3,437,218,0,1133,1134,3,409,204,0,1134,1135,
+ 3,435,217,0,1135,1136,3,439,219,0,1136,170,1,0,0,0,1137,1138,3,417,208,
+ 0,1138,1139,3,427,213,0,1139,1140,3,439,219,0,1140,1141,3,409,204,0,1141,
+ 1142,3,435,217,0,1142,1143,3,443,221,0,1143,1144,3,401,200,0,1144,1145,
+ 3,423,211,0,1145,172,1,0,0,0,1146,1147,3,417,208,0,1147,1148,3,427,213,
+ 0,1148,1149,3,439,219,0,1149,1150,3,429,214,0,1150,174,1,0,0,0,1151,1152,
+ 3,417,208,0,1152,1153,3,437,218,0,1153,176,1,0,0,0,1154,1155,3,417,208,
+ 0,1155,1156,3,437,218,0,1156,1157,3,537,268,0,1157,1158,3,429,214,0,1158,
+ 1159,3,403,201,0,1159,1160,3,419,209,0,1160,1161,3,409,204,0,1161,1162,
+ 3,405,202,0,1162,1163,3,439,219,0,1163,1164,3,537,268,0,1164,1165,3,417,
+ 208,0,1165,1166,3,407,203,0,1166,178,1,0,0,0,1167,1168,3,419,209,0,1168,
+ 1169,3,429,214,0,1169,1170,3,417,208,0,1170,1171,3,427,213,0,1171,180,
+ 1,0,0,0,1172,1173,3,421,210,0,1173,1174,3,409,204,0,1174,1175,3,449,224,
+ 0,1175,182,1,0,0,0,1176,1177,3,421,210,0,1177,1178,3,417,208,0,1178,1179,
+ 3,423,211,0,1179,1180,3,423,211,0,1180,184,1,0,0,0,1181,1182,3,423,211,
+ 0,1182,1183,3,401,200,0,1183,1184,3,437,218,0,1184,1185,3,439,219,0,1185,
+ 186,1,0,0,0,1186,1187,3,423,211,0,1187,1188,3,401,200,0,1188,1189,3,449,
+ 224,0,1189,1190,3,429,214,0,1190,1191,3,441,220,0,1191,1192,3,439,219,
+ 0,1192,188,1,0,0,0,1193,1194,3,423,211,0,1194,1195,3,409,204,0,1195,1196,
+ 3,401,200,0,1196,1197,3,407,203,0,1197,1198,3,417,208,0,1198,1199,3,427,
+ 213,0,1199,1200,3,413,206,0,1200,190,1,0,0,0,1201,1202,3,423,211,0,1202,
+ 1203,3,409,204,0,1203,1204,3,411,205,0,1204,1205,3,439,219,0,1205,192,
+ 1,0,0,0,1206,1207,3,423,211,0,1207,1208,3,417,208,0,1208,1209,3,411,205,
+ 0,1209,1210,3,409,204,0,1210,1211,3,439,219,0,1211,1212,3,417,208,0,1212,
+ 1213,3,425,212,0,1213,1214,3,409,204,0,1214,194,1,0,0,0,1215,1216,3,423,
+ 211,0,1216,1217,3,417,208,0,1217,1218,3,421,210,0,1218,1219,3,409,204,
+ 0,1219,196,1,0,0,0,1220,1221,3,423,211,0,1221,1222,3,417,208,0,1222,1223,
+ 3,425,212,0,1223,1224,3,417,208,0,1224,1225,3,439,219,0,1225,198,1,0,
+ 0,0,1226,1227,3,423,211,0,1227,1228,3,417,208,0,1228,1229,3,443,221,0,
+ 1229,1230,3,409,204,0,1230,200,1,0,0,0,1231,1232,3,423,211,0,1232,1233,
+ 3,429,214,0,1233,1234,3,405,202,0,1234,1235,3,401,200,0,1235,1236,3,423,
+ 211,0,1236,202,1,0,0,0,1237,1238,3,423,211,0,1238,1239,3,429,214,0,1239,
+ 1240,3,413,206,0,1240,1241,3,437,218,0,1241,204,1,0,0,0,1242,1243,3,425,
+ 212,0,1243,1244,3,401,200,0,1244,1245,3,439,219,0,1245,1246,3,409,204,
+ 0,1246,1247,3,435,217,0,1247,1248,3,417,208,0,1248,1249,3,401,200,0,1249,
+ 1250,3,423,211,0,1250,1251,3,417,208,0,1251,1252,3,451,225,0,1252,1253,
+ 3,409,204,0,1253,206,1,0,0,0,1254,1255,3,425,212,0,1255,1256,3,401,200,
+ 0,1256,1257,3,439,219,0,1257,1258,3,409,204,0,1258,1259,3,435,217,0,1259,
+ 1260,3,417,208,0,1260,1261,3,401,200,0,1261,1262,3,423,211,0,1262,1263,
+ 3,417,208,0,1263,1264,3,451,225,0,1264,1265,3,409,204,0,1265,1266,3,407,
+ 203,0,1266,208,1,0,0,0,1267,1268,3,425,212,0,1268,1269,3,401,200,0,1269,
+ 1270,3,447,223,0,1270,210,1,0,0,0,1271,1272,3,425,212,0,1272,1273,3,409,
+ 204,0,1273,1274,3,435,217,0,1274,1275,3,413,206,0,1275,1276,3,409,204,
+ 0,1276,1277,3,437,218,0,1277,212,1,0,0,0,1278,1279,3,425,212,0,1279,1280,
+ 3,417,208,0,1280,1281,3,427,213,0,1281,214,1,0,0,0,1282,1283,3,425,212,
+ 0,1283,1284,3,417,208,0,1284,1285,3,427,213,0,1285,1286,3,441,220,0,1286,
+ 1287,3,439,219,0,1287,1288,3,409,204,0,1288,216,1,0,0,0,1289,1290,3,425,
+ 212,0,1290,1291,3,429,214,0,1291,1292,3,407,203,0,1292,1293,3,417,208,
+ 0,1293,1294,3,411,205,0,1294,1295,3,449,224,0,1295,218,1,0,0,0,1296,1297,
+ 3,425,212,0,1297,1298,3,429,214,0,1298,1299,3,427,213,0,1299,1300,3,439,
+ 219,0,1300,1301,3,415,207,0,1301,220,1,0,0,0,1302,1303,3,425,212,0,1303,
+ 1304,3,429,214,0,1304,1305,3,443,221,0,1305,1306,3,409,204,0,1306,222,
+ 1,0,0,0,1307,1308,3,425,212,0,1308,1309,3,441,220,0,1309,1310,3,439,219,
+ 0,1310,1311,3,401,200,0,1311,1312,3,439,219,0,1312,1313,3,417,208,0,1313,
+ 1314,3,429,214,0,1314,1315,3,427,213,0,1315,224,1,0,0,0,1316,1317,3,427,
+ 213,0,1317,1318,3,401,200,0,1318,1319,3,427,213,0,1319,226,1,0,0,0,1320,
+ 1321,3,427,213,0,1321,1322,3,429,214,0,1322,228,1,0,0,0,1323,1324,3,427,
+ 213,0,1324,1325,3,429,214,0,1325,1326,3,439,219,0,1326,230,1,0,0,0,1327,
+ 1328,3,427,213,0,1328,1329,3,441,220,0,1329,1330,3,423,211,0,1330,1331,
+ 3,423,211,0,1331,232,1,0,0,0,1332,1333,3,427,213,0,1333,1334,3,441,220,
+ 0,1334,1335,3,423,211,0,1335,1336,3,423,211,0,1336,1337,3,437,218,0,1337,
+ 234,1,0,0,0,1338,1339,3,429,214,0,1339,1340,3,411,205,0,1340,1341,3,411,
+ 205,0,1341,1342,3,437,218,0,1342,1343,3,409,204,0,1343,1344,3,439,219,
+ 0,1344,236,1,0,0,0,1345,1346,3,429,214,0,1346,1347,3,427,213,0,1347,238,
+ 1,0,0,0,1348,1349,3,429,214,0,1349,1350,3,431,215,0,1350,1351,3,439,219,
+ 0,1351,1352,3,417,208,0,1352,1353,3,425,212,0,1353,1354,3,417,208,0,1354,
+ 1355,3,451,225,0,1355,1356,3,409,204,0,1356,240,1,0,0,0,1357,1358,3,429,
+ 214,0,1358,1359,3,435,217,0,1359,242,1,0,0,0,1360,1361,3,429,214,0,1361,
+ 1362,3,435,217,0,1362,1363,3,407,203,0,1363,1364,3,409,204,0,1364,1365,
+ 3,435,217,0,1365,244,1,0,0,0,1366,1367,3,429,214,0,1367,1368,3,441,220,
+ 0,1368,1369,3,439,219,0,1369,1370,3,409,204,0,1370,1371,3,435,217,0,1371,
+ 246,1,0,0,0,1372,1373,3,429,214,0,1373,1374,3,441,220,0,1374,1375,3,439,
+ 219,0,1375,1376,3,411,205,0,1376,1377,3,417,208,0,1377,1378,3,423,211,
+ 0,1378,1379,3,409,204,0,1379,248,1,0,0,0,1380,1381,3,429,214,0,1381,1382,
+ 3,443,221,0,1382,1383,3,409,204,0,1383,1384,3,435,217,0,1384,250,1,0,
+ 0,0,1385,1386,3,431,215,0,1386,1387,3,401,200,0,1387,1388,3,435,217,0,
+ 1388,1389,3,439,219,0,1389,1390,3,417,208,0,1390,1391,3,439,219,0,1391,
+ 1392,3,417,208,0,1392,1393,3,429,214,0,1393,1394,3,427,213,0,1394,252,
+ 1,0,0,0,1395,1396,3,431,215,0,1396,1397,3,429,214,0,1397,1398,3,431,215,
+ 0,1398,1399,3,441,220,0,1399,1400,3,423,211,0,1400,1401,3,401,200,0,1401,
+ 1402,3,439,219,0,1402,1403,3,409,204,0,1403,254,1,0,0,0,1404,1405,3,431,
+ 215,0,1405,1406,3,435,217,0,1406,1407,3,409,204,0,1407,1408,3,405,202,
+ 0,1408,1409,3,409,204,0,1409,1410,3,407,203,0,1410,1411,3,417,208,0,1411,
+ 1412,3,427,213,0,1412,1413,3,413,206,0,1413,256,1,0,0,0,1414,1415,3,431,
+ 215,0,1415,1416,3,435,217,0,1416,1417,3,409,204,0,1417,1418,3,445,222,
+ 0,1418,1419,3,415,207,0,1419,1420,3,409,204,0,1420,1421,3,435,217,0,1421,
+ 1422,3,409,204,0,1422,258,1,0,0,0,1423,1424,3,431,215,0,1424,1425,3,435,
+ 217,0,1425,1426,3,417,208,0,1426,1427,3,425,212,0,1427,1428,3,401,200,
+ 0,1428,1429,3,435,217,0,1429,1430,3,449,224,0,1430,260,1,0,0,0,1431,1432,
+ 3,431,215,0,1432,1433,3,435,217,0,1433,1434,3,429,214,0,1434,1435,3,419,
+ 209,0,1435,1436,3,409,204,0,1436,1437,3,405,202,0,1437,1438,3,439,219,
+ 0,1438,1439,3,417,208,0,1439,1440,3,429,214,0,1440,1441,3,427,213,0,1441,
+ 262,1,0,0,0,1442,1443,3,433,216,0,1443,1444,3,441,220,0,1444,1445,3,401,
+ 200,0,1445,1446,3,435,217,0,1446,1447,3,439,219,0,1447,1448,3,409,204,
+ 0,1448,1449,3,435,217,0,1449,264,1,0,0,0,1450,1451,3,435,217,0,1451,1452,
+ 3,401,200,0,1452,1453,3,427,213,0,1453,1454,3,413,206,0,1454,1455,3,409,
+ 204,0,1455,266,1,0,0,0,1456,1457,3,435,217,0,1457,1458,3,409,204,0,1458,
+ 1459,3,423,211,0,1459,1460,3,429,214,0,1460,1461,3,401,200,0,1461,1462,
+ 3,407,203,0,1462,268,1,0,0,0,1463,1464,3,435,217,0,1464,1465,3,409,204,
+ 0,1465,1466,3,425,212,0,1466,1467,3,429,214,0,1467,1468,3,443,221,0,1468,
+ 1469,3,409,204,0,1469,270,1,0,0,0,1470,1471,3,435,217,0,1471,1472,3,409,
+ 204,0,1472,1473,3,427,213,0,1473,1474,3,401,200,0,1474,1475,3,425,212,
+ 0,1475,1476,3,409,204,0,1476,272,1,0,0,0,1477,1478,3,435,217,0,1478,1479,
+ 3,409,204,0,1479,1480,3,431,215,0,1480,1481,3,423,211,0,1481,1482,3,401,
+ 200,0,1482,1483,3,405,202,0,1483,1484,3,409,204,0,1484,274,1,0,0,0,1485,
+ 1486,3,435,217,0,1486,1487,3,409,204,0,1487,1488,3,431,215,0,1488,1489,
+ 3,423,211,0,1489,1490,3,417,208,0,1490,1491,3,405,202,0,1491,1492,3,401,
+ 200,0,1492,276,1,0,0,0,1493,1494,3,435,217,0,1494,1495,3,409,204,0,1495,
+ 1496,3,431,215,0,1496,1497,3,423,211,0,1497,1498,3,417,208,0,1498,1499,
+ 3,405,202,0,1499,1500,3,401,200,0,1500,1501,3,439,219,0,1501,1502,3,409,
+ 204,0,1502,1503,3,407,203,0,1503,278,1,0,0,0,1504,1505,3,435,217,0,1505,
+ 1506,3,417,208,0,1506,1507,3,413,206,0,1507,1508,3,415,207,0,1508,1509,
+ 3,439,219,0,1509,280,1,0,0,0,1510,1511,3,435,217,0,1511,1512,3,429,214,
+ 0,1512,1513,3,423,211,0,1513,1514,3,423,211,0,1514,1515,3,441,220,0,1515,
+ 1516,3,431,215,0,1516,282,1,0,0,0,1517,1518,3,435,217,0,1518,1519,3,429,
+ 214,0,1519,1520,3,445,222,0,1520,284,1,0,0,0,1521,1522,3,435,217,0,1522,
+ 1523,3,429,214,0,1523,1524,3,445,222,0,1524,1525,3,437,218,0,1525,286,
+ 1,0,0,0,1526,1527,3,437,218,0,1527,1528,3,401,200,0,1528,1529,3,425,212,
+ 0,1529,1530,3,431,215,0,1530,1531,3,423,211,0,1531,1532,3,409,204,0,1532,
+ 288,1,0,0,0,1533,1534,3,437,218,0,1534,1535,3,409,204,0,1535,1536,3,405,
+ 202,0,1536,1537,3,429,214,0,1537,1538,3,427,213,0,1538,1539,3,407,203,
+ 0,1539,290,1,0,0,0,1540,1541,3,437,218,0,1541,1542,3,409,204,0,1542,1543,
+ 3,423,211,0,1543,1544,3,409,204,0,1544,1545,3,405,202,0,1545,1546,3,439,
+ 219,0,1546,292,1,0,0,0,1547,1548,3,437,218,0,1548,1549,3,409,204,0,1549,
+ 1550,3,425,212,0,1550,1551,3,417,208,0,1551,294,1,0,0,0,1552,1553,3,437,
+ 218,0,1553,1554,3,409,204,0,1554,1555,3,427,213,0,1555,1556,3,407,203,
+ 0,1556,1557,3,437,218,0,1557,296,1,0,0,0,1558,1559,3,437,218,0,1559,1560,
+ 3,409,204,0,1560,1561,3,439,219,0,1561,298,1,0,0,0,1562,1563,3,437,218,
+ 0,1563,1564,3,409,204,0,1564,1565,3,439,219,0,1565,1566,3,439,219,0,1566,
+ 1567,3,417,208,0,1567,1568,3,427,213,0,1568,1569,3,413,206,0,1569,1570,
+ 3,437,218,0,1570,300,1,0,0,0,1571,1572,3,437,218,0,1572,1573,3,415,207,
+ 0,1573,1574,3,429,214,0,1574,1575,3,445,222,0,1575,302,1,0,0,0,1576,1577,
+ 3,437,218,0,1577,1578,3,429,214,0,1578,1579,3,441,220,0,1579,1580,3,435,
+ 217,0,1580,1581,3,405,202,0,1581,1582,3,409,204,0,1582,304,1,0,0,0,1583,
+ 1584,3,437,218,0,1584,1585,3,439,219,0,1585,1586,3,401,200,0,1586,1587,
+ 3,435,217,0,1587,1588,3,439,219,0,1588,306,1,0,0,0,1589,1590,3,437,218,
+ 0,1590,1591,3,439,219,0,1591,1592,3,429,214,0,1592,1593,3,431,215,0,1593,
+ 308,1,0,0,0,1594,1595,3,437,218,0,1595,1596,3,441,220,0,1596,1597,3,403,
+ 201,0,1597,1598,3,437,218,0,1598,1599,3,439,219,0,1599,1600,3,435,217,
+ 0,1600,1601,3,417,208,0,1601,1602,3,427,213,0,1602,1603,3,413,206,0,1603,
+ 310,1,0,0,0,1604,1605,3,437,218,0,1605,1606,3,449,224,0,1606,1607,3,427,
+ 213,0,1607,1608,3,405,202,0,1608,312,1,0,0,0,1609,1610,3,437,218,0,1610,
+ 1611,3,449,224,0,1611,1612,3,427,213,0,1612,1613,3,439,219,0,1613,1614,
+ 3,401,200,0,1614,1615,3,447,223,0,1615,314,1,0,0,0,1616,1617,3,437,218,
+ 0,1617,1618,3,449,224,0,1618,1619,3,437,218,0,1619,1620,3,439,219,0,1620,
+ 1621,3,409,204,0,1621,1622,3,425,212,0,1622,316,1,0,0,0,1623,1624,3,439,
+ 219,0,1624,1625,3,401,200,0,1625,1626,3,403,201,0,1626,1627,3,423,211,
+ 0,1627,1628,3,409,204,0,1628,318,1,0,0,0,1629,1630,3,439,219,0,1630,1631,
+ 3,401,200,0,1631,1632,3,403,201,0,1632,1633,3,423,211,0,1633,1634,3,409,
+ 204,0,1634,1635,3,437,218,0,1635,320,1,0,0,0,1636,1637,3,439,219,0,1637,
+ 1638,3,409,204,0,1638,1639,3,425,212,0,1639,1640,3,431,215,0,1640,1641,
+ 3,429,214,0,1641,1642,3,435,217,0,1642,1643,3,401,200,0,1643,1644,3,435,
+ 217,0,1644,1645,3,449,224,0,1645,322,1,0,0,0,1646,1647,3,439,219,0,1647,
+ 1648,3,409,204,0,1648,1649,3,437,218,0,1649,1650,3,439,219,0,1650,324,
+ 1,0,0,0,1651,1652,3,439,219,0,1652,1653,3,415,207,0,1653,1654,3,409,204,
+ 0,1654,1655,3,427,213,0,1655,326,1,0,0,0,1656,1657,3,439,219,0,1657,1658,
+ 3,417,208,0,1658,1659,3,409,204,0,1659,1660,3,437,218,0,1660,328,1,0,
+ 0,0,1661,1662,3,439,219,0,1662,1663,3,417,208,0,1663,1664,3,425,212,0,
+ 1664,1665,3,409,204,0,1665,1666,3,429,214,0,1666,1667,3,441,220,0,1667,
+ 1668,3,439,219,0,1668,330,1,0,0,0,1669,1670,3,439,219,0,1670,1671,3,417,
+ 208,0,1671,1672,3,425,212,0,1672,1673,3,409,204,0,1673,1674,3,437,218,
+ 0,1674,1675,3,439,219,0,1675,1676,3,401,200,0,1676,1677,3,425,212,0,1677,
+ 1678,3,431,215,0,1678,332,1,0,0,0,1679,1680,3,439,219,0,1680,1681,3,429,
+ 214,0,1681,334,1,0,0,0,1682,1683,3,439,219,0,1683,1684,3,429,214,0,1684,
+ 1685,3,431,215,0,1685,336,1,0,0,0,1686,1687,3,439,219,0,1687,1688,3,429,
+ 214,0,1688,1689,3,439,219,0,1689,1690,3,401,200,0,1690,1691,3,423,211,
+ 0,1691,1692,3,437,218,0,1692,338,1,0,0,0,1693,1694,3,439,219,0,1694,1695,
+ 3,435,217,0,1695,1696,3,401,200,0,1696,1697,3,417,208,0,1697,1698,3,423,
+ 211,0,1698,1699,3,417,208,0,1699,1700,3,427,213,0,1700,1701,3,413,206,
+ 0,1701,340,1,0,0,0,1702,1703,3,439,219,0,1703,1704,3,435,217,0,1704,1705,
+ 3,417,208,0,1705,1706,3,425,212,0,1706,342,1,0,0,0,1707,1708,3,439,219,
+ 0,1708,1709,3,435,217,0,1709,1710,3,441,220,0,1710,1711,3,427,213,0,1711,
+ 1712,3,405,202,0,1712,1713,3,401,200,0,1713,1714,3,439,219,0,1714,1715,
+ 3,409,204,0,1715,344,1,0,0,0,1716,1717,3,439,219,0,1717,1718,3,439,219,
+ 0,1718,1719,3,423,211,0,1719,346,1,0,0,0,1720,1721,3,439,219,0,1721,1722,
+ 3,449,224,0,1722,1723,3,431,215,0,1723,1724,3,409,204,0,1724,348,1,0,
+ 0,0,1725,1726,3,441,220,0,1726,1727,3,427,213,0,1727,1728,3,403,201,0,
+ 1728,1729,3,429,214,0,1729,1730,3,441,220,0,1730,1731,3,427,213,0,1731,
+ 1732,3,407,203,0,1732,1733,3,409,204,0,1733,1734,3,407,203,0,1734,350,
+ 1,0,0,0,1735,1736,3,441,220,0,1736,1737,3,427,213,0,1737,1738,3,417,208,
+ 0,1738,1739,3,429,214,0,1739,1740,3,427,213,0,1740,352,1,0,0,0,1741,1742,
+ 3,441,220,0,1742,1743,3,431,215,0,1743,1744,3,407,203,0,1744,1745,3,401,
+ 200,0,1745,1746,3,439,219,0,1746,1747,3,409,204,0,1747,354,1,0,0,0,1748,
+ 1749,3,441,220,0,1749,1750,3,437,218,0,1750,1751,3,409,204,0,1751,356,
+ 1,0,0,0,1752,1753,3,441,220,0,1753,1754,3,437,218,0,1754,1755,3,417,208,
+ 0,1755,1756,3,427,213,0,1756,1757,3,413,206,0,1757,358,1,0,0,0,1758,1759,
+ 3,441,220,0,1759,1760,3,441,220,0,1760,1761,3,417,208,0,1761,1762,3,407,
+ 203,0,1762,360,1,0,0,0,1763,1764,3,443,221,0,1764,1765,3,401,200,0,1765,
+ 1766,3,423,211,0,1766,1767,3,441,220,0,1767,1768,3,409,204,0,1768,1769,
+ 3,437,218,0,1769,362,1,0,0,0,1770,1771,3,443,221,0,1771,1772,3,417,208,
+ 0,1772,1773,3,409,204,0,1773,1774,3,445,222,0,1774,364,1,0,0,0,1775,1776,
+ 3,443,221,0,1776,1777,3,429,214,0,1777,1778,3,423,211,0,1778,1779,3,441,
+ 220,0,1779,1780,3,425,212,0,1780,1781,3,409,204,0,1781,366,1,0,0,0,1782,
+ 1783,3,445,222,0,1783,1784,3,401,200,0,1784,1785,3,439,219,0,1785,1786,
+ 3,405,202,0,1786,1787,3,415,207,0,1787,368,1,0,0,0,1788,1789,3,445,222,
+ 0,1789,1790,3,409,204,0,1790,1791,3,409,204,0,1791,1792,3,421,210,0,1792,
+ 370,1,0,0,0,1793,1794,3,445,222,0,1794,1795,3,415,207,0,1795,1796,3,409,
+ 204,0,1796,1797,3,427,213,0,1797,372,1,0,0,0,1798,1799,3,445,222,0,1799,
+ 1800,3,415,207,0,1800,1801,3,409,204,0,1801,1802,3,435,217,0,1802,1803,
+ 3,409,204,0,1803,374,1,0,0,0,1804,1805,3,445,222,0,1805,1806,3,417,208,
+ 0,1806,1807,3,427,213,0,1807,1808,3,407,203,0,1808,1809,3,429,214,0,1809,
+ 1810,3,445,222,0,1810,376,1,0,0,0,1811,1812,3,445,222,0,1812,1813,3,417,
+ 208,0,1813,1814,3,439,219,0,1814,1815,3,415,207,0,1815,378,1,0,0,0,1816,
+ 1817,3,449,224,0,1817,1818,3,409,204,0,1818,1819,3,401,200,0,1819,1820,
+ 3,435,217,0,1820,1827,1,0,0,0,1821,1822,3,449,224,0,1822,1823,3,449,224,
+ 0,1823,1824,3,449,224,0,1824,1825,3,449,224,0,1825,1827,1,0,0,0,1826,
+ 1816,1,0,0,0,1826,1821,1,0,0,0,1827,380,1,0,0,0,1828,1829,5,102,0,0,1829,
+ 1830,5,97,0,0,1830,1831,5,108,0,0,1831,1832,5,115,0,0,1832,1833,5,101,
+ 0,0,1833,382,1,0,0,0,1834,1835,5,116,0,0,1835,1836,5,114,0,0,1836,1837,
+ 5,117,0,0,1837,1838,5,101,0,0,1838,384,1,0,0,0,1839,1840,3,467,233,0,
+ 1840,1841,3,403,201,0,1841,1870,1,0,0,0,1842,1843,3,467,233,0,1843,1844,
+ 3,411,205,0,1844,1870,1,0,0,0,1845,1846,3,467,233,0,1846,1847,3,435,217,
+ 0,1847,1870,1,0,0,0,1848,1849,3,467,233,0,1849,1850,3,427,213,0,1850,
+ 1870,1,0,0,0,1851,1852,3,467,233,0,1852,1853,3,439,219,0,1853,1870,1,
+ 0,0,0,1854,1855,3,467,233,0,1855,1856,5,48,0,0,1856,1870,1,0,0,0,1857,
+ 1858,3,467,233,0,1858,1859,3,401,200,0,1859,1870,1,0,0,0,1860,1861,3,
+ 467,233,0,1861,1862,3,443,221,0,1862,1870,1,0,0,0,1863,1864,3,467,233,
+ 0,1864,1865,3,467,233,0,1865,1870,1,0,0,0,1866,1867,3,467,233,0,1867,
+ 1868,3,521,260,0,1868,1870,1,0,0,0,1869,1839,1,0,0,0,1869,1842,1,0,0,
+ 0,1869,1845,1,0,0,0,1869,1848,1,0,0,0,1869,1851,1,0,0,0,1869,1854,1,0,
+ 0,0,1869,1857,1,0,0,0,1869,1860,1,0,0,0,1869,1863,1,0,0,0,1869,1866,1,
+ 0,0,0,1870,386,1,0,0,0,1871,1875,3,453,226,0,1872,1875,3,537,268,0,1873,
+ 1875,3,477,238,0,1874,1871,1,0,0,0,1874,1872,1,0,0,0,1874,1873,1,0,0,
+ 0,1875,1882,1,0,0,0,1876,1881,3,453,226,0,1877,1881,3,537,268,0,1878,
+ 1881,3,457,228,0,1879,1881,3,477,238,0,1880,1876,1,0,0,0,1880,1877,1,
+ 0,0,0,1880,1878,1,0,0,0,1880,1879,1,0,0,0,1881,1884,1,0,0,0,1882,1880,
+ 1,0,0,0,1882,1883,1,0,0,0,1883,1912,1,0,0,0,1884,1882,1,0,0,0,1885,1893,
+ 3,465,232,0,1886,1892,8,0,0,0,1887,1892,3,385,192,0,1888,1889,3,465,232,
+ 0,1889,1890,3,465,232,0,1890,1892,1,0,0,0,1891,1886,1,0,0,0,1891,1887,
+ 1,0,0,0,1891,1888,1,0,0,0,1892,1895,1,0,0,0,1893,1891,1,0,0,0,1893,1894,
+ 1,0,0,0,1894,1896,1,0,0,0,1895,1893,1,0,0,0,1896,1897,3,465,232,0,1897,
+ 1912,1,0,0,0,1898,1906,3,519,259,0,1899,1905,8,1,0,0,1900,1905,3,385,
+ 192,0,1901,1902,3,519,259,0,1902,1903,3,519,259,0,1903,1905,1,0,0,0,1904,
+ 1899,1,0,0,0,1904,1900,1,0,0,0,1904,1901,1,0,0,0,1905,1908,1,0,0,0,1906,
+ 1904,1,0,0,0,1906,1907,1,0,0,0,1907,1909,1,0,0,0,1908,1906,1,0,0,0,1909,
+ 1910,3,519,259,0,1910,1912,1,0,0,0,1911,1874,1,0,0,0,1911,1885,1,0,0,
+ 0,1911,1898,1,0,0,0,1912,388,1,0,0,0,1913,1914,3,395,197,0,1914,1918,
+ 3,479,239,0,1915,1917,3,459,229,0,1916,1915,1,0,0,0,1917,1920,1,0,0,0,
+ 1918,1916,1,0,0,0,1918,1919,1,0,0,0,1919,1923,1,0,0,0,1920,1918,1,0,0,
+ 0,1921,1924,3,431,215,0,1922,1924,3,409,204,0,1923,1921,1,0,0,0,1923,
+ 1922,1,0,0,0,1924,1927,1,0,0,0,1925,1928,3,515,257,0,1926,1928,3,475,
+ 237,0,1927,1925,1,0,0,0,1927,1926,1,0,0,0,1927,1928,1,0,0,0,1928,1930,
+ 1,0,0,0,1929,1931,3,457,228,0,1930,1929,1,0,0,0,1931,1932,1,0,0,0,1932,
+ 1930,1,0,0,0,1932,1933,1,0,0,0,1933,1990,1,0,0,0,1934,1937,3,395,197,
+ 0,1935,1938,3,431,215,0,1936,1938,3,409,204,0,1937,1935,1,0,0,0,1937,
+ 1936,1,0,0,0,1938,1941,1,0,0,0,1939,1942,3,515,257,0,1940,1942,3,475,
+ 237,0,1941,1939,1,0,0,0,1941,1940,1,0,0,0,1941,1942,1,0,0,0,1942,1944,
+ 1,0,0,0,1943,1945,3,457,228,0,1944,1943,1,0,0,0,1945,1946,1,0,0,0,1946,
+ 1944,1,0,0,0,1946,1947,1,0,0,0,1947,1990,1,0,0,0,1948,1949,3,393,196,
+ 0,1949,1953,3,479,239,0,1950,1952,3,457,228,0,1951,1950,1,0,0,0,1952,
+ 1955,1,0,0,0,1953,1951,1,0,0,0,1953,1954,1,0,0,0,1954,1956,1,0,0,0,1955,
+ 1953,1,0,0,0,1956,1959,3,409,204,0,1957,1960,3,515,257,0,1958,1960,3,
+ 475,237,0,1959,1957,1,0,0,0,1959,1958,1,0,0,0,1959,1960,1,0,0,0,1960,
+ 1962,1,0,0,0,1961,1963,3,457,228,0,1962,1961,1,0,0,0,1963,1964,1,0,0,
+ 0,1964,1962,1,0,0,0,1964,1965,1,0,0,0,1965,1990,1,0,0,0,1966,1967,3,479,
+ 239,0,1967,1968,3,393,196,0,1968,1971,3,409,204,0,1969,1972,3,515,257,
+ 0,1970,1972,3,475,237,0,1971,1969,1,0,0,0,1971,1970,1,0,0,0,1971,1972,
+ 1,0,0,0,1972,1974,1,0,0,0,1973,1975,3,457,228,0,1974,1973,1,0,0,0,1975,
+ 1976,1,0,0,0,1976,1974,1,0,0,0,1976,1977,1,0,0,0,1977,1990,1,0,0,0,1978,
+ 1979,3,393,196,0,1979,1982,3,409,204,0,1980,1983,3,515,257,0,1981,1983,
+ 3,475,237,0,1982,1980,1,0,0,0,1982,1981,1,0,0,0,1982,1983,1,0,0,0,1983,
+ 1985,1,0,0,0,1984,1986,3,457,228,0,1985,1984,1,0,0,0,1986,1987,1,0,0,
+ 0,1987,1985,1,0,0,0,1987,1988,1,0,0,0,1988,1990,1,0,0,0,1989,1913,1,0,
+ 0,0,1989,1934,1,0,0,0,1989,1948,1,0,0,0,1989,1966,1,0,0,0,1989,1978,1,
+ 0,0,0,1990,390,1,0,0,0,1991,1993,5,48,0,0,1992,1994,3,455,227,0,1993,
+ 1992,1,0,0,0,1994,1995,1,0,0,0,1995,1993,1,0,0,0,1995,1996,1,0,0,0,1996,
+ 392,1,0,0,0,1997,1999,3,457,228,0,1998,1997,1,0,0,0,1999,2000,1,0,0,0,
+ 2000,1998,1,0,0,0,2000,2001,1,0,0,0,2001,394,1,0,0,0,2002,2003,5,48,0,
+ 0,2003,2005,3,447,223,0,2004,2006,3,459,229,0,2005,2004,1,0,0,0,2006,
+ 2007,1,0,0,0,2007,2005,1,0,0,0,2007,2008,1,0,0,0,2008,396,1,0,0,0,2009,
+ 2017,3,521,260,0,2010,2016,8,2,0,0,2011,2016,3,385,192,0,2012,2013,3,
+ 521,260,0,2013,2014,3,521,260,0,2014,2016,1,0,0,0,2015,2010,1,0,0,0,2015,
+ 2011,1,0,0,0,2015,2012,1,0,0,0,2016,2019,1,0,0,0,2017,2015,1,0,0,0,2017,
+ 2018,1,0,0,0,2018,2020,1,0,0,0,2019,2017,1,0,0,0,2020,2021,3,521,260,
+ 0,2021,398,1,0,0,0,2022,2030,3,495,247,0,2023,2029,8,3,0,0,2024,2029,
+ 3,385,192,0,2025,2026,3,495,247,0,2026,2027,3,495,247,0,2027,2029,1,0,
+ 0,0,2028,2023,1,0,0,0,2028,2024,1,0,0,0,2028,2025,1,0,0,0,2029,2032,1,
+ 0,0,0,2030,2028,1,0,0,0,2030,2031,1,0,0,0,2031,2033,1,0,0,0,2032,2030,
+ 1,0,0,0,2033,2034,3,527,263,0,2034,400,1,0,0,0,2035,2036,7,4,0,0,2036,
+ 402,1,0,0,0,2037,2038,7,5,0,0,2038,404,1,0,0,0,2039,2040,7,6,0,0,2040,
+ 406,1,0,0,0,2041,2042,7,7,0,0,2042,408,1,0,0,0,2043,2044,7,8,0,0,2044,
+ 410,1,0,0,0,2045,2046,7,9,0,0,2046,412,1,0,0,0,2047,2048,7,10,0,0,2048,
+ 414,1,0,0,0,2049,2050,7,11,0,0,2050,416,1,0,0,0,2051,2052,7,12,0,0,2052,
+ 418,1,0,0,0,2053,2054,7,13,0,0,2054,420,1,0,0,0,2055,2056,7,14,0,0,2056,
+ 422,1,0,0,0,2057,2058,7,15,0,0,2058,424,1,0,0,0,2059,2060,7,16,0,0,2060,
+ 426,1,0,0,0,2061,2062,7,17,0,0,2062,428,1,0,0,0,2063,2064,7,18,0,0,2064,
+ 430,1,0,0,0,2065,2066,7,19,0,0,2066,432,1,0,0,0,2067,2068,7,20,0,0,2068,
+ 434,1,0,0,0,2069,2070,7,21,0,0,2070,436,1,0,0,0,2071,2072,7,22,0,0,2072,
+ 438,1,0,0,0,2073,2074,7,23,0,0,2074,440,1,0,0,0,2075,2076,7,24,0,0,2076,
+ 442,1,0,0,0,2077,2078,7,25,0,0,2078,444,1,0,0,0,2079,2080,7,26,0,0,2080,
+ 446,1,0,0,0,2081,2082,7,27,0,0,2082,448,1,0,0,0,2083,2084,7,28,0,0,2084,
+ 450,1,0,0,0,2085,2086,7,29,0,0,2086,452,1,0,0,0,2087,2088,7,30,0,0,2088,
+ 454,1,0,0,0,2089,2090,7,31,0,0,2090,456,1,0,0,0,2091,2092,7,32,0,0,2092,
+ 458,1,0,0,0,2093,2094,7,33,0,0,2094,460,1,0,0,0,2095,2096,5,45,0,0,2096,
+ 2097,5,62,0,0,2097,462,1,0,0,0,2098,2099,5,42,0,0,2099,464,1,0,0,0,2100,
+ 2101,5,96,0,0,2101,466,1,0,0,0,2102,2103,5,92,0,0,2103,468,1,0,0,0,2104,
+ 2105,5,58,0,0,2105,470,1,0,0,0,2106,2107,5,44,0,0,2107,472,1,0,0,0,2108,
+ 2109,5,124,0,0,2109,2110,5,124,0,0,2110,474,1,0,0,0,2111,2112,5,45,0,
+ 0,2112,476,1,0,0,0,2113,2114,5,36,0,0,2114,478,1,0,0,0,2115,2116,5,46,
+ 0,0,2116,480,1,0,0,0,2117,2118,5,61,0,0,2118,2119,5,61,0,0,2119,482,1,
+ 0,0,0,2120,2121,5,61,0,0,2121,484,1,0,0,0,2122,2123,5,62,0,0,2123,2124,
+ 5,61,0,0,2124,486,1,0,0,0,2125,2126,5,62,0,0,2126,488,1,0,0,0,2127,2128,
+ 5,35,0,0,2128,490,1,0,0,0,2129,2130,5,126,0,0,2130,2131,5,42,0,0,2131,
+ 492,1,0,0,0,2132,2133,5,61,0,0,2133,2134,5,126,0,0,2134,2135,5,42,0,0,
+ 2135,494,1,0,0,0,2136,2137,5,123,0,0,2137,496,1,0,0,0,2138,2139,5,91,
+ 0,0,2139,498,1,0,0,0,2140,2141,5,40,0,0,2141,500,1,0,0,0,2142,2143,5,
+ 60,0,0,2143,2144,5,61,0,0,2144,502,1,0,0,0,2145,2146,5,60,0,0,2146,504,
+ 1,0,0,0,2147,2148,5,33,0,0,2148,2152,5,61,0,0,2149,2150,5,60,0,0,2150,
+ 2152,5,62,0,0,2151,2147,1,0,0,0,2151,2149,1,0,0,0,2152,506,1,0,0,0,2153,
+ 2154,5,33,0,0,2154,2155,5,126,0,0,2155,2156,5,42,0,0,2156,508,1,0,0,0,
+ 2157,2158,5,33,0,0,2158,2159,5,126,0,0,2159,510,1,0,0,0,2160,2161,5,63,
+ 0,0,2161,2162,5,63,0,0,2162,512,1,0,0,0,2163,2164,5,37,0,0,2164,514,1,
+ 0,0,0,2165,2166,5,43,0,0,2166,516,1,0,0,0,2167,2168,5,63,0,0,2168,518,
+ 1,0,0,0,2169,2170,5,34,0,0,2170,520,1,0,0,0,2171,2172,5,39,0,0,2172,522,
+ 1,0,0,0,2173,2174,5,126,0,0,2174,524,1,0,0,0,2175,2176,5,61,0,0,2176,
+ 2177,5,126,0,0,2177,526,1,0,0,0,2178,2179,5,125,0,0,2179,528,1,0,0,0,
+ 2180,2181,5,93,0,0,2181,530,1,0,0,0,2182,2183,5,41,0,0,2183,532,1,0,0,
+ 0,2184,2185,5,59,0,0,2185,534,1,0,0,0,2186,2187,5,47,0,0,2187,536,1,0,
+ 0,0,2188,2189,5,95,0,0,2189,538,1,0,0,0,2190,2191,5,47,0,0,2191,2192,
+ 5,42,0,0,2192,2196,1,0,0,0,2193,2195,9,0,0,0,2194,2193,1,0,0,0,2195,2198,
+ 1,0,0,0,2196,2197,1,0,0,0,2196,2194,1,0,0,0,2197,2199,1,0,0,0,2198,2196,
+ 1,0,0,0,2199,2200,5,42,0,0,2200,2201,5,47,0,0,2201,2202,1,0,0,0,2202,
+ 2203,6,269,0,0,2203,540,1,0,0,0,2204,2205,5,45,0,0,2205,2206,5,45,0,0,
+ 2206,2210,1,0,0,0,2207,2209,8,34,0,0,2208,2207,1,0,0,0,2209,2212,1,0,
+ 0,0,2210,2208,1,0,0,0,2210,2211,1,0,0,0,2211,2214,1,0,0,0,2212,2210,1,
+ 0,0,0,2213,2215,7,35,0,0,2214,2213,1,0,0,0,2215,2216,1,0,0,0,2216,2217,
+ 6,270,0,0,2217,542,1,0,0,0,2218,2219,7,36,0,0,2219,2220,1,0,0,0,2220,
+ 2221,6,271,1,0,2221,544,1,0,0,0,39,0,607,1112,1826,1869,1874,1880,1882,
+ 1891,1893,1904,1906,1911,1918,1923,1927,1932,1937,1941,1946,1953,1959,
+ 1964,1971,1976,1982,1987,1989,1995,2000,2007,2015,2017,2028,2030,2151,
+ 2196,2210,2214,2,6,0,0,0,1,0
+ };
+ staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0]));
+
+ antlr4::atn::ATNDeserializer deserializer;
+ staticData->atn = deserializer.deserialize(staticData->serializedATN);
+
+ const size_t count = staticData->atn->getNumberOfDecisions();
+ staticData->decisionToDFA.reserve(count);
+ for (size_t i = 0; i < count; i++) {
+ staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i);
+ }
+ hogqllexerLexerStaticData = staticData.release();
+}
+
+}
+
+HogQLLexer::HogQLLexer(CharStream *input) : Lexer(input) {
+ HogQLLexer::initialize();
+ _interpreter = new atn::LexerATNSimulator(this, *hogqllexerLexerStaticData->atn, hogqllexerLexerStaticData->decisionToDFA, hogqllexerLexerStaticData->sharedContextCache);
+}
+
+HogQLLexer::~HogQLLexer() {
+ delete _interpreter;
+}
+
+std::string HogQLLexer::getGrammarFileName() const {
+ return "HogQLLexer.g4";
+}
+
+const std::vector& HogQLLexer::getRuleNames() const {
+ return hogqllexerLexerStaticData->ruleNames;
+}
+
+const std::vector& HogQLLexer::getChannelNames() const {
+ return hogqllexerLexerStaticData->channelNames;
+}
+
+const std::vector& HogQLLexer::getModeNames() const {
+ return hogqllexerLexerStaticData->modeNames;
+}
+
+const dfa::Vocabulary& HogQLLexer::getVocabulary() const {
+ return hogqllexerLexerStaticData->vocabulary;
+}
+
+antlr4::atn::SerializedATNView HogQLLexer::getSerializedATN() const {
+ return hogqllexerLexerStaticData->serializedATN;
+}
+
+const atn::ATN& HogQLLexer::getATN() const {
+ return *hogqllexerLexerStaticData->atn;
+}
+
+
+
+
+void HogQLLexer::initialize() {
+#if ANTLR4_USE_THREAD_LOCAL_CACHE
+ hogqllexerLexerInitialize();
+#else
+ ::antlr4::internal::call_once(hogqllexerLexerOnceFlag, hogqllexerLexerInitialize);
+#endif
+}
diff --git a/hogql_parser/HogQLLexer.h b/hogql_parser/HogQLLexer.h
new file mode 100644
index 0000000000000..78bfe64dc0bfc
--- /dev/null
+++ b/hogql_parser/HogQLLexer.h
@@ -0,0 +1,94 @@
+
+// Generated from HogQLLexer.g4 by ANTLR 4.13.0
+
+#pragma once
+
+
+#include "antlr4-runtime.h"
+
+
+
+
+class HogQLLexer : public antlr4::Lexer {
+public:
+ enum {
+ ADD = 1, AFTER = 2, ALIAS = 3, ALL = 4, ALTER = 5, AND = 6, ANTI = 7,
+ ANY = 8, ARRAY = 9, AS = 10, ASCENDING = 11, ASOF = 12, AST = 13, ASYNC = 14,
+ ATTACH = 15, BETWEEN = 16, BOTH = 17, BY = 18, CASE = 19, CAST = 20,
+ CHECK = 21, CLEAR = 22, CLUSTER = 23, CODEC = 24, COHORT = 25, COLLATE = 26,
+ COLUMN = 27, COMMENT = 28, CONSTRAINT = 29, CREATE = 30, CROSS = 31,
+ CUBE = 32, CURRENT = 33, DATABASE = 34, DATABASES = 35, DATE = 36, DAY = 37,
+ DEDUPLICATE = 38, DEFAULT = 39, DELAY = 40, DELETE = 41, DESC = 42,
+ DESCENDING = 43, DESCRIBE = 44, DETACH = 45, DICTIONARIES = 46, DICTIONARY = 47,
+ DISK = 48, DISTINCT = 49, DISTRIBUTED = 50, DROP = 51, ELSE = 52, END = 53,
+ ENGINE = 54, EVENTS = 55, EXISTS = 56, EXPLAIN = 57, EXPRESSION = 58,
+ EXTRACT = 59, FETCHES = 60, FINAL = 61, FIRST = 62, FLUSH = 63, FOLLOWING = 64,
+ FOR = 65, FORMAT = 66, FREEZE = 67, FROM = 68, FULL = 69, FUNCTION = 70,
+ GLOBAL = 71, GRANULARITY = 72, GROUP = 73, HAVING = 74, HIERARCHICAL = 75,
+ HOUR = 76, ID = 77, IF = 78, ILIKE = 79, IN = 80, INDEX = 81, INF = 82,
+ INJECTIVE = 83, INNER = 84, INSERT = 85, INTERVAL = 86, INTO = 87, IS = 88,
+ IS_OBJECT_ID = 89, JOIN = 90, KEY = 91, KILL = 92, LAST = 93, LAYOUT = 94,
+ LEADING = 95, LEFT = 96, LIFETIME = 97, LIKE = 98, LIMIT = 99, LIVE = 100,
+ LOCAL = 101, LOGS = 102, MATERIALIZE = 103, MATERIALIZED = 104, MAX = 105,
+ MERGES = 106, MIN = 107, MINUTE = 108, MODIFY = 109, MONTH = 110, MOVE = 111,
+ MUTATION = 112, NAN_SQL = 113, NO = 114, NOT = 115, NULL_SQL = 116,
+ NULLS = 117, OFFSET = 118, ON = 119, OPTIMIZE = 120, OR = 121, ORDER = 122,
+ OUTER = 123, OUTFILE = 124, OVER = 125, PARTITION = 126, POPULATE = 127,
+ PRECEDING = 128, PREWHERE = 129, PRIMARY = 130, PROJECTION = 131, QUARTER = 132,
+ RANGE = 133, RELOAD = 134, REMOVE = 135, RENAME = 136, REPLACE = 137,
+ REPLICA = 138, REPLICATED = 139, RIGHT = 140, ROLLUP = 141, ROW = 142,
+ ROWS = 143, SAMPLE = 144, SECOND = 145, SELECT = 146, SEMI = 147, SENDS = 148,
+ SET = 149, SETTINGS = 150, SHOW = 151, SOURCE = 152, START = 153, STOP = 154,
+ SUBSTRING = 155, SYNC = 156, SYNTAX = 157, SYSTEM = 158, TABLE = 159,
+ TABLES = 160, TEMPORARY = 161, TEST = 162, THEN = 163, TIES = 164, TIMEOUT = 165,
+ TIMESTAMP = 166, TO = 167, TOP = 168, TOTALS = 169, TRAILING = 170,
+ TRIM = 171, TRUNCATE = 172, TTL = 173, TYPE = 174, UNBOUNDED = 175,
+ UNION = 176, UPDATE = 177, USE = 178, USING = 179, UUID = 180, VALUES = 181,
+ VIEW = 182, VOLUME = 183, WATCH = 184, WEEK = 185, WHEN = 186, WHERE = 187,
+ WINDOW = 188, WITH = 189, YEAR = 190, JSON_FALSE = 191, JSON_TRUE = 192,
+ ESCAPE_CHAR = 193, IDENTIFIER = 194, FLOATING_LITERAL = 195, OCTAL_LITERAL = 196,
+ DECIMAL_LITERAL = 197, HEXADECIMAL_LITERAL = 198, STRING_LITERAL = 199,
+ PLACEHOLDER = 200, ARROW = 201, ASTERISK = 202, BACKQUOTE = 203, BACKSLASH = 204,
+ COLON = 205, COMMA = 206, CONCAT = 207, DASH = 208, DOLLAR = 209, DOT = 210,
+ EQ_DOUBLE = 211, EQ_SINGLE = 212, GT_EQ = 213, GT = 214, HASH = 215,
+ IREGEX_SINGLE = 216, IREGEX_DOUBLE = 217, LBRACE = 218, LBRACKET = 219,
+ LPAREN = 220, LT_EQ = 221, LT = 222, NOT_EQ = 223, NOT_IREGEX = 224,
+ NOT_REGEX = 225, NULLISH = 226, PERCENT = 227, PLUS = 228, QUERY = 229,
+ QUOTE_DOUBLE = 230, QUOTE_SINGLE = 231, REGEX_SINGLE = 232, REGEX_DOUBLE = 233,
+ RBRACE = 234, RBRACKET = 235, RPAREN = 236, SEMICOLON = 237, SLASH = 238,
+ UNDERSCORE = 239, MULTI_LINE_COMMENT = 240, SINGLE_LINE_COMMENT = 241,
+ WHITESPACE = 242
+ };
+
+ explicit HogQLLexer(antlr4::CharStream *input);
+
+ ~HogQLLexer() override;
+
+
+ std::string getGrammarFileName() const override;
+
+ const std::vector& getRuleNames() const override;
+
+ const std::vector& getChannelNames() const override;
+
+ const std::vector& getModeNames() const override;
+
+ const antlr4::dfa::Vocabulary& getVocabulary() const override;
+
+ antlr4::atn::SerializedATNView getSerializedATN() const override;
+
+ const antlr4::atn::ATN& getATN() const override;
+
+ // By default the static state used to implement the lexer is lazily initialized during the first
+ // call to the constructor. You can call this function if you wish to initialize the static state
+ // ahead of time.
+ static void initialize();
+
+private:
+
+ // Individual action functions triggered by action() above.
+
+ // Individual semantic predicate functions triggered by sempred() above.
+
+};
+
diff --git a/hogql_parser/HogQLLexer.interp b/hogql_parser/HogQLLexer.interp
new file mode 100644
index 0000000000000..3e078ad307c5d
--- /dev/null
+++ b/hogql_parser/HogQLLexer.interp
@@ -0,0 +1,773 @@
+token literal names:
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+null
+'false'
+'true'
+null
+null
+null
+null
+null
+null
+null
+null
+'->'
+'*'
+'`'
+'\\'
+':'
+','
+'||'
+'-'
+'$'
+'.'
+'=='
+'='
+'>='
+'>'
+'#'
+'~*'
+'=~*'
+'{'
+'['
+'('
+'<='
+'<'
+null
+'!~*'
+'!~'
+'??'
+'%'
+'+'
+'?'
+'"'
+'\''
+'~'
+'=~'
+'}'
+']'
+')'
+';'
+'/'
+'_'
+null
+null
+null
+
+token symbolic names:
+null
+ADD
+AFTER
+ALIAS
+ALL
+ALTER
+AND
+ANTI
+ANY
+ARRAY
+AS
+ASCENDING
+ASOF
+AST
+ASYNC
+ATTACH
+BETWEEN
+BOTH
+BY
+CASE
+CAST
+CHECK
+CLEAR
+CLUSTER
+CODEC
+COHORT
+COLLATE
+COLUMN
+COMMENT
+CONSTRAINT
+CREATE
+CROSS
+CUBE
+CURRENT
+DATABASE
+DATABASES
+DATE
+DAY
+DEDUPLICATE
+DEFAULT
+DELAY
+DELETE
+DESC
+DESCENDING
+DESCRIBE
+DETACH
+DICTIONARIES
+DICTIONARY
+DISK
+DISTINCT
+DISTRIBUTED
+DROP
+ELSE
+END
+ENGINE
+EVENTS
+EXISTS
+EXPLAIN
+EXPRESSION
+EXTRACT
+FETCHES
+FINAL
+FIRST
+FLUSH
+FOLLOWING
+FOR
+FORMAT
+FREEZE
+FROM
+FULL
+FUNCTION
+GLOBAL
+GRANULARITY
+GROUP
+HAVING
+HIERARCHICAL
+HOUR
+ID
+IF
+ILIKE
+IN
+INDEX
+INF
+INJECTIVE
+INNER
+INSERT
+INTERVAL
+INTO
+IS
+IS_OBJECT_ID
+JOIN
+KEY
+KILL
+LAST
+LAYOUT
+LEADING
+LEFT
+LIFETIME
+LIKE
+LIMIT
+LIVE
+LOCAL
+LOGS
+MATERIALIZE
+MATERIALIZED
+MAX
+MERGES
+MIN
+MINUTE
+MODIFY
+MONTH
+MOVE
+MUTATION
+NAN_SQL
+NO
+NOT
+NULL_SQL
+NULLS
+OFFSET
+ON
+OPTIMIZE
+OR
+ORDER
+OUTER
+OUTFILE
+OVER
+PARTITION
+POPULATE
+PRECEDING
+PREWHERE
+PRIMARY
+PROJECTION
+QUARTER
+RANGE
+RELOAD
+REMOVE
+RENAME
+REPLACE
+REPLICA
+REPLICATED
+RIGHT
+ROLLUP
+ROW
+ROWS
+SAMPLE
+SECOND
+SELECT
+SEMI
+SENDS
+SET
+SETTINGS
+SHOW
+SOURCE
+START
+STOP
+SUBSTRING
+SYNC
+SYNTAX
+SYSTEM
+TABLE
+TABLES
+TEMPORARY
+TEST
+THEN
+TIES
+TIMEOUT
+TIMESTAMP
+TO
+TOP
+TOTALS
+TRAILING
+TRIM
+TRUNCATE
+TTL
+TYPE
+UNBOUNDED
+UNION
+UPDATE
+USE
+USING
+UUID
+VALUES
+VIEW
+VOLUME
+WATCH
+WEEK
+WHEN
+WHERE
+WINDOW
+WITH
+YEAR
+JSON_FALSE
+JSON_TRUE
+ESCAPE_CHAR
+IDENTIFIER
+FLOATING_LITERAL
+OCTAL_LITERAL
+DECIMAL_LITERAL
+HEXADECIMAL_LITERAL
+STRING_LITERAL
+PLACEHOLDER
+ARROW
+ASTERISK
+BACKQUOTE
+BACKSLASH
+COLON
+COMMA
+CONCAT
+DASH
+DOLLAR
+DOT
+EQ_DOUBLE
+EQ_SINGLE
+GT_EQ
+GT
+HASH
+IREGEX_SINGLE
+IREGEX_DOUBLE
+LBRACE
+LBRACKET
+LPAREN
+LT_EQ
+LT
+NOT_EQ
+NOT_IREGEX
+NOT_REGEX
+NULLISH
+PERCENT
+PLUS
+QUERY
+QUOTE_DOUBLE
+QUOTE_SINGLE
+REGEX_SINGLE
+REGEX_DOUBLE
+RBRACE
+RBRACKET
+RPAREN
+SEMICOLON
+SLASH
+UNDERSCORE
+MULTI_LINE_COMMENT
+SINGLE_LINE_COMMENT
+WHITESPACE
+
+rule names:
+ADD
+AFTER
+ALIAS
+ALL
+ALTER
+AND
+ANTI
+ANY
+ARRAY
+AS
+ASCENDING
+ASOF
+AST
+ASYNC
+ATTACH
+BETWEEN
+BOTH
+BY
+CASE
+CAST
+CHECK
+CLEAR
+CLUSTER
+CODEC
+COHORT
+COLLATE
+COLUMN
+COMMENT
+CONSTRAINT
+CREATE
+CROSS
+CUBE
+CURRENT
+DATABASE
+DATABASES
+DATE
+DAY
+DEDUPLICATE
+DEFAULT
+DELAY
+DELETE
+DESC
+DESCENDING
+DESCRIBE
+DETACH
+DICTIONARIES
+DICTIONARY
+DISK
+DISTINCT
+DISTRIBUTED
+DROP
+ELSE
+END
+ENGINE
+EVENTS
+EXISTS
+EXPLAIN
+EXPRESSION
+EXTRACT
+FETCHES
+FINAL
+FIRST
+FLUSH
+FOLLOWING
+FOR
+FORMAT
+FREEZE
+FROM
+FULL
+FUNCTION
+GLOBAL
+GRANULARITY
+GROUP
+HAVING
+HIERARCHICAL
+HOUR
+ID
+IF
+ILIKE
+IN
+INDEX
+INF
+INJECTIVE
+INNER
+INSERT
+INTERVAL
+INTO
+IS
+IS_OBJECT_ID
+JOIN
+KEY
+KILL
+LAST
+LAYOUT
+LEADING
+LEFT
+LIFETIME
+LIKE
+LIMIT
+LIVE
+LOCAL
+LOGS
+MATERIALIZE
+MATERIALIZED
+MAX
+MERGES
+MIN
+MINUTE
+MODIFY
+MONTH
+MOVE
+MUTATION
+NAN_SQL
+NO
+NOT
+NULL_SQL
+NULLS
+OFFSET
+ON
+OPTIMIZE
+OR
+ORDER
+OUTER
+OUTFILE
+OVER
+PARTITION
+POPULATE
+PRECEDING
+PREWHERE
+PRIMARY
+PROJECTION
+QUARTER
+RANGE
+RELOAD
+REMOVE
+RENAME
+REPLACE
+REPLICA
+REPLICATED
+RIGHT
+ROLLUP
+ROW
+ROWS
+SAMPLE
+SECOND
+SELECT
+SEMI
+SENDS
+SET
+SETTINGS
+SHOW
+SOURCE
+START
+STOP
+SUBSTRING
+SYNC
+SYNTAX
+SYSTEM
+TABLE
+TABLES
+TEMPORARY
+TEST
+THEN
+TIES
+TIMEOUT
+TIMESTAMP
+TO
+TOP
+TOTALS
+TRAILING
+TRIM
+TRUNCATE
+TTL
+TYPE
+UNBOUNDED
+UNION
+UPDATE
+USE
+USING
+UUID
+VALUES
+VIEW
+VOLUME
+WATCH
+WEEK
+WHEN
+WHERE
+WINDOW
+WITH
+YEAR
+JSON_FALSE
+JSON_TRUE
+ESCAPE_CHAR
+IDENTIFIER
+FLOATING_LITERAL
+OCTAL_LITERAL
+DECIMAL_LITERAL
+HEXADECIMAL_LITERAL
+STRING_LITERAL
+PLACEHOLDER
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+LETTER
+OCT_DIGIT
+DEC_DIGIT
+HEX_DIGIT
+ARROW
+ASTERISK
+BACKQUOTE
+BACKSLASH
+COLON
+COMMA
+CONCAT
+DASH
+DOLLAR
+DOT
+EQ_DOUBLE
+EQ_SINGLE
+GT_EQ
+GT
+HASH
+IREGEX_SINGLE
+IREGEX_DOUBLE
+LBRACE
+LBRACKET
+LPAREN
+LT_EQ
+LT
+NOT_EQ
+NOT_IREGEX
+NOT_REGEX
+NULLISH
+PERCENT
+PLUS
+QUERY
+QUOTE_DOUBLE
+QUOTE_SINGLE
+REGEX_SINGLE
+REGEX_DOUBLE
+RBRACE
+RBRACKET
+RPAREN
+SEMICOLON
+SLASH
+UNDERSCORE
+MULTI_LINE_COMMENT
+SINGLE_LINE_COMMENT
+WHITESPACE
+
+channel names:
+DEFAULT_TOKEN_CHANNEL
+HIDDEN
+
+mode names:
+DEFAULT_MODE
+
+atn:
+[4, 0, 242, 2222, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 2, 159, 7, 159, 2, 160, 7, 160, 2, 161, 7, 161, 2, 162, 7, 162, 2, 163, 7, 163, 2, 164, 7, 164, 2, 165, 7, 165, 2, 166, 7, 166, 2, 167, 7, 167, 2, 168, 7, 168, 2, 169, 7, 169, 2, 170, 7, 170, 2, 171, 7, 171, 2, 172, 7, 172, 2, 173, 7, 173, 2, 174, 7, 174, 2, 175, 7, 175, 2, 176, 7, 176, 2, 177, 7, 177, 2, 178, 7, 178, 2, 179, 7, 179, 2, 180, 7, 180, 2, 181, 7, 181, 2, 182, 7, 182, 2, 183, 7, 183, 2, 184, 7, 184, 2, 185, 7, 185, 2, 186, 7, 186, 2, 187, 7, 187, 2, 188, 7, 188, 2, 189, 7, 189, 2, 190, 7, 190, 2, 191, 7, 191, 2, 192, 7, 192, 2, 193, 7, 193, 2, 194, 7, 194, 2, 195, 7, 195, 2, 196, 7, 196, 2, 197, 7, 197, 2, 198, 7, 198, 2, 199, 7, 199, 2, 200, 7, 200, 2, 201, 7, 201, 2, 202, 7, 202, 2, 203, 7, 203, 2, 204, 7, 204, 2, 205, 7, 205, 2, 206, 7, 206, 2, 207, 7, 207, 2, 208, 7, 208, 2, 209, 7, 209, 2, 210, 7, 210, 2, 211, 7, 211, 2, 212, 7, 212, 2, 213, 7, 213, 2, 214, 7, 214, 2, 215, 7, 215, 2, 216, 7, 216, 2, 217, 7, 217, 2, 218, 7, 218, 2, 219, 7, 219, 2, 220, 7, 220, 2, 221, 7, 221, 2, 222, 7, 222, 2, 223, 7, 223, 2, 224, 7, 224, 2, 225, 7, 225, 2, 226, 7, 226, 2, 227, 7, 227, 2, 228, 7, 228, 2, 229, 7, 229, 2, 230, 7, 230, 2, 231, 7, 231, 2, 232, 7, 232, 2, 233, 7, 233, 2, 234, 7, 234, 2, 235, 7, 235, 2, 236, 7, 236, 2, 237, 7, 237, 2, 238, 7, 238, 2, 239, 7, 239, 2, 240, 7, 240, 2, 241, 7, 241, 2, 242, 7, 242, 2, 243, 7, 243, 2, 244, 7, 244, 2, 245, 7, 245, 2, 246, 7, 246, 2, 247, 7, 247, 2, 248, 7, 248, 2, 249, 7, 249, 2, 250, 7, 250, 2, 251, 7, 251, 2, 252, 7, 252, 2, 253, 7, 253, 2, 254, 7, 254, 2, 255, 7, 255, 2, 256, 7, 256, 2, 257, 7, 257, 2, 258, 7, 258, 2, 259, 7, 259, 2, 260, 7, 260, 2, 261, 7, 261, 2, 262, 7, 262, 2, 263, 7, 263, 2, 264, 7, 264, 2, 265, 7, 265, 2, 266, 7, 266, 2, 267, 7, 267, 2, 268, 7, 268, 2, 269, 7, 269, 2, 270, 7, 270, 2, 271, 7, 271, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 3, 10, 608, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 3, 81, 1113, 8, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 1, 92, 1, 92, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 100, 1, 101, 1, 101, 1, 101, 1, 101, 1, 101, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 119, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 158, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 159, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 160, 1, 161, 1, 161, 1, 161, 1, 161, 1, 161, 1, 162, 1, 162, 1, 162, 1, 162, 1, 162, 1, 163, 1, 163, 1, 163, 1, 163, 1, 163, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 164, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 165, 1, 166, 1, 166, 1, 166, 1, 167, 1, 167, 1, 167, 1, 167, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 168, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 169, 1, 170, 1, 170, 1, 170, 1, 170, 1, 170, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 171, 1, 172, 1, 172, 1, 172, 1, 172, 1, 173, 1, 173, 1, 173, 1, 173, 1, 173, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 174, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 175, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 176, 1, 177, 1, 177, 1, 177, 1, 177, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 178, 1, 179, 1, 179, 1, 179, 1, 179, 1, 179, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 180, 1, 181, 1, 181, 1, 181, 1, 181, 1, 181, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 182, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 183, 1, 184, 1, 184, 1, 184, 1, 184, 1, 184, 1, 185, 1, 185, 1, 185, 1, 185, 1, 185, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 186, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 187, 1, 188, 1, 188, 1, 188, 1, 188, 1, 188, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 1, 189, 3, 189, 1827, 8, 189, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 190, 1, 191, 1, 191, 1, 191, 1, 191, 1, 191, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 1, 192, 3, 192, 1870, 8, 192, 1, 193, 1, 193, 1, 193, 3, 193, 1875, 8, 193, 1, 193, 1, 193, 1, 193, 1, 193, 5, 193, 1881, 8, 193, 10, 193, 12, 193, 1884, 9, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 5, 193, 1892, 8, 193, 10, 193, 12, 193, 1895, 9, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 1, 193, 5, 193, 1905, 8, 193, 10, 193, 12, 193, 1908, 9, 193, 1, 193, 1, 193, 3, 193, 1912, 8, 193, 1, 194, 1, 194, 1, 194, 5, 194, 1917, 8, 194, 10, 194, 12, 194, 1920, 9, 194, 1, 194, 1, 194, 3, 194, 1924, 8, 194, 1, 194, 1, 194, 3, 194, 1928, 8, 194, 1, 194, 4, 194, 1931, 8, 194, 11, 194, 12, 194, 1932, 1, 194, 1, 194, 1, 194, 3, 194, 1938, 8, 194, 1, 194, 1, 194, 3, 194, 1942, 8, 194, 1, 194, 4, 194, 1945, 8, 194, 11, 194, 12, 194, 1946, 1, 194, 1, 194, 1, 194, 5, 194, 1952, 8, 194, 10, 194, 12, 194, 1955, 9, 194, 1, 194, 1, 194, 1, 194, 3, 194, 1960, 8, 194, 1, 194, 4, 194, 1963, 8, 194, 11, 194, 12, 194, 1964, 1, 194, 1, 194, 1, 194, 1, 194, 1, 194, 3, 194, 1972, 8, 194, 1, 194, 4, 194, 1975, 8, 194, 11, 194, 12, 194, 1976, 1, 194, 1, 194, 1, 194, 1, 194, 3, 194, 1983, 8, 194, 1, 194, 4, 194, 1986, 8, 194, 11, 194, 12, 194, 1987, 3, 194, 1990, 8, 194, 1, 195, 1, 195, 4, 195, 1994, 8, 195, 11, 195, 12, 195, 1995, 1, 196, 4, 196, 1999, 8, 196, 11, 196, 12, 196, 2000, 1, 197, 1, 197, 1, 197, 4, 197, 2006, 8, 197, 11, 197, 12, 197, 2007, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 1, 198, 5, 198, 2016, 8, 198, 10, 198, 12, 198, 2019, 9, 198, 1, 198, 1, 198, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 1, 199, 5, 199, 2029, 8, 199, 10, 199, 12, 199, 2032, 9, 199, 1, 199, 1, 199, 1, 200, 1, 200, 1, 201, 1, 201, 1, 202, 1, 202, 1, 203, 1, 203, 1, 204, 1, 204, 1, 205, 1, 205, 1, 206, 1, 206, 1, 207, 1, 207, 1, 208, 1, 208, 1, 209, 1, 209, 1, 210, 1, 210, 1, 211, 1, 211, 1, 212, 1, 212, 1, 213, 1, 213, 1, 214, 1, 214, 1, 215, 1, 215, 1, 216, 1, 216, 1, 217, 1, 217, 1, 218, 1, 218, 1, 219, 1, 219, 1, 220, 1, 220, 1, 221, 1, 221, 1, 222, 1, 222, 1, 223, 1, 223, 1, 224, 1, 224, 1, 225, 1, 225, 1, 226, 1, 226, 1, 227, 1, 227, 1, 228, 1, 228, 1, 229, 1, 229, 1, 230, 1, 230, 1, 230, 1, 231, 1, 231, 1, 232, 1, 232, 1, 233, 1, 233, 1, 234, 1, 234, 1, 235, 1, 235, 1, 236, 1, 236, 1, 236, 1, 237, 1, 237, 1, 238, 1, 238, 1, 239, 1, 239, 1, 240, 1, 240, 1, 240, 1, 241, 1, 241, 1, 242, 1, 242, 1, 242, 1, 243, 1, 243, 1, 244, 1, 244, 1, 245, 1, 245, 1, 245, 1, 246, 1, 246, 1, 246, 1, 246, 1, 247, 1, 247, 1, 248, 1, 248, 1, 249, 1, 249, 1, 250, 1, 250, 1, 250, 1, 251, 1, 251, 1, 252, 1, 252, 1, 252, 1, 252, 3, 252, 2152, 8, 252, 1, 253, 1, 253, 1, 253, 1, 253, 1, 254, 1, 254, 1, 254, 1, 255, 1, 255, 1, 255, 1, 256, 1, 256, 1, 257, 1, 257, 1, 258, 1, 258, 1, 259, 1, 259, 1, 260, 1, 260, 1, 261, 1, 261, 1, 262, 1, 262, 1, 262, 1, 263, 1, 263, 1, 264, 1, 264, 1, 265, 1, 265, 1, 266, 1, 266, 1, 267, 1, 267, 1, 268, 1, 268, 1, 269, 1, 269, 1, 269, 1, 269, 5, 269, 2195, 8, 269, 10, 269, 12, 269, 2198, 9, 269, 1, 269, 1, 269, 1, 269, 1, 269, 1, 269, 1, 270, 1, 270, 1, 270, 1, 270, 5, 270, 2209, 8, 270, 10, 270, 12, 270, 2212, 9, 270, 1, 270, 3, 270, 2215, 8, 270, 1, 270, 1, 270, 1, 271, 1, 271, 1, 271, 1, 271, 1, 2196, 0, 272, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, 141, 71, 143, 72, 145, 73, 147, 74, 149, 75, 151, 76, 153, 77, 155, 78, 157, 79, 159, 80, 161, 81, 163, 82, 165, 83, 167, 84, 169, 85, 171, 86, 173, 87, 175, 88, 177, 89, 179, 90, 181, 91, 183, 92, 185, 93, 187, 94, 189, 95, 191, 96, 193, 97, 195, 98, 197, 99, 199, 100, 201, 101, 203, 102, 205, 103, 207, 104, 209, 105, 211, 106, 213, 107, 215, 108, 217, 109, 219, 110, 221, 111, 223, 112, 225, 113, 227, 114, 229, 115, 231, 116, 233, 117, 235, 118, 237, 119, 239, 120, 241, 121, 243, 122, 245, 123, 247, 124, 249, 125, 251, 126, 253, 127, 255, 128, 257, 129, 259, 130, 261, 131, 263, 132, 265, 133, 267, 134, 269, 135, 271, 136, 273, 137, 275, 138, 277, 139, 279, 140, 281, 141, 283, 142, 285, 143, 287, 144, 289, 145, 291, 146, 293, 147, 295, 148, 297, 149, 299, 150, 301, 151, 303, 152, 305, 153, 307, 154, 309, 155, 311, 156, 313, 157, 315, 158, 317, 159, 319, 160, 321, 161, 323, 162, 325, 163, 327, 164, 329, 165, 331, 166, 333, 167, 335, 168, 337, 169, 339, 170, 341, 171, 343, 172, 345, 173, 347, 174, 349, 175, 351, 176, 353, 177, 355, 178, 357, 179, 359, 180, 361, 181, 363, 182, 365, 183, 367, 184, 369, 185, 371, 186, 373, 187, 375, 188, 377, 189, 379, 190, 381, 191, 383, 192, 385, 193, 387, 194, 389, 195, 391, 196, 393, 197, 395, 198, 397, 199, 399, 200, 401, 0, 403, 0, 405, 0, 407, 0, 409, 0, 411, 0, 413, 0, 415, 0, 417, 0, 419, 0, 421, 0, 423, 0, 425, 0, 427, 0, 429, 0, 431, 0, 433, 0, 435, 0, 437, 0, 439, 0, 441, 0, 443, 0, 445, 0, 447, 0, 449, 0, 451, 0, 453, 0, 455, 0, 457, 0, 459, 0, 461, 201, 463, 202, 465, 203, 467, 204, 469, 205, 471, 206, 473, 207, 475, 208, 477, 209, 479, 210, 481, 211, 483, 212, 485, 213, 487, 214, 489, 215, 491, 216, 493, 217, 495, 218, 497, 219, 499, 220, 501, 221, 503, 222, 505, 223, 507, 224, 509, 225, 511, 226, 513, 227, 515, 228, 517, 229, 519, 230, 521, 231, 523, 232, 525, 233, 527, 234, 529, 235, 531, 236, 533, 237, 535, 238, 537, 239, 539, 240, 541, 241, 543, 242, 1, 0, 37, 2, 0, 92, 92, 96, 96, 2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 2, 0, 92, 92, 125, 125, 2, 0, 65, 65, 97, 97, 2, 0, 66, 66, 98, 98, 2, 0, 67, 67, 99, 99, 2, 0, 68, 68, 100, 100, 2, 0, 69, 69, 101, 101, 2, 0, 70, 70, 102, 102, 2, 0, 71, 71, 103, 103, 2, 0, 72, 72, 104, 104, 2, 0, 73, 73, 105, 105, 2, 0, 74, 74, 106, 106, 2, 0, 75, 75, 107, 107, 2, 0, 76, 76, 108, 108, 2, 0, 77, 77, 109, 109, 2, 0, 78, 78, 110, 110, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 81, 81, 113, 113, 2, 0, 82, 82, 114, 114, 2, 0, 83, 83, 115, 115, 2, 0, 84, 84, 116, 116, 2, 0, 85, 85, 117, 117, 2, 0, 86, 86, 118, 118, 2, 0, 87, 87, 119, 119, 2, 0, 88, 88, 120, 120, 2, 0, 89, 89, 121, 121, 2, 0, 90, 90, 122, 122, 2, 0, 65, 90, 97, 122, 1, 0, 48, 55, 1, 0, 48, 57, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 10, 10, 13, 13, 2, 1, 10, 10, 13, 13, 2, 0, 9, 13, 32, 32, 2252, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, 0, 0, 0, 0, 169, 1, 0, 0, 0, 0, 171, 1, 0, 0, 0, 0, 173, 1, 0, 0, 0, 0, 175, 1, 0, 0, 0, 0, 177, 1, 0, 0, 0, 0, 179, 1, 0, 0, 0, 0, 181, 1, 0, 0, 0, 0, 183, 1, 0, 0, 0, 0, 185, 1, 0, 0, 0, 0, 187, 1, 0, 0, 0, 0, 189, 1, 0, 0, 0, 0, 191, 1, 0, 0, 0, 0, 193, 1, 0, 0, 0, 0, 195, 1, 0, 0, 0, 0, 197, 1, 0, 0, 0, 0, 199, 1, 0, 0, 0, 0, 201, 1, 0, 0, 0, 0, 203, 1, 0, 0, 0, 0, 205, 1, 0, 0, 0, 0, 207, 1, 0, 0, 0, 0, 209, 1, 0, 0, 0, 0, 211, 1, 0, 0, 0, 0, 213, 1, 0, 0, 0, 0, 215, 1, 0, 0, 0, 0, 217, 1, 0, 0, 0, 0, 219, 1, 0, 0, 0, 0, 221, 1, 0, 0, 0, 0, 223, 1, 0, 0, 0, 0, 225, 1, 0, 0, 0, 0, 227, 1, 0, 0, 0, 0, 229, 1, 0, 0, 0, 0, 231, 1, 0, 0, 0, 0, 233, 1, 0, 0, 0, 0, 235, 1, 0, 0, 0, 0, 237, 1, 0, 0, 0, 0, 239, 1, 0, 0, 0, 0, 241, 1, 0, 0, 0, 0, 243, 1, 0, 0, 0, 0, 245, 1, 0, 0, 0, 0, 247, 1, 0, 0, 0, 0, 249, 1, 0, 0, 0, 0, 251, 1, 0, 0, 0, 0, 253, 1, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 257, 1, 0, 0, 0, 0, 259, 1, 0, 0, 0, 0, 261, 1, 0, 0, 0, 0, 263, 1, 0, 0, 0, 0, 265, 1, 0, 0, 0, 0, 267, 1, 0, 0, 0, 0, 269, 1, 0, 0, 0, 0, 271, 1, 0, 0, 0, 0, 273, 1, 0, 0, 0, 0, 275, 1, 0, 0, 0, 0, 277, 1, 0, 0, 0, 0, 279, 1, 0, 0, 0, 0, 281, 1, 0, 0, 0, 0, 283, 1, 0, 0, 0, 0, 285, 1, 0, 0, 0, 0, 287, 1, 0, 0, 0, 0, 289, 1, 0, 0, 0, 0, 291, 1, 0, 0, 0, 0, 293, 1, 0, 0, 0, 0, 295, 1, 0, 0, 0, 0, 297, 1, 0, 0, 0, 0, 299, 1, 0, 0, 0, 0, 301, 1, 0, 0, 0, 0, 303, 1, 0, 0, 0, 0, 305, 1, 0, 0, 0, 0, 307, 1, 0, 0, 0, 0, 309, 1, 0, 0, 0, 0, 311, 1, 0, 0, 0, 0, 313, 1, 0, 0, 0, 0, 315, 1, 0, 0, 0, 0, 317, 1, 0, 0, 0, 0, 319, 1, 0, 0, 0, 0, 321, 1, 0, 0, 0, 0, 323, 1, 0, 0, 0, 0, 325, 1, 0, 0, 0, 0, 327, 1, 0, 0, 0, 0, 329, 1, 0, 0, 0, 0, 331, 1, 0, 0, 0, 0, 333, 1, 0, 0, 0, 0, 335, 1, 0, 0, 0, 0, 337, 1, 0, 0, 0, 0, 339, 1, 0, 0, 0, 0, 341, 1, 0, 0, 0, 0, 343, 1, 0, 0, 0, 0, 345, 1, 0, 0, 0, 0, 347, 1, 0, 0, 0, 0, 349, 1, 0, 0, 0, 0, 351, 1, 0, 0, 0, 0, 353, 1, 0, 0, 0, 0, 355, 1, 0, 0, 0, 0, 357, 1, 0, 0, 0, 0, 359, 1, 0, 0, 0, 0, 361, 1, 0, 0, 0, 0, 363, 1, 0, 0, 0, 0, 365, 1, 0, 0, 0, 0, 367, 1, 0, 0, 0, 0, 369, 1, 0, 0, 0, 0, 371, 1, 0, 0, 0, 0, 373, 1, 0, 0, 0, 0, 375, 1, 0, 0, 0, 0, 377, 1, 0, 0, 0, 0, 379, 1, 0, 0, 0, 0, 381, 1, 0, 0, 0, 0, 383, 1, 0, 0, 0, 0, 385, 1, 0, 0, 0, 0, 387, 1, 0, 0, 0, 0, 389, 1, 0, 0, 0, 0, 391, 1, 0, 0, 0, 0, 393, 1, 0, 0, 0, 0, 395, 1, 0, 0, 0, 0, 397, 1, 0, 0, 0, 0, 399, 1, 0, 0, 0, 0, 461, 1, 0, 0, 0, 0, 463, 1, 0, 0, 0, 0, 465, 1, 0, 0, 0, 0, 467, 1, 0, 0, 0, 0, 469, 1, 0, 0, 0, 0, 471, 1, 0, 0, 0, 0, 473, 1, 0, 0, 0, 0, 475, 1, 0, 0, 0, 0, 477, 1, 0, 0, 0, 0, 479, 1, 0, 0, 0, 0, 481, 1, 0, 0, 0, 0, 483, 1, 0, 0, 0, 0, 485, 1, 0, 0, 0, 0, 487, 1, 0, 0, 0, 0, 489, 1, 0, 0, 0, 0, 491, 1, 0, 0, 0, 0, 493, 1, 0, 0, 0, 0, 495, 1, 0, 0, 0, 0, 497, 1, 0, 0, 0, 0, 499, 1, 0, 0, 0, 0, 501, 1, 0, 0, 0, 0, 503, 1, 0, 0, 0, 0, 505, 1, 0, 0, 0, 0, 507, 1, 0, 0, 0, 0, 509, 1, 0, 0, 0, 0, 511, 1, 0, 0, 0, 0, 513, 1, 0, 0, 0, 0, 515, 1, 0, 0, 0, 0, 517, 1, 0, 0, 0, 0, 519, 1, 0, 0, 0, 0, 521, 1, 0, 0, 0, 0, 523, 1, 0, 0, 0, 0, 525, 1, 0, 0, 0, 0, 527, 1, 0, 0, 0, 0, 529, 1, 0, 0, 0, 0, 531, 1, 0, 0, 0, 0, 533, 1, 0, 0, 0, 0, 535, 1, 0, 0, 0, 0, 537, 1, 0, 0, 0, 0, 539, 1, 0, 0, 0, 0, 541, 1, 0, 0, 0, 0, 543, 1, 0, 0, 0, 1, 545, 1, 0, 0, 0, 3, 549, 1, 0, 0, 0, 5, 555, 1, 0, 0, 0, 7, 561, 1, 0, 0, 0, 9, 565, 1, 0, 0, 0, 11, 571, 1, 0, 0, 0, 13, 575, 1, 0, 0, 0, 15, 580, 1, 0, 0, 0, 17, 584, 1, 0, 0, 0, 19, 590, 1, 0, 0, 0, 21, 607, 1, 0, 0, 0, 23, 609, 1, 0, 0, 0, 25, 614, 1, 0, 0, 0, 27, 618, 1, 0, 0, 0, 29, 624, 1, 0, 0, 0, 31, 631, 1, 0, 0, 0, 33, 639, 1, 0, 0, 0, 35, 644, 1, 0, 0, 0, 37, 647, 1, 0, 0, 0, 39, 652, 1, 0, 0, 0, 41, 657, 1, 0, 0, 0, 43, 663, 1, 0, 0, 0, 45, 669, 1, 0, 0, 0, 47, 677, 1, 0, 0, 0, 49, 683, 1, 0, 0, 0, 51, 690, 1, 0, 0, 0, 53, 698, 1, 0, 0, 0, 55, 705, 1, 0, 0, 0, 57, 713, 1, 0, 0, 0, 59, 724, 1, 0, 0, 0, 61, 731, 1, 0, 0, 0, 63, 737, 1, 0, 0, 0, 65, 742, 1, 0, 0, 0, 67, 750, 1, 0, 0, 0, 69, 759, 1, 0, 0, 0, 71, 769, 1, 0, 0, 0, 73, 774, 1, 0, 0, 0, 75, 778, 1, 0, 0, 0, 77, 790, 1, 0, 0, 0, 79, 798, 1, 0, 0, 0, 81, 804, 1, 0, 0, 0, 83, 811, 1, 0, 0, 0, 85, 816, 1, 0, 0, 0, 87, 827, 1, 0, 0, 0, 89, 836, 1, 0, 0, 0, 91, 843, 1, 0, 0, 0, 93, 856, 1, 0, 0, 0, 95, 867, 1, 0, 0, 0, 97, 872, 1, 0, 0, 0, 99, 881, 1, 0, 0, 0, 101, 893, 1, 0, 0, 0, 103, 898, 1, 0, 0, 0, 105, 903, 1, 0, 0, 0, 107, 907, 1, 0, 0, 0, 109, 914, 1, 0, 0, 0, 111, 921, 1, 0, 0, 0, 113, 928, 1, 0, 0, 0, 115, 936, 1, 0, 0, 0, 117, 947, 1, 0, 0, 0, 119, 955, 1, 0, 0, 0, 121, 963, 1, 0, 0, 0, 123, 969, 1, 0, 0, 0, 125, 975, 1, 0, 0, 0, 127, 981, 1, 0, 0, 0, 129, 991, 1, 0, 0, 0, 131, 995, 1, 0, 0, 0, 133, 1002, 1, 0, 0, 0, 135, 1009, 1, 0, 0, 0, 137, 1014, 1, 0, 0, 0, 139, 1019, 1, 0, 0, 0, 141, 1028, 1, 0, 0, 0, 143, 1035, 1, 0, 0, 0, 145, 1047, 1, 0, 0, 0, 147, 1053, 1, 0, 0, 0, 149, 1060, 1, 0, 0, 0, 151, 1073, 1, 0, 0, 0, 153, 1078, 1, 0, 0, 0, 155, 1081, 1, 0, 0, 0, 157, 1084, 1, 0, 0, 0, 159, 1090, 1, 0, 0, 0, 161, 1093, 1, 0, 0, 0, 163, 1112, 1, 0, 0, 0, 165, 1114, 1, 0, 0, 0, 167, 1124, 1, 0, 0, 0, 169, 1130, 1, 0, 0, 0, 171, 1137, 1, 0, 0, 0, 173, 1146, 1, 0, 0, 0, 175, 1151, 1, 0, 0, 0, 177, 1154, 1, 0, 0, 0, 179, 1167, 1, 0, 0, 0, 181, 1172, 1, 0, 0, 0, 183, 1176, 1, 0, 0, 0, 185, 1181, 1, 0, 0, 0, 187, 1186, 1, 0, 0, 0, 189, 1193, 1, 0, 0, 0, 191, 1201, 1, 0, 0, 0, 193, 1206, 1, 0, 0, 0, 195, 1215, 1, 0, 0, 0, 197, 1220, 1, 0, 0, 0, 199, 1226, 1, 0, 0, 0, 201, 1231, 1, 0, 0, 0, 203, 1237, 1, 0, 0, 0, 205, 1242, 1, 0, 0, 0, 207, 1254, 1, 0, 0, 0, 209, 1267, 1, 0, 0, 0, 211, 1271, 1, 0, 0, 0, 213, 1278, 1, 0, 0, 0, 215, 1282, 1, 0, 0, 0, 217, 1289, 1, 0, 0, 0, 219, 1296, 1, 0, 0, 0, 221, 1302, 1, 0, 0, 0, 223, 1307, 1, 0, 0, 0, 225, 1316, 1, 0, 0, 0, 227, 1320, 1, 0, 0, 0, 229, 1323, 1, 0, 0, 0, 231, 1327, 1, 0, 0, 0, 233, 1332, 1, 0, 0, 0, 235, 1338, 1, 0, 0, 0, 237, 1345, 1, 0, 0, 0, 239, 1348, 1, 0, 0, 0, 241, 1357, 1, 0, 0, 0, 243, 1360, 1, 0, 0, 0, 245, 1366, 1, 0, 0, 0, 247, 1372, 1, 0, 0, 0, 249, 1380, 1, 0, 0, 0, 251, 1385, 1, 0, 0, 0, 253, 1395, 1, 0, 0, 0, 255, 1404, 1, 0, 0, 0, 257, 1414, 1, 0, 0, 0, 259, 1423, 1, 0, 0, 0, 261, 1431, 1, 0, 0, 0, 263, 1442, 1, 0, 0, 0, 265, 1450, 1, 0, 0, 0, 267, 1456, 1, 0, 0, 0, 269, 1463, 1, 0, 0, 0, 271, 1470, 1, 0, 0, 0, 273, 1477, 1, 0, 0, 0, 275, 1485, 1, 0, 0, 0, 277, 1493, 1, 0, 0, 0, 279, 1504, 1, 0, 0, 0, 281, 1510, 1, 0, 0, 0, 283, 1517, 1, 0, 0, 0, 285, 1521, 1, 0, 0, 0, 287, 1526, 1, 0, 0, 0, 289, 1533, 1, 0, 0, 0, 291, 1540, 1, 0, 0, 0, 293, 1547, 1, 0, 0, 0, 295, 1552, 1, 0, 0, 0, 297, 1558, 1, 0, 0, 0, 299, 1562, 1, 0, 0, 0, 301, 1571, 1, 0, 0, 0, 303, 1576, 1, 0, 0, 0, 305, 1583, 1, 0, 0, 0, 307, 1589, 1, 0, 0, 0, 309, 1594, 1, 0, 0, 0, 311, 1604, 1, 0, 0, 0, 313, 1609, 1, 0, 0, 0, 315, 1616, 1, 0, 0, 0, 317, 1623, 1, 0, 0, 0, 319, 1629, 1, 0, 0, 0, 321, 1636, 1, 0, 0, 0, 323, 1646, 1, 0, 0, 0, 325, 1651, 1, 0, 0, 0, 327, 1656, 1, 0, 0, 0, 329, 1661, 1, 0, 0, 0, 331, 1669, 1, 0, 0, 0, 333, 1679, 1, 0, 0, 0, 335, 1682, 1, 0, 0, 0, 337, 1686, 1, 0, 0, 0, 339, 1693, 1, 0, 0, 0, 341, 1702, 1, 0, 0, 0, 343, 1707, 1, 0, 0, 0, 345, 1716, 1, 0, 0, 0, 347, 1720, 1, 0, 0, 0, 349, 1725, 1, 0, 0, 0, 351, 1735, 1, 0, 0, 0, 353, 1741, 1, 0, 0, 0, 355, 1748, 1, 0, 0, 0, 357, 1752, 1, 0, 0, 0, 359, 1758, 1, 0, 0, 0, 361, 1763, 1, 0, 0, 0, 363, 1770, 1, 0, 0, 0, 365, 1775, 1, 0, 0, 0, 367, 1782, 1, 0, 0, 0, 369, 1788, 1, 0, 0, 0, 371, 1793, 1, 0, 0, 0, 373, 1798, 1, 0, 0, 0, 375, 1804, 1, 0, 0, 0, 377, 1811, 1, 0, 0, 0, 379, 1826, 1, 0, 0, 0, 381, 1828, 1, 0, 0, 0, 383, 1834, 1, 0, 0, 0, 385, 1869, 1, 0, 0, 0, 387, 1911, 1, 0, 0, 0, 389, 1989, 1, 0, 0, 0, 391, 1991, 1, 0, 0, 0, 393, 1998, 1, 0, 0, 0, 395, 2002, 1, 0, 0, 0, 397, 2009, 1, 0, 0, 0, 399, 2022, 1, 0, 0, 0, 401, 2035, 1, 0, 0, 0, 403, 2037, 1, 0, 0, 0, 405, 2039, 1, 0, 0, 0, 407, 2041, 1, 0, 0, 0, 409, 2043, 1, 0, 0, 0, 411, 2045, 1, 0, 0, 0, 413, 2047, 1, 0, 0, 0, 415, 2049, 1, 0, 0, 0, 417, 2051, 1, 0, 0, 0, 419, 2053, 1, 0, 0, 0, 421, 2055, 1, 0, 0, 0, 423, 2057, 1, 0, 0, 0, 425, 2059, 1, 0, 0, 0, 427, 2061, 1, 0, 0, 0, 429, 2063, 1, 0, 0, 0, 431, 2065, 1, 0, 0, 0, 433, 2067, 1, 0, 0, 0, 435, 2069, 1, 0, 0, 0, 437, 2071, 1, 0, 0, 0, 439, 2073, 1, 0, 0, 0, 441, 2075, 1, 0, 0, 0, 443, 2077, 1, 0, 0, 0, 445, 2079, 1, 0, 0, 0, 447, 2081, 1, 0, 0, 0, 449, 2083, 1, 0, 0, 0, 451, 2085, 1, 0, 0, 0, 453, 2087, 1, 0, 0, 0, 455, 2089, 1, 0, 0, 0, 457, 2091, 1, 0, 0, 0, 459, 2093, 1, 0, 0, 0, 461, 2095, 1, 0, 0, 0, 463, 2098, 1, 0, 0, 0, 465, 2100, 1, 0, 0, 0, 467, 2102, 1, 0, 0, 0, 469, 2104, 1, 0, 0, 0, 471, 2106, 1, 0, 0, 0, 473, 2108, 1, 0, 0, 0, 475, 2111, 1, 0, 0, 0, 477, 2113, 1, 0, 0, 0, 479, 2115, 1, 0, 0, 0, 481, 2117, 1, 0, 0, 0, 483, 2120, 1, 0, 0, 0, 485, 2122, 1, 0, 0, 0, 487, 2125, 1, 0, 0, 0, 489, 2127, 1, 0, 0, 0, 491, 2129, 1, 0, 0, 0, 493, 2132, 1, 0, 0, 0, 495, 2136, 1, 0, 0, 0, 497, 2138, 1, 0, 0, 0, 499, 2140, 1, 0, 0, 0, 501, 2142, 1, 0, 0, 0, 503, 2145, 1, 0, 0, 0, 505, 2151, 1, 0, 0, 0, 507, 2153, 1, 0, 0, 0, 509, 2157, 1, 0, 0, 0, 511, 2160, 1, 0, 0, 0, 513, 2163, 1, 0, 0, 0, 515, 2165, 1, 0, 0, 0, 517, 2167, 1, 0, 0, 0, 519, 2169, 1, 0, 0, 0, 521, 2171, 1, 0, 0, 0, 523, 2173, 1, 0, 0, 0, 525, 2175, 1, 0, 0, 0, 527, 2178, 1, 0, 0, 0, 529, 2180, 1, 0, 0, 0, 531, 2182, 1, 0, 0, 0, 533, 2184, 1, 0, 0, 0, 535, 2186, 1, 0, 0, 0, 537, 2188, 1, 0, 0, 0, 539, 2190, 1, 0, 0, 0, 541, 2204, 1, 0, 0, 0, 543, 2218, 1, 0, 0, 0, 545, 546, 3, 401, 200, 0, 546, 547, 3, 407, 203, 0, 547, 548, 3, 407, 203, 0, 548, 2, 1, 0, 0, 0, 549, 550, 3, 401, 200, 0, 550, 551, 3, 411, 205, 0, 551, 552, 3, 439, 219, 0, 552, 553, 3, 409, 204, 0, 553, 554, 3, 435, 217, 0, 554, 4, 1, 0, 0, 0, 555, 556, 3, 401, 200, 0, 556, 557, 3, 423, 211, 0, 557, 558, 3, 417, 208, 0, 558, 559, 3, 401, 200, 0, 559, 560, 3, 437, 218, 0, 560, 6, 1, 0, 0, 0, 561, 562, 3, 401, 200, 0, 562, 563, 3, 423, 211, 0, 563, 564, 3, 423, 211, 0, 564, 8, 1, 0, 0, 0, 565, 566, 3, 401, 200, 0, 566, 567, 3, 423, 211, 0, 567, 568, 3, 439, 219, 0, 568, 569, 3, 409, 204, 0, 569, 570, 3, 435, 217, 0, 570, 10, 1, 0, 0, 0, 571, 572, 3, 401, 200, 0, 572, 573, 3, 427, 213, 0, 573, 574, 3, 407, 203, 0, 574, 12, 1, 0, 0, 0, 575, 576, 3, 401, 200, 0, 576, 577, 3, 427, 213, 0, 577, 578, 3, 439, 219, 0, 578, 579, 3, 417, 208, 0, 579, 14, 1, 0, 0, 0, 580, 581, 3, 401, 200, 0, 581, 582, 3, 427, 213, 0, 582, 583, 3, 449, 224, 0, 583, 16, 1, 0, 0, 0, 584, 585, 3, 401, 200, 0, 585, 586, 3, 435, 217, 0, 586, 587, 3, 435, 217, 0, 587, 588, 3, 401, 200, 0, 588, 589, 3, 449, 224, 0, 589, 18, 1, 0, 0, 0, 590, 591, 3, 401, 200, 0, 591, 592, 3, 437, 218, 0, 592, 20, 1, 0, 0, 0, 593, 594, 3, 401, 200, 0, 594, 595, 3, 437, 218, 0, 595, 596, 3, 405, 202, 0, 596, 608, 1, 0, 0, 0, 597, 598, 3, 401, 200, 0, 598, 599, 3, 437, 218, 0, 599, 600, 3, 405, 202, 0, 600, 601, 3, 409, 204, 0, 601, 602, 3, 427, 213, 0, 602, 603, 3, 407, 203, 0, 603, 604, 3, 417, 208, 0, 604, 605, 3, 427, 213, 0, 605, 606, 3, 413, 206, 0, 606, 608, 1, 0, 0, 0, 607, 593, 1, 0, 0, 0, 607, 597, 1, 0, 0, 0, 608, 22, 1, 0, 0, 0, 609, 610, 3, 401, 200, 0, 610, 611, 3, 437, 218, 0, 611, 612, 3, 429, 214, 0, 612, 613, 3, 411, 205, 0, 613, 24, 1, 0, 0, 0, 614, 615, 3, 401, 200, 0, 615, 616, 3, 437, 218, 0, 616, 617, 3, 439, 219, 0, 617, 26, 1, 0, 0, 0, 618, 619, 3, 401, 200, 0, 619, 620, 3, 437, 218, 0, 620, 621, 3, 449, 224, 0, 621, 622, 3, 427, 213, 0, 622, 623, 3, 405, 202, 0, 623, 28, 1, 0, 0, 0, 624, 625, 3, 401, 200, 0, 625, 626, 3, 439, 219, 0, 626, 627, 3, 439, 219, 0, 627, 628, 3, 401, 200, 0, 628, 629, 3, 405, 202, 0, 629, 630, 3, 415, 207, 0, 630, 30, 1, 0, 0, 0, 631, 632, 3, 403, 201, 0, 632, 633, 3, 409, 204, 0, 633, 634, 3, 439, 219, 0, 634, 635, 3, 445, 222, 0, 635, 636, 3, 409, 204, 0, 636, 637, 3, 409, 204, 0, 637, 638, 3, 427, 213, 0, 638, 32, 1, 0, 0, 0, 639, 640, 3, 403, 201, 0, 640, 641, 3, 429, 214, 0, 641, 642, 3, 439, 219, 0, 642, 643, 3, 415, 207, 0, 643, 34, 1, 0, 0, 0, 644, 645, 3, 403, 201, 0, 645, 646, 3, 449, 224, 0, 646, 36, 1, 0, 0, 0, 647, 648, 3, 405, 202, 0, 648, 649, 3, 401, 200, 0, 649, 650, 3, 437, 218, 0, 650, 651, 3, 409, 204, 0, 651, 38, 1, 0, 0, 0, 652, 653, 3, 405, 202, 0, 653, 654, 3, 401, 200, 0, 654, 655, 3, 437, 218, 0, 655, 656, 3, 439, 219, 0, 656, 40, 1, 0, 0, 0, 657, 658, 3, 405, 202, 0, 658, 659, 3, 415, 207, 0, 659, 660, 3, 409, 204, 0, 660, 661, 3, 405, 202, 0, 661, 662, 3, 421, 210, 0, 662, 42, 1, 0, 0, 0, 663, 664, 3, 405, 202, 0, 664, 665, 3, 423, 211, 0, 665, 666, 3, 409, 204, 0, 666, 667, 3, 401, 200, 0, 667, 668, 3, 435, 217, 0, 668, 44, 1, 0, 0, 0, 669, 670, 3, 405, 202, 0, 670, 671, 3, 423, 211, 0, 671, 672, 3, 441, 220, 0, 672, 673, 3, 437, 218, 0, 673, 674, 3, 439, 219, 0, 674, 675, 3, 409, 204, 0, 675, 676, 3, 435, 217, 0, 676, 46, 1, 0, 0, 0, 677, 678, 3, 405, 202, 0, 678, 679, 3, 429, 214, 0, 679, 680, 3, 407, 203, 0, 680, 681, 3, 409, 204, 0, 681, 682, 3, 405, 202, 0, 682, 48, 1, 0, 0, 0, 683, 684, 3, 405, 202, 0, 684, 685, 3, 429, 214, 0, 685, 686, 3, 415, 207, 0, 686, 687, 3, 429, 214, 0, 687, 688, 3, 435, 217, 0, 688, 689, 3, 439, 219, 0, 689, 50, 1, 0, 0, 0, 690, 691, 3, 405, 202, 0, 691, 692, 3, 429, 214, 0, 692, 693, 3, 423, 211, 0, 693, 694, 3, 423, 211, 0, 694, 695, 3, 401, 200, 0, 695, 696, 3, 439, 219, 0, 696, 697, 3, 409, 204, 0, 697, 52, 1, 0, 0, 0, 698, 699, 3, 405, 202, 0, 699, 700, 3, 429, 214, 0, 700, 701, 3, 423, 211, 0, 701, 702, 3, 441, 220, 0, 702, 703, 3, 425, 212, 0, 703, 704, 3, 427, 213, 0, 704, 54, 1, 0, 0, 0, 705, 706, 3, 405, 202, 0, 706, 707, 3, 429, 214, 0, 707, 708, 3, 425, 212, 0, 708, 709, 3, 425, 212, 0, 709, 710, 3, 409, 204, 0, 710, 711, 3, 427, 213, 0, 711, 712, 3, 439, 219, 0, 712, 56, 1, 0, 0, 0, 713, 714, 3, 405, 202, 0, 714, 715, 3, 429, 214, 0, 715, 716, 3, 427, 213, 0, 716, 717, 3, 437, 218, 0, 717, 718, 3, 439, 219, 0, 718, 719, 3, 435, 217, 0, 719, 720, 3, 401, 200, 0, 720, 721, 3, 417, 208, 0, 721, 722, 3, 427, 213, 0, 722, 723, 3, 439, 219, 0, 723, 58, 1, 0, 0, 0, 724, 725, 3, 405, 202, 0, 725, 726, 3, 435, 217, 0, 726, 727, 3, 409, 204, 0, 727, 728, 3, 401, 200, 0, 728, 729, 3, 439, 219, 0, 729, 730, 3, 409, 204, 0, 730, 60, 1, 0, 0, 0, 731, 732, 3, 405, 202, 0, 732, 733, 3, 435, 217, 0, 733, 734, 3, 429, 214, 0, 734, 735, 3, 437, 218, 0, 735, 736, 3, 437, 218, 0, 736, 62, 1, 0, 0, 0, 737, 738, 3, 405, 202, 0, 738, 739, 3, 441, 220, 0, 739, 740, 3, 403, 201, 0, 740, 741, 3, 409, 204, 0, 741, 64, 1, 0, 0, 0, 742, 743, 3, 405, 202, 0, 743, 744, 3, 441, 220, 0, 744, 745, 3, 435, 217, 0, 745, 746, 3, 435, 217, 0, 746, 747, 3, 409, 204, 0, 747, 748, 3, 427, 213, 0, 748, 749, 3, 439, 219, 0, 749, 66, 1, 0, 0, 0, 750, 751, 3, 407, 203, 0, 751, 752, 3, 401, 200, 0, 752, 753, 3, 439, 219, 0, 753, 754, 3, 401, 200, 0, 754, 755, 3, 403, 201, 0, 755, 756, 3, 401, 200, 0, 756, 757, 3, 437, 218, 0, 757, 758, 3, 409, 204, 0, 758, 68, 1, 0, 0, 0, 759, 760, 3, 407, 203, 0, 760, 761, 3, 401, 200, 0, 761, 762, 3, 439, 219, 0, 762, 763, 3, 401, 200, 0, 763, 764, 3, 403, 201, 0, 764, 765, 3, 401, 200, 0, 765, 766, 3, 437, 218, 0, 766, 767, 3, 409, 204, 0, 767, 768, 3, 437, 218, 0, 768, 70, 1, 0, 0, 0, 769, 770, 3, 407, 203, 0, 770, 771, 3, 401, 200, 0, 771, 772, 3, 439, 219, 0, 772, 773, 3, 409, 204, 0, 773, 72, 1, 0, 0, 0, 774, 775, 3, 407, 203, 0, 775, 776, 3, 401, 200, 0, 776, 777, 3, 449, 224, 0, 777, 74, 1, 0, 0, 0, 778, 779, 3, 407, 203, 0, 779, 780, 3, 409, 204, 0, 780, 781, 3, 407, 203, 0, 781, 782, 3, 441, 220, 0, 782, 783, 3, 431, 215, 0, 783, 784, 3, 423, 211, 0, 784, 785, 3, 417, 208, 0, 785, 786, 3, 405, 202, 0, 786, 787, 3, 401, 200, 0, 787, 788, 3, 439, 219, 0, 788, 789, 3, 409, 204, 0, 789, 76, 1, 0, 0, 0, 790, 791, 3, 407, 203, 0, 791, 792, 3, 409, 204, 0, 792, 793, 3, 411, 205, 0, 793, 794, 3, 401, 200, 0, 794, 795, 3, 441, 220, 0, 795, 796, 3, 423, 211, 0, 796, 797, 3, 439, 219, 0, 797, 78, 1, 0, 0, 0, 798, 799, 3, 407, 203, 0, 799, 800, 3, 409, 204, 0, 800, 801, 3, 423, 211, 0, 801, 802, 3, 401, 200, 0, 802, 803, 3, 449, 224, 0, 803, 80, 1, 0, 0, 0, 804, 805, 3, 407, 203, 0, 805, 806, 3, 409, 204, 0, 806, 807, 3, 423, 211, 0, 807, 808, 3, 409, 204, 0, 808, 809, 3, 439, 219, 0, 809, 810, 3, 409, 204, 0, 810, 82, 1, 0, 0, 0, 811, 812, 3, 407, 203, 0, 812, 813, 3, 409, 204, 0, 813, 814, 3, 437, 218, 0, 814, 815, 3, 405, 202, 0, 815, 84, 1, 0, 0, 0, 816, 817, 3, 407, 203, 0, 817, 818, 3, 409, 204, 0, 818, 819, 3, 437, 218, 0, 819, 820, 3, 405, 202, 0, 820, 821, 3, 409, 204, 0, 821, 822, 3, 427, 213, 0, 822, 823, 3, 407, 203, 0, 823, 824, 3, 417, 208, 0, 824, 825, 3, 427, 213, 0, 825, 826, 3, 413, 206, 0, 826, 86, 1, 0, 0, 0, 827, 828, 3, 407, 203, 0, 828, 829, 3, 409, 204, 0, 829, 830, 3, 437, 218, 0, 830, 831, 3, 405, 202, 0, 831, 832, 3, 435, 217, 0, 832, 833, 3, 417, 208, 0, 833, 834, 3, 403, 201, 0, 834, 835, 3, 409, 204, 0, 835, 88, 1, 0, 0, 0, 836, 837, 3, 407, 203, 0, 837, 838, 3, 409, 204, 0, 838, 839, 3, 439, 219, 0, 839, 840, 3, 401, 200, 0, 840, 841, 3, 405, 202, 0, 841, 842, 3, 415, 207, 0, 842, 90, 1, 0, 0, 0, 843, 844, 3, 407, 203, 0, 844, 845, 3, 417, 208, 0, 845, 846, 3, 405, 202, 0, 846, 847, 3, 439, 219, 0, 847, 848, 3, 417, 208, 0, 848, 849, 3, 429, 214, 0, 849, 850, 3, 427, 213, 0, 850, 851, 3, 401, 200, 0, 851, 852, 3, 435, 217, 0, 852, 853, 3, 417, 208, 0, 853, 854, 3, 409, 204, 0, 854, 855, 3, 437, 218, 0, 855, 92, 1, 0, 0, 0, 856, 857, 3, 407, 203, 0, 857, 858, 3, 417, 208, 0, 858, 859, 3, 405, 202, 0, 859, 860, 3, 439, 219, 0, 860, 861, 3, 417, 208, 0, 861, 862, 3, 429, 214, 0, 862, 863, 3, 427, 213, 0, 863, 864, 3, 401, 200, 0, 864, 865, 3, 435, 217, 0, 865, 866, 3, 449, 224, 0, 866, 94, 1, 0, 0, 0, 867, 868, 3, 407, 203, 0, 868, 869, 3, 417, 208, 0, 869, 870, 3, 437, 218, 0, 870, 871, 3, 421, 210, 0, 871, 96, 1, 0, 0, 0, 872, 873, 3, 407, 203, 0, 873, 874, 3, 417, 208, 0, 874, 875, 3, 437, 218, 0, 875, 876, 3, 439, 219, 0, 876, 877, 3, 417, 208, 0, 877, 878, 3, 427, 213, 0, 878, 879, 3, 405, 202, 0, 879, 880, 3, 439, 219, 0, 880, 98, 1, 0, 0, 0, 881, 882, 3, 407, 203, 0, 882, 883, 3, 417, 208, 0, 883, 884, 3, 437, 218, 0, 884, 885, 3, 439, 219, 0, 885, 886, 3, 435, 217, 0, 886, 887, 3, 417, 208, 0, 887, 888, 3, 403, 201, 0, 888, 889, 3, 441, 220, 0, 889, 890, 3, 439, 219, 0, 890, 891, 3, 409, 204, 0, 891, 892, 3, 407, 203, 0, 892, 100, 1, 0, 0, 0, 893, 894, 3, 407, 203, 0, 894, 895, 3, 435, 217, 0, 895, 896, 3, 429, 214, 0, 896, 897, 3, 431, 215, 0, 897, 102, 1, 0, 0, 0, 898, 899, 3, 409, 204, 0, 899, 900, 3, 423, 211, 0, 900, 901, 3, 437, 218, 0, 901, 902, 3, 409, 204, 0, 902, 104, 1, 0, 0, 0, 903, 904, 3, 409, 204, 0, 904, 905, 3, 427, 213, 0, 905, 906, 3, 407, 203, 0, 906, 106, 1, 0, 0, 0, 907, 908, 3, 409, 204, 0, 908, 909, 3, 427, 213, 0, 909, 910, 3, 413, 206, 0, 910, 911, 3, 417, 208, 0, 911, 912, 3, 427, 213, 0, 912, 913, 3, 409, 204, 0, 913, 108, 1, 0, 0, 0, 914, 915, 3, 409, 204, 0, 915, 916, 3, 443, 221, 0, 916, 917, 3, 409, 204, 0, 917, 918, 3, 427, 213, 0, 918, 919, 3, 439, 219, 0, 919, 920, 3, 437, 218, 0, 920, 110, 1, 0, 0, 0, 921, 922, 3, 409, 204, 0, 922, 923, 3, 447, 223, 0, 923, 924, 3, 417, 208, 0, 924, 925, 3, 437, 218, 0, 925, 926, 3, 439, 219, 0, 926, 927, 3, 437, 218, 0, 927, 112, 1, 0, 0, 0, 928, 929, 3, 409, 204, 0, 929, 930, 3, 447, 223, 0, 930, 931, 3, 431, 215, 0, 931, 932, 3, 423, 211, 0, 932, 933, 3, 401, 200, 0, 933, 934, 3, 417, 208, 0, 934, 935, 3, 427, 213, 0, 935, 114, 1, 0, 0, 0, 936, 937, 3, 409, 204, 0, 937, 938, 3, 447, 223, 0, 938, 939, 3, 431, 215, 0, 939, 940, 3, 435, 217, 0, 940, 941, 3, 409, 204, 0, 941, 942, 3, 437, 218, 0, 942, 943, 3, 437, 218, 0, 943, 944, 3, 417, 208, 0, 944, 945, 3, 429, 214, 0, 945, 946, 3, 427, 213, 0, 946, 116, 1, 0, 0, 0, 947, 948, 3, 409, 204, 0, 948, 949, 3, 447, 223, 0, 949, 950, 3, 439, 219, 0, 950, 951, 3, 435, 217, 0, 951, 952, 3, 401, 200, 0, 952, 953, 3, 405, 202, 0, 953, 954, 3, 439, 219, 0, 954, 118, 1, 0, 0, 0, 955, 956, 3, 411, 205, 0, 956, 957, 3, 409, 204, 0, 957, 958, 3, 439, 219, 0, 958, 959, 3, 405, 202, 0, 959, 960, 3, 415, 207, 0, 960, 961, 3, 409, 204, 0, 961, 962, 3, 437, 218, 0, 962, 120, 1, 0, 0, 0, 963, 964, 3, 411, 205, 0, 964, 965, 3, 417, 208, 0, 965, 966, 3, 427, 213, 0, 966, 967, 3, 401, 200, 0, 967, 968, 3, 423, 211, 0, 968, 122, 1, 0, 0, 0, 969, 970, 3, 411, 205, 0, 970, 971, 3, 417, 208, 0, 971, 972, 3, 435, 217, 0, 972, 973, 3, 437, 218, 0, 973, 974, 3, 439, 219, 0, 974, 124, 1, 0, 0, 0, 975, 976, 3, 411, 205, 0, 976, 977, 3, 423, 211, 0, 977, 978, 3, 441, 220, 0, 978, 979, 3, 437, 218, 0, 979, 980, 3, 415, 207, 0, 980, 126, 1, 0, 0, 0, 981, 982, 3, 411, 205, 0, 982, 983, 3, 429, 214, 0, 983, 984, 3, 423, 211, 0, 984, 985, 3, 423, 211, 0, 985, 986, 3, 429, 214, 0, 986, 987, 3, 445, 222, 0, 987, 988, 3, 417, 208, 0, 988, 989, 3, 427, 213, 0, 989, 990, 3, 413, 206, 0, 990, 128, 1, 0, 0, 0, 991, 992, 3, 411, 205, 0, 992, 993, 3, 429, 214, 0, 993, 994, 3, 435, 217, 0, 994, 130, 1, 0, 0, 0, 995, 996, 3, 411, 205, 0, 996, 997, 3, 429, 214, 0, 997, 998, 3, 435, 217, 0, 998, 999, 3, 425, 212, 0, 999, 1000, 3, 401, 200, 0, 1000, 1001, 3, 439, 219, 0, 1001, 132, 1, 0, 0, 0, 1002, 1003, 3, 411, 205, 0, 1003, 1004, 3, 435, 217, 0, 1004, 1005, 3, 409, 204, 0, 1005, 1006, 3, 409, 204, 0, 1006, 1007, 3, 451, 225, 0, 1007, 1008, 3, 409, 204, 0, 1008, 134, 1, 0, 0, 0, 1009, 1010, 3, 411, 205, 0, 1010, 1011, 3, 435, 217, 0, 1011, 1012, 3, 429, 214, 0, 1012, 1013, 3, 425, 212, 0, 1013, 136, 1, 0, 0, 0, 1014, 1015, 3, 411, 205, 0, 1015, 1016, 3, 441, 220, 0, 1016, 1017, 3, 423, 211, 0, 1017, 1018, 3, 423, 211, 0, 1018, 138, 1, 0, 0, 0, 1019, 1020, 3, 411, 205, 0, 1020, 1021, 3, 441, 220, 0, 1021, 1022, 3, 427, 213, 0, 1022, 1023, 3, 405, 202, 0, 1023, 1024, 3, 439, 219, 0, 1024, 1025, 3, 417, 208, 0, 1025, 1026, 3, 429, 214, 0, 1026, 1027, 3, 427, 213, 0, 1027, 140, 1, 0, 0, 0, 1028, 1029, 3, 413, 206, 0, 1029, 1030, 3, 423, 211, 0, 1030, 1031, 3, 429, 214, 0, 1031, 1032, 3, 403, 201, 0, 1032, 1033, 3, 401, 200, 0, 1033, 1034, 3, 423, 211, 0, 1034, 142, 1, 0, 0, 0, 1035, 1036, 3, 413, 206, 0, 1036, 1037, 3, 435, 217, 0, 1037, 1038, 3, 401, 200, 0, 1038, 1039, 3, 427, 213, 0, 1039, 1040, 3, 441, 220, 0, 1040, 1041, 3, 423, 211, 0, 1041, 1042, 3, 401, 200, 0, 1042, 1043, 3, 435, 217, 0, 1043, 1044, 3, 417, 208, 0, 1044, 1045, 3, 439, 219, 0, 1045, 1046, 3, 449, 224, 0, 1046, 144, 1, 0, 0, 0, 1047, 1048, 3, 413, 206, 0, 1048, 1049, 3, 435, 217, 0, 1049, 1050, 3, 429, 214, 0, 1050, 1051, 3, 441, 220, 0, 1051, 1052, 3, 431, 215, 0, 1052, 146, 1, 0, 0, 0, 1053, 1054, 3, 415, 207, 0, 1054, 1055, 3, 401, 200, 0, 1055, 1056, 3, 443, 221, 0, 1056, 1057, 3, 417, 208, 0, 1057, 1058, 3, 427, 213, 0, 1058, 1059, 3, 413, 206, 0, 1059, 148, 1, 0, 0, 0, 1060, 1061, 3, 415, 207, 0, 1061, 1062, 3, 417, 208, 0, 1062, 1063, 3, 409, 204, 0, 1063, 1064, 3, 435, 217, 0, 1064, 1065, 3, 401, 200, 0, 1065, 1066, 3, 435, 217, 0, 1066, 1067, 3, 405, 202, 0, 1067, 1068, 3, 415, 207, 0, 1068, 1069, 3, 417, 208, 0, 1069, 1070, 3, 405, 202, 0, 1070, 1071, 3, 401, 200, 0, 1071, 1072, 3, 423, 211, 0, 1072, 150, 1, 0, 0, 0, 1073, 1074, 3, 415, 207, 0, 1074, 1075, 3, 429, 214, 0, 1075, 1076, 3, 441, 220, 0, 1076, 1077, 3, 435, 217, 0, 1077, 152, 1, 0, 0, 0, 1078, 1079, 3, 417, 208, 0, 1079, 1080, 3, 407, 203, 0, 1080, 154, 1, 0, 0, 0, 1081, 1082, 3, 417, 208, 0, 1082, 1083, 3, 411, 205, 0, 1083, 156, 1, 0, 0, 0, 1084, 1085, 3, 417, 208, 0, 1085, 1086, 3, 423, 211, 0, 1086, 1087, 3, 417, 208, 0, 1087, 1088, 3, 421, 210, 0, 1088, 1089, 3, 409, 204, 0, 1089, 158, 1, 0, 0, 0, 1090, 1091, 3, 417, 208, 0, 1091, 1092, 3, 427, 213, 0, 1092, 160, 1, 0, 0, 0, 1093, 1094, 3, 417, 208, 0, 1094, 1095, 3, 427, 213, 0, 1095, 1096, 3, 407, 203, 0, 1096, 1097, 3, 409, 204, 0, 1097, 1098, 3, 447, 223, 0, 1098, 162, 1, 0, 0, 0, 1099, 1100, 3, 417, 208, 0, 1100, 1101, 3, 427, 213, 0, 1101, 1102, 3, 411, 205, 0, 1102, 1113, 1, 0, 0, 0, 1103, 1104, 3, 417, 208, 0, 1104, 1105, 3, 427, 213, 0, 1105, 1106, 3, 411, 205, 0, 1106, 1107, 3, 417, 208, 0, 1107, 1108, 3, 427, 213, 0, 1108, 1109, 3, 417, 208, 0, 1109, 1110, 3, 439, 219, 0, 1110, 1111, 3, 449, 224, 0, 1111, 1113, 1, 0, 0, 0, 1112, 1099, 1, 0, 0, 0, 1112, 1103, 1, 0, 0, 0, 1113, 164, 1, 0, 0, 0, 1114, 1115, 3, 417, 208, 0, 1115, 1116, 3, 427, 213, 0, 1116, 1117, 3, 419, 209, 0, 1117, 1118, 3, 409, 204, 0, 1118, 1119, 3, 405, 202, 0, 1119, 1120, 3, 439, 219, 0, 1120, 1121, 3, 417, 208, 0, 1121, 1122, 3, 443, 221, 0, 1122, 1123, 3, 409, 204, 0, 1123, 166, 1, 0, 0, 0, 1124, 1125, 3, 417, 208, 0, 1125, 1126, 3, 427, 213, 0, 1126, 1127, 3, 427, 213, 0, 1127, 1128, 3, 409, 204, 0, 1128, 1129, 3, 435, 217, 0, 1129, 168, 1, 0, 0, 0, 1130, 1131, 3, 417, 208, 0, 1131, 1132, 3, 427, 213, 0, 1132, 1133, 3, 437, 218, 0, 1133, 1134, 3, 409, 204, 0, 1134, 1135, 3, 435, 217, 0, 1135, 1136, 3, 439, 219, 0, 1136, 170, 1, 0, 0, 0, 1137, 1138, 3, 417, 208, 0, 1138, 1139, 3, 427, 213, 0, 1139, 1140, 3, 439, 219, 0, 1140, 1141, 3, 409, 204, 0, 1141, 1142, 3, 435, 217, 0, 1142, 1143, 3, 443, 221, 0, 1143, 1144, 3, 401, 200, 0, 1144, 1145, 3, 423, 211, 0, 1145, 172, 1, 0, 0, 0, 1146, 1147, 3, 417, 208, 0, 1147, 1148, 3, 427, 213, 0, 1148, 1149, 3, 439, 219, 0, 1149, 1150, 3, 429, 214, 0, 1150, 174, 1, 0, 0, 0, 1151, 1152, 3, 417, 208, 0, 1152, 1153, 3, 437, 218, 0, 1153, 176, 1, 0, 0, 0, 1154, 1155, 3, 417, 208, 0, 1155, 1156, 3, 437, 218, 0, 1156, 1157, 3, 537, 268, 0, 1157, 1158, 3, 429, 214, 0, 1158, 1159, 3, 403, 201, 0, 1159, 1160, 3, 419, 209, 0, 1160, 1161, 3, 409, 204, 0, 1161, 1162, 3, 405, 202, 0, 1162, 1163, 3, 439, 219, 0, 1163, 1164, 3, 537, 268, 0, 1164, 1165, 3, 417, 208, 0, 1165, 1166, 3, 407, 203, 0, 1166, 178, 1, 0, 0, 0, 1167, 1168, 3, 419, 209, 0, 1168, 1169, 3, 429, 214, 0, 1169, 1170, 3, 417, 208, 0, 1170, 1171, 3, 427, 213, 0, 1171, 180, 1, 0, 0, 0, 1172, 1173, 3, 421, 210, 0, 1173, 1174, 3, 409, 204, 0, 1174, 1175, 3, 449, 224, 0, 1175, 182, 1, 0, 0, 0, 1176, 1177, 3, 421, 210, 0, 1177, 1178, 3, 417, 208, 0, 1178, 1179, 3, 423, 211, 0, 1179, 1180, 3, 423, 211, 0, 1180, 184, 1, 0, 0, 0, 1181, 1182, 3, 423, 211, 0, 1182, 1183, 3, 401, 200, 0, 1183, 1184, 3, 437, 218, 0, 1184, 1185, 3, 439, 219, 0, 1185, 186, 1, 0, 0, 0, 1186, 1187, 3, 423, 211, 0, 1187, 1188, 3, 401, 200, 0, 1188, 1189, 3, 449, 224, 0, 1189, 1190, 3, 429, 214, 0, 1190, 1191, 3, 441, 220, 0, 1191, 1192, 3, 439, 219, 0, 1192, 188, 1, 0, 0, 0, 1193, 1194, 3, 423, 211, 0, 1194, 1195, 3, 409, 204, 0, 1195, 1196, 3, 401, 200, 0, 1196, 1197, 3, 407, 203, 0, 1197, 1198, 3, 417, 208, 0, 1198, 1199, 3, 427, 213, 0, 1199, 1200, 3, 413, 206, 0, 1200, 190, 1, 0, 0, 0, 1201, 1202, 3, 423, 211, 0, 1202, 1203, 3, 409, 204, 0, 1203, 1204, 3, 411, 205, 0, 1204, 1205, 3, 439, 219, 0, 1205, 192, 1, 0, 0, 0, 1206, 1207, 3, 423, 211, 0, 1207, 1208, 3, 417, 208, 0, 1208, 1209, 3, 411, 205, 0, 1209, 1210, 3, 409, 204, 0, 1210, 1211, 3, 439, 219, 0, 1211, 1212, 3, 417, 208, 0, 1212, 1213, 3, 425, 212, 0, 1213, 1214, 3, 409, 204, 0, 1214, 194, 1, 0, 0, 0, 1215, 1216, 3, 423, 211, 0, 1216, 1217, 3, 417, 208, 0, 1217, 1218, 3, 421, 210, 0, 1218, 1219, 3, 409, 204, 0, 1219, 196, 1, 0, 0, 0, 1220, 1221, 3, 423, 211, 0, 1221, 1222, 3, 417, 208, 0, 1222, 1223, 3, 425, 212, 0, 1223, 1224, 3, 417, 208, 0, 1224, 1225, 3, 439, 219, 0, 1225, 198, 1, 0, 0, 0, 1226, 1227, 3, 423, 211, 0, 1227, 1228, 3, 417, 208, 0, 1228, 1229, 3, 443, 221, 0, 1229, 1230, 3, 409, 204, 0, 1230, 200, 1, 0, 0, 0, 1231, 1232, 3, 423, 211, 0, 1232, 1233, 3, 429, 214, 0, 1233, 1234, 3, 405, 202, 0, 1234, 1235, 3, 401, 200, 0, 1235, 1236, 3, 423, 211, 0, 1236, 202, 1, 0, 0, 0, 1237, 1238, 3, 423, 211, 0, 1238, 1239, 3, 429, 214, 0, 1239, 1240, 3, 413, 206, 0, 1240, 1241, 3, 437, 218, 0, 1241, 204, 1, 0, 0, 0, 1242, 1243, 3, 425, 212, 0, 1243, 1244, 3, 401, 200, 0, 1244, 1245, 3, 439, 219, 0, 1245, 1246, 3, 409, 204, 0, 1246, 1247, 3, 435, 217, 0, 1247, 1248, 3, 417, 208, 0, 1248, 1249, 3, 401, 200, 0, 1249, 1250, 3, 423, 211, 0, 1250, 1251, 3, 417, 208, 0, 1251, 1252, 3, 451, 225, 0, 1252, 1253, 3, 409, 204, 0, 1253, 206, 1, 0, 0, 0, 1254, 1255, 3, 425, 212, 0, 1255, 1256, 3, 401, 200, 0, 1256, 1257, 3, 439, 219, 0, 1257, 1258, 3, 409, 204, 0, 1258, 1259, 3, 435, 217, 0, 1259, 1260, 3, 417, 208, 0, 1260, 1261, 3, 401, 200, 0, 1261, 1262, 3, 423, 211, 0, 1262, 1263, 3, 417, 208, 0, 1263, 1264, 3, 451, 225, 0, 1264, 1265, 3, 409, 204, 0, 1265, 1266, 3, 407, 203, 0, 1266, 208, 1, 0, 0, 0, 1267, 1268, 3, 425, 212, 0, 1268, 1269, 3, 401, 200, 0, 1269, 1270, 3, 447, 223, 0, 1270, 210, 1, 0, 0, 0, 1271, 1272, 3, 425, 212, 0, 1272, 1273, 3, 409, 204, 0, 1273, 1274, 3, 435, 217, 0, 1274, 1275, 3, 413, 206, 0, 1275, 1276, 3, 409, 204, 0, 1276, 1277, 3, 437, 218, 0, 1277, 212, 1, 0, 0, 0, 1278, 1279, 3, 425, 212, 0, 1279, 1280, 3, 417, 208, 0, 1280, 1281, 3, 427, 213, 0, 1281, 214, 1, 0, 0, 0, 1282, 1283, 3, 425, 212, 0, 1283, 1284, 3, 417, 208, 0, 1284, 1285, 3, 427, 213, 0, 1285, 1286, 3, 441, 220, 0, 1286, 1287, 3, 439, 219, 0, 1287, 1288, 3, 409, 204, 0, 1288, 216, 1, 0, 0, 0, 1289, 1290, 3, 425, 212, 0, 1290, 1291, 3, 429, 214, 0, 1291, 1292, 3, 407, 203, 0, 1292, 1293, 3, 417, 208, 0, 1293, 1294, 3, 411, 205, 0, 1294, 1295, 3, 449, 224, 0, 1295, 218, 1, 0, 0, 0, 1296, 1297, 3, 425, 212, 0, 1297, 1298, 3, 429, 214, 0, 1298, 1299, 3, 427, 213, 0, 1299, 1300, 3, 439, 219, 0, 1300, 1301, 3, 415, 207, 0, 1301, 220, 1, 0, 0, 0, 1302, 1303, 3, 425, 212, 0, 1303, 1304, 3, 429, 214, 0, 1304, 1305, 3, 443, 221, 0, 1305, 1306, 3, 409, 204, 0, 1306, 222, 1, 0, 0, 0, 1307, 1308, 3, 425, 212, 0, 1308, 1309, 3, 441, 220, 0, 1309, 1310, 3, 439, 219, 0, 1310, 1311, 3, 401, 200, 0, 1311, 1312, 3, 439, 219, 0, 1312, 1313, 3, 417, 208, 0, 1313, 1314, 3, 429, 214, 0, 1314, 1315, 3, 427, 213, 0, 1315, 224, 1, 0, 0, 0, 1316, 1317, 3, 427, 213, 0, 1317, 1318, 3, 401, 200, 0, 1318, 1319, 3, 427, 213, 0, 1319, 226, 1, 0, 0, 0, 1320, 1321, 3, 427, 213, 0, 1321, 1322, 3, 429, 214, 0, 1322, 228, 1, 0, 0, 0, 1323, 1324, 3, 427, 213, 0, 1324, 1325, 3, 429, 214, 0, 1325, 1326, 3, 439, 219, 0, 1326, 230, 1, 0, 0, 0, 1327, 1328, 3, 427, 213, 0, 1328, 1329, 3, 441, 220, 0, 1329, 1330, 3, 423, 211, 0, 1330, 1331, 3, 423, 211, 0, 1331, 232, 1, 0, 0, 0, 1332, 1333, 3, 427, 213, 0, 1333, 1334, 3, 441, 220, 0, 1334, 1335, 3, 423, 211, 0, 1335, 1336, 3, 423, 211, 0, 1336, 1337, 3, 437, 218, 0, 1337, 234, 1, 0, 0, 0, 1338, 1339, 3, 429, 214, 0, 1339, 1340, 3, 411, 205, 0, 1340, 1341, 3, 411, 205, 0, 1341, 1342, 3, 437, 218, 0, 1342, 1343, 3, 409, 204, 0, 1343, 1344, 3, 439, 219, 0, 1344, 236, 1, 0, 0, 0, 1345, 1346, 3, 429, 214, 0, 1346, 1347, 3, 427, 213, 0, 1347, 238, 1, 0, 0, 0, 1348, 1349, 3, 429, 214, 0, 1349, 1350, 3, 431, 215, 0, 1350, 1351, 3, 439, 219, 0, 1351, 1352, 3, 417, 208, 0, 1352, 1353, 3, 425, 212, 0, 1353, 1354, 3, 417, 208, 0, 1354, 1355, 3, 451, 225, 0, 1355, 1356, 3, 409, 204, 0, 1356, 240, 1, 0, 0, 0, 1357, 1358, 3, 429, 214, 0, 1358, 1359, 3, 435, 217, 0, 1359, 242, 1, 0, 0, 0, 1360, 1361, 3, 429, 214, 0, 1361, 1362, 3, 435, 217, 0, 1362, 1363, 3, 407, 203, 0, 1363, 1364, 3, 409, 204, 0, 1364, 1365, 3, 435, 217, 0, 1365, 244, 1, 0, 0, 0, 1366, 1367, 3, 429, 214, 0, 1367, 1368, 3, 441, 220, 0, 1368, 1369, 3, 439, 219, 0, 1369, 1370, 3, 409, 204, 0, 1370, 1371, 3, 435, 217, 0, 1371, 246, 1, 0, 0, 0, 1372, 1373, 3, 429, 214, 0, 1373, 1374, 3, 441, 220, 0, 1374, 1375, 3, 439, 219, 0, 1375, 1376, 3, 411, 205, 0, 1376, 1377, 3, 417, 208, 0, 1377, 1378, 3, 423, 211, 0, 1378, 1379, 3, 409, 204, 0, 1379, 248, 1, 0, 0, 0, 1380, 1381, 3, 429, 214, 0, 1381, 1382, 3, 443, 221, 0, 1382, 1383, 3, 409, 204, 0, 1383, 1384, 3, 435, 217, 0, 1384, 250, 1, 0, 0, 0, 1385, 1386, 3, 431, 215, 0, 1386, 1387, 3, 401, 200, 0, 1387, 1388, 3, 435, 217, 0, 1388, 1389, 3, 439, 219, 0, 1389, 1390, 3, 417, 208, 0, 1390, 1391, 3, 439, 219, 0, 1391, 1392, 3, 417, 208, 0, 1392, 1393, 3, 429, 214, 0, 1393, 1394, 3, 427, 213, 0, 1394, 252, 1, 0, 0, 0, 1395, 1396, 3, 431, 215, 0, 1396, 1397, 3, 429, 214, 0, 1397, 1398, 3, 431, 215, 0, 1398, 1399, 3, 441, 220, 0, 1399, 1400, 3, 423, 211, 0, 1400, 1401, 3, 401, 200, 0, 1401, 1402, 3, 439, 219, 0, 1402, 1403, 3, 409, 204, 0, 1403, 254, 1, 0, 0, 0, 1404, 1405, 3, 431, 215, 0, 1405, 1406, 3, 435, 217, 0, 1406, 1407, 3, 409, 204, 0, 1407, 1408, 3, 405, 202, 0, 1408, 1409, 3, 409, 204, 0, 1409, 1410, 3, 407, 203, 0, 1410, 1411, 3, 417, 208, 0, 1411, 1412, 3, 427, 213, 0, 1412, 1413, 3, 413, 206, 0, 1413, 256, 1, 0, 0, 0, 1414, 1415, 3, 431, 215, 0, 1415, 1416, 3, 435, 217, 0, 1416, 1417, 3, 409, 204, 0, 1417, 1418, 3, 445, 222, 0, 1418, 1419, 3, 415, 207, 0, 1419, 1420, 3, 409, 204, 0, 1420, 1421, 3, 435, 217, 0, 1421, 1422, 3, 409, 204, 0, 1422, 258, 1, 0, 0, 0, 1423, 1424, 3, 431, 215, 0, 1424, 1425, 3, 435, 217, 0, 1425, 1426, 3, 417, 208, 0, 1426, 1427, 3, 425, 212, 0, 1427, 1428, 3, 401, 200, 0, 1428, 1429, 3, 435, 217, 0, 1429, 1430, 3, 449, 224, 0, 1430, 260, 1, 0, 0, 0, 1431, 1432, 3, 431, 215, 0, 1432, 1433, 3, 435, 217, 0, 1433, 1434, 3, 429, 214, 0, 1434, 1435, 3, 419, 209, 0, 1435, 1436, 3, 409, 204, 0, 1436, 1437, 3, 405, 202, 0, 1437, 1438, 3, 439, 219, 0, 1438, 1439, 3, 417, 208, 0, 1439, 1440, 3, 429, 214, 0, 1440, 1441, 3, 427, 213, 0, 1441, 262, 1, 0, 0, 0, 1442, 1443, 3, 433, 216, 0, 1443, 1444, 3, 441, 220, 0, 1444, 1445, 3, 401, 200, 0, 1445, 1446, 3, 435, 217, 0, 1446, 1447, 3, 439, 219, 0, 1447, 1448, 3, 409, 204, 0, 1448, 1449, 3, 435, 217, 0, 1449, 264, 1, 0, 0, 0, 1450, 1451, 3, 435, 217, 0, 1451, 1452, 3, 401, 200, 0, 1452, 1453, 3, 427, 213, 0, 1453, 1454, 3, 413, 206, 0, 1454, 1455, 3, 409, 204, 0, 1455, 266, 1, 0, 0, 0, 1456, 1457, 3, 435, 217, 0, 1457, 1458, 3, 409, 204, 0, 1458, 1459, 3, 423, 211, 0, 1459, 1460, 3, 429, 214, 0, 1460, 1461, 3, 401, 200, 0, 1461, 1462, 3, 407, 203, 0, 1462, 268, 1, 0, 0, 0, 1463, 1464, 3, 435, 217, 0, 1464, 1465, 3, 409, 204, 0, 1465, 1466, 3, 425, 212, 0, 1466, 1467, 3, 429, 214, 0, 1467, 1468, 3, 443, 221, 0, 1468, 1469, 3, 409, 204, 0, 1469, 270, 1, 0, 0, 0, 1470, 1471, 3, 435, 217, 0, 1471, 1472, 3, 409, 204, 0, 1472, 1473, 3, 427, 213, 0, 1473, 1474, 3, 401, 200, 0, 1474, 1475, 3, 425, 212, 0, 1475, 1476, 3, 409, 204, 0, 1476, 272, 1, 0, 0, 0, 1477, 1478, 3, 435, 217, 0, 1478, 1479, 3, 409, 204, 0, 1479, 1480, 3, 431, 215, 0, 1480, 1481, 3, 423, 211, 0, 1481, 1482, 3, 401, 200, 0, 1482, 1483, 3, 405, 202, 0, 1483, 1484, 3, 409, 204, 0, 1484, 274, 1, 0, 0, 0, 1485, 1486, 3, 435, 217, 0, 1486, 1487, 3, 409, 204, 0, 1487, 1488, 3, 431, 215, 0, 1488, 1489, 3, 423, 211, 0, 1489, 1490, 3, 417, 208, 0, 1490, 1491, 3, 405, 202, 0, 1491, 1492, 3, 401, 200, 0, 1492, 276, 1, 0, 0, 0, 1493, 1494, 3, 435, 217, 0, 1494, 1495, 3, 409, 204, 0, 1495, 1496, 3, 431, 215, 0, 1496, 1497, 3, 423, 211, 0, 1497, 1498, 3, 417, 208, 0, 1498, 1499, 3, 405, 202, 0, 1499, 1500, 3, 401, 200, 0, 1500, 1501, 3, 439, 219, 0, 1501, 1502, 3, 409, 204, 0, 1502, 1503, 3, 407, 203, 0, 1503, 278, 1, 0, 0, 0, 1504, 1505, 3, 435, 217, 0, 1505, 1506, 3, 417, 208, 0, 1506, 1507, 3, 413, 206, 0, 1507, 1508, 3, 415, 207, 0, 1508, 1509, 3, 439, 219, 0, 1509, 280, 1, 0, 0, 0, 1510, 1511, 3, 435, 217, 0, 1511, 1512, 3, 429, 214, 0, 1512, 1513, 3, 423, 211, 0, 1513, 1514, 3, 423, 211, 0, 1514, 1515, 3, 441, 220, 0, 1515, 1516, 3, 431, 215, 0, 1516, 282, 1, 0, 0, 0, 1517, 1518, 3, 435, 217, 0, 1518, 1519, 3, 429, 214, 0, 1519, 1520, 3, 445, 222, 0, 1520, 284, 1, 0, 0, 0, 1521, 1522, 3, 435, 217, 0, 1522, 1523, 3, 429, 214, 0, 1523, 1524, 3, 445, 222, 0, 1524, 1525, 3, 437, 218, 0, 1525, 286, 1, 0, 0, 0, 1526, 1527, 3, 437, 218, 0, 1527, 1528, 3, 401, 200, 0, 1528, 1529, 3, 425, 212, 0, 1529, 1530, 3, 431, 215, 0, 1530, 1531, 3, 423, 211, 0, 1531, 1532, 3, 409, 204, 0, 1532, 288, 1, 0, 0, 0, 1533, 1534, 3, 437, 218, 0, 1534, 1535, 3, 409, 204, 0, 1535, 1536, 3, 405, 202, 0, 1536, 1537, 3, 429, 214, 0, 1537, 1538, 3, 427, 213, 0, 1538, 1539, 3, 407, 203, 0, 1539, 290, 1, 0, 0, 0, 1540, 1541, 3, 437, 218, 0, 1541, 1542, 3, 409, 204, 0, 1542, 1543, 3, 423, 211, 0, 1543, 1544, 3, 409, 204, 0, 1544, 1545, 3, 405, 202, 0, 1545, 1546, 3, 439, 219, 0, 1546, 292, 1, 0, 0, 0, 1547, 1548, 3, 437, 218, 0, 1548, 1549, 3, 409, 204, 0, 1549, 1550, 3, 425, 212, 0, 1550, 1551, 3, 417, 208, 0, 1551, 294, 1, 0, 0, 0, 1552, 1553, 3, 437, 218, 0, 1553, 1554, 3, 409, 204, 0, 1554, 1555, 3, 427, 213, 0, 1555, 1556, 3, 407, 203, 0, 1556, 1557, 3, 437, 218, 0, 1557, 296, 1, 0, 0, 0, 1558, 1559, 3, 437, 218, 0, 1559, 1560, 3, 409, 204, 0, 1560, 1561, 3, 439, 219, 0, 1561, 298, 1, 0, 0, 0, 1562, 1563, 3, 437, 218, 0, 1563, 1564, 3, 409, 204, 0, 1564, 1565, 3, 439, 219, 0, 1565, 1566, 3, 439, 219, 0, 1566, 1567, 3, 417, 208, 0, 1567, 1568, 3, 427, 213, 0, 1568, 1569, 3, 413, 206, 0, 1569, 1570, 3, 437, 218, 0, 1570, 300, 1, 0, 0, 0, 1571, 1572, 3, 437, 218, 0, 1572, 1573, 3, 415, 207, 0, 1573, 1574, 3, 429, 214, 0, 1574, 1575, 3, 445, 222, 0, 1575, 302, 1, 0, 0, 0, 1576, 1577, 3, 437, 218, 0, 1577, 1578, 3, 429, 214, 0, 1578, 1579, 3, 441, 220, 0, 1579, 1580, 3, 435, 217, 0, 1580, 1581, 3, 405, 202, 0, 1581, 1582, 3, 409, 204, 0, 1582, 304, 1, 0, 0, 0, 1583, 1584, 3, 437, 218, 0, 1584, 1585, 3, 439, 219, 0, 1585, 1586, 3, 401, 200, 0, 1586, 1587, 3, 435, 217, 0, 1587, 1588, 3, 439, 219, 0, 1588, 306, 1, 0, 0, 0, 1589, 1590, 3, 437, 218, 0, 1590, 1591, 3, 439, 219, 0, 1591, 1592, 3, 429, 214, 0, 1592, 1593, 3, 431, 215, 0, 1593, 308, 1, 0, 0, 0, 1594, 1595, 3, 437, 218, 0, 1595, 1596, 3, 441, 220, 0, 1596, 1597, 3, 403, 201, 0, 1597, 1598, 3, 437, 218, 0, 1598, 1599, 3, 439, 219, 0, 1599, 1600, 3, 435, 217, 0, 1600, 1601, 3, 417, 208, 0, 1601, 1602, 3, 427, 213, 0, 1602, 1603, 3, 413, 206, 0, 1603, 310, 1, 0, 0, 0, 1604, 1605, 3, 437, 218, 0, 1605, 1606, 3, 449, 224, 0, 1606, 1607, 3, 427, 213, 0, 1607, 1608, 3, 405, 202, 0, 1608, 312, 1, 0, 0, 0, 1609, 1610, 3, 437, 218, 0, 1610, 1611, 3, 449, 224, 0, 1611, 1612, 3, 427, 213, 0, 1612, 1613, 3, 439, 219, 0, 1613, 1614, 3, 401, 200, 0, 1614, 1615, 3, 447, 223, 0, 1615, 314, 1, 0, 0, 0, 1616, 1617, 3, 437, 218, 0, 1617, 1618, 3, 449, 224, 0, 1618, 1619, 3, 437, 218, 0, 1619, 1620, 3, 439, 219, 0, 1620, 1621, 3, 409, 204, 0, 1621, 1622, 3, 425, 212, 0, 1622, 316, 1, 0, 0, 0, 1623, 1624, 3, 439, 219, 0, 1624, 1625, 3, 401, 200, 0, 1625, 1626, 3, 403, 201, 0, 1626, 1627, 3, 423, 211, 0, 1627, 1628, 3, 409, 204, 0, 1628, 318, 1, 0, 0, 0, 1629, 1630, 3, 439, 219, 0, 1630, 1631, 3, 401, 200, 0, 1631, 1632, 3, 403, 201, 0, 1632, 1633, 3, 423, 211, 0, 1633, 1634, 3, 409, 204, 0, 1634, 1635, 3, 437, 218, 0, 1635, 320, 1, 0, 0, 0, 1636, 1637, 3, 439, 219, 0, 1637, 1638, 3, 409, 204, 0, 1638, 1639, 3, 425, 212, 0, 1639, 1640, 3, 431, 215, 0, 1640, 1641, 3, 429, 214, 0, 1641, 1642, 3, 435, 217, 0, 1642, 1643, 3, 401, 200, 0, 1643, 1644, 3, 435, 217, 0, 1644, 1645, 3, 449, 224, 0, 1645, 322, 1, 0, 0, 0, 1646, 1647, 3, 439, 219, 0, 1647, 1648, 3, 409, 204, 0, 1648, 1649, 3, 437, 218, 0, 1649, 1650, 3, 439, 219, 0, 1650, 324, 1, 0, 0, 0, 1651, 1652, 3, 439, 219, 0, 1652, 1653, 3, 415, 207, 0, 1653, 1654, 3, 409, 204, 0, 1654, 1655, 3, 427, 213, 0, 1655, 326, 1, 0, 0, 0, 1656, 1657, 3, 439, 219, 0, 1657, 1658, 3, 417, 208, 0, 1658, 1659, 3, 409, 204, 0, 1659, 1660, 3, 437, 218, 0, 1660, 328, 1, 0, 0, 0, 1661, 1662, 3, 439, 219, 0, 1662, 1663, 3, 417, 208, 0, 1663, 1664, 3, 425, 212, 0, 1664, 1665, 3, 409, 204, 0, 1665, 1666, 3, 429, 214, 0, 1666, 1667, 3, 441, 220, 0, 1667, 1668, 3, 439, 219, 0, 1668, 330, 1, 0, 0, 0, 1669, 1670, 3, 439, 219, 0, 1670, 1671, 3, 417, 208, 0, 1671, 1672, 3, 425, 212, 0, 1672, 1673, 3, 409, 204, 0, 1673, 1674, 3, 437, 218, 0, 1674, 1675, 3, 439, 219, 0, 1675, 1676, 3, 401, 200, 0, 1676, 1677, 3, 425, 212, 0, 1677, 1678, 3, 431, 215, 0, 1678, 332, 1, 0, 0, 0, 1679, 1680, 3, 439, 219, 0, 1680, 1681, 3, 429, 214, 0, 1681, 334, 1, 0, 0, 0, 1682, 1683, 3, 439, 219, 0, 1683, 1684, 3, 429, 214, 0, 1684, 1685, 3, 431, 215, 0, 1685, 336, 1, 0, 0, 0, 1686, 1687, 3, 439, 219, 0, 1687, 1688, 3, 429, 214, 0, 1688, 1689, 3, 439, 219, 0, 1689, 1690, 3, 401, 200, 0, 1690, 1691, 3, 423, 211, 0, 1691, 1692, 3, 437, 218, 0, 1692, 338, 1, 0, 0, 0, 1693, 1694, 3, 439, 219, 0, 1694, 1695, 3, 435, 217, 0, 1695, 1696, 3, 401, 200, 0, 1696, 1697, 3, 417, 208, 0, 1697, 1698, 3, 423, 211, 0, 1698, 1699, 3, 417, 208, 0, 1699, 1700, 3, 427, 213, 0, 1700, 1701, 3, 413, 206, 0, 1701, 340, 1, 0, 0, 0, 1702, 1703, 3, 439, 219, 0, 1703, 1704, 3, 435, 217, 0, 1704, 1705, 3, 417, 208, 0, 1705, 1706, 3, 425, 212, 0, 1706, 342, 1, 0, 0, 0, 1707, 1708, 3, 439, 219, 0, 1708, 1709, 3, 435, 217, 0, 1709, 1710, 3, 441, 220, 0, 1710, 1711, 3, 427, 213, 0, 1711, 1712, 3, 405, 202, 0, 1712, 1713, 3, 401, 200, 0, 1713, 1714, 3, 439, 219, 0, 1714, 1715, 3, 409, 204, 0, 1715, 344, 1, 0, 0, 0, 1716, 1717, 3, 439, 219, 0, 1717, 1718, 3, 439, 219, 0, 1718, 1719, 3, 423, 211, 0, 1719, 346, 1, 0, 0, 0, 1720, 1721, 3, 439, 219, 0, 1721, 1722, 3, 449, 224, 0, 1722, 1723, 3, 431, 215, 0, 1723, 1724, 3, 409, 204, 0, 1724, 348, 1, 0, 0, 0, 1725, 1726, 3, 441, 220, 0, 1726, 1727, 3, 427, 213, 0, 1727, 1728, 3, 403, 201, 0, 1728, 1729, 3, 429, 214, 0, 1729, 1730, 3, 441, 220, 0, 1730, 1731, 3, 427, 213, 0, 1731, 1732, 3, 407, 203, 0, 1732, 1733, 3, 409, 204, 0, 1733, 1734, 3, 407, 203, 0, 1734, 350, 1, 0, 0, 0, 1735, 1736, 3, 441, 220, 0, 1736, 1737, 3, 427, 213, 0, 1737, 1738, 3, 417, 208, 0, 1738, 1739, 3, 429, 214, 0, 1739, 1740, 3, 427, 213, 0, 1740, 352, 1, 0, 0, 0, 1741, 1742, 3, 441, 220, 0, 1742, 1743, 3, 431, 215, 0, 1743, 1744, 3, 407, 203, 0, 1744, 1745, 3, 401, 200, 0, 1745, 1746, 3, 439, 219, 0, 1746, 1747, 3, 409, 204, 0, 1747, 354, 1, 0, 0, 0, 1748, 1749, 3, 441, 220, 0, 1749, 1750, 3, 437, 218, 0, 1750, 1751, 3, 409, 204, 0, 1751, 356, 1, 0, 0, 0, 1752, 1753, 3, 441, 220, 0, 1753, 1754, 3, 437, 218, 0, 1754, 1755, 3, 417, 208, 0, 1755, 1756, 3, 427, 213, 0, 1756, 1757, 3, 413, 206, 0, 1757, 358, 1, 0, 0, 0, 1758, 1759, 3, 441, 220, 0, 1759, 1760, 3, 441, 220, 0, 1760, 1761, 3, 417, 208, 0, 1761, 1762, 3, 407, 203, 0, 1762, 360, 1, 0, 0, 0, 1763, 1764, 3, 443, 221, 0, 1764, 1765, 3, 401, 200, 0, 1765, 1766, 3, 423, 211, 0, 1766, 1767, 3, 441, 220, 0, 1767, 1768, 3, 409, 204, 0, 1768, 1769, 3, 437, 218, 0, 1769, 362, 1, 0, 0, 0, 1770, 1771, 3, 443, 221, 0, 1771, 1772, 3, 417, 208, 0, 1772, 1773, 3, 409, 204, 0, 1773, 1774, 3, 445, 222, 0, 1774, 364, 1, 0, 0, 0, 1775, 1776, 3, 443, 221, 0, 1776, 1777, 3, 429, 214, 0, 1777, 1778, 3, 423, 211, 0, 1778, 1779, 3, 441, 220, 0, 1779, 1780, 3, 425, 212, 0, 1780, 1781, 3, 409, 204, 0, 1781, 366, 1, 0, 0, 0, 1782, 1783, 3, 445, 222, 0, 1783, 1784, 3, 401, 200, 0, 1784, 1785, 3, 439, 219, 0, 1785, 1786, 3, 405, 202, 0, 1786, 1787, 3, 415, 207, 0, 1787, 368, 1, 0, 0, 0, 1788, 1789, 3, 445, 222, 0, 1789, 1790, 3, 409, 204, 0, 1790, 1791, 3, 409, 204, 0, 1791, 1792, 3, 421, 210, 0, 1792, 370, 1, 0, 0, 0, 1793, 1794, 3, 445, 222, 0, 1794, 1795, 3, 415, 207, 0, 1795, 1796, 3, 409, 204, 0, 1796, 1797, 3, 427, 213, 0, 1797, 372, 1, 0, 0, 0, 1798, 1799, 3, 445, 222, 0, 1799, 1800, 3, 415, 207, 0, 1800, 1801, 3, 409, 204, 0, 1801, 1802, 3, 435, 217, 0, 1802, 1803, 3, 409, 204, 0, 1803, 374, 1, 0, 0, 0, 1804, 1805, 3, 445, 222, 0, 1805, 1806, 3, 417, 208, 0, 1806, 1807, 3, 427, 213, 0, 1807, 1808, 3, 407, 203, 0, 1808, 1809, 3, 429, 214, 0, 1809, 1810, 3, 445, 222, 0, 1810, 376, 1, 0, 0, 0, 1811, 1812, 3, 445, 222, 0, 1812, 1813, 3, 417, 208, 0, 1813, 1814, 3, 439, 219, 0, 1814, 1815, 3, 415, 207, 0, 1815, 378, 1, 0, 0, 0, 1816, 1817, 3, 449, 224, 0, 1817, 1818, 3, 409, 204, 0, 1818, 1819, 3, 401, 200, 0, 1819, 1820, 3, 435, 217, 0, 1820, 1827, 1, 0, 0, 0, 1821, 1822, 3, 449, 224, 0, 1822, 1823, 3, 449, 224, 0, 1823, 1824, 3, 449, 224, 0, 1824, 1825, 3, 449, 224, 0, 1825, 1827, 1, 0, 0, 0, 1826, 1816, 1, 0, 0, 0, 1826, 1821, 1, 0, 0, 0, 1827, 380, 1, 0, 0, 0, 1828, 1829, 5, 102, 0, 0, 1829, 1830, 5, 97, 0, 0, 1830, 1831, 5, 108, 0, 0, 1831, 1832, 5, 115, 0, 0, 1832, 1833, 5, 101, 0, 0, 1833, 382, 1, 0, 0, 0, 1834, 1835, 5, 116, 0, 0, 1835, 1836, 5, 114, 0, 0, 1836, 1837, 5, 117, 0, 0, 1837, 1838, 5, 101, 0, 0, 1838, 384, 1, 0, 0, 0, 1839, 1840, 3, 467, 233, 0, 1840, 1841, 3, 403, 201, 0, 1841, 1870, 1, 0, 0, 0, 1842, 1843, 3, 467, 233, 0, 1843, 1844, 3, 411, 205, 0, 1844, 1870, 1, 0, 0, 0, 1845, 1846, 3, 467, 233, 0, 1846, 1847, 3, 435, 217, 0, 1847, 1870, 1, 0, 0, 0, 1848, 1849, 3, 467, 233, 0, 1849, 1850, 3, 427, 213, 0, 1850, 1870, 1, 0, 0, 0, 1851, 1852, 3, 467, 233, 0, 1852, 1853, 3, 439, 219, 0, 1853, 1870, 1, 0, 0, 0, 1854, 1855, 3, 467, 233, 0, 1855, 1856, 5, 48, 0, 0, 1856, 1870, 1, 0, 0, 0, 1857, 1858, 3, 467, 233, 0, 1858, 1859, 3, 401, 200, 0, 1859, 1870, 1, 0, 0, 0, 1860, 1861, 3, 467, 233, 0, 1861, 1862, 3, 443, 221, 0, 1862, 1870, 1, 0, 0, 0, 1863, 1864, 3, 467, 233, 0, 1864, 1865, 3, 467, 233, 0, 1865, 1870, 1, 0, 0, 0, 1866, 1867, 3, 467, 233, 0, 1867, 1868, 3, 521, 260, 0, 1868, 1870, 1, 0, 0, 0, 1869, 1839, 1, 0, 0, 0, 1869, 1842, 1, 0, 0, 0, 1869, 1845, 1, 0, 0, 0, 1869, 1848, 1, 0, 0, 0, 1869, 1851, 1, 0, 0, 0, 1869, 1854, 1, 0, 0, 0, 1869, 1857, 1, 0, 0, 0, 1869, 1860, 1, 0, 0, 0, 1869, 1863, 1, 0, 0, 0, 1869, 1866, 1, 0, 0, 0, 1870, 386, 1, 0, 0, 0, 1871, 1875, 3, 453, 226, 0, 1872, 1875, 3, 537, 268, 0, 1873, 1875, 3, 477, 238, 0, 1874, 1871, 1, 0, 0, 0, 1874, 1872, 1, 0, 0, 0, 1874, 1873, 1, 0, 0, 0, 1875, 1882, 1, 0, 0, 0, 1876, 1881, 3, 453, 226, 0, 1877, 1881, 3, 537, 268, 0, 1878, 1881, 3, 457, 228, 0, 1879, 1881, 3, 477, 238, 0, 1880, 1876, 1, 0, 0, 0, 1880, 1877, 1, 0, 0, 0, 1880, 1878, 1, 0, 0, 0, 1880, 1879, 1, 0, 0, 0, 1881, 1884, 1, 0, 0, 0, 1882, 1880, 1, 0, 0, 0, 1882, 1883, 1, 0, 0, 0, 1883, 1912, 1, 0, 0, 0, 1884, 1882, 1, 0, 0, 0, 1885, 1893, 3, 465, 232, 0, 1886, 1892, 8, 0, 0, 0, 1887, 1892, 3, 385, 192, 0, 1888, 1889, 3, 465, 232, 0, 1889, 1890, 3, 465, 232, 0, 1890, 1892, 1, 0, 0, 0, 1891, 1886, 1, 0, 0, 0, 1891, 1887, 1, 0, 0, 0, 1891, 1888, 1, 0, 0, 0, 1892, 1895, 1, 0, 0, 0, 1893, 1891, 1, 0, 0, 0, 1893, 1894, 1, 0, 0, 0, 1894, 1896, 1, 0, 0, 0, 1895, 1893, 1, 0, 0, 0, 1896, 1897, 3, 465, 232, 0, 1897, 1912, 1, 0, 0, 0, 1898, 1906, 3, 519, 259, 0, 1899, 1905, 8, 1, 0, 0, 1900, 1905, 3, 385, 192, 0, 1901, 1902, 3, 519, 259, 0, 1902, 1903, 3, 519, 259, 0, 1903, 1905, 1, 0, 0, 0, 1904, 1899, 1, 0, 0, 0, 1904, 1900, 1, 0, 0, 0, 1904, 1901, 1, 0, 0, 0, 1905, 1908, 1, 0, 0, 0, 1906, 1904, 1, 0, 0, 0, 1906, 1907, 1, 0, 0, 0, 1907, 1909, 1, 0, 0, 0, 1908, 1906, 1, 0, 0, 0, 1909, 1910, 3, 519, 259, 0, 1910, 1912, 1, 0, 0, 0, 1911, 1874, 1, 0, 0, 0, 1911, 1885, 1, 0, 0, 0, 1911, 1898, 1, 0, 0, 0, 1912, 388, 1, 0, 0, 0, 1913, 1914, 3, 395, 197, 0, 1914, 1918, 3, 479, 239, 0, 1915, 1917, 3, 459, 229, 0, 1916, 1915, 1, 0, 0, 0, 1917, 1920, 1, 0, 0, 0, 1918, 1916, 1, 0, 0, 0, 1918, 1919, 1, 0, 0, 0, 1919, 1923, 1, 0, 0, 0, 1920, 1918, 1, 0, 0, 0, 1921, 1924, 3, 431, 215, 0, 1922, 1924, 3, 409, 204, 0, 1923, 1921, 1, 0, 0, 0, 1923, 1922, 1, 0, 0, 0, 1924, 1927, 1, 0, 0, 0, 1925, 1928, 3, 515, 257, 0, 1926, 1928, 3, 475, 237, 0, 1927, 1925, 1, 0, 0, 0, 1927, 1926, 1, 0, 0, 0, 1927, 1928, 1, 0, 0, 0, 1928, 1930, 1, 0, 0, 0, 1929, 1931, 3, 457, 228, 0, 1930, 1929, 1, 0, 0, 0, 1931, 1932, 1, 0, 0, 0, 1932, 1930, 1, 0, 0, 0, 1932, 1933, 1, 0, 0, 0, 1933, 1990, 1, 0, 0, 0, 1934, 1937, 3, 395, 197, 0, 1935, 1938, 3, 431, 215, 0, 1936, 1938, 3, 409, 204, 0, 1937, 1935, 1, 0, 0, 0, 1937, 1936, 1, 0, 0, 0, 1938, 1941, 1, 0, 0, 0, 1939, 1942, 3, 515, 257, 0, 1940, 1942, 3, 475, 237, 0, 1941, 1939, 1, 0, 0, 0, 1941, 1940, 1, 0, 0, 0, 1941, 1942, 1, 0, 0, 0, 1942, 1944, 1, 0, 0, 0, 1943, 1945, 3, 457, 228, 0, 1944, 1943, 1, 0, 0, 0, 1945, 1946, 1, 0, 0, 0, 1946, 1944, 1, 0, 0, 0, 1946, 1947, 1, 0, 0, 0, 1947, 1990, 1, 0, 0, 0, 1948, 1949, 3, 393, 196, 0, 1949, 1953, 3, 479, 239, 0, 1950, 1952, 3, 457, 228, 0, 1951, 1950, 1, 0, 0, 0, 1952, 1955, 1, 0, 0, 0, 1953, 1951, 1, 0, 0, 0, 1953, 1954, 1, 0, 0, 0, 1954, 1956, 1, 0, 0, 0, 1955, 1953, 1, 0, 0, 0, 1956, 1959, 3, 409, 204, 0, 1957, 1960, 3, 515, 257, 0, 1958, 1960, 3, 475, 237, 0, 1959, 1957, 1, 0, 0, 0, 1959, 1958, 1, 0, 0, 0, 1959, 1960, 1, 0, 0, 0, 1960, 1962, 1, 0, 0, 0, 1961, 1963, 3, 457, 228, 0, 1962, 1961, 1, 0, 0, 0, 1963, 1964, 1, 0, 0, 0, 1964, 1962, 1, 0, 0, 0, 1964, 1965, 1, 0, 0, 0, 1965, 1990, 1, 0, 0, 0, 1966, 1967, 3, 479, 239, 0, 1967, 1968, 3, 393, 196, 0, 1968, 1971, 3, 409, 204, 0, 1969, 1972, 3, 515, 257, 0, 1970, 1972, 3, 475, 237, 0, 1971, 1969, 1, 0, 0, 0, 1971, 1970, 1, 0, 0, 0, 1971, 1972, 1, 0, 0, 0, 1972, 1974, 1, 0, 0, 0, 1973, 1975, 3, 457, 228, 0, 1974, 1973, 1, 0, 0, 0, 1975, 1976, 1, 0, 0, 0, 1976, 1974, 1, 0, 0, 0, 1976, 1977, 1, 0, 0, 0, 1977, 1990, 1, 0, 0, 0, 1978, 1979, 3, 393, 196, 0, 1979, 1982, 3, 409, 204, 0, 1980, 1983, 3, 515, 257, 0, 1981, 1983, 3, 475, 237, 0, 1982, 1980, 1, 0, 0, 0, 1982, 1981, 1, 0, 0, 0, 1982, 1983, 1, 0, 0, 0, 1983, 1985, 1, 0, 0, 0, 1984, 1986, 3, 457, 228, 0, 1985, 1984, 1, 0, 0, 0, 1986, 1987, 1, 0, 0, 0, 1987, 1985, 1, 0, 0, 0, 1987, 1988, 1, 0, 0, 0, 1988, 1990, 1, 0, 0, 0, 1989, 1913, 1, 0, 0, 0, 1989, 1934, 1, 0, 0, 0, 1989, 1948, 1, 0, 0, 0, 1989, 1966, 1, 0, 0, 0, 1989, 1978, 1, 0, 0, 0, 1990, 390, 1, 0, 0, 0, 1991, 1993, 5, 48, 0, 0, 1992, 1994, 3, 455, 227, 0, 1993, 1992, 1, 0, 0, 0, 1994, 1995, 1, 0, 0, 0, 1995, 1993, 1, 0, 0, 0, 1995, 1996, 1, 0, 0, 0, 1996, 392, 1, 0, 0, 0, 1997, 1999, 3, 457, 228, 0, 1998, 1997, 1, 0, 0, 0, 1999, 2000, 1, 0, 0, 0, 2000, 1998, 1, 0, 0, 0, 2000, 2001, 1, 0, 0, 0, 2001, 394, 1, 0, 0, 0, 2002, 2003, 5, 48, 0, 0, 2003, 2005, 3, 447, 223, 0, 2004, 2006, 3, 459, 229, 0, 2005, 2004, 1, 0, 0, 0, 2006, 2007, 1, 0, 0, 0, 2007, 2005, 1, 0, 0, 0, 2007, 2008, 1, 0, 0, 0, 2008, 396, 1, 0, 0, 0, 2009, 2017, 3, 521, 260, 0, 2010, 2016, 8, 2, 0, 0, 2011, 2016, 3, 385, 192, 0, 2012, 2013, 3, 521, 260, 0, 2013, 2014, 3, 521, 260, 0, 2014, 2016, 1, 0, 0, 0, 2015, 2010, 1, 0, 0, 0, 2015, 2011, 1, 0, 0, 0, 2015, 2012, 1, 0, 0, 0, 2016, 2019, 1, 0, 0, 0, 2017, 2015, 1, 0, 0, 0, 2017, 2018, 1, 0, 0, 0, 2018, 2020, 1, 0, 0, 0, 2019, 2017, 1, 0, 0, 0, 2020, 2021, 3, 521, 260, 0, 2021, 398, 1, 0, 0, 0, 2022, 2030, 3, 495, 247, 0, 2023, 2029, 8, 3, 0, 0, 2024, 2029, 3, 385, 192, 0, 2025, 2026, 3, 495, 247, 0, 2026, 2027, 3, 495, 247, 0, 2027, 2029, 1, 0, 0, 0, 2028, 2023, 1, 0, 0, 0, 2028, 2024, 1, 0, 0, 0, 2028, 2025, 1, 0, 0, 0, 2029, 2032, 1, 0, 0, 0, 2030, 2028, 1, 0, 0, 0, 2030, 2031, 1, 0, 0, 0, 2031, 2033, 1, 0, 0, 0, 2032, 2030, 1, 0, 0, 0, 2033, 2034, 3, 527, 263, 0, 2034, 400, 1, 0, 0, 0, 2035, 2036, 7, 4, 0, 0, 2036, 402, 1, 0, 0, 0, 2037, 2038, 7, 5, 0, 0, 2038, 404, 1, 0, 0, 0, 2039, 2040, 7, 6, 0, 0, 2040, 406, 1, 0, 0, 0, 2041, 2042, 7, 7, 0, 0, 2042, 408, 1, 0, 0, 0, 2043, 2044, 7, 8, 0, 0, 2044, 410, 1, 0, 0, 0, 2045, 2046, 7, 9, 0, 0, 2046, 412, 1, 0, 0, 0, 2047, 2048, 7, 10, 0, 0, 2048, 414, 1, 0, 0, 0, 2049, 2050, 7, 11, 0, 0, 2050, 416, 1, 0, 0, 0, 2051, 2052, 7, 12, 0, 0, 2052, 418, 1, 0, 0, 0, 2053, 2054, 7, 13, 0, 0, 2054, 420, 1, 0, 0, 0, 2055, 2056, 7, 14, 0, 0, 2056, 422, 1, 0, 0, 0, 2057, 2058, 7, 15, 0, 0, 2058, 424, 1, 0, 0, 0, 2059, 2060, 7, 16, 0, 0, 2060, 426, 1, 0, 0, 0, 2061, 2062, 7, 17, 0, 0, 2062, 428, 1, 0, 0, 0, 2063, 2064, 7, 18, 0, 0, 2064, 430, 1, 0, 0, 0, 2065, 2066, 7, 19, 0, 0, 2066, 432, 1, 0, 0, 0, 2067, 2068, 7, 20, 0, 0, 2068, 434, 1, 0, 0, 0, 2069, 2070, 7, 21, 0, 0, 2070, 436, 1, 0, 0, 0, 2071, 2072, 7, 22, 0, 0, 2072, 438, 1, 0, 0, 0, 2073, 2074, 7, 23, 0, 0, 2074, 440, 1, 0, 0, 0, 2075, 2076, 7, 24, 0, 0, 2076, 442, 1, 0, 0, 0, 2077, 2078, 7, 25, 0, 0, 2078, 444, 1, 0, 0, 0, 2079, 2080, 7, 26, 0, 0, 2080, 446, 1, 0, 0, 0, 2081, 2082, 7, 27, 0, 0, 2082, 448, 1, 0, 0, 0, 2083, 2084, 7, 28, 0, 0, 2084, 450, 1, 0, 0, 0, 2085, 2086, 7, 29, 0, 0, 2086, 452, 1, 0, 0, 0, 2087, 2088, 7, 30, 0, 0, 2088, 454, 1, 0, 0, 0, 2089, 2090, 7, 31, 0, 0, 2090, 456, 1, 0, 0, 0, 2091, 2092, 7, 32, 0, 0, 2092, 458, 1, 0, 0, 0, 2093, 2094, 7, 33, 0, 0, 2094, 460, 1, 0, 0, 0, 2095, 2096, 5, 45, 0, 0, 2096, 2097, 5, 62, 0, 0, 2097, 462, 1, 0, 0, 0, 2098, 2099, 5, 42, 0, 0, 2099, 464, 1, 0, 0, 0, 2100, 2101, 5, 96, 0, 0, 2101, 466, 1, 0, 0, 0, 2102, 2103, 5, 92, 0, 0, 2103, 468, 1, 0, 0, 0, 2104, 2105, 5, 58, 0, 0, 2105, 470, 1, 0, 0, 0, 2106, 2107, 5, 44, 0, 0, 2107, 472, 1, 0, 0, 0, 2108, 2109, 5, 124, 0, 0, 2109, 2110, 5, 124, 0, 0, 2110, 474, 1, 0, 0, 0, 2111, 2112, 5, 45, 0, 0, 2112, 476, 1, 0, 0, 0, 2113, 2114, 5, 36, 0, 0, 2114, 478, 1, 0, 0, 0, 2115, 2116, 5, 46, 0, 0, 2116, 480, 1, 0, 0, 0, 2117, 2118, 5, 61, 0, 0, 2118, 2119, 5, 61, 0, 0, 2119, 482, 1, 0, 0, 0, 2120, 2121, 5, 61, 0, 0, 2121, 484, 1, 0, 0, 0, 2122, 2123, 5, 62, 0, 0, 2123, 2124, 5, 61, 0, 0, 2124, 486, 1, 0, 0, 0, 2125, 2126, 5, 62, 0, 0, 2126, 488, 1, 0, 0, 0, 2127, 2128, 5, 35, 0, 0, 2128, 490, 1, 0, 0, 0, 2129, 2130, 5, 126, 0, 0, 2130, 2131, 5, 42, 0, 0, 2131, 492, 1, 0, 0, 0, 2132, 2133, 5, 61, 0, 0, 2133, 2134, 5, 126, 0, 0, 2134, 2135, 5, 42, 0, 0, 2135, 494, 1, 0, 0, 0, 2136, 2137, 5, 123, 0, 0, 2137, 496, 1, 0, 0, 0, 2138, 2139, 5, 91, 0, 0, 2139, 498, 1, 0, 0, 0, 2140, 2141, 5, 40, 0, 0, 2141, 500, 1, 0, 0, 0, 2142, 2143, 5, 60, 0, 0, 2143, 2144, 5, 61, 0, 0, 2144, 502, 1, 0, 0, 0, 2145, 2146, 5, 60, 0, 0, 2146, 504, 1, 0, 0, 0, 2147, 2148, 5, 33, 0, 0, 2148, 2152, 5, 61, 0, 0, 2149, 2150, 5, 60, 0, 0, 2150, 2152, 5, 62, 0, 0, 2151, 2147, 1, 0, 0, 0, 2151, 2149, 1, 0, 0, 0, 2152, 506, 1, 0, 0, 0, 2153, 2154, 5, 33, 0, 0, 2154, 2155, 5, 126, 0, 0, 2155, 2156, 5, 42, 0, 0, 2156, 508, 1, 0, 0, 0, 2157, 2158, 5, 33, 0, 0, 2158, 2159, 5, 126, 0, 0, 2159, 510, 1, 0, 0, 0, 2160, 2161, 5, 63, 0, 0, 2161, 2162, 5, 63, 0, 0, 2162, 512, 1, 0, 0, 0, 2163, 2164, 5, 37, 0, 0, 2164, 514, 1, 0, 0, 0, 2165, 2166, 5, 43, 0, 0, 2166, 516, 1, 0, 0, 0, 2167, 2168, 5, 63, 0, 0, 2168, 518, 1, 0, 0, 0, 2169, 2170, 5, 34, 0, 0, 2170, 520, 1, 0, 0, 0, 2171, 2172, 5, 39, 0, 0, 2172, 522, 1, 0, 0, 0, 2173, 2174, 5, 126, 0, 0, 2174, 524, 1, 0, 0, 0, 2175, 2176, 5, 61, 0, 0, 2176, 2177, 5, 126, 0, 0, 2177, 526, 1, 0, 0, 0, 2178, 2179, 5, 125, 0, 0, 2179, 528, 1, 0, 0, 0, 2180, 2181, 5, 93, 0, 0, 2181, 530, 1, 0, 0, 0, 2182, 2183, 5, 41, 0, 0, 2183, 532, 1, 0, 0, 0, 2184, 2185, 5, 59, 0, 0, 2185, 534, 1, 0, 0, 0, 2186, 2187, 5, 47, 0, 0, 2187, 536, 1, 0, 0, 0, 2188, 2189, 5, 95, 0, 0, 2189, 538, 1, 0, 0, 0, 2190, 2191, 5, 47, 0, 0, 2191, 2192, 5, 42, 0, 0, 2192, 2196, 1, 0, 0, 0, 2193, 2195, 9, 0, 0, 0, 2194, 2193, 1, 0, 0, 0, 2195, 2198, 1, 0, 0, 0, 2196, 2197, 1, 0, 0, 0, 2196, 2194, 1, 0, 0, 0, 2197, 2199, 1, 0, 0, 0, 2198, 2196, 1, 0, 0, 0, 2199, 2200, 5, 42, 0, 0, 2200, 2201, 5, 47, 0, 0, 2201, 2202, 1, 0, 0, 0, 2202, 2203, 6, 269, 0, 0, 2203, 540, 1, 0, 0, 0, 2204, 2205, 5, 45, 0, 0, 2205, 2206, 5, 45, 0, 0, 2206, 2210, 1, 0, 0, 0, 2207, 2209, 8, 34, 0, 0, 2208, 2207, 1, 0, 0, 0, 2209, 2212, 1, 0, 0, 0, 2210, 2208, 1, 0, 0, 0, 2210, 2211, 1, 0, 0, 0, 2211, 2214, 1, 0, 0, 0, 2212, 2210, 1, 0, 0, 0, 2213, 2215, 7, 35, 0, 0, 2214, 2213, 1, 0, 0, 0, 2215, 2216, 1, 0, 0, 0, 2216, 2217, 6, 270, 0, 0, 2217, 542, 1, 0, 0, 0, 2218, 2219, 7, 36, 0, 0, 2219, 2220, 1, 0, 0, 0, 2220, 2221, 6, 271, 1, 0, 2221, 544, 1, 0, 0, 0, 39, 0, 607, 1112, 1826, 1869, 1874, 1880, 1882, 1891, 1893, 1904, 1906, 1911, 1918, 1923, 1927, 1932, 1937, 1941, 1946, 1953, 1959, 1964, 1971, 1976, 1982, 1987, 1989, 1995, 2000, 2007, 2015, 2017, 2028, 2030, 2151, 2196, 2210, 2214, 2, 6, 0, 0, 0, 1, 0]
\ No newline at end of file
diff --git a/hogql_parser/HogQLLexer.tokens b/hogql_parser/HogQLLexer.tokens
new file mode 100644
index 0000000000000..10fd925b09195
--- /dev/null
+++ b/hogql_parser/HogQLLexer.tokens
@@ -0,0 +1,282 @@
+ADD=1
+AFTER=2
+ALIAS=3
+ALL=4
+ALTER=5
+AND=6
+ANTI=7
+ANY=8
+ARRAY=9
+AS=10
+ASCENDING=11
+ASOF=12
+AST=13
+ASYNC=14
+ATTACH=15
+BETWEEN=16
+BOTH=17
+BY=18
+CASE=19
+CAST=20
+CHECK=21
+CLEAR=22
+CLUSTER=23
+CODEC=24
+COHORT=25
+COLLATE=26
+COLUMN=27
+COMMENT=28
+CONSTRAINT=29
+CREATE=30
+CROSS=31
+CUBE=32
+CURRENT=33
+DATABASE=34
+DATABASES=35
+DATE=36
+DAY=37
+DEDUPLICATE=38
+DEFAULT=39
+DELAY=40
+DELETE=41
+DESC=42
+DESCENDING=43
+DESCRIBE=44
+DETACH=45
+DICTIONARIES=46
+DICTIONARY=47
+DISK=48
+DISTINCT=49
+DISTRIBUTED=50
+DROP=51
+ELSE=52
+END=53
+ENGINE=54
+EVENTS=55
+EXISTS=56
+EXPLAIN=57
+EXPRESSION=58
+EXTRACT=59
+FETCHES=60
+FINAL=61
+FIRST=62
+FLUSH=63
+FOLLOWING=64
+FOR=65
+FORMAT=66
+FREEZE=67
+FROM=68
+FULL=69
+FUNCTION=70
+GLOBAL=71
+GRANULARITY=72
+GROUP=73
+HAVING=74
+HIERARCHICAL=75
+HOUR=76
+ID=77
+IF=78
+ILIKE=79
+IN=80
+INDEX=81
+INF=82
+INJECTIVE=83
+INNER=84
+INSERT=85
+INTERVAL=86
+INTO=87
+IS=88
+IS_OBJECT_ID=89
+JOIN=90
+KEY=91
+KILL=92
+LAST=93
+LAYOUT=94
+LEADING=95
+LEFT=96
+LIFETIME=97
+LIKE=98
+LIMIT=99
+LIVE=100
+LOCAL=101
+LOGS=102
+MATERIALIZE=103
+MATERIALIZED=104
+MAX=105
+MERGES=106
+MIN=107
+MINUTE=108
+MODIFY=109
+MONTH=110
+MOVE=111
+MUTATION=112
+NAN_SQL=113
+NO=114
+NOT=115
+NULL_SQL=116
+NULLS=117
+OFFSET=118
+ON=119
+OPTIMIZE=120
+OR=121
+ORDER=122
+OUTER=123
+OUTFILE=124
+OVER=125
+PARTITION=126
+POPULATE=127
+PRECEDING=128
+PREWHERE=129
+PRIMARY=130
+PROJECTION=131
+QUARTER=132
+RANGE=133
+RELOAD=134
+REMOVE=135
+RENAME=136
+REPLACE=137
+REPLICA=138
+REPLICATED=139
+RIGHT=140
+ROLLUP=141
+ROW=142
+ROWS=143
+SAMPLE=144
+SECOND=145
+SELECT=146
+SEMI=147
+SENDS=148
+SET=149
+SETTINGS=150
+SHOW=151
+SOURCE=152
+START=153
+STOP=154
+SUBSTRING=155
+SYNC=156
+SYNTAX=157
+SYSTEM=158
+TABLE=159
+TABLES=160
+TEMPORARY=161
+TEST=162
+THEN=163
+TIES=164
+TIMEOUT=165
+TIMESTAMP=166
+TO=167
+TOP=168
+TOTALS=169
+TRAILING=170
+TRIM=171
+TRUNCATE=172
+TTL=173
+TYPE=174
+UNBOUNDED=175
+UNION=176
+UPDATE=177
+USE=178
+USING=179
+UUID=180
+VALUES=181
+VIEW=182
+VOLUME=183
+WATCH=184
+WEEK=185
+WHEN=186
+WHERE=187
+WINDOW=188
+WITH=189
+YEAR=190
+JSON_FALSE=191
+JSON_TRUE=192
+ESCAPE_CHAR=193
+IDENTIFIER=194
+FLOATING_LITERAL=195
+OCTAL_LITERAL=196
+DECIMAL_LITERAL=197
+HEXADECIMAL_LITERAL=198
+STRING_LITERAL=199
+PLACEHOLDER=200
+ARROW=201
+ASTERISK=202
+BACKQUOTE=203
+BACKSLASH=204
+COLON=205
+COMMA=206
+CONCAT=207
+DASH=208
+DOLLAR=209
+DOT=210
+EQ_DOUBLE=211
+EQ_SINGLE=212
+GT_EQ=213
+GT=214
+HASH=215
+IREGEX_SINGLE=216
+IREGEX_DOUBLE=217
+LBRACE=218
+LBRACKET=219
+LPAREN=220
+LT_EQ=221
+LT=222
+NOT_EQ=223
+NOT_IREGEX=224
+NOT_REGEX=225
+NULLISH=226
+PERCENT=227
+PLUS=228
+QUERY=229
+QUOTE_DOUBLE=230
+QUOTE_SINGLE=231
+REGEX_SINGLE=232
+REGEX_DOUBLE=233
+RBRACE=234
+RBRACKET=235
+RPAREN=236
+SEMICOLON=237
+SLASH=238
+UNDERSCORE=239
+MULTI_LINE_COMMENT=240
+SINGLE_LINE_COMMENT=241
+WHITESPACE=242
+'false'=191
+'true'=192
+'->'=201
+'*'=202
+'`'=203
+'\\'=204
+':'=205
+','=206
+'||'=207
+'-'=208
+'$'=209
+'.'=210
+'=='=211
+'='=212
+'>='=213
+'>'=214
+'#'=215
+'~*'=216
+'=~*'=217
+'{'=218
+'['=219
+'('=220
+'<='=221
+'<'=222
+'!~*'=224
+'!~'=225
+'??'=226
+'%'=227
+'+'=228
+'?'=229
+'"'=230
+'\''=231
+'~'=232
+'=~'=233
+'}'=234
+']'=235
+')'=236
+';'=237
+'/'=238
+'_'=239
diff --git a/hogql_parser/HogQLParser.cpp b/hogql_parser/HogQLParser.cpp
new file mode 100644
index 0000000000000..779d2dbf7d4ed
--- /dev/null
+++ b/hogql_parser/HogQLParser.cpp
@@ -0,0 +1,9562 @@
+
+// Generated from HogQLParser.g4 by ANTLR 4.13.0
+
+
+#include "HogQLParserVisitor.h"
+
+#include "HogQLParser.h"
+
+
+using namespace antlrcpp;
+
+using namespace antlr4;
+
+namespace {
+
+struct HogQLParserStaticData final {
+ HogQLParserStaticData(std::vector ruleNames,
+ std::vector literalNames,
+ std::vector symbolicNames)
+ : ruleNames(std::move(ruleNames)), literalNames(std::move(literalNames)),
+ symbolicNames(std::move(symbolicNames)),
+ vocabulary(this->literalNames, this->symbolicNames) {}
+
+ HogQLParserStaticData(const HogQLParserStaticData&) = delete;
+ HogQLParserStaticData(HogQLParserStaticData&&) = delete;
+ HogQLParserStaticData& operator=(const HogQLParserStaticData&) = delete;
+ HogQLParserStaticData& operator=(HogQLParserStaticData&&) = delete;
+
+ std::vector decisionToDFA;
+ antlr4::atn::PredictionContextCache sharedContextCache;
+ const std::vector ruleNames;
+ const std::vector literalNames;
+ const std::vector symbolicNames;
+ const antlr4::dfa::Vocabulary vocabulary;
+ antlr4::atn::SerializedATNView serializedATN;
+ std::unique_ptr atn;
+};
+
+::antlr4::internal::OnceFlag hogqlparserParserOnceFlag;
+#if ANTLR4_USE_THREAD_LOCAL_CACHE
+static thread_local
+#endif
+HogQLParserStaticData *hogqlparserParserStaticData = nullptr;
+
+void hogqlparserParserInitialize() {
+#if ANTLR4_USE_THREAD_LOCAL_CACHE
+ if (hogqlparserParserStaticData != nullptr) {
+ return;
+ }
+#else
+ assert(hogqlparserParserStaticData == nullptr);
+#endif
+ auto staticData = std::make_unique(
+ std::vector{
+ "select", "selectUnionStmt", "selectStmtWithParens", "selectStmt",
+ "withClause", "topClause", "fromClause", "arrayJoinClause", "windowClause",
+ "prewhereClause", "whereClause", "groupByClause", "havingClause",
+ "orderByClause", "projectionOrderByClause", "limitAndOffsetClause",
+ "offsetOnlyClause", "settingsClause", "joinExpr", "joinOp", "joinOpCross",
+ "joinConstraintClause", "sampleClause", "orderExprList", "orderExpr",
+ "ratioExpr", "settingExprList", "settingExpr", "windowExpr", "winPartitionByClause",
+ "winOrderByClause", "winFrameClause", "winFrameExtend", "winFrameBound",
+ "expr", "columnTypeExpr", "columnExprList", "columnExpr", "columnArgList",
+ "columnArgExpr", "columnLambdaExpr", "withExprList", "withExpr", "columnIdentifier",
+ "nestedIdentifier", "tableExpr", "tableFunctionExpr", "tableIdentifier",
+ "tableArgList", "databaseIdentifier", "floatingLiteral", "numberLiteral",
+ "literal", "interval", "keyword", "keywordForAlias", "alias", "identifier",
+ "enumValue"
+ },
+ std::vector{
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "'false'", "'true'", "", "", "", "", "", "", "", "",
+ "'->'", "'*'", "'`'", "'\\'", "':'", "','", "'||'", "'-'", "'$'",
+ "'.'", "'=='", "'='", "'>='", "'>'", "'#'", "'~*'", "'=~*'", "'{'",
+ "'['", "'('", "'<='", "'<'", "", "'!~*'", "'!~'", "'\\u003F\\u003F'",
+ "'%'", "'+'", "'\\u003F'", "'\"'", "'''", "'~'", "'=~'", "'}'", "']'",
+ "')'", "';'", "'/'", "'_'"
+ },
+ std::vector{
+ "", "ADD", "AFTER", "ALIAS", "ALL", "ALTER", "AND", "ANTI", "ANY",
+ "ARRAY", "AS", "ASCENDING", "ASOF", "AST", "ASYNC", "ATTACH", "BETWEEN",
+ "BOTH", "BY", "CASE", "CAST", "CHECK", "CLEAR", "CLUSTER", "CODEC",
+ "COHORT", "COLLATE", "COLUMN", "COMMENT", "CONSTRAINT", "CREATE",
+ "CROSS", "CUBE", "CURRENT", "DATABASE", "DATABASES", "DATE", "DAY",
+ "DEDUPLICATE", "DEFAULT", "DELAY", "DELETE", "DESC", "DESCENDING",
+ "DESCRIBE", "DETACH", "DICTIONARIES", "DICTIONARY", "DISK", "DISTINCT",
+ "DISTRIBUTED", "DROP", "ELSE", "END", "ENGINE", "EVENTS", "EXISTS",
+ "EXPLAIN", "EXPRESSION", "EXTRACT", "FETCHES", "FINAL", "FIRST", "FLUSH",
+ "FOLLOWING", "FOR", "FORMAT", "FREEZE", "FROM", "FULL", "FUNCTION",
+ "GLOBAL", "GRANULARITY", "GROUP", "HAVING", "HIERARCHICAL", "HOUR",
+ "ID", "IF", "ILIKE", "IN", "INDEX", "INF", "INJECTIVE", "INNER", "INSERT",
+ "INTERVAL", "INTO", "IS", "IS_OBJECT_ID", "JOIN", "KEY", "KILL", "LAST",
+ "LAYOUT", "LEADING", "LEFT", "LIFETIME", "LIKE", "LIMIT", "LIVE",
+ "LOCAL", "LOGS", "MATERIALIZE", "MATERIALIZED", "MAX", "MERGES", "MIN",
+ "MINUTE", "MODIFY", "MONTH", "MOVE", "MUTATION", "NAN_SQL", "NO",
+ "NOT", "NULL_SQL", "NULLS", "OFFSET", "ON", "OPTIMIZE", "OR", "ORDER",
+ "OUTER", "OUTFILE", "OVER", "PARTITION", "POPULATE", "PRECEDING",
+ "PREWHERE", "PRIMARY", "PROJECTION", "QUARTER", "RANGE", "RELOAD",
+ "REMOVE", "RENAME", "REPLACE", "REPLICA", "REPLICATED", "RIGHT", "ROLLUP",
+ "ROW", "ROWS", "SAMPLE", "SECOND", "SELECT", "SEMI", "SENDS", "SET",
+ "SETTINGS", "SHOW", "SOURCE", "START", "STOP", "SUBSTRING", "SYNC",
+ "SYNTAX", "SYSTEM", "TABLE", "TABLES", "TEMPORARY", "TEST", "THEN",
+ "TIES", "TIMEOUT", "TIMESTAMP", "TO", "TOP", "TOTALS", "TRAILING",
+ "TRIM", "TRUNCATE", "TTL", "TYPE", "UNBOUNDED", "UNION", "UPDATE",
+ "USE", "USING", "UUID", "VALUES", "VIEW", "VOLUME", "WATCH", "WEEK",
+ "WHEN", "WHERE", "WINDOW", "WITH", "YEAR", "JSON_FALSE", "JSON_TRUE",
+ "ESCAPE_CHAR", "IDENTIFIER", "FLOATING_LITERAL", "OCTAL_LITERAL",
+ "DECIMAL_LITERAL", "HEXADECIMAL_LITERAL", "STRING_LITERAL", "PLACEHOLDER",
+ "ARROW", "ASTERISK", "BACKQUOTE", "BACKSLASH", "COLON", "COMMA", "CONCAT",
+ "DASH", "DOLLAR", "DOT", "EQ_DOUBLE", "EQ_SINGLE", "GT_EQ", "GT",
+ "HASH", "IREGEX_SINGLE", "IREGEX_DOUBLE", "LBRACE", "LBRACKET", "LPAREN",
+ "LT_EQ", "LT", "NOT_EQ", "NOT_IREGEX", "NOT_REGEX", "NULLISH", "PERCENT",
+ "PLUS", "QUERY", "QUOTE_DOUBLE", "QUOTE_SINGLE", "REGEX_SINGLE", "REGEX_DOUBLE",
+ "RBRACE", "RBRACKET", "RPAREN", "SEMICOLON", "SLASH", "UNDERSCORE",
+ "MULTI_LINE_COMMENT", "SINGLE_LINE_COMMENT", "WHITESPACE"
+ }
+ );
+ static const int32_t serializedATNSegment[] = {
+ 4,1,242,919,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,
+ 7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,
+ 14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,
+ 21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,
+ 28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,
+ 35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,7,
+ 42,2,43,7,43,2,44,7,44,2,45,7,45,2,46,7,46,2,47,7,47,2,48,7,48,2,49,7,
+ 49,2,50,7,50,2,51,7,51,2,52,7,52,2,53,7,53,2,54,7,54,2,55,7,55,2,56,7,
+ 56,2,57,7,57,2,58,7,58,1,0,1,0,3,0,121,8,0,1,0,1,0,1,1,1,1,1,1,1,1,5,
+ 1,129,8,1,10,1,12,1,132,9,1,1,2,1,2,1,2,1,2,1,2,3,2,139,8,2,1,3,3,3,142,
+ 8,3,1,3,1,3,3,3,146,8,3,1,3,3,3,149,8,3,1,3,1,3,3,3,153,8,3,1,3,3,3,156,
+ 8,3,1,3,3,3,159,8,3,1,3,3,3,162,8,3,1,3,3,3,165,8,3,1,3,1,3,3,3,169,8,
+ 3,1,3,1,3,3,3,173,8,3,1,3,3,3,176,8,3,1,3,3,3,179,8,3,1,3,3,3,182,8,3,
+ 1,3,1,3,3,3,186,8,3,1,3,3,3,189,8,3,1,4,1,4,1,4,1,5,1,5,1,5,1,5,3,5,198,
+ 8,5,1,6,1,6,1,6,1,7,3,7,204,8,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,
+ 8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,5,8,223,8,8,10,8,12,8,226,9,8,1,9,1,9,1,
+ 9,1,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,3,11,242,8,11,
+ 1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,15,1,15,1,15,
+ 1,15,3,15,259,8,15,1,15,1,15,1,15,1,15,3,15,265,8,15,1,15,1,15,1,15,1,
+ 15,3,15,271,8,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,3,15,282,
+ 8,15,3,15,284,8,15,1,16,1,16,1,16,1,17,1,17,1,17,1,18,1,18,1,18,3,18,
+ 295,8,18,1,18,3,18,298,8,18,1,18,1,18,1,18,1,18,3,18,304,8,18,1,18,1,
+ 18,1,18,1,18,1,18,1,18,3,18,312,8,18,1,18,1,18,1,18,1,18,5,18,318,8,18,
+ 10,18,12,18,321,9,18,1,19,3,19,324,8,19,1,19,1,19,1,19,3,19,329,8,19,
+ 1,19,3,19,332,8,19,1,19,3,19,335,8,19,1,19,1,19,3,19,339,8,19,1,19,1,
+ 19,3,19,343,8,19,1,19,3,19,346,8,19,3,19,348,8,19,1,19,3,19,351,8,19,
+ 1,19,1,19,3,19,355,8,19,1,19,1,19,3,19,359,8,19,1,19,3,19,362,8,19,3,
+ 19,364,8,19,3,19,366,8,19,1,20,1,20,1,20,3,20,371,8,20,1,21,1,21,1,21,
+ 1,21,1,21,1,21,1,21,1,21,1,21,3,21,382,8,21,1,22,1,22,1,22,1,22,3,22,
+ 388,8,22,1,23,1,23,1,23,5,23,393,8,23,10,23,12,23,396,9,23,1,24,1,24,
+ 3,24,400,8,24,1,24,1,24,3,24,404,8,24,1,24,1,24,3,24,408,8,24,1,25,1,
+ 25,1,25,3,25,413,8,25,1,26,1,26,1,26,5,26,418,8,26,10,26,12,26,421,9,
+ 26,1,27,1,27,1,27,1,27,1,28,3,28,428,8,28,1,28,3,28,431,8,28,1,28,3,28,
+ 434,8,28,1,29,1,29,1,29,1,29,1,30,1,30,1,30,1,30,1,31,1,31,1,31,1,32,
+ 1,32,1,32,1,32,1,32,1,32,3,32,453,8,32,1,33,1,33,1,33,1,33,1,33,1,33,
+ 1,33,1,33,1,33,1,33,1,33,1,33,3,33,467,8,33,1,34,1,34,1,34,1,35,1,35,
+ 1,35,1,35,1,35,1,35,1,35,1,35,1,35,5,35,481,8,35,10,35,12,35,484,9,35,
+ 1,35,1,35,1,35,1,35,1,35,1,35,1,35,5,35,493,8,35,10,35,12,35,496,9,35,
+ 1,35,1,35,1,35,1,35,1,35,1,35,1,35,5,35,505,8,35,10,35,12,35,508,9,35,
+ 1,35,1,35,1,35,1,35,1,35,3,35,515,8,35,1,35,1,35,3,35,519,8,35,1,36,1,
+ 36,1,36,5,36,524,8,36,10,36,12,36,527,9,36,1,37,1,37,1,37,3,37,532,8,
+ 37,1,37,1,37,1,37,1,37,1,37,4,37,539,8,37,11,37,12,37,540,1,37,1,37,3,
+ 37,545,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,
+ 37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,
+ 37,1,37,1,37,1,37,3,37,576,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,
+ 37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,3,37,593,8,37,1,37,1,37,1,37,1,
+ 37,1,37,1,37,1,37,1,37,1,37,1,37,3,37,605,8,37,1,37,1,37,1,37,1,37,1,
+ 37,1,37,1,37,1,37,3,37,615,8,37,1,37,3,37,618,8,37,1,37,1,37,3,37,622,
+ 8,37,1,37,3,37,625,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,
+ 1,37,3,37,637,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,
+ 1,37,1,37,1,37,1,37,1,37,3,37,654,8,37,1,37,1,37,3,37,658,8,37,1,37,1,
+ 37,1,37,1,37,3,37,664,8,37,1,37,1,37,1,37,1,37,1,37,3,37,671,8,37,1,37,
+ 1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,3,37,683,8,37,1,37,1,37,
+ 3,37,687,8,37,1,37,3,37,690,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,3,
+ 37,699,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,
+ 37,3,37,713,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,
+ 37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,
+ 37,3,37,740,8,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,3,37,749,8,37,5,37,
+ 751,8,37,10,37,12,37,754,9,37,1,38,1,38,1,38,5,38,759,8,38,10,38,12,38,
+ 762,9,38,1,39,1,39,3,39,766,8,39,1,40,1,40,1,40,1,40,5,40,772,8,40,10,
+ 40,12,40,775,9,40,1,40,1,40,1,40,1,40,1,40,5,40,782,8,40,10,40,12,40,
+ 785,9,40,3,40,787,8,40,1,40,1,40,1,40,1,41,1,41,1,41,5,41,795,8,41,10,
+ 41,12,41,798,9,41,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,3,
+ 42,810,8,42,1,43,1,43,1,43,1,43,3,43,816,8,43,1,43,3,43,819,8,43,1,44,
+ 1,44,1,44,5,44,824,8,44,10,44,12,44,827,9,44,1,45,1,45,1,45,1,45,1,45,
+ 1,45,1,45,1,45,3,45,837,8,45,1,45,1,45,1,45,1,45,3,45,843,8,45,5,45,845,
+ 8,45,10,45,12,45,848,9,45,1,46,1,46,1,46,3,46,853,8,46,1,46,1,46,1,47,
+ 1,47,1,47,3,47,860,8,47,1,47,1,47,1,48,1,48,1,48,5,48,867,8,48,10,48,
+ 12,48,870,9,48,1,49,1,49,1,50,1,50,1,50,1,50,1,50,1,50,3,50,880,8,50,
+ 3,50,882,8,50,1,51,3,51,885,8,51,1,51,1,51,1,51,1,51,1,51,1,51,3,51,893,
+ 8,51,1,52,1,52,1,52,3,52,898,8,52,1,53,1,53,1,54,1,54,1,55,1,55,1,56,
+ 1,56,3,56,908,8,56,1,57,1,57,1,57,3,57,913,8,57,1,58,1,58,1,58,1,58,1,
+ 58,0,3,36,74,90,59,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,
+ 38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,
+ 84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,0,16,2,0,
+ 32,32,141,141,2,0,84,84,96,96,3,0,4,4,8,8,12,12,4,0,4,4,7,8,12,12,147,
+ 147,2,0,96,96,140,140,2,0,4,4,8,8,2,0,11,11,42,43,2,0,62,62,93,93,2,0,
+ 133,133,143,143,3,0,17,17,95,95,170,170,2,0,79,79,98,98,1,0,196,197,2,
+ 0,208,208,228,228,8,0,37,37,76,76,108,108,110,110,132,132,145,145,185,
+ 185,190,190,13,0,2,24,26,36,38,75,77,81,83,107,109,109,111,112,114,115,
+ 117,130,133,144,146,184,186,189,191,192,4,0,36,36,62,62,77,77,91,91,1039,
+ 0,120,1,0,0,0,2,124,1,0,0,0,4,138,1,0,0,0,6,141,1,0,0,0,8,190,1,0,0,0,
+ 10,193,1,0,0,0,12,199,1,0,0,0,14,203,1,0,0,0,16,209,1,0,0,0,18,227,1,
+ 0,0,0,20,230,1,0,0,0,22,233,1,0,0,0,24,243,1,0,0,0,26,246,1,0,0,0,28,
+ 250,1,0,0,0,30,283,1,0,0,0,32,285,1,0,0,0,34,288,1,0,0,0,36,303,1,0,0,
+ 0,38,365,1,0,0,0,40,370,1,0,0,0,42,381,1,0,0,0,44,383,1,0,0,0,46,389,
+ 1,0,0,0,48,397,1,0,0,0,50,409,1,0,0,0,52,414,1,0,0,0,54,422,1,0,0,0,56,
+ 427,1,0,0,0,58,435,1,0,0,0,60,439,1,0,0,0,62,443,1,0,0,0,64,452,1,0,0,
+ 0,66,466,1,0,0,0,68,468,1,0,0,0,70,518,1,0,0,0,72,520,1,0,0,0,74,657,
+ 1,0,0,0,76,755,1,0,0,0,78,765,1,0,0,0,80,786,1,0,0,0,82,791,1,0,0,0,84,
+ 809,1,0,0,0,86,818,1,0,0,0,88,820,1,0,0,0,90,836,1,0,0,0,92,849,1,0,0,
+ 0,94,859,1,0,0,0,96,863,1,0,0,0,98,871,1,0,0,0,100,881,1,0,0,0,102,884,
+ 1,0,0,0,104,897,1,0,0,0,106,899,1,0,0,0,108,901,1,0,0,0,110,903,1,0,0,
+ 0,112,907,1,0,0,0,114,912,1,0,0,0,116,914,1,0,0,0,118,121,3,2,1,0,119,
+ 121,3,6,3,0,120,118,1,0,0,0,120,119,1,0,0,0,121,122,1,0,0,0,122,123,5,
+ 0,0,1,123,1,1,0,0,0,124,130,3,4,2,0,125,126,5,176,0,0,126,127,5,4,0,0,
+ 127,129,3,4,2,0,128,125,1,0,0,0,129,132,1,0,0,0,130,128,1,0,0,0,130,131,
+ 1,0,0,0,131,3,1,0,0,0,132,130,1,0,0,0,133,139,3,6,3,0,134,135,5,220,0,
+ 0,135,136,3,2,1,0,136,137,5,236,0,0,137,139,1,0,0,0,138,133,1,0,0,0,138,
+ 134,1,0,0,0,139,5,1,0,0,0,140,142,3,8,4,0,141,140,1,0,0,0,141,142,1,0,
+ 0,0,142,143,1,0,0,0,143,145,5,146,0,0,144,146,5,49,0,0,145,144,1,0,0,
+ 0,145,146,1,0,0,0,146,148,1,0,0,0,147,149,3,10,5,0,148,147,1,0,0,0,148,
+ 149,1,0,0,0,149,150,1,0,0,0,150,152,3,72,36,0,151,153,3,12,6,0,152,151,
+ 1,0,0,0,152,153,1,0,0,0,153,155,1,0,0,0,154,156,3,14,7,0,155,154,1,0,
+ 0,0,155,156,1,0,0,0,156,158,1,0,0,0,157,159,3,18,9,0,158,157,1,0,0,0,
+ 158,159,1,0,0,0,159,161,1,0,0,0,160,162,3,20,10,0,161,160,1,0,0,0,161,
+ 162,1,0,0,0,162,164,1,0,0,0,163,165,3,22,11,0,164,163,1,0,0,0,164,165,
+ 1,0,0,0,165,168,1,0,0,0,166,167,5,189,0,0,167,169,7,0,0,0,168,166,1,0,
+ 0,0,168,169,1,0,0,0,169,172,1,0,0,0,170,171,5,189,0,0,171,173,5,169,0,
+ 0,172,170,1,0,0,0,172,173,1,0,0,0,173,175,1,0,0,0,174,176,3,24,12,0,175,
+ 174,1,0,0,0,175,176,1,0,0,0,176,178,1,0,0,0,177,179,3,16,8,0,178,177,
+ 1,0,0,0,178,179,1,0,0,0,179,181,1,0,0,0,180,182,3,26,13,0,181,180,1,0,
+ 0,0,181,182,1,0,0,0,182,185,1,0,0,0,183,186,3,30,15,0,184,186,3,32,16,
+ 0,185,183,1,0,0,0,185,184,1,0,0,0,185,186,1,0,0,0,186,188,1,0,0,0,187,
+ 189,3,34,17,0,188,187,1,0,0,0,188,189,1,0,0,0,189,7,1,0,0,0,190,191,5,
+ 189,0,0,191,192,3,82,41,0,192,9,1,0,0,0,193,194,5,168,0,0,194,197,5,197,
+ 0,0,195,196,5,189,0,0,196,198,5,164,0,0,197,195,1,0,0,0,197,198,1,0,0,
+ 0,198,11,1,0,0,0,199,200,5,68,0,0,200,201,3,36,18,0,201,13,1,0,0,0,202,
+ 204,7,1,0,0,203,202,1,0,0,0,203,204,1,0,0,0,204,205,1,0,0,0,205,206,5,
+ 9,0,0,206,207,5,90,0,0,207,208,3,72,36,0,208,15,1,0,0,0,209,210,5,188,
+ 0,0,210,211,3,114,57,0,211,212,5,10,0,0,212,213,5,220,0,0,213,214,3,56,
+ 28,0,214,224,5,236,0,0,215,216,5,206,0,0,216,217,3,114,57,0,217,218,5,
+ 10,0,0,218,219,5,220,0,0,219,220,3,56,28,0,220,221,5,236,0,0,221,223,
+ 1,0,0,0,222,215,1,0,0,0,223,226,1,0,0,0,224,222,1,0,0,0,224,225,1,0,0,
+ 0,225,17,1,0,0,0,226,224,1,0,0,0,227,228,5,129,0,0,228,229,3,74,37,0,
+ 229,19,1,0,0,0,230,231,5,187,0,0,231,232,3,74,37,0,232,21,1,0,0,0,233,
+ 234,5,73,0,0,234,241,5,18,0,0,235,236,7,0,0,0,236,237,5,220,0,0,237,238,
+ 3,72,36,0,238,239,5,236,0,0,239,242,1,0,0,0,240,242,3,72,36,0,241,235,
+ 1,0,0,0,241,240,1,0,0,0,242,23,1,0,0,0,243,244,5,74,0,0,244,245,3,74,
+ 37,0,245,25,1,0,0,0,246,247,5,122,0,0,247,248,5,18,0,0,248,249,3,46,23,
+ 0,249,27,1,0,0,0,250,251,5,122,0,0,251,252,5,18,0,0,252,253,3,72,36,0,
+ 253,29,1,0,0,0,254,255,5,99,0,0,255,258,3,74,37,0,256,257,5,206,0,0,257,
+ 259,3,74,37,0,258,256,1,0,0,0,258,259,1,0,0,0,259,264,1,0,0,0,260,261,
+ 5,189,0,0,261,265,5,164,0,0,262,263,5,18,0,0,263,265,3,72,36,0,264,260,
+ 1,0,0,0,264,262,1,0,0,0,264,265,1,0,0,0,265,284,1,0,0,0,266,267,5,99,
+ 0,0,267,270,3,74,37,0,268,269,5,189,0,0,269,271,5,164,0,0,270,268,1,0,
+ 0,0,270,271,1,0,0,0,271,272,1,0,0,0,272,273,5,118,0,0,273,274,3,74,37,
+ 0,274,284,1,0,0,0,275,276,5,99,0,0,276,277,3,74,37,0,277,278,5,118,0,
+ 0,278,281,3,74,37,0,279,280,5,18,0,0,280,282,3,72,36,0,281,279,1,0,0,
+ 0,281,282,1,0,0,0,282,284,1,0,0,0,283,254,1,0,0,0,283,266,1,0,0,0,283,
+ 275,1,0,0,0,284,31,1,0,0,0,285,286,5,118,0,0,286,287,3,74,37,0,287,33,
+ 1,0,0,0,288,289,5,150,0,0,289,290,3,52,26,0,290,35,1,0,0,0,291,292,6,
+ 18,-1,0,292,294,3,90,45,0,293,295,5,61,0,0,294,293,1,0,0,0,294,295,1,
+ 0,0,0,295,297,1,0,0,0,296,298,3,44,22,0,297,296,1,0,0,0,297,298,1,0,0,
+ 0,298,304,1,0,0,0,299,300,5,220,0,0,300,301,3,36,18,0,301,302,5,236,0,
+ 0,302,304,1,0,0,0,303,291,1,0,0,0,303,299,1,0,0,0,304,319,1,0,0,0,305,
+ 306,10,3,0,0,306,307,3,40,20,0,307,308,3,36,18,4,308,318,1,0,0,0,309,
+ 311,10,4,0,0,310,312,3,38,19,0,311,310,1,0,0,0,311,312,1,0,0,0,312,313,
+ 1,0,0,0,313,314,5,90,0,0,314,315,3,36,18,0,315,316,3,42,21,0,316,318,
+ 1,0,0,0,317,305,1,0,0,0,317,309,1,0,0,0,318,321,1,0,0,0,319,317,1,0,0,
+ 0,319,320,1,0,0,0,320,37,1,0,0,0,321,319,1,0,0,0,322,324,7,2,0,0,323,
+ 322,1,0,0,0,323,324,1,0,0,0,324,325,1,0,0,0,325,332,5,84,0,0,326,328,
+ 5,84,0,0,327,329,7,2,0,0,328,327,1,0,0,0,328,329,1,0,0,0,329,332,1,0,
+ 0,0,330,332,7,2,0,0,331,323,1,0,0,0,331,326,1,0,0,0,331,330,1,0,0,0,332,
+ 366,1,0,0,0,333,335,7,3,0,0,334,333,1,0,0,0,334,335,1,0,0,0,335,336,1,
+ 0,0,0,336,338,7,4,0,0,337,339,5,123,0,0,338,337,1,0,0,0,338,339,1,0,0,
+ 0,339,348,1,0,0,0,340,342,7,4,0,0,341,343,5,123,0,0,342,341,1,0,0,0,342,
+ 343,1,0,0,0,343,345,1,0,0,0,344,346,7,3,0,0,345,344,1,0,0,0,345,346,1,
+ 0,0,0,346,348,1,0,0,0,347,334,1,0,0,0,347,340,1,0,0,0,348,366,1,0,0,0,
+ 349,351,7,5,0,0,350,349,1,0,0,0,350,351,1,0,0,0,351,352,1,0,0,0,352,354,
+ 5,69,0,0,353,355,5,123,0,0,354,353,1,0,0,0,354,355,1,0,0,0,355,364,1,
+ 0,0,0,356,358,5,69,0,0,357,359,5,123,0,0,358,357,1,0,0,0,358,359,1,0,
+ 0,0,359,361,1,0,0,0,360,362,7,5,0,0,361,360,1,0,0,0,361,362,1,0,0,0,362,
+ 364,1,0,0,0,363,350,1,0,0,0,363,356,1,0,0,0,364,366,1,0,0,0,365,331,1,
+ 0,0,0,365,347,1,0,0,0,365,363,1,0,0,0,366,39,1,0,0,0,367,368,5,31,0,0,
+ 368,371,5,90,0,0,369,371,5,206,0,0,370,367,1,0,0,0,370,369,1,0,0,0,371,
+ 41,1,0,0,0,372,373,5,119,0,0,373,382,3,72,36,0,374,375,5,179,0,0,375,
+ 376,5,220,0,0,376,377,3,72,36,0,377,378,5,236,0,0,378,382,1,0,0,0,379,
+ 380,5,179,0,0,380,382,3,72,36,0,381,372,1,0,0,0,381,374,1,0,0,0,381,379,
+ 1,0,0,0,382,43,1,0,0,0,383,384,5,144,0,0,384,387,3,50,25,0,385,386,5,
+ 118,0,0,386,388,3,50,25,0,387,385,1,0,0,0,387,388,1,0,0,0,388,45,1,0,
+ 0,0,389,394,3,48,24,0,390,391,5,206,0,0,391,393,3,48,24,0,392,390,1,0,
+ 0,0,393,396,1,0,0,0,394,392,1,0,0,0,394,395,1,0,0,0,395,47,1,0,0,0,396,
+ 394,1,0,0,0,397,399,3,74,37,0,398,400,7,6,0,0,399,398,1,0,0,0,399,400,
+ 1,0,0,0,400,403,1,0,0,0,401,402,5,117,0,0,402,404,7,7,0,0,403,401,1,0,
+ 0,0,403,404,1,0,0,0,404,407,1,0,0,0,405,406,5,26,0,0,406,408,5,199,0,
+ 0,407,405,1,0,0,0,407,408,1,0,0,0,408,49,1,0,0,0,409,412,3,102,51,0,410,
+ 411,5,238,0,0,411,413,3,102,51,0,412,410,1,0,0,0,412,413,1,0,0,0,413,
+ 51,1,0,0,0,414,419,3,54,27,0,415,416,5,206,0,0,416,418,3,54,27,0,417,
+ 415,1,0,0,0,418,421,1,0,0,0,419,417,1,0,0,0,419,420,1,0,0,0,420,53,1,
+ 0,0,0,421,419,1,0,0,0,422,423,3,114,57,0,423,424,5,212,0,0,424,425,3,
+ 104,52,0,425,55,1,0,0,0,426,428,3,58,29,0,427,426,1,0,0,0,427,428,1,0,
+ 0,0,428,430,1,0,0,0,429,431,3,60,30,0,430,429,1,0,0,0,430,431,1,0,0,0,
+ 431,433,1,0,0,0,432,434,3,62,31,0,433,432,1,0,0,0,433,434,1,0,0,0,434,
+ 57,1,0,0,0,435,436,5,126,0,0,436,437,5,18,0,0,437,438,3,72,36,0,438,59,
+ 1,0,0,0,439,440,5,122,0,0,440,441,5,18,0,0,441,442,3,46,23,0,442,61,1,
+ 0,0,0,443,444,7,8,0,0,444,445,3,64,32,0,445,63,1,0,0,0,446,453,3,66,33,
+ 0,447,448,5,16,0,0,448,449,3,66,33,0,449,450,5,6,0,0,450,451,3,66,33,
+ 0,451,453,1,0,0,0,452,446,1,0,0,0,452,447,1,0,0,0,453,65,1,0,0,0,454,
+ 455,5,33,0,0,455,467,5,142,0,0,456,457,5,175,0,0,457,467,5,128,0,0,458,
+ 459,5,175,0,0,459,467,5,64,0,0,460,461,3,102,51,0,461,462,5,128,0,0,462,
+ 467,1,0,0,0,463,464,3,102,51,0,464,465,5,64,0,0,465,467,1,0,0,0,466,454,
+ 1,0,0,0,466,456,1,0,0,0,466,458,1,0,0,0,466,460,1,0,0,0,466,463,1,0,0,
+ 0,467,67,1,0,0,0,468,469,3,74,37,0,469,470,5,0,0,1,470,69,1,0,0,0,471,
+ 519,3,114,57,0,472,473,3,114,57,0,473,474,5,220,0,0,474,475,3,114,57,
+ 0,475,482,3,70,35,0,476,477,5,206,0,0,477,478,3,114,57,0,478,479,3,70,
+ 35,0,479,481,1,0,0,0,480,476,1,0,0,0,481,484,1,0,0,0,482,480,1,0,0,0,
+ 482,483,1,0,0,0,483,485,1,0,0,0,484,482,1,0,0,0,485,486,5,236,0,0,486,
+ 519,1,0,0,0,487,488,3,114,57,0,488,489,5,220,0,0,489,494,3,116,58,0,490,
+ 491,5,206,0,0,491,493,3,116,58,0,492,490,1,0,0,0,493,496,1,0,0,0,494,
+ 492,1,0,0,0,494,495,1,0,0,0,495,497,1,0,0,0,496,494,1,0,0,0,497,498,5,
+ 236,0,0,498,519,1,0,0,0,499,500,3,114,57,0,500,501,5,220,0,0,501,506,
+ 3,70,35,0,502,503,5,206,0,0,503,505,3,70,35,0,504,502,1,0,0,0,505,508,
+ 1,0,0,0,506,504,1,0,0,0,506,507,1,0,0,0,507,509,1,0,0,0,508,506,1,0,0,
+ 0,509,510,5,236,0,0,510,519,1,0,0,0,511,512,3,114,57,0,512,514,5,220,
+ 0,0,513,515,3,72,36,0,514,513,1,0,0,0,514,515,1,0,0,0,515,516,1,0,0,0,
+ 516,517,5,236,0,0,517,519,1,0,0,0,518,471,1,0,0,0,518,472,1,0,0,0,518,
+ 487,1,0,0,0,518,499,1,0,0,0,518,511,1,0,0,0,519,71,1,0,0,0,520,525,3,
+ 74,37,0,521,522,5,206,0,0,522,524,3,74,37,0,523,521,1,0,0,0,524,527,1,
+ 0,0,0,525,523,1,0,0,0,525,526,1,0,0,0,526,73,1,0,0,0,527,525,1,0,0,0,
+ 528,529,6,37,-1,0,529,531,5,19,0,0,530,532,3,74,37,0,531,530,1,0,0,0,
+ 531,532,1,0,0,0,532,538,1,0,0,0,533,534,5,186,0,0,534,535,3,74,37,0,535,
+ 536,5,163,0,0,536,537,3,74,37,0,537,539,1,0,0,0,538,533,1,0,0,0,539,540,
+ 1,0,0,0,540,538,1,0,0,0,540,541,1,0,0,0,541,544,1,0,0,0,542,543,5,52,
+ 0,0,543,545,3,74,37,0,544,542,1,0,0,0,544,545,1,0,0,0,545,546,1,0,0,0,
+ 546,547,5,53,0,0,547,658,1,0,0,0,548,549,5,20,0,0,549,550,5,220,0,0,550,
+ 551,3,74,37,0,551,552,5,10,0,0,552,553,3,70,35,0,553,554,5,236,0,0,554,
+ 658,1,0,0,0,555,556,5,36,0,0,556,658,5,199,0,0,557,558,5,59,0,0,558,559,
+ 5,220,0,0,559,560,3,106,53,0,560,561,5,68,0,0,561,562,3,74,37,0,562,563,
+ 5,236,0,0,563,658,1,0,0,0,564,565,5,86,0,0,565,566,3,74,37,0,566,567,
+ 3,106,53,0,567,658,1,0,0,0,568,569,5,155,0,0,569,570,5,220,0,0,570,571,
+ 3,74,37,0,571,572,5,68,0,0,572,575,3,74,37,0,573,574,5,65,0,0,574,576,
+ 3,74,37,0,575,573,1,0,0,0,575,576,1,0,0,0,576,577,1,0,0,0,577,578,5,236,
+ 0,0,578,658,1,0,0,0,579,580,5,166,0,0,580,658,5,199,0,0,581,582,5,171,
+ 0,0,582,583,5,220,0,0,583,584,7,9,0,0,584,585,5,199,0,0,585,586,5,68,
+ 0,0,586,587,3,74,37,0,587,588,5,236,0,0,588,658,1,0,0,0,589,590,3,114,
+ 57,0,590,592,5,220,0,0,591,593,3,72,36,0,592,591,1,0,0,0,592,593,1,0,
+ 0,0,593,594,1,0,0,0,594,595,5,236,0,0,595,596,1,0,0,0,596,597,5,125,0,
+ 0,597,598,5,220,0,0,598,599,3,56,28,0,599,600,5,236,0,0,600,658,1,0,0,
+ 0,601,602,3,114,57,0,602,604,5,220,0,0,603,605,3,72,36,0,604,603,1,0,
+ 0,0,604,605,1,0,0,0,605,606,1,0,0,0,606,607,5,236,0,0,607,608,1,0,0,0,
+ 608,609,5,125,0,0,609,610,3,114,57,0,610,658,1,0,0,0,611,617,3,114,57,
+ 0,612,614,5,220,0,0,613,615,3,72,36,0,614,613,1,0,0,0,614,615,1,0,0,0,
+ 615,616,1,0,0,0,616,618,5,236,0,0,617,612,1,0,0,0,617,618,1,0,0,0,618,
+ 619,1,0,0,0,619,621,5,220,0,0,620,622,5,49,0,0,621,620,1,0,0,0,621,622,
+ 1,0,0,0,622,624,1,0,0,0,623,625,3,76,38,0,624,623,1,0,0,0,624,625,1,0,
+ 0,0,625,626,1,0,0,0,626,627,5,236,0,0,627,658,1,0,0,0,628,658,3,104,52,
+ 0,629,630,5,208,0,0,630,658,3,74,37,18,631,632,5,115,0,0,632,658,3,74,
+ 37,12,633,634,3,94,47,0,634,635,5,210,0,0,635,637,1,0,0,0,636,633,1,0,
+ 0,0,636,637,1,0,0,0,637,638,1,0,0,0,638,658,5,202,0,0,639,640,5,220,0,
+ 0,640,641,3,2,1,0,641,642,5,236,0,0,642,658,1,0,0,0,643,644,5,220,0,0,
+ 644,645,3,74,37,0,645,646,5,236,0,0,646,658,1,0,0,0,647,648,5,220,0,0,
+ 648,649,3,72,36,0,649,650,5,236,0,0,650,658,1,0,0,0,651,653,5,219,0,0,
+ 652,654,3,72,36,0,653,652,1,0,0,0,653,654,1,0,0,0,654,655,1,0,0,0,655,
+ 658,5,235,0,0,656,658,3,86,43,0,657,528,1,0,0,0,657,548,1,0,0,0,657,555,
+ 1,0,0,0,657,557,1,0,0,0,657,564,1,0,0,0,657,568,1,0,0,0,657,579,1,0,0,
+ 0,657,581,1,0,0,0,657,589,1,0,0,0,657,601,1,0,0,0,657,611,1,0,0,0,657,
+ 628,1,0,0,0,657,629,1,0,0,0,657,631,1,0,0,0,657,636,1,0,0,0,657,639,1,
+ 0,0,0,657,643,1,0,0,0,657,647,1,0,0,0,657,651,1,0,0,0,657,656,1,0,0,0,
+ 658,752,1,0,0,0,659,663,10,17,0,0,660,664,5,202,0,0,661,664,5,238,0,0,
+ 662,664,5,227,0,0,663,660,1,0,0,0,663,661,1,0,0,0,663,662,1,0,0,0,664,
+ 665,1,0,0,0,665,751,3,74,37,18,666,670,10,16,0,0,667,671,5,228,0,0,668,
+ 671,5,208,0,0,669,671,5,207,0,0,670,667,1,0,0,0,670,668,1,0,0,0,670,669,
+ 1,0,0,0,671,672,1,0,0,0,672,751,3,74,37,17,673,698,10,15,0,0,674,699,
+ 5,211,0,0,675,699,5,212,0,0,676,699,5,223,0,0,677,699,5,221,0,0,678,699,
+ 5,222,0,0,679,699,5,213,0,0,680,699,5,214,0,0,681,683,5,115,0,0,682,681,
+ 1,0,0,0,682,683,1,0,0,0,683,684,1,0,0,0,684,686,5,80,0,0,685,687,5,25,
+ 0,0,686,685,1,0,0,0,686,687,1,0,0,0,687,699,1,0,0,0,688,690,5,115,0,0,
+ 689,688,1,0,0,0,689,690,1,0,0,0,690,691,1,0,0,0,691,699,7,10,0,0,692,
+ 699,5,232,0,0,693,699,5,233,0,0,694,699,5,225,0,0,695,699,5,216,0,0,696,
+ 699,5,217,0,0,697,699,5,224,0,0,698,674,1,0,0,0,698,675,1,0,0,0,698,676,
+ 1,0,0,0,698,677,1,0,0,0,698,678,1,0,0,0,698,679,1,0,0,0,698,680,1,0,0,
+ 0,698,682,1,0,0,0,698,689,1,0,0,0,698,692,1,0,0,0,698,693,1,0,0,0,698,
+ 694,1,0,0,0,698,695,1,0,0,0,698,696,1,0,0,0,698,697,1,0,0,0,699,700,1,
+ 0,0,0,700,751,3,74,37,16,701,702,10,13,0,0,702,703,5,226,0,0,703,751,
+ 3,74,37,14,704,705,10,11,0,0,705,706,5,6,0,0,706,751,3,74,37,12,707,708,
+ 10,10,0,0,708,709,5,121,0,0,709,751,3,74,37,11,710,712,10,9,0,0,711,713,
+ 5,115,0,0,712,711,1,0,0,0,712,713,1,0,0,0,713,714,1,0,0,0,714,715,5,16,
+ 0,0,715,716,3,74,37,0,716,717,5,6,0,0,717,718,3,74,37,10,718,751,1,0,
+ 0,0,719,720,10,8,0,0,720,721,5,229,0,0,721,722,3,74,37,0,722,723,5,205,
+ 0,0,723,724,3,74,37,8,724,751,1,0,0,0,725,726,10,21,0,0,726,727,5,219,
+ 0,0,727,728,3,74,37,0,728,729,5,235,0,0,729,751,1,0,0,0,730,731,10,20,
+ 0,0,731,732,5,210,0,0,732,751,5,197,0,0,733,734,10,19,0,0,734,735,5,210,
+ 0,0,735,751,3,114,57,0,736,737,10,14,0,0,737,739,5,88,0,0,738,740,5,115,
+ 0,0,739,738,1,0,0,0,739,740,1,0,0,0,740,741,1,0,0,0,741,751,5,116,0,0,
+ 742,748,10,7,0,0,743,749,3,112,56,0,744,745,5,10,0,0,745,749,3,114,57,
+ 0,746,747,5,10,0,0,747,749,5,199,0,0,748,743,1,0,0,0,748,744,1,0,0,0,
+ 748,746,1,0,0,0,749,751,1,0,0,0,750,659,1,0,0,0,750,666,1,0,0,0,750,673,
+ 1,0,0,0,750,701,1,0,0,0,750,704,1,0,0,0,750,707,1,0,0,0,750,710,1,0,0,
+ 0,750,719,1,0,0,0,750,725,1,0,0,0,750,730,1,0,0,0,750,733,1,0,0,0,750,
+ 736,1,0,0,0,750,742,1,0,0,0,751,754,1,0,0,0,752,750,1,0,0,0,752,753,1,
+ 0,0,0,753,75,1,0,0,0,754,752,1,0,0,0,755,760,3,78,39,0,756,757,5,206,
+ 0,0,757,759,3,78,39,0,758,756,1,0,0,0,759,762,1,0,0,0,760,758,1,0,0,0,
+ 760,761,1,0,0,0,761,77,1,0,0,0,762,760,1,0,0,0,763,766,3,80,40,0,764,
+ 766,3,74,37,0,765,763,1,0,0,0,765,764,1,0,0,0,766,79,1,0,0,0,767,768,
+ 5,220,0,0,768,773,3,114,57,0,769,770,5,206,0,0,770,772,3,114,57,0,771,
+ 769,1,0,0,0,772,775,1,0,0,0,773,771,1,0,0,0,773,774,1,0,0,0,774,776,1,
+ 0,0,0,775,773,1,0,0,0,776,777,5,236,0,0,777,787,1,0,0,0,778,783,3,114,
+ 57,0,779,780,5,206,0,0,780,782,3,114,57,0,781,779,1,0,0,0,782,785,1,0,
+ 0,0,783,781,1,0,0,0,783,784,1,0,0,0,784,787,1,0,0,0,785,783,1,0,0,0,786,
+ 767,1,0,0,0,786,778,1,0,0,0,787,788,1,0,0,0,788,789,5,201,0,0,789,790,
+ 3,74,37,0,790,81,1,0,0,0,791,796,3,84,42,0,792,793,5,206,0,0,793,795,
+ 3,84,42,0,794,792,1,0,0,0,795,798,1,0,0,0,796,794,1,0,0,0,796,797,1,0,
+ 0,0,797,83,1,0,0,0,798,796,1,0,0,0,799,800,3,114,57,0,800,801,5,10,0,
+ 0,801,802,5,220,0,0,802,803,3,2,1,0,803,804,5,236,0,0,804,810,1,0,0,0,
+ 805,806,3,74,37,0,806,807,5,10,0,0,807,808,3,114,57,0,808,810,1,0,0,0,
+ 809,799,1,0,0,0,809,805,1,0,0,0,810,85,1,0,0,0,811,819,5,200,0,0,812,
+ 813,3,94,47,0,813,814,5,210,0,0,814,816,1,0,0,0,815,812,1,0,0,0,815,816,
+ 1,0,0,0,816,817,1,0,0,0,817,819,3,88,44,0,818,811,1,0,0,0,818,815,1,0,
+ 0,0,819,87,1,0,0,0,820,825,3,114,57,0,821,822,5,210,0,0,822,824,3,114,
+ 57,0,823,821,1,0,0,0,824,827,1,0,0,0,825,823,1,0,0,0,825,826,1,0,0,0,
+ 826,89,1,0,0,0,827,825,1,0,0,0,828,829,6,45,-1,0,829,837,3,94,47,0,830,
+ 837,3,92,46,0,831,832,5,220,0,0,832,833,3,2,1,0,833,834,5,236,0,0,834,
+ 837,1,0,0,0,835,837,5,200,0,0,836,828,1,0,0,0,836,830,1,0,0,0,836,831,
+ 1,0,0,0,836,835,1,0,0,0,837,846,1,0,0,0,838,842,10,2,0,0,839,843,3,112,
+ 56,0,840,841,5,10,0,0,841,843,3,114,57,0,842,839,1,0,0,0,842,840,1,0,
+ 0,0,843,845,1,0,0,0,844,838,1,0,0,0,845,848,1,0,0,0,846,844,1,0,0,0,846,
+ 847,1,0,0,0,847,91,1,0,0,0,848,846,1,0,0,0,849,850,3,114,57,0,850,852,
+ 5,220,0,0,851,853,3,96,48,0,852,851,1,0,0,0,852,853,1,0,0,0,853,854,1,
+ 0,0,0,854,855,5,236,0,0,855,93,1,0,0,0,856,857,3,98,49,0,857,858,5,210,
+ 0,0,858,860,1,0,0,0,859,856,1,0,0,0,859,860,1,0,0,0,860,861,1,0,0,0,861,
+ 862,3,114,57,0,862,95,1,0,0,0,863,868,3,74,37,0,864,865,5,206,0,0,865,
+ 867,3,74,37,0,866,864,1,0,0,0,867,870,1,0,0,0,868,866,1,0,0,0,868,869,
+ 1,0,0,0,869,97,1,0,0,0,870,868,1,0,0,0,871,872,3,114,57,0,872,99,1,0,
+ 0,0,873,882,5,195,0,0,874,875,5,210,0,0,875,882,7,11,0,0,876,877,5,197,
+ 0,0,877,879,5,210,0,0,878,880,7,11,0,0,879,878,1,0,0,0,879,880,1,0,0,
+ 0,880,882,1,0,0,0,881,873,1,0,0,0,881,874,1,0,0,0,881,876,1,0,0,0,882,
+ 101,1,0,0,0,883,885,7,12,0,0,884,883,1,0,0,0,884,885,1,0,0,0,885,892,
+ 1,0,0,0,886,893,3,100,50,0,887,893,5,196,0,0,888,893,5,197,0,0,889,893,
+ 5,198,0,0,890,893,5,82,0,0,891,893,5,113,0,0,892,886,1,0,0,0,892,887,
+ 1,0,0,0,892,888,1,0,0,0,892,889,1,0,0,0,892,890,1,0,0,0,892,891,1,0,0,
+ 0,893,103,1,0,0,0,894,898,3,102,51,0,895,898,5,199,0,0,896,898,5,116,
+ 0,0,897,894,1,0,0,0,897,895,1,0,0,0,897,896,1,0,0,0,898,105,1,0,0,0,899,
+ 900,7,13,0,0,900,107,1,0,0,0,901,902,7,14,0,0,902,109,1,0,0,0,903,904,
+ 7,15,0,0,904,111,1,0,0,0,905,908,5,194,0,0,906,908,3,110,55,0,907,905,
+ 1,0,0,0,907,906,1,0,0,0,908,113,1,0,0,0,909,913,5,194,0,0,910,913,3,106,
+ 53,0,911,913,3,108,54,0,912,909,1,0,0,0,912,910,1,0,0,0,912,911,1,0,0,
+ 0,913,115,1,0,0,0,914,915,5,199,0,0,915,916,5,212,0,0,916,917,3,102,51,
+ 0,917,117,1,0,0,0,114,120,130,138,141,145,148,152,155,158,161,164,168,
+ 172,175,178,181,185,188,197,203,224,241,258,264,270,281,283,294,297,303,
+ 311,317,319,323,328,331,334,338,342,345,347,350,354,358,361,363,365,370,
+ 381,387,394,399,403,407,412,419,427,430,433,452,466,482,494,506,514,518,
+ 525,531,540,544,575,592,604,614,617,621,624,636,653,657,663,670,682,686,
+ 689,698,712,739,748,750,752,760,765,773,783,786,796,809,815,818,825,836,
+ 842,846,852,859,868,879,881,884,892,897,907,912
+ };
+ staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0]));
+
+ antlr4::atn::ATNDeserializer deserializer;
+ staticData->atn = deserializer.deserialize(staticData->serializedATN);
+
+ const size_t count = staticData->atn->getNumberOfDecisions();
+ staticData->decisionToDFA.reserve(count);
+ for (size_t i = 0; i < count; i++) {
+ staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i);
+ }
+ hogqlparserParserStaticData = staticData.release();
+}
+
+}
+
+HogQLParser::HogQLParser(TokenStream *input) : HogQLParser(input, antlr4::atn::ParserATNSimulatorOptions()) {}
+
+HogQLParser::HogQLParser(TokenStream *input, const antlr4::atn::ParserATNSimulatorOptions &options) : Parser(input) {
+ HogQLParser::initialize();
+ _interpreter = new atn::ParserATNSimulator(this, *hogqlparserParserStaticData->atn, hogqlparserParserStaticData->decisionToDFA, hogqlparserParserStaticData->sharedContextCache, options);
+}
+
+HogQLParser::~HogQLParser() {
+ delete _interpreter;
+}
+
+const atn::ATN& HogQLParser::getATN() const {
+ return *hogqlparserParserStaticData->atn;
+}
+
+std::string HogQLParser::getGrammarFileName() const {
+ return "HogQLParser.g4";
+}
+
+const std::vector& HogQLParser::getRuleNames() const {
+ return hogqlparserParserStaticData->ruleNames;
+}
+
+const dfa::Vocabulary& HogQLParser::getVocabulary() const {
+ return hogqlparserParserStaticData->vocabulary;
+}
+
+antlr4::atn::SerializedATNView HogQLParser::getSerializedATN() const {
+ return hogqlparserParserStaticData->serializedATN;
+}
+
+
+//----------------- SelectContext ------------------------------------------------------------------
+
+HogQLParser::SelectContext::SelectContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::SelectContext::EOF() {
+ return getToken(HogQLParser::EOF, 0);
+}
+
+HogQLParser::SelectUnionStmtContext* HogQLParser::SelectContext::selectUnionStmt() {
+ return getRuleContext(0);
+}
+
+HogQLParser::SelectStmtContext* HogQLParser::SelectContext::selectStmt() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::SelectContext::getRuleIndex() const {
+ return HogQLParser::RuleSelect;
+}
+
+
+std::any HogQLParser::SelectContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitSelect(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::SelectContext* HogQLParser::select() {
+ SelectContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 0, HogQLParser::RuleSelect);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(120);
+ _errHandler->sync(this);
+ switch (getInterpreter()->adaptivePredict(_input, 0, _ctx)) {
+ case 1: {
+ setState(118);
+ selectUnionStmt();
+ break;
+ }
+
+ case 2: {
+ setState(119);
+ selectStmt();
+ break;
+ }
+
+ default:
+ break;
+ }
+ setState(122);
+ match(HogQLParser::EOF);
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- SelectUnionStmtContext ------------------------------------------------------------------
+
+HogQLParser::SelectUnionStmtContext::SelectUnionStmtContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+std::vector HogQLParser::SelectUnionStmtContext::selectStmtWithParens() {
+ return getRuleContexts();
+}
+
+HogQLParser::SelectStmtWithParensContext* HogQLParser::SelectUnionStmtContext::selectStmtWithParens(size_t i) {
+ return getRuleContext(i);
+}
+
+std::vector HogQLParser::SelectUnionStmtContext::UNION() {
+ return getTokens(HogQLParser::UNION);
+}
+
+tree::TerminalNode* HogQLParser::SelectUnionStmtContext::UNION(size_t i) {
+ return getToken(HogQLParser::UNION, i);
+}
+
+std::vector HogQLParser::SelectUnionStmtContext::ALL() {
+ return getTokens(HogQLParser::ALL);
+}
+
+tree::TerminalNode* HogQLParser::SelectUnionStmtContext::ALL(size_t i) {
+ return getToken(HogQLParser::ALL, i);
+}
+
+
+size_t HogQLParser::SelectUnionStmtContext::getRuleIndex() const {
+ return HogQLParser::RuleSelectUnionStmt;
+}
+
+
+std::any HogQLParser::SelectUnionStmtContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitSelectUnionStmt(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::SelectUnionStmtContext* HogQLParser::selectUnionStmt() {
+ SelectUnionStmtContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 2, HogQLParser::RuleSelectUnionStmt);
+ size_t _la = 0;
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(124);
+ selectStmtWithParens();
+ setState(130);
+ _errHandler->sync(this);
+ _la = _input->LA(1);
+ while (_la == HogQLParser::UNION) {
+ setState(125);
+ match(HogQLParser::UNION);
+ setState(126);
+ match(HogQLParser::ALL);
+ setState(127);
+ selectStmtWithParens();
+ setState(132);
+ _errHandler->sync(this);
+ _la = _input->LA(1);
+ }
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- SelectStmtWithParensContext ------------------------------------------------------------------
+
+HogQLParser::SelectStmtWithParensContext::SelectStmtWithParensContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+HogQLParser::SelectStmtContext* HogQLParser::SelectStmtWithParensContext::selectStmt() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtWithParensContext::LPAREN() {
+ return getToken(HogQLParser::LPAREN, 0);
+}
+
+HogQLParser::SelectUnionStmtContext* HogQLParser::SelectStmtWithParensContext::selectUnionStmt() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtWithParensContext::RPAREN() {
+ return getToken(HogQLParser::RPAREN, 0);
+}
+
+
+size_t HogQLParser::SelectStmtWithParensContext::getRuleIndex() const {
+ return HogQLParser::RuleSelectStmtWithParens;
+}
+
+
+std::any HogQLParser::SelectStmtWithParensContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitSelectStmtWithParens(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::SelectStmtWithParensContext* HogQLParser::selectStmtWithParens() {
+ SelectStmtWithParensContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 4, HogQLParser::RuleSelectStmtWithParens);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ setState(138);
+ _errHandler->sync(this);
+ switch (_input->LA(1)) {
+ case HogQLParser::SELECT:
+ case HogQLParser::WITH: {
+ enterOuterAlt(_localctx, 1);
+ setState(133);
+ selectStmt();
+ break;
+ }
+
+ case HogQLParser::LPAREN: {
+ enterOuterAlt(_localctx, 2);
+ setState(134);
+ match(HogQLParser::LPAREN);
+ setState(135);
+ selectUnionStmt();
+ setState(136);
+ match(HogQLParser::RPAREN);
+ break;
+ }
+
+ default:
+ throw NoViableAltException(this);
+ }
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- SelectStmtContext ------------------------------------------------------------------
+
+HogQLParser::SelectStmtContext::SelectStmtContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtContext::SELECT() {
+ return getToken(HogQLParser::SELECT, 0);
+}
+
+HogQLParser::ColumnExprListContext* HogQLParser::SelectStmtContext::columnExprList() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtContext::DISTINCT() {
+ return getToken(HogQLParser::DISTINCT, 0);
+}
+
+HogQLParser::TopClauseContext* HogQLParser::SelectStmtContext::topClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::ArrayJoinClauseContext* HogQLParser::SelectStmtContext::arrayJoinClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::PrewhereClauseContext* HogQLParser::SelectStmtContext::prewhereClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::GroupByClauseContext* HogQLParser::SelectStmtContext::groupByClause() {
+ return getRuleContext(0);
+}
+
+std::vector HogQLParser::SelectStmtContext::WITH() {
+ return getTokens(HogQLParser::WITH);
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtContext::WITH(size_t i) {
+ return getToken(HogQLParser::WITH, i);
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtContext::TOTALS() {
+ return getToken(HogQLParser::TOTALS, 0);
+}
+
+HogQLParser::HavingClauseContext* HogQLParser::SelectStmtContext::havingClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::WindowClauseContext* HogQLParser::SelectStmtContext::windowClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::OrderByClauseContext* HogQLParser::SelectStmtContext::orderByClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::LimitAndOffsetClauseContext* HogQLParser::SelectStmtContext::limitAndOffsetClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::OffsetOnlyClauseContext* HogQLParser::SelectStmtContext::offsetOnlyClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::SettingsClauseContext* HogQLParser::SelectStmtContext::settingsClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::WithClauseContext* HogQLParser::SelectStmtContext::withClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::FromClauseContext* HogQLParser::SelectStmtContext::fromClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::WhereClauseContext* HogQLParser::SelectStmtContext::whereClause() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtContext::CUBE() {
+ return getToken(HogQLParser::CUBE, 0);
+}
+
+tree::TerminalNode* HogQLParser::SelectStmtContext::ROLLUP() {
+ return getToken(HogQLParser::ROLLUP, 0);
+}
+
+
+size_t HogQLParser::SelectStmtContext::getRuleIndex() const {
+ return HogQLParser::RuleSelectStmt;
+}
+
+
+std::any HogQLParser::SelectStmtContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitSelectStmt(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::SelectStmtContext* HogQLParser::selectStmt() {
+ SelectStmtContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 6, HogQLParser::RuleSelectStmt);
+ size_t _la = 0;
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(141);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::WITH) {
+ setState(140);
+ antlrcpp::downCast(_localctx)->with = withClause();
+ }
+ setState(143);
+ match(HogQLParser::SELECT);
+ setState(145);
+ _errHandler->sync(this);
+
+ switch (getInterpreter()->adaptivePredict(_input, 4, _ctx)) {
+ case 1: {
+ setState(144);
+ match(HogQLParser::DISTINCT);
+ break;
+ }
+
+ default:
+ break;
+ }
+ setState(148);
+ _errHandler->sync(this);
+
+ switch (getInterpreter()->adaptivePredict(_input, 5, _ctx)) {
+ case 1: {
+ setState(147);
+ topClause();
+ break;
+ }
+
+ default:
+ break;
+ }
+ setState(150);
+ antlrcpp::downCast(_localctx)->columns = columnExprList();
+ setState(152);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::FROM) {
+ setState(151);
+ antlrcpp::downCast(_localctx)->from = fromClause();
+ }
+ setState(155);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::ARRAY || _la == HogQLParser::INNER
+
+ || _la == HogQLParser::LEFT) {
+ setState(154);
+ arrayJoinClause();
+ }
+ setState(158);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::PREWHERE) {
+ setState(157);
+ prewhereClause();
+ }
+ setState(161);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::WHERE) {
+ setState(160);
+ antlrcpp::downCast(_localctx)->where = whereClause();
+ }
+ setState(164);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::GROUP) {
+ setState(163);
+ groupByClause();
+ }
+ setState(168);
+ _errHandler->sync(this);
+
+ switch (getInterpreter()->adaptivePredict(_input, 11, _ctx)) {
+ case 1: {
+ setState(166);
+ match(HogQLParser::WITH);
+ setState(167);
+ _la = _input->LA(1);
+ if (!(_la == HogQLParser::CUBE || _la == HogQLParser::ROLLUP)) {
+ _errHandler->recoverInline(this);
+ }
+ else {
+ _errHandler->reportMatch(this);
+ consume();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ setState(172);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::WITH) {
+ setState(170);
+ match(HogQLParser::WITH);
+ setState(171);
+ match(HogQLParser::TOTALS);
+ }
+ setState(175);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::HAVING) {
+ setState(174);
+ havingClause();
+ }
+ setState(178);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::WINDOW) {
+ setState(177);
+ windowClause();
+ }
+ setState(181);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::ORDER) {
+ setState(180);
+ orderByClause();
+ }
+ setState(185);
+ _errHandler->sync(this);
+ switch (_input->LA(1)) {
+ case HogQLParser::LIMIT: {
+ setState(183);
+ limitAndOffsetClause();
+ break;
+ }
+
+ case HogQLParser::OFFSET: {
+ setState(184);
+ offsetOnlyClause();
+ break;
+ }
+
+ case HogQLParser::EOF:
+ case HogQLParser::SETTINGS:
+ case HogQLParser::UNION:
+ case HogQLParser::RPAREN: {
+ break;
+ }
+
+ default:
+ break;
+ }
+ setState(188);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::SETTINGS) {
+ setState(187);
+ settingsClause();
+ }
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- WithClauseContext ------------------------------------------------------------------
+
+HogQLParser::WithClauseContext::WithClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::WithClauseContext::WITH() {
+ return getToken(HogQLParser::WITH, 0);
+}
+
+HogQLParser::WithExprListContext* HogQLParser::WithClauseContext::withExprList() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::WithClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleWithClause;
+}
+
+
+std::any HogQLParser::WithClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitWithClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::WithClauseContext* HogQLParser::withClause() {
+ WithClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 8, HogQLParser::RuleWithClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(190);
+ match(HogQLParser::WITH);
+ setState(191);
+ withExprList();
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- TopClauseContext ------------------------------------------------------------------
+
+HogQLParser::TopClauseContext::TopClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::TopClauseContext::TOP() {
+ return getToken(HogQLParser::TOP, 0);
+}
+
+tree::TerminalNode* HogQLParser::TopClauseContext::DECIMAL_LITERAL() {
+ return getToken(HogQLParser::DECIMAL_LITERAL, 0);
+}
+
+tree::TerminalNode* HogQLParser::TopClauseContext::WITH() {
+ return getToken(HogQLParser::WITH, 0);
+}
+
+tree::TerminalNode* HogQLParser::TopClauseContext::TIES() {
+ return getToken(HogQLParser::TIES, 0);
+}
+
+
+size_t HogQLParser::TopClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleTopClause;
+}
+
+
+std::any HogQLParser::TopClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitTopClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::TopClauseContext* HogQLParser::topClause() {
+ TopClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 10, HogQLParser::RuleTopClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(193);
+ match(HogQLParser::TOP);
+ setState(194);
+ match(HogQLParser::DECIMAL_LITERAL);
+ setState(197);
+ _errHandler->sync(this);
+
+ switch (getInterpreter()->adaptivePredict(_input, 18, _ctx)) {
+ case 1: {
+ setState(195);
+ match(HogQLParser::WITH);
+ setState(196);
+ match(HogQLParser::TIES);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- FromClauseContext ------------------------------------------------------------------
+
+HogQLParser::FromClauseContext::FromClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::FromClauseContext::FROM() {
+ return getToken(HogQLParser::FROM, 0);
+}
+
+HogQLParser::JoinExprContext* HogQLParser::FromClauseContext::joinExpr() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::FromClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleFromClause;
+}
+
+
+std::any HogQLParser::FromClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitFromClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::FromClauseContext* HogQLParser::fromClause() {
+ FromClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 12, HogQLParser::RuleFromClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(199);
+ match(HogQLParser::FROM);
+ setState(200);
+ joinExpr(0);
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- ArrayJoinClauseContext ------------------------------------------------------------------
+
+HogQLParser::ArrayJoinClauseContext::ArrayJoinClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::ArrayJoinClauseContext::ARRAY() {
+ return getToken(HogQLParser::ARRAY, 0);
+}
+
+tree::TerminalNode* HogQLParser::ArrayJoinClauseContext::JOIN() {
+ return getToken(HogQLParser::JOIN, 0);
+}
+
+HogQLParser::ColumnExprListContext* HogQLParser::ArrayJoinClauseContext::columnExprList() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::ArrayJoinClauseContext::LEFT() {
+ return getToken(HogQLParser::LEFT, 0);
+}
+
+tree::TerminalNode* HogQLParser::ArrayJoinClauseContext::INNER() {
+ return getToken(HogQLParser::INNER, 0);
+}
+
+
+size_t HogQLParser::ArrayJoinClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleArrayJoinClause;
+}
+
+
+std::any HogQLParser::ArrayJoinClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitArrayJoinClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::ArrayJoinClauseContext* HogQLParser::arrayJoinClause() {
+ ArrayJoinClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 14, HogQLParser::RuleArrayJoinClause);
+ size_t _la = 0;
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(203);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::INNER
+
+ || _la == HogQLParser::LEFT) {
+ setState(202);
+ _la = _input->LA(1);
+ if (!(_la == HogQLParser::INNER
+
+ || _la == HogQLParser::LEFT)) {
+ _errHandler->recoverInline(this);
+ }
+ else {
+ _errHandler->reportMatch(this);
+ consume();
+ }
+ }
+ setState(205);
+ match(HogQLParser::ARRAY);
+ setState(206);
+ match(HogQLParser::JOIN);
+ setState(207);
+ columnExprList();
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- WindowClauseContext ------------------------------------------------------------------
+
+HogQLParser::WindowClauseContext::WindowClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::WindowClauseContext::WINDOW() {
+ return getToken(HogQLParser::WINDOW, 0);
+}
+
+std::vector HogQLParser::WindowClauseContext::identifier() {
+ return getRuleContexts();
+}
+
+HogQLParser::IdentifierContext* HogQLParser::WindowClauseContext::identifier(size_t i) {
+ return getRuleContext(i);
+}
+
+std::vector HogQLParser::WindowClauseContext::AS() {
+ return getTokens(HogQLParser::AS);
+}
+
+tree::TerminalNode* HogQLParser::WindowClauseContext::AS(size_t i) {
+ return getToken(HogQLParser::AS, i);
+}
+
+std::vector HogQLParser::WindowClauseContext::LPAREN() {
+ return getTokens(HogQLParser::LPAREN);
+}
+
+tree::TerminalNode* HogQLParser::WindowClauseContext::LPAREN(size_t i) {
+ return getToken(HogQLParser::LPAREN, i);
+}
+
+std::vector HogQLParser::WindowClauseContext::windowExpr() {
+ return getRuleContexts();
+}
+
+HogQLParser::WindowExprContext* HogQLParser::WindowClauseContext::windowExpr(size_t i) {
+ return getRuleContext(i);
+}
+
+std::vector HogQLParser::WindowClauseContext::RPAREN() {
+ return getTokens(HogQLParser::RPAREN);
+}
+
+tree::TerminalNode* HogQLParser::WindowClauseContext::RPAREN(size_t i) {
+ return getToken(HogQLParser::RPAREN, i);
+}
+
+std::vector HogQLParser::WindowClauseContext::COMMA() {
+ return getTokens(HogQLParser::COMMA);
+}
+
+tree::TerminalNode* HogQLParser::WindowClauseContext::COMMA(size_t i) {
+ return getToken(HogQLParser::COMMA, i);
+}
+
+
+size_t HogQLParser::WindowClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleWindowClause;
+}
+
+
+std::any HogQLParser::WindowClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitWindowClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::WindowClauseContext* HogQLParser::windowClause() {
+ WindowClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 16, HogQLParser::RuleWindowClause);
+ size_t _la = 0;
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(209);
+ match(HogQLParser::WINDOW);
+ setState(210);
+ identifier();
+ setState(211);
+ match(HogQLParser::AS);
+ setState(212);
+ match(HogQLParser::LPAREN);
+ setState(213);
+ windowExpr();
+ setState(214);
+ match(HogQLParser::RPAREN);
+ setState(224);
+ _errHandler->sync(this);
+ _la = _input->LA(1);
+ while (_la == HogQLParser::COMMA) {
+ setState(215);
+ match(HogQLParser::COMMA);
+ setState(216);
+ identifier();
+ setState(217);
+ match(HogQLParser::AS);
+ setState(218);
+ match(HogQLParser::LPAREN);
+ setState(219);
+ windowExpr();
+ setState(220);
+ match(HogQLParser::RPAREN);
+ setState(226);
+ _errHandler->sync(this);
+ _la = _input->LA(1);
+ }
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- PrewhereClauseContext ------------------------------------------------------------------
+
+HogQLParser::PrewhereClauseContext::PrewhereClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::PrewhereClauseContext::PREWHERE() {
+ return getToken(HogQLParser::PREWHERE, 0);
+}
+
+HogQLParser::ColumnExprContext* HogQLParser::PrewhereClauseContext::columnExpr() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::PrewhereClauseContext::getRuleIndex() const {
+ return HogQLParser::RulePrewhereClause;
+}
+
+
+std::any HogQLParser::PrewhereClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitPrewhereClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::PrewhereClauseContext* HogQLParser::prewhereClause() {
+ PrewhereClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 18, HogQLParser::RulePrewhereClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(227);
+ match(HogQLParser::PREWHERE);
+ setState(228);
+ columnExpr(0);
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- WhereClauseContext ------------------------------------------------------------------
+
+HogQLParser::WhereClauseContext::WhereClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::WhereClauseContext::WHERE() {
+ return getToken(HogQLParser::WHERE, 0);
+}
+
+HogQLParser::ColumnExprContext* HogQLParser::WhereClauseContext::columnExpr() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::WhereClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleWhereClause;
+}
+
+
+std::any HogQLParser::WhereClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitWhereClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::WhereClauseContext* HogQLParser::whereClause() {
+ WhereClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 20, HogQLParser::RuleWhereClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(230);
+ match(HogQLParser::WHERE);
+ setState(231);
+ columnExpr(0);
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- GroupByClauseContext ------------------------------------------------------------------
+
+HogQLParser::GroupByClauseContext::GroupByClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::GroupByClauseContext::GROUP() {
+ return getToken(HogQLParser::GROUP, 0);
+}
+
+tree::TerminalNode* HogQLParser::GroupByClauseContext::BY() {
+ return getToken(HogQLParser::BY, 0);
+}
+
+tree::TerminalNode* HogQLParser::GroupByClauseContext::LPAREN() {
+ return getToken(HogQLParser::LPAREN, 0);
+}
+
+HogQLParser::ColumnExprListContext* HogQLParser::GroupByClauseContext::columnExprList() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::GroupByClauseContext::RPAREN() {
+ return getToken(HogQLParser::RPAREN, 0);
+}
+
+tree::TerminalNode* HogQLParser::GroupByClauseContext::CUBE() {
+ return getToken(HogQLParser::CUBE, 0);
+}
+
+tree::TerminalNode* HogQLParser::GroupByClauseContext::ROLLUP() {
+ return getToken(HogQLParser::ROLLUP, 0);
+}
+
+
+size_t HogQLParser::GroupByClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleGroupByClause;
+}
+
+
+std::any HogQLParser::GroupByClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitGroupByClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::GroupByClauseContext* HogQLParser::groupByClause() {
+ GroupByClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 22, HogQLParser::RuleGroupByClause);
+ size_t _la = 0;
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(233);
+ match(HogQLParser::GROUP);
+ setState(234);
+ match(HogQLParser::BY);
+ setState(241);
+ _errHandler->sync(this);
+ switch (getInterpreter()->adaptivePredict(_input, 21, _ctx)) {
+ case 1: {
+ setState(235);
+ _la = _input->LA(1);
+ if (!(_la == HogQLParser::CUBE || _la == HogQLParser::ROLLUP)) {
+ _errHandler->recoverInline(this);
+ }
+ else {
+ _errHandler->reportMatch(this);
+ consume();
+ }
+ setState(236);
+ match(HogQLParser::LPAREN);
+ setState(237);
+ columnExprList();
+ setState(238);
+ match(HogQLParser::RPAREN);
+ break;
+ }
+
+ case 2: {
+ setState(240);
+ columnExprList();
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- HavingClauseContext ------------------------------------------------------------------
+
+HogQLParser::HavingClauseContext::HavingClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::HavingClauseContext::HAVING() {
+ return getToken(HogQLParser::HAVING, 0);
+}
+
+HogQLParser::ColumnExprContext* HogQLParser::HavingClauseContext::columnExpr() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::HavingClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleHavingClause;
+}
+
+
+std::any HogQLParser::HavingClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitHavingClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::HavingClauseContext* HogQLParser::havingClause() {
+ HavingClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 24, HogQLParser::RuleHavingClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(243);
+ match(HogQLParser::HAVING);
+ setState(244);
+ columnExpr(0);
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- OrderByClauseContext ------------------------------------------------------------------
+
+HogQLParser::OrderByClauseContext::OrderByClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::OrderByClauseContext::ORDER() {
+ return getToken(HogQLParser::ORDER, 0);
+}
+
+tree::TerminalNode* HogQLParser::OrderByClauseContext::BY() {
+ return getToken(HogQLParser::BY, 0);
+}
+
+HogQLParser::OrderExprListContext* HogQLParser::OrderByClauseContext::orderExprList() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::OrderByClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleOrderByClause;
+}
+
+
+std::any HogQLParser::OrderByClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitOrderByClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::OrderByClauseContext* HogQLParser::orderByClause() {
+ OrderByClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 26, HogQLParser::RuleOrderByClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(246);
+ match(HogQLParser::ORDER);
+ setState(247);
+ match(HogQLParser::BY);
+ setState(248);
+ orderExprList();
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- ProjectionOrderByClauseContext ------------------------------------------------------------------
+
+HogQLParser::ProjectionOrderByClauseContext::ProjectionOrderByClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::ProjectionOrderByClauseContext::ORDER() {
+ return getToken(HogQLParser::ORDER, 0);
+}
+
+tree::TerminalNode* HogQLParser::ProjectionOrderByClauseContext::BY() {
+ return getToken(HogQLParser::BY, 0);
+}
+
+HogQLParser::ColumnExprListContext* HogQLParser::ProjectionOrderByClauseContext::columnExprList() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::ProjectionOrderByClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleProjectionOrderByClause;
+}
+
+
+std::any HogQLParser::ProjectionOrderByClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitProjectionOrderByClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::ProjectionOrderByClauseContext* HogQLParser::projectionOrderByClause() {
+ ProjectionOrderByClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 28, HogQLParser::RuleProjectionOrderByClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(250);
+ match(HogQLParser::ORDER);
+ setState(251);
+ match(HogQLParser::BY);
+ setState(252);
+ columnExprList();
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- LimitAndOffsetClauseContext ------------------------------------------------------------------
+
+HogQLParser::LimitAndOffsetClauseContext::LimitAndOffsetClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::LimitAndOffsetClauseContext::LIMIT() {
+ return getToken(HogQLParser::LIMIT, 0);
+}
+
+std::vector HogQLParser::LimitAndOffsetClauseContext::columnExpr() {
+ return getRuleContexts();
+}
+
+HogQLParser::ColumnExprContext* HogQLParser::LimitAndOffsetClauseContext::columnExpr(size_t i) {
+ return getRuleContext(i);
+}
+
+tree::TerminalNode* HogQLParser::LimitAndOffsetClauseContext::COMMA() {
+ return getToken(HogQLParser::COMMA, 0);
+}
+
+tree::TerminalNode* HogQLParser::LimitAndOffsetClauseContext::BY() {
+ return getToken(HogQLParser::BY, 0);
+}
+
+HogQLParser::ColumnExprListContext* HogQLParser::LimitAndOffsetClauseContext::columnExprList() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::LimitAndOffsetClauseContext::WITH() {
+ return getToken(HogQLParser::WITH, 0);
+}
+
+tree::TerminalNode* HogQLParser::LimitAndOffsetClauseContext::TIES() {
+ return getToken(HogQLParser::TIES, 0);
+}
+
+tree::TerminalNode* HogQLParser::LimitAndOffsetClauseContext::OFFSET() {
+ return getToken(HogQLParser::OFFSET, 0);
+}
+
+
+size_t HogQLParser::LimitAndOffsetClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleLimitAndOffsetClause;
+}
+
+
+std::any HogQLParser::LimitAndOffsetClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitLimitAndOffsetClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::LimitAndOffsetClauseContext* HogQLParser::limitAndOffsetClause() {
+ LimitAndOffsetClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 30, HogQLParser::RuleLimitAndOffsetClause);
+ size_t _la = 0;
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ setState(283);
+ _errHandler->sync(this);
+ switch (getInterpreter()->adaptivePredict(_input, 26, _ctx)) {
+ case 1: {
+ enterOuterAlt(_localctx, 1);
+ setState(254);
+ match(HogQLParser::LIMIT);
+ setState(255);
+ columnExpr(0);
+ setState(258);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::COMMA) {
+ setState(256);
+ match(HogQLParser::COMMA);
+ setState(257);
+ columnExpr(0);
+ }
+ setState(264);
+ _errHandler->sync(this);
+ switch (_input->LA(1)) {
+ case HogQLParser::WITH: {
+ setState(260);
+ match(HogQLParser::WITH);
+ setState(261);
+ match(HogQLParser::TIES);
+ break;
+ }
+
+ case HogQLParser::BY: {
+ setState(262);
+ match(HogQLParser::BY);
+ setState(263);
+ columnExprList();
+ break;
+ }
+
+ case HogQLParser::EOF:
+ case HogQLParser::SETTINGS:
+ case HogQLParser::UNION:
+ case HogQLParser::RPAREN: {
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ case 2: {
+ enterOuterAlt(_localctx, 2);
+ setState(266);
+ match(HogQLParser::LIMIT);
+ setState(267);
+ columnExpr(0);
+ setState(270);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::WITH) {
+ setState(268);
+ match(HogQLParser::WITH);
+ setState(269);
+ match(HogQLParser::TIES);
+ }
+ setState(272);
+ match(HogQLParser::OFFSET);
+ setState(273);
+ columnExpr(0);
+ break;
+ }
+
+ case 3: {
+ enterOuterAlt(_localctx, 3);
+ setState(275);
+ match(HogQLParser::LIMIT);
+ setState(276);
+ columnExpr(0);
+ setState(277);
+ match(HogQLParser::OFFSET);
+ setState(278);
+ columnExpr(0);
+ setState(281);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if (_la == HogQLParser::BY) {
+ setState(279);
+ match(HogQLParser::BY);
+ setState(280);
+ columnExprList();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- OffsetOnlyClauseContext ------------------------------------------------------------------
+
+HogQLParser::OffsetOnlyClauseContext::OffsetOnlyClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::OffsetOnlyClauseContext::OFFSET() {
+ return getToken(HogQLParser::OFFSET, 0);
+}
+
+HogQLParser::ColumnExprContext* HogQLParser::OffsetOnlyClauseContext::columnExpr() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::OffsetOnlyClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleOffsetOnlyClause;
+}
+
+
+std::any HogQLParser::OffsetOnlyClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitOffsetOnlyClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::OffsetOnlyClauseContext* HogQLParser::offsetOnlyClause() {
+ OffsetOnlyClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 32, HogQLParser::RuleOffsetOnlyClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(285);
+ match(HogQLParser::OFFSET);
+ setState(286);
+ columnExpr(0);
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- SettingsClauseContext ------------------------------------------------------------------
+
+HogQLParser::SettingsClauseContext::SettingsClauseContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+tree::TerminalNode* HogQLParser::SettingsClauseContext::SETTINGS() {
+ return getToken(HogQLParser::SETTINGS, 0);
+}
+
+HogQLParser::SettingExprListContext* HogQLParser::SettingsClauseContext::settingExprList() {
+ return getRuleContext(0);
+}
+
+
+size_t HogQLParser::SettingsClauseContext::getRuleIndex() const {
+ return HogQLParser::RuleSettingsClause;
+}
+
+
+std::any HogQLParser::SettingsClauseContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitSettingsClause(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::SettingsClauseContext* HogQLParser::settingsClause() {
+ SettingsClauseContext *_localctx = _tracker.createInstance(_ctx, getState());
+ enterRule(_localctx, 34, HogQLParser::RuleSettingsClause);
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ exitRule();
+ });
+ try {
+ enterOuterAlt(_localctx, 1);
+ setState(288);
+ match(HogQLParser::SETTINGS);
+ setState(289);
+ settingExprList();
+
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+
+ return _localctx;
+}
+
+//----------------- JoinExprContext ------------------------------------------------------------------
+
+HogQLParser::JoinExprContext::JoinExprContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+
+size_t HogQLParser::JoinExprContext::getRuleIndex() const {
+ return HogQLParser::RuleJoinExpr;
+}
+
+void HogQLParser::JoinExprContext::copyFrom(JoinExprContext *ctx) {
+ ParserRuleContext::copyFrom(ctx);
+}
+
+//----------------- JoinExprOpContext ------------------------------------------------------------------
+
+std::vector HogQLParser::JoinExprOpContext::joinExpr() {
+ return getRuleContexts();
+}
+
+HogQLParser::JoinExprContext* HogQLParser::JoinExprOpContext::joinExpr(size_t i) {
+ return getRuleContext(i);
+}
+
+tree::TerminalNode* HogQLParser::JoinExprOpContext::JOIN() {
+ return getToken(HogQLParser::JOIN, 0);
+}
+
+HogQLParser::JoinConstraintClauseContext* HogQLParser::JoinExprOpContext::joinConstraintClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::JoinOpContext* HogQLParser::JoinExprOpContext::joinOp() {
+ return getRuleContext(0);
+}
+
+HogQLParser::JoinExprOpContext::JoinExprOpContext(JoinExprContext *ctx) { copyFrom(ctx); }
+
+
+std::any HogQLParser::JoinExprOpContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitJoinExprOp(this);
+ else
+ return visitor->visitChildren(this);
+}
+//----------------- JoinExprTableContext ------------------------------------------------------------------
+
+HogQLParser::TableExprContext* HogQLParser::JoinExprTableContext::tableExpr() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::JoinExprTableContext::FINAL() {
+ return getToken(HogQLParser::FINAL, 0);
+}
+
+HogQLParser::SampleClauseContext* HogQLParser::JoinExprTableContext::sampleClause() {
+ return getRuleContext(0);
+}
+
+HogQLParser::JoinExprTableContext::JoinExprTableContext(JoinExprContext *ctx) { copyFrom(ctx); }
+
+
+std::any HogQLParser::JoinExprTableContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitJoinExprTable(this);
+ else
+ return visitor->visitChildren(this);
+}
+//----------------- JoinExprParensContext ------------------------------------------------------------------
+
+tree::TerminalNode* HogQLParser::JoinExprParensContext::LPAREN() {
+ return getToken(HogQLParser::LPAREN, 0);
+}
+
+HogQLParser::JoinExprContext* HogQLParser::JoinExprParensContext::joinExpr() {
+ return getRuleContext(0);
+}
+
+tree::TerminalNode* HogQLParser::JoinExprParensContext::RPAREN() {
+ return getToken(HogQLParser::RPAREN, 0);
+}
+
+HogQLParser::JoinExprParensContext::JoinExprParensContext(JoinExprContext *ctx) { copyFrom(ctx); }
+
+
+std::any HogQLParser::JoinExprParensContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitJoinExprParens(this);
+ else
+ return visitor->visitChildren(this);
+}
+//----------------- JoinExprCrossOpContext ------------------------------------------------------------------
+
+std::vector HogQLParser::JoinExprCrossOpContext::joinExpr() {
+ return getRuleContexts();
+}
+
+HogQLParser::JoinExprContext* HogQLParser::JoinExprCrossOpContext::joinExpr(size_t i) {
+ return getRuleContext(i);
+}
+
+HogQLParser::JoinOpCrossContext* HogQLParser::JoinExprCrossOpContext::joinOpCross() {
+ return getRuleContext(0);
+}
+
+HogQLParser::JoinExprCrossOpContext::JoinExprCrossOpContext(JoinExprContext *ctx) { copyFrom(ctx); }
+
+
+std::any HogQLParser::JoinExprCrossOpContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitJoinExprCrossOp(this);
+ else
+ return visitor->visitChildren(this);
+}
+
+HogQLParser::JoinExprContext* HogQLParser::joinExpr() {
+ return joinExpr(0);
+}
+
+HogQLParser::JoinExprContext* HogQLParser::joinExpr(int precedence) {
+ ParserRuleContext *parentContext = _ctx;
+ size_t parentState = getState();
+ HogQLParser::JoinExprContext *_localctx = _tracker.createInstance(_ctx, parentState);
+ HogQLParser::JoinExprContext *previousContext = _localctx;
+ (void)previousContext; // Silence compiler, in case the context is not used by generated code.
+ size_t startState = 36;
+ enterRecursionRule(_localctx, 36, HogQLParser::RuleJoinExpr, precedence);
+
+ size_t _la = 0;
+
+#if __cplusplus > 201703L
+ auto onExit = finally([=, this] {
+#else
+ auto onExit = finally([=] {
+#endif
+ unrollRecursionContexts(parentContext);
+ });
+ try {
+ size_t alt;
+ enterOuterAlt(_localctx, 1);
+ setState(303);
+ _errHandler->sync(this);
+ switch (getInterpreter()->adaptivePredict(_input, 29, _ctx)) {
+ case 1: {
+ _localctx = _tracker.createInstance(_localctx);
+ _ctx = _localctx;
+ previousContext = _localctx;
+
+ setState(292);
+ tableExpr(0);
+ setState(294);
+ _errHandler->sync(this);
+
+ switch (getInterpreter()->adaptivePredict(_input, 27, _ctx)) {
+ case 1: {
+ setState(293);
+ match(HogQLParser::FINAL);
+ break;
+ }
+
+ default:
+ break;
+ }
+ setState(297);
+ _errHandler->sync(this);
+
+ switch (getInterpreter()->adaptivePredict(_input, 28, _ctx)) {
+ case 1: {
+ setState(296);
+ sampleClause();
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ case 2: {
+ _localctx = _tracker.createInstance(_localctx);
+ _ctx = _localctx;
+ previousContext = _localctx;
+ setState(299);
+ match(HogQLParser::LPAREN);
+ setState(300);
+ joinExpr(0);
+ setState(301);
+ match(HogQLParser::RPAREN);
+ break;
+ }
+
+ default:
+ break;
+ }
+ _ctx->stop = _input->LT(-1);
+ setState(319);
+ _errHandler->sync(this);
+ alt = getInterpreter()->adaptivePredict(_input, 32, _ctx);
+ while (alt != 2 && alt != atn::ATN::INVALID_ALT_NUMBER) {
+ if (alt == 1) {
+ if (!_parseListeners.empty())
+ triggerExitRuleEvent();
+ previousContext = _localctx;
+ setState(317);
+ _errHandler->sync(this);
+ switch (getInterpreter()->adaptivePredict(_input, 31, _ctx)) {
+ case 1: {
+ auto newContext = _tracker.createInstance(_tracker.createInstance(parentContext, parentState));
+ _localctx = newContext;
+ pushNewRecursionContext(newContext, startState, RuleJoinExpr);
+ setState(305);
+
+ if (!(precpred(_ctx, 3))) throw FailedPredicateException(this, "precpred(_ctx, 3)");
+ setState(306);
+ joinOpCross();
+ setState(307);
+ joinExpr(4);
+ break;
+ }
+
+ case 2: {
+ auto newContext = _tracker.createInstance(_tracker.createInstance(parentContext, parentState));
+ _localctx = newContext;
+ pushNewRecursionContext(newContext, startState, RuleJoinExpr);
+ setState(309);
+
+ if (!(precpred(_ctx, 4))) throw FailedPredicateException(this, "precpred(_ctx, 4)");
+ setState(311);
+ _errHandler->sync(this);
+
+ _la = _input->LA(1);
+ if ((((_la & ~ 0x3fULL) == 0) &&
+ ((1ULL << _la) & 4496) != 0) || ((((_la - 69) & ~ 0x3fULL) == 0) &&
+ ((1ULL << (_la - 69)) & 134250497) != 0) || _la == HogQLParser::RIGHT
+
+ || _la == HogQLParser::SEMI) {
+ setState(310);
+ joinOp();
+ }
+ setState(313);
+ match(HogQLParser::JOIN);
+ setState(314);
+ joinExpr(0);
+ setState(315);
+ joinConstraintClause();
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+ setState(321);
+ _errHandler->sync(this);
+ alt = getInterpreter()->adaptivePredict(_input, 32, _ctx);
+ }
+ }
+ catch (RecognitionException &e) {
+ _errHandler->reportError(this, e);
+ _localctx->exception = std::current_exception();
+ _errHandler->recover(this, _localctx->exception);
+ }
+ return _localctx;
+}
+
+//----------------- JoinOpContext ------------------------------------------------------------------
+
+HogQLParser::JoinOpContext::JoinOpContext(ParserRuleContext *parent, size_t invokingState)
+ : ParserRuleContext(parent, invokingState) {
+}
+
+
+size_t HogQLParser::JoinOpContext::getRuleIndex() const {
+ return HogQLParser::RuleJoinOp;
+}
+
+void HogQLParser::JoinOpContext::copyFrom(JoinOpContext *ctx) {
+ ParserRuleContext::copyFrom(ctx);
+}
+
+//----------------- JoinOpFullContext ------------------------------------------------------------------
+
+tree::TerminalNode* HogQLParser::JoinOpFullContext::FULL() {
+ return getToken(HogQLParser::FULL, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpFullContext::OUTER() {
+ return getToken(HogQLParser::OUTER, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpFullContext::ALL() {
+ return getToken(HogQLParser::ALL, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpFullContext::ANY() {
+ return getToken(HogQLParser::ANY, 0);
+}
+
+HogQLParser::JoinOpFullContext::JoinOpFullContext(JoinOpContext *ctx) { copyFrom(ctx); }
+
+
+std::any HogQLParser::JoinOpFullContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitJoinOpFull(this);
+ else
+ return visitor->visitChildren(this);
+}
+//----------------- JoinOpInnerContext ------------------------------------------------------------------
+
+tree::TerminalNode* HogQLParser::JoinOpInnerContext::INNER() {
+ return getToken(HogQLParser::INNER, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpInnerContext::ALL() {
+ return getToken(HogQLParser::ALL, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpInnerContext::ANY() {
+ return getToken(HogQLParser::ANY, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpInnerContext::ASOF() {
+ return getToken(HogQLParser::ASOF, 0);
+}
+
+HogQLParser::JoinOpInnerContext::JoinOpInnerContext(JoinOpContext *ctx) { copyFrom(ctx); }
+
+
+std::any HogQLParser::JoinOpInnerContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitJoinOpInner(this);
+ else
+ return visitor->visitChildren(this);
+}
+//----------------- JoinOpLeftRightContext ------------------------------------------------------------------
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::LEFT() {
+ return getToken(HogQLParser::LEFT, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::RIGHT() {
+ return getToken(HogQLParser::RIGHT, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::OUTER() {
+ return getToken(HogQLParser::OUTER, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::SEMI() {
+ return getToken(HogQLParser::SEMI, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::ALL() {
+ return getToken(HogQLParser::ALL, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::ANTI() {
+ return getToken(HogQLParser::ANTI, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::ANY() {
+ return getToken(HogQLParser::ANY, 0);
+}
+
+tree::TerminalNode* HogQLParser::JoinOpLeftRightContext::ASOF() {
+ return getToken(HogQLParser::ASOF, 0);
+}
+
+HogQLParser::JoinOpLeftRightContext::JoinOpLeftRightContext(JoinOpContext *ctx) { copyFrom(ctx); }
+
+
+std::any HogQLParser::JoinOpLeftRightContext::accept(tree::ParseTreeVisitor *visitor) {
+ if (auto parserVisitor = dynamic_cast(visitor))
+ return parserVisitor->visitJoinOpLeftRight(this);
+ else
+ return visitor->visitChildren(this);
+}
+HogQLParser::JoinOpContext* HogQLParser::joinOp() {
+ JoinOpContext *_localctx = _tracker.createInstance