From 4f87de7da5ef64734b60f262ec9bb5c774b65362 Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Sat, 1 Apr 2023 21:56:01 +0800 Subject: [PATCH] feat: database view collection (#1587) * test: create view collection * feat: view collection class * feat: list view * chore: skip sync view collection * test: should create view collection in difference schema * test: create view collection in collection manager * feat: create view collection by user sql * test: view resourcer * feat: view collection * feat: view collection cannot be added, deleted, or modified * feat: view collection cannot be added, deleted, or modified * feat: view collection cannot be added, deleted, or modified * feat: view collection cannot be added, deleted, or modified * refactor: connect to database view * refactor: sync from database * chore: rename list view sql * chore: list view fields api * chore: create collection without viewName * feat: bring out fields when selecting a view * chore: bring out fields when selecting a view * feat: view field inference class * chore: bring out fields when selecting a view * chore: sync form database view * chore: sync form database view * refactor: view collection local * feat: view get api * feat: database type infer * feat: integer map * chore: remove from in view list * chore: build error * chore: uniq collection * fix: typo * chore: replace collection list source field * fix: destroy view collection * chore: timestamp field map * refactor: interface avalableTypes * refactor: interface avalableTypes * chore: list fields test * refactor: interface avalableTypes * chore: uiSchema response in field source * fix: view query * chore: collection snippet * refactor: view collection support preview * fix: handle field source * fix: typo * fix: configure fileds title * fix: configure fileds title * fix: configure fileds title * fix: sync from databse interface * fix: sync from databse interface * feat: set fields api * fix: sync from databse fix * feat: possibleTypes * chore: fields get * fix: sync from databse * fix: list view test * fix: view test in difference schema * chore: comment * feat: when there is only one source collection, the view is a subset of a Collection * feat: view collection add field * fix: inherit query with schema * fix: test * fix: ci test * fix: test with schema * chore: set pg default search path * chore: mysql test * fix: test with schema * chore: test * chore: action test * chore: view column usage return type * feat: mysql field inference * fix: tableName * chore: node sql parser * fix: sql build * fix: database build * fix: mysql test * feat: view collection uiSchema title * fix: incorrect field source display when switching views * refactor: view collection not allow modify * fix: view collection is allow add, delete, and modify * fix: mysql test * fix: sqlite test * fix: sqlite test * fix: sqlite test * fix: sqlite test * chore: add id field as default target key * style: style improve * feat: load source field options * style: style improve * chore: disable remove column in view collection * chore: support creating view collection with different schemas with the same name * chore: support creating view collection with different schemas with the same name * fix: query view in difference schema * refactor: view collection viewname * fix: query view collection in difference schema * fix: field load * chore: field options * fix: mysql test * fix: uiSchema component error when using a view field in a block * fix: sqlite test * chore: test * fix: dump user views * fix: view collection can be updated and edited in table block * chore: sync from database display last field configuration * chore: loadCollections * chore: sync from database display last field configuration * fix: field options merge issues * style: preview table * fix: view collection is allow using in kanban blocks * refactor: code improve * fix: view collection can be updated an edited in calendar block * chore: disable infer field without interface * feat: preview only shows source or interface fields * fix: test * refactor: locale * feat: sql parser * chore: remove node-sql-parser * fix: yarn.lock * test: view repository * fix: view repository test * chore: console.log * chore: console.log * fix: mysql without schema * fix: mysql without schema * chore: preview with field schema * chore: tableActionInitializers * style: preview style improve * chore: parameter is filter when there is no filterByTk * fix: preview pagination * fix: preview pagination * style: preview table style improve * fix: sync from database loading * chore: preview performance optimization * chore: preview performance optimization * feat: limit & offset * chore: preview performance optimization * test: field with dot column * fix: datetime interface display * fix: missing boolean type * fix: sync * fix: sync from database * style: style improve * style: style improve * style: style improve * chore: preview table * chore: preview table * chore: preview table * fix: styling --------- Co-authored-by: katherinehhh Co-authored-by: chenos --- docker-compose.yml | 4 +- .../src/__tests__/create-action.test.ts | 1 + .../src/__tests__/remove-action.test.ts | 2 + .../actions/src/__tests__/set-action.test.ts | 1 + .../src/__tests__/toggle-action.test.ts | 1 + .../src/block-provider/BlockProvider.tsx | 20 +- .../collection-manager/CollectionField.tsx | 4 +- .../CollectionManagerShortcut.tsx | 4 + .../Configuration/AddCollectionAction.tsx | 16 +- .../Configuration/AddFieldAction.tsx | 136 +- .../Configuration/ConfigurationTable.tsx | 94 +- .../Configuration/EditFieldAction.tsx | 8 +- .../Configuration/SyncFieldsAction.tsx | 194 + .../Configuration/index.tsx | 3 +- .../Configuration/schemas/collectionFields.ts | 10 +- .../Configuration/schemas/collections.ts | 3 +- .../hooks/useCollectionManager.ts | 12 +- .../interfaces/attachment.ts | 1 + .../collection-manager/interfaces/checkbox.ts | 1 + .../interfaces/checkboxGroup.ts | 1 + .../interfaces/chinaRegion.ts | 1 + .../interfaces/createdAt.ts | 1 + .../interfaces/createdBy.ts | 1 + .../collection-manager/interfaces/datetime.ts | 1 + .../collection-manager/interfaces/email.ts | 1 + .../src/collection-manager/interfaces/icon.ts | 1 + .../src/collection-manager/interfaces/id.ts | 1 + .../collection-manager/interfaces/input.ts | 1 + .../collection-manager/interfaces/integer.ts | 1 + .../src/collection-manager/interfaces/json.ts | 1 + .../collection-manager/interfaces/linkTo.ts | 1 + .../src/collection-manager/interfaces/m2m.tsx | 1 + .../src/collection-manager/interfaces/m2o.tsx | 1 + .../collection-manager/interfaces/markdown.ts | 1 + .../interfaces/multipleSelect.ts | 1 + .../collection-manager/interfaces/number.ts | 1 + .../src/collection-manager/interfaces/o2m.tsx | 1 + .../src/collection-manager/interfaces/o2o.tsx | 1 + .../collection-manager/interfaces/password.ts | 1 + .../collection-manager/interfaces/percent.ts | 33 +- .../collection-manager/interfaces/phone.ts | 1 + .../interfaces/radioGroup.ts | 1 + .../collection-manager/interfaces/richText.ts | 1 + .../collection-manager/interfaces/select.ts | 1 + .../collection-manager/interfaces/subTable.ts | 1 + .../collection-manager/interfaces/textarea.ts | 1 + .../src/collection-manager/interfaces/time.ts | 1 + .../interfaces/updatedAt.ts | 1 + .../interfaces/updatedBy.ts | 1 + .../templates/components/PreviewFields.tsx | 216 + .../templates/components/PreviewTable.tsx | 105 + .../collection-manager/templates/index.tsx | 2 +- .../src/collection-manager/templates/types.ts | 3 +- .../src/collection-manager/templates/view.tsx | 106 + packages/core/client/src/locale/en_US.ts | 4 + packages/core/client/src/locale/ja_JP.ts | 4 + packages/core/client/src/locale/zh_CN.ts | 4 + .../buttons/CalendarActionInitializers.tsx | 6 + .../CalendarFormActionInitializers.tsx | 22 + .../buttons/KanbanActionInitializers.tsx | 6 + .../ReadPrettyFormActionInitializers.tsx | 18 + .../buttons/RecordBlockInitializers.tsx | 46 +- .../buttons/TableActionColumnInitializers.tsx | 17 +- .../buttons/TableActionInitializers.tsx | 26 +- .../items/DetailsBlockInitializer.tsx | 14 +- .../items/TableBlockInitializer.tsx | 14 +- .../client/src/schema-initializer/utils.ts | 2 + .../database/src/__tests__/repository.test.ts | 14 + .../database/src/__tests__/sql-parser.test.ts | 13 + .../src/__tests__/view/list-view.test.ts | 34 + .../__tests__/view/view-collection.test.ts | 199 + .../src/__tests__/view/view-inference.test.ts | 103 + .../__tests__/view/view-repository.test.ts | 67 + packages/core/database/src/collection.ts | 49 +- .../core/database/src/database-utils/index.ts | 1 + packages/core/database/src/database.ts | 41 +- packages/core/database/src/fields/field.ts | 6 + .../core/database/src/fields/json-field.ts | 1 + packages/core/database/src/index.ts | 2 + packages/core/database/src/mock-database.ts | 12 +- packages/core/database/src/model.ts | 4 + packages/core/database/src/options-parser.ts | 20 +- .../query-interface/mysql-query-interface.ts | 51 +- .../postgres-query-interface.ts | 30 +- .../src/query-interface/query-interface.ts | 31 + .../query-interface/sqlite-query-interface.ts | 60 +- packages/core/database/src/repository.ts | 6 +- .../core/database/src/sql-parser/index.js | 10698 ++++++++++++++++ .../core/database/src/sql-parser/readme.md | 2 + .../core/database/src/sql-parser/sql.pegjs | 1297 ++ packages/core/database/src/view-collection.ts | 20 + .../core/database/src/view/field-type-map.ts | 56 + .../core/database/src/view/view-inference.ts | 106 + .../src/__tests__/association-field.test.ts | 9 +- .../__tests__/field-options/indexes.test.ts | 1 + .../http-api/view-collection.test.ts | 381 + .../__tests__/view/view-collection.test.ts | 122 + .../hooks/beforeCreateForViewCollection.ts | 16 + .../src/resourcers/collections.ts | 32 + .../src/resourcers/views.ts | 55 + .../plugins/collection-manager/src/server.ts | 72 +- .../src/server/__tests__/dump-action.test.ts | 3 +- .../plugins/duplicator/src/server/dumper.ts | 15 +- .../src/client/ImportInitializerProvider.tsx | 6 +- 104 files changed, 14610 insertions(+), 217 deletions(-) create mode 100644 packages/core/client/src/collection-manager/Configuration/SyncFieldsAction.tsx create mode 100644 packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx create mode 100644 packages/core/client/src/collection-manager/templates/components/PreviewTable.tsx create mode 100644 packages/core/client/src/collection-manager/templates/view.tsx create mode 100644 packages/core/database/src/__tests__/sql-parser.test.ts create mode 100644 packages/core/database/src/__tests__/view/list-view.test.ts create mode 100644 packages/core/database/src/__tests__/view/view-collection.test.ts create mode 100644 packages/core/database/src/__tests__/view/view-inference.test.ts create mode 100644 packages/core/database/src/__tests__/view/view-repository.test.ts create mode 100644 packages/core/database/src/sql-parser/index.js create mode 100644 packages/core/database/src/sql-parser/readme.md create mode 100644 packages/core/database/src/sql-parser/sql.pegjs create mode 100644 packages/core/database/src/view-collection.ts create mode 100644 packages/core/database/src/view/field-type-map.ts create mode 100644 packages/core/database/src/view/view-inference.ts create mode 100644 packages/plugins/collection-manager/src/__tests__/http-api/view-collection.test.ts create mode 100644 packages/plugins/collection-manager/src/__tests__/view/view-collection.test.ts create mode 100644 packages/plugins/collection-manager/src/hooks/beforeCreateForViewCollection.ts create mode 100644 packages/plugins/collection-manager/src/resourcers/collections.ts create mode 100644 packages/plugins/collection-manager/src/resourcers/views.ts diff --git a/docker-compose.yml b/docker-compose.yml index 1e43cfe08..37009aeb9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,13 +25,15 @@ services: networks: - nocobase postgres: - image: postgres:10 + image: postgres:latest restart: always networks: - nocobase command: postgres -c wal_level=logical ports: - "${DB_POSTGRES_PORT}:5432" + volumes: + - ./storage/db/postgres/backups:/backups environment: POSTGRES_USER: ${DB_USER} POSTGRES_DB: ${DB_DATABASE} diff --git a/packages/core/actions/src/__tests__/create-action.test.ts b/packages/core/actions/src/__tests__/create-action.test.ts index 3b44e0402..43e8b7491 100644 --- a/packages/core/actions/src/__tests__/create-action.test.ts +++ b/packages/core/actions/src/__tests__/create-action.test.ts @@ -9,6 +9,7 @@ describe('create action', () => { beforeEach(async () => { app = mockServer(); + await app.db.clean({ drop: true }); registerActions(app); Post = app.collection({ diff --git a/packages/core/actions/src/__tests__/remove-action.test.ts b/packages/core/actions/src/__tests__/remove-action.test.ts index 1b888ee7f..080e7d3e8 100644 --- a/packages/core/actions/src/__tests__/remove-action.test.ts +++ b/packages/core/actions/src/__tests__/remove-action.test.ts @@ -13,6 +13,8 @@ describe('remove action', () => { app = mockServer(); registerActions(app); + await app.db.clean({ drop: true }); + PostTag = app.collection({ name: 'posts_tags', fields: [{ type: 'string', name: 'tagged_at' }], diff --git a/packages/core/actions/src/__tests__/set-action.test.ts b/packages/core/actions/src/__tests__/set-action.test.ts index 5bf4e48a8..117a085aa 100644 --- a/packages/core/actions/src/__tests__/set-action.test.ts +++ b/packages/core/actions/src/__tests__/set-action.test.ts @@ -10,6 +10,7 @@ describe('set action', () => { beforeEach(async () => { app = mockServer(); + await app.db.clean({ drop: true }); registerActions(app); PostTag = app.collection({ diff --git a/packages/core/actions/src/__tests__/toggle-action.test.ts b/packages/core/actions/src/__tests__/toggle-action.test.ts index 451cc076e..dcfea48e9 100644 --- a/packages/core/actions/src/__tests__/toggle-action.test.ts +++ b/packages/core/actions/src/__tests__/toggle-action.test.ts @@ -10,6 +10,7 @@ describe('toggle action', () => { beforeEach(async () => { app = mockServer(); + await app.db.clean({ drop: true }); registerActions(app); PostTag = app.collection({ diff --git a/packages/core/client/src/block-provider/BlockProvider.tsx b/packages/core/client/src/block-provider/BlockProvider.tsx index 69925b641..9fdcd3e1c 100644 --- a/packages/core/client/src/block-provider/BlockProvider.tsx +++ b/packages/core/client/src/block-provider/BlockProvider.tsx @@ -292,9 +292,27 @@ export const useSourceIdFromParentRecord = () => { export const useParamsFromRecord = () => { const filterByTk = useFilterByTk(); - return { + const record = useRecord(); + const { fields } = useCollection(); + const filterFields = fields + .filter((v) => { + return ['boolean', 'date', 'integer', 'radio', 'sort', 'string', 'time', 'uid', 'uuid'].includes(v.type); + }) + .map((v) => v.name); + const filter = Object.keys(record) + .filter((key) => filterFields.includes(key)) + .reduce((result, key) => { + result[key] = record[key]; + return result; + }, {}); + + const obj = { filterByTk: filterByTk, }; + if (!filterByTk) { + obj['filter'] = filter; + } + return obj; }; export const RecordLink = (props) => { diff --git a/packages/core/client/src/collection-manager/CollectionField.tsx b/packages/core/client/src/collection-manager/CollectionField.tsx index d353847b1..00e39271b 100644 --- a/packages/core/client/src/collection-manager/CollectionField.tsx +++ b/packages/core/client/src/collection-manager/CollectionField.tsx @@ -13,7 +13,7 @@ const InternalField: React.FC = (props) => { const fieldSchema = useFieldSchema(); const { name, interface: interfaceType, uiSchema, defaultValue } = useCollectionField(); const collectionField = useCollectionField(); - const component = useComponent(uiSchema?.['x-component']); + const component = useComponent(uiSchema?.['x-component'] || 'Input'); const compile = useCompile(); const setFieldProps = (key, value) => { field[key] = typeof field[key] === 'undefined' ? value : field[key]; @@ -73,7 +73,6 @@ const InternalField: React.FC = (props) => { if (!uiSchema) { return null; } - return React.createElement(component, props, props.children); }; @@ -107,7 +106,6 @@ export const CollectionField = connect((props) => { const fieldSchema = useFieldSchema(); const field = fieldSchema?.['x-component-props']?.['field']; const { snapshot } = useActionContext(); - return ( { ViewFieldAction, EditCategory, EditCategoryAction, + SyncFieldsAction, + SyncFieldsActionCom }} /> // diff --git a/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx b/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx index 844425f97..7e8b64617 100644 --- a/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx +++ b/packages/core/client/src/collection-manager/Configuration/AddCollectionAction.tsx @@ -28,8 +28,9 @@ const getSchema = (schema, category, compile): ISchema => { properties['defaultValue']['x-decorator'] = 'FormItem'; } const initialValue: any = { - name: `t_${uid()}`, + name: schema.name !== 'view' ? `t_${uid()}` : null, template: schema.name, + view: schema.name === 'view', category, ...cloneDeep(schema.default), }; @@ -201,7 +202,7 @@ const useCreateCollection = (schema?: any) => { if (schema?.events?.beforeSubmit) { schema.events.beforeSubmit(values); } - const fields = useDefaultCollectionFields(values); + const fields = values?.template !== 'view' ? useDefaultCollectionFields(values) : values.fields; if (values.autoCreateReverseField) { } else { delete values.reverseField; @@ -235,8 +236,15 @@ export const AddCollectionAction = (props) => { const [schema, setSchema] = useState({}); const compile = useCompile(); const { t } = useTranslation(); - const items = templateOptions().map((option) => { - return { label: compile(option.title), key: option.name }; + const collectionTemplates = templateOptions(); + const items = []; + collectionTemplates.forEach((item) => { + if (item.divider) { + items.push({ + type: 'divider', + }); + } + items.push({ label: compile(item.title), key: item.name }); }); const { state: { category }, diff --git a/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx b/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx index 3d6b83efa..77b77c293 100644 --- a/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx +++ b/packages/core/client/src/collection-manager/Configuration/AddFieldAction.tsx @@ -212,72 +212,74 @@ export const AddFieldAction = (props) => { return optionArr; }; return ( - - - { - //@ts-ignore - const targetScope = e.item.props['data-targetScope']; - targetScope && setTargetScope(targetScope); - const schema = getSchema(getInterface(e.key), record, compile); - if (schema) { - setSchema(schema); - setVisible(true); - } - }} - > - {getFieldOptions().map((option) => { - return ( - option.children.length > 0 && ( - - {option.children - .filter((child) => !['o2o', 'subTable'].includes(child.name)) - .map((child) => { - return ( - - {compile(child.title)} - - ); - })} - - ) - ); - })} - - } - > - {children || ( - - )} - - - - + record.template !== 'view' && ( + + + { + //@ts-ignore + const targetScope = e.item.props['data-targetScope']; + targetScope && setTargetScope(targetScope); + const schema = getSchema(getInterface(e.key), record, compile); + if (schema) { + setSchema(schema); + setVisible(true); + } + }} + > + {getFieldOptions().map((option) => { + return ( + option.children.length > 0 && ( + + {option.children + .filter((child) => !['o2o', 'subTable'].includes(child.name)) + .map((child) => { + return ( + + {compile(child.title)} + + ); + })} + + ) + ); + })} + + } + > + {children || ( + + )} + + + + + ) ); }; diff --git a/packages/core/client/src/collection-manager/Configuration/ConfigurationTable.tsx b/packages/core/client/src/collection-manager/Configuration/ConfigurationTable.tsx index ec7981ab2..9036d2c38 100644 --- a/packages/core/client/src/collection-manager/Configuration/ConfigurationTable.tsx +++ b/packages/core/client/src/collection-manager/Configuration/ConfigurationTable.tsx @@ -14,6 +14,7 @@ import { AddSubFieldAction } from './AddSubFieldAction'; import { FieldSummary } from './components/FieldSummary'; import { EditSubFieldAction } from './EditSubFieldAction'; import { collectionSchema } from './schemas/collections'; +import { useAPIClient } from '../../api-client'; const useAsyncDataSource = (service: any) => { return (field: any, options?: any) => { @@ -77,23 +78,32 @@ export const ConfigurationTable = () => { const { data: { database }, } = useCurrentAppInfo(); + const data = useContext(CollectionCategroriesContext); + const api = useAPIClient(); + const resource = api.resource('dbViews'); const collectonsRef: any = useRef(); collectonsRef.current = collections; const compile = useCompile(); const loadCollections = async (field, options) => { const { targetScope } = options; - return collectonsRef.current - ?.filter((item) => !(item.autoCreate && item.isThrough)) - .filter((item) => - targetScope - ? targetScope['template']?.includes(item.template) || targetScope[field.props.name]?.includes(item.name) - : true, - ) - .map((item: any) => ({ - label: compile(item.title), - value: item.name, - })); + const isFieldInherits = field.props?.name === 'inherits'; + const filteredItems = collectonsRef.current.filter((item) => { + const isAutoCreateAndThrough = item.autoCreate && item.isThrough; + if (isAutoCreateAndThrough) { + return false; + } + if (isFieldInherits && item.template === 'view') { + return false; + } + const templateIncluded = !targetScope?.template || targetScope.template.includes(item.template); + const nameIncluded = !targetScope?.[field.props?.name] || targetScope[field.props.name].includes(item.name); + return templateIncluded && nameIncluded; + }); + return filteredItems.map((item) => ({ + label: compile(item.title), + value: item.name, + })); }; const loadCategories = async () => { return data.data.map((item: any) => ({ @@ -101,31 +111,45 @@ export const ConfigurationTable = () => { value: item.id, })); }; + + const loadDBViews = async () => { + return resource.list().then(({ data }) => { + return data?.data?.map((item: any) => { + const schema = item.schema; + return { + label: schema ? `${schema}.${compile(item.name)}` : item.name, + value: schema?`${schema}_${item.name}`:item.name + }; + }); + }); + }; const ctx = useContext(SchemaComponentContext); return ( - - - + + + ); }; diff --git a/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx b/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx index 233fa3631..624b27af4 100644 --- a/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx +++ b/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx @@ -19,10 +19,12 @@ const getSchema = (schema: IField, record: any, compile, getContainer): ISchema return; } const properties = cloneDeep(schema.properties) as any; - properties.name['x-disabled'] = true; + if (properties?.name) { + properties.name['x-disabled'] = true; + } if (schema.hasDefaultValue === true) { - properties['defaultValue'] = cloneDeep(schema.default.uiSchema); + properties['defaultValue'] = cloneDeep(schema.default.uiSchema)||{}; properties['defaultValue']['title'] = compile('{{ t("Default value") }}'); properties['defaultValue']['x-decorator'] = 'FormItem'; properties['defaultValue']['x-reactions'] = { @@ -156,7 +158,7 @@ export const EditFieldAction = (props) => { const defaultValues: any = cloneDeep(data?.data) || {}; if (!defaultValues?.reverseField) { defaultValues.autoCreateReverseField = false; - defaultValues.reverseField = interfaceConf.default?.reverseField; + defaultValues.reverseField = interfaceConf?.default?.reverseField; set(defaultValues.reverseField, 'name', `f_${uid()}`); set(defaultValues.reverseField, 'uiSchema.title', record.__parent.title); } diff --git a/packages/core/client/src/collection-manager/Configuration/SyncFieldsAction.tsx b/packages/core/client/src/collection-manager/Configuration/SyncFieldsAction.tsx new file mode 100644 index 000000000..98786f22b --- /dev/null +++ b/packages/core/client/src/collection-manager/Configuration/SyncFieldsAction.tsx @@ -0,0 +1,194 @@ +import { PlusOutlined } from '@ant-design/icons'; +import { ArrayTable } from '@formily/antd'; +import { useForm } from '@formily/react'; +import { uid } from '@formily/shared'; +import { Button } from 'antd'; +import { cloneDeep } from 'lodash'; +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useRequest } from '../../api-client'; +import { RecordProvider, useRecord } from '../../record-provider'; +import { ActionContext, SchemaComponent, useActionContext, useCompile } from '../../schema-component'; +import { useCancelAction } from '../action-hooks'; +import { useCollectionManager } from '../hooks'; +import { IField } from '../interfaces/types'; +import { useResourceActionContext, useResourceContext } from '../ResourceActionProvider'; +import * as components from './components'; +import { useAPIClient } from '../../api-client'; +import { PreviewFields } from '../templates/components/PreviewFields'; +import { PreviewTable } from '../templates/components/PreviewTable'; + +const getSchema = (schema: IField, record: any, compile) => { + if (!schema) { + return; + } + + const properties = cloneDeep(schema.properties) as any; + + if (schema.hasDefaultValue === true) { + properties['defaultValue'] = cloneDeep(schema?.default?.uiSchema); + properties['defaultValue']['title'] = compile('{{ t("Default value") }}'); + properties['defaultValue']['x-decorator'] = 'FormItem'; + } + const initialValue: any = { + name: `f_${uid()}`, + ...cloneDeep(schema.default), + interface: schema.name, + }; + if (initialValue.reverseField) { + initialValue.reverseField.name = `f_${uid()}`; + } + // initialValue.uiSchema.title = schema.title; + return { + type: 'object', + properties: { + [uid()]: { + type: 'void', + 'x-component': 'Action.Drawer', + 'x-component-props': { + getContainer: '{{ getContainer }}', + }, + 'x-decorator': 'Form', + 'x-decorator-props': { + useValues(options) { + return useRequest( + () => + Promise.resolve({ + data: initialValue, + }), + options, + ); + }, + }, + title: `${compile('{{ t("Sync from database") }}')}`, + properties: { + schema: { + type: 'string', + 'x-hidden': true, + default: record?.schema, + }, + viewName: { + type: 'string', + 'x-hidden': true, + default: record?.viewName, + }, + fields: { + type: 'array', + 'x-component': PreviewFields, + 'x-component-props': { + ...record, + }, + default: record.fields, + }, + preview: { + type: 'object', + 'x-component': PreviewTable, + 'x-component-props': { + ...record, + }, + 'x-reactions': { + dependencies: ['fields'], + fulfill: { + schema: { + 'x-component-props': '{{{...record,...$form.values}}}', //任意层次属性都支持表达式 + }, + }, + }, + }, + footer: { + type: 'void', + 'x-component': 'Action.Drawer.Footer', + properties: { + action1: { + title: '{{ t("Cancel") }}', + 'x-component': 'Action', + 'x-component-props': { + useAction: '{{ useCancelAction }}', + }, + }, + action2: { + title: '{{ t("Submit") }}', + 'x-component': 'Action', + 'x-component-props': { + type: 'primary', + useAction: '{{ useSyncFromDatabase }}', + }, + }, + }, + }, + }, + }, + }, + }; +}; + +const useSyncFromDatabase = () => { + const form = useForm(); + const { refreshCM } = useCollectionManager(); + const ctx = useActionContext(); + const { refresh } = useResourceActionContext(); + const { targetKey } = useResourceContext(); + const { [targetKey]: filterByTk } = useRecord(); + const api = useAPIClient(); + return { + async run() { + await form.submit(); + await api.resource(`collections`).setFields({ + filterByTk, + values: form.values, + }); + ctx.setVisible(false); + await form.reset(); + refresh(); + await refreshCM(); + }, + }; +}; + +export const SyncFieldsAction = (props) => { + const record = useRecord(); + return ; +}; + +export const SyncFieldsActionCom = (props) => { + const { scope, getContainer, item: record, children } = props; + const [visible, setVisible] = useState(false); + const [schema, setSchema] = useState({}); + const compile = useCompile(); + const { t } = useTranslation(); + return ( + record.template === 'view' && ( + + + {children || ( + + )} + + + + ) + ); +}; diff --git a/packages/core/client/src/collection-manager/Configuration/index.tsx b/packages/core/client/src/collection-manager/Configuration/index.tsx index c69d4c0ea..faec9c4f1 100644 --- a/packages/core/client/src/collection-manager/Configuration/index.tsx +++ b/packages/core/client/src/collection-manager/Configuration/index.tsx @@ -13,7 +13,8 @@ export * from './AddCollectionAction'; export * from './EditCollectionAction'; export * from './ConfigurationTabs'; export * from './AddCategoryAction'; -export * from './EditCategoryAction' +export * from './EditCategoryAction'; +export * from './SyncFieldsAction'; registerValidateFormats({ uid: /^[A-Za-z0-9][A-Za-z0-9_-]*$/, diff --git a/packages/core/client/src/collection-manager/Configuration/schemas/collectionFields.ts b/packages/core/client/src/collection-manager/Configuration/schemas/collectionFields.ts index fdfbdef60..41ce21c5c 100644 --- a/packages/core/client/src/collection-manager/Configuration/schemas/collectionFields.ts +++ b/packages/core/client/src/collection-manager/Configuration/schemas/collectionFields.ts @@ -73,7 +73,7 @@ export const collectionFieldSchema: ISchema = { params: { paginate: false, filter: { - 'interface.$not': null, + $or: [{ 'interface.$not': null }, { 'options.source.$notEmpty': true }], }, sort: ['sort'], // appends: ['uiSchema'], @@ -106,6 +106,14 @@ export const collectionFieldSchema: ISchema = { }, }, }, + syncfromDatabase: { + type: 'void', + title: '{{ t("Sync from database") }}', + 'x-component': 'SyncFieldsAction', + 'x-component-props': { + type: 'primary', + }, + }, create: { type: 'void', title: '{{ t("Add new") }}', diff --git a/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts b/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts index 4cdb3e03e..b2bed6ca1 100644 --- a/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts +++ b/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts @@ -258,7 +258,8 @@ export const collectionTableSchema: ISchema = { }, 'x-reactions': (field) => { const i = field.path.segments[1]; - const table = field.form.getValuesIn(`table.${i}`); + const key = field.path.segments[0]; + const table = field.form.getValuesIn(`${key}.${i}`); if (table) { field.title = `${compile(table.title)} - ${compile('{{ t("Configure fields") }}')}`; } diff --git a/packages/core/client/src/collection-manager/hooks/useCollectionManager.ts b/packages/core/client/src/collection-manager/hooks/useCollectionManager.ts index 85b63a1cf..d67f25d3b 100644 --- a/packages/core/client/src/collection-manager/hooks/useCollectionManager.ts +++ b/packages/core/client/src/collection-manager/hooks/useCollectionManager.ts @@ -62,7 +62,7 @@ export const useCollectionManager = () => { return getParents(name); }; - const getChildrenCollections = (name) => { + const getChildrenCollections = (name, isSupportView = false) => { const children = []; const getChildren = (name) => { const inheritCollections = collections.filter((v) => { @@ -73,6 +73,16 @@ export const useCollectionManager = () => { children.push(v); return getChildren(collectionKey); }); + if (isSupportView) { + const sourceCollections = collections.filter((v) => { + return v.sources?.length === 1 && v?.sources[0] === name; + }); + sourceCollections.forEach((v) => { + const collectionKey = v.name; + children.push(v); + return getChildren(collectionKey); + }); + } return uniqBy(children, 'key'); }; return getChildren(name); diff --git a/packages/core/client/src/collection-manager/interfaces/attachment.ts b/packages/core/client/src/collection-manager/interfaces/attachment.ts index b36db1494..e816022e4 100644 --- a/packages/core/client/src/collection-manager/interfaces/attachment.ts +++ b/packages/core/client/src/collection-manager/interfaces/attachment.ts @@ -22,6 +22,7 @@ export const attachment: IField = { }, }, }, + availableTypes:['belongsToMany'], schemaInitialize(schema: ISchema, { block }) { if (['Table', 'Kanban'].includes(block)) { schema['x-component-props'] = schema['x-component-props'] || {}; diff --git a/packages/core/client/src/collection-manager/interfaces/checkbox.ts b/packages/core/client/src/collection-manager/interfaces/checkbox.ts index 3792a1794..6f3d783a1 100644 --- a/packages/core/client/src/collection-manager/interfaces/checkbox.ts +++ b/packages/core/client/src/collection-manager/interfaces/checkbox.ts @@ -15,6 +15,7 @@ export const checkbox: IField = { 'x-component': 'Checkbox', }, }, + availableTypes: ['boolean'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/checkboxGroup.ts b/packages/core/client/src/collection-manager/interfaces/checkboxGroup.ts index a59e33ac1..539a250e7 100644 --- a/packages/core/client/src/collection-manager/interfaces/checkboxGroup.ts +++ b/packages/core/client/src/collection-manager/interfaces/checkboxGroup.ts @@ -17,6 +17,7 @@ export const checkboxGroup: IField = { 'x-component': 'Checkbox.Group', }, }, + availableTypes:['array'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/chinaRegion.ts b/packages/core/client/src/collection-manager/interfaces/chinaRegion.ts index 7d8900cd3..6f4ab2d8c 100644 --- a/packages/core/client/src/collection-manager/interfaces/chinaRegion.ts +++ b/packages/core/client/src/collection-manager/interfaces/chinaRegion.ts @@ -34,6 +34,7 @@ export const chinaRegion: IField = { }, }, }, + availableTypes:['belongsToMany'], initialize: (values: any) => { if (!values.through) { values.through = `t_${uid()}`; diff --git a/packages/core/client/src/collection-manager/interfaces/createdAt.ts b/packages/core/client/src/collection-manager/interfaces/createdAt.ts index 8d622cece..12b971b8b 100644 --- a/packages/core/client/src/collection-manager/interfaces/createdAt.ts +++ b/packages/core/client/src/collection-manager/interfaces/createdAt.ts @@ -20,6 +20,7 @@ export const createdAt: IField = { 'x-read-pretty': true, }, }, + availableTypes:['date'], properties: { ...defaultProps, ...dateTimeProps, diff --git a/packages/core/client/src/collection-manager/interfaces/createdBy.ts b/packages/core/client/src/collection-manager/interfaces/createdBy.ts index 8619fccc9..07b5569ad 100644 --- a/packages/core/client/src/collection-manager/interfaces/createdBy.ts +++ b/packages/core/client/src/collection-manager/interfaces/createdBy.ts @@ -28,6 +28,7 @@ export const createdBy: IField = { 'x-read-pretty': true, }, }, + availableTypes:['belongsTo'], properties: { ...defaultProps, }, diff --git a/packages/core/client/src/collection-manager/interfaces/datetime.ts b/packages/core/client/src/collection-manager/interfaces/datetime.ts index c21b630b5..52ced3434 100644 --- a/packages/core/client/src/collection-manager/interfaces/datetime.ts +++ b/packages/core/client/src/collection-manager/interfaces/datetime.ts @@ -20,6 +20,7 @@ export const datetime: IField = { }, }, }, + availableTypes:['date'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/email.ts b/packages/core/client/src/collection-manager/interfaces/email.ts index 05a21d33b..fa6a1a1b0 100644 --- a/packages/core/client/src/collection-manager/interfaces/email.ts +++ b/packages/core/client/src/collection-manager/interfaces/email.ts @@ -18,6 +18,7 @@ export const email: IField = { 'x-validator': 'email', }, }, + availableTypes:['string'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/icon.ts b/packages/core/client/src/collection-manager/interfaces/icon.ts index 3056375b4..fc19dc29a 100644 --- a/packages/core/client/src/collection-manager/interfaces/icon.ts +++ b/packages/core/client/src/collection-manager/interfaces/icon.ts @@ -16,6 +16,7 @@ export const icon: IField = { 'x-component': 'IconPicker', }, }, + availableTypes:['string'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/id.ts b/packages/core/client/src/collection-manager/interfaces/id.ts index 4a08ccdb8..e9bce1618 100644 --- a/packages/core/client/src/collection-manager/interfaces/id.ts +++ b/packages/core/client/src/collection-manager/interfaces/id.ts @@ -21,6 +21,7 @@ export const id: IField = { 'x-read-pretty': true, }, }, + availableTypes:['bigInt','integer'], properties: { 'uiSchema.title': { type: 'string', diff --git a/packages/core/client/src/collection-manager/interfaces/input.ts b/packages/core/client/src/collection-manager/interfaces/input.ts index d1d63307e..b1f76c86a 100644 --- a/packages/core/client/src/collection-manager/interfaces/input.ts +++ b/packages/core/client/src/collection-manager/interfaces/input.ts @@ -18,6 +18,7 @@ export const input: IField = { 'x-component': 'Input', }, }, + availableTypes:['string'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/integer.ts b/packages/core/client/src/collection-manager/interfaces/integer.ts index 792bef3c9..b8e51159d 100644 --- a/packages/core/client/src/collection-manager/interfaces/integer.ts +++ b/packages/core/client/src/collection-manager/interfaces/integer.ts @@ -29,6 +29,7 @@ export const integer: IField = { 'x-validator': 'integer', }, }, + availableTypes:['bigInt','integer'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/json.ts b/packages/core/client/src/collection-manager/interfaces/json.ts index 5943d80a0..bcb9d6907 100644 --- a/packages/core/client/src/collection-manager/interfaces/json.ts +++ b/packages/core/client/src/collection-manager/interfaces/json.ts @@ -39,6 +39,7 @@ export const json: IField = { default: null }, }, + availableTypes:['json','array'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/linkTo.ts b/packages/core/client/src/collection-manager/interfaces/linkTo.ts index de8732852..b1492c531 100644 --- a/packages/core/client/src/collection-manager/interfaces/linkTo.ts +++ b/packages/core/client/src/collection-manager/interfaces/linkTo.ts @@ -45,6 +45,7 @@ export const linkTo: IField = { }, }, }, + availableTypes:['belongsToMany'], schemaInitialize(schema: ISchema, { readPretty, block }) { if (block === 'Form') { if (schema['x-component'] === 'AssociationSelect') { diff --git a/packages/core/client/src/collection-manager/interfaces/m2m.tsx b/packages/core/client/src/collection-manager/interfaces/m2m.tsx index 2bc4c4c14..983de25f0 100644 --- a/packages/core/client/src/collection-manager/interfaces/m2m.tsx +++ b/packages/core/client/src/collection-manager/interfaces/m2m.tsx @@ -51,6 +51,7 @@ export const m2m: IField = { }, }, }, + availableTypes:['belongsToMany'], schemaInitialize(schema: ISchema, { readPretty, block }) { if (block === 'Form') { if (schema['x-component'] === 'AssociationSelect') { diff --git a/packages/core/client/src/collection-manager/interfaces/m2o.tsx b/packages/core/client/src/collection-manager/interfaces/m2o.tsx index 65268c3d8..d8ebdfbc5 100644 --- a/packages/core/client/src/collection-manager/interfaces/m2o.tsx +++ b/packages/core/client/src/collection-manager/interfaces/m2o.tsx @@ -50,6 +50,7 @@ export const m2o: IField = { }, }, }, + availableTypes:['belongsTo'], schemaInitialize(schema: ISchema, { block, readPretty }) { if (block === 'Form') { if (schema['x-component'] === 'AssociationSelect') { diff --git a/packages/core/client/src/collection-manager/interfaces/markdown.ts b/packages/core/client/src/collection-manager/interfaces/markdown.ts index 5788ce698..312b3caf5 100644 --- a/packages/core/client/src/collection-manager/interfaces/markdown.ts +++ b/packages/core/client/src/collection-manager/interfaces/markdown.ts @@ -17,6 +17,7 @@ export const markdown: IField = { 'x-component': 'Markdown', }, }, + availableTypes:['text'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/multipleSelect.ts b/packages/core/client/src/collection-manager/interfaces/multipleSelect.ts index 00c8b733e..44bcc1887 100644 --- a/packages/core/client/src/collection-manager/interfaces/multipleSelect.ts +++ b/packages/core/client/src/collection-manager/interfaces/multipleSelect.ts @@ -21,6 +21,7 @@ export const multipleSelect: IField = { enum: [], }, }, + availableTypes:['array'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/number.ts b/packages/core/client/src/collection-manager/interfaces/number.ts index ca32bcdc5..2cdc7871f 100644 --- a/packages/core/client/src/collection-manager/interfaces/number.ts +++ b/packages/core/client/src/collection-manager/interfaces/number.ts @@ -22,6 +22,7 @@ export const number: IField = { }, }, }, + availableTypes:['double'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/o2m.tsx b/packages/core/client/src/collection-manager/interfaces/o2m.tsx index 5d2a0ef9b..006c0611a 100644 --- a/packages/core/client/src/collection-manager/interfaces/o2m.tsx +++ b/packages/core/client/src/collection-manager/interfaces/o2m.tsx @@ -50,6 +50,7 @@ export const o2m: IField = { }, }, }, + availableTypes:['hasMany'], schemaInitialize(schema: ISchema, { field, block, readPretty }) { if (block === 'Form') { if (schema['x-component'] === 'TableField') { diff --git a/packages/core/client/src/collection-manager/interfaces/o2o.tsx b/packages/core/client/src/collection-manager/interfaces/o2o.tsx index e69f5c863..4cfac495a 100644 --- a/packages/core/client/src/collection-manager/interfaces/o2o.tsx +++ b/packages/core/client/src/collection-manager/interfaces/o2o.tsx @@ -117,6 +117,7 @@ export const o2o: IField = { }, }, }, + availableTypes:['hasOne'], schemaInitialize(schema: ISchema, { field, block, readPretty, action }) { internalSchameInitialize(schema, { field, block, readPretty, action }); if (['Table', 'Kanban'].includes(block)) { diff --git a/packages/core/client/src/collection-manager/interfaces/password.ts b/packages/core/client/src/collection-manager/interfaces/password.ts index 7ff1fc680..22c475d6e 100644 --- a/packages/core/client/src/collection-manager/interfaces/password.ts +++ b/packages/core/client/src/collection-manager/interfaces/password.ts @@ -18,6 +18,7 @@ export const password: IField = { 'x-component': 'Password', }, }, + availableTypes:['password'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/percent.ts b/packages/core/client/src/collection-manager/interfaces/percent.ts index b06a1d52e..a2a680993 100644 --- a/packages/core/client/src/collection-manager/interfaces/percent.ts +++ b/packages/core/client/src/collection-manager/interfaces/percent.ts @@ -13,7 +13,7 @@ registerValidateRules({ return { type: 'error', message: `${i18n.t('The field value cannot be greater than ')}${maxValue * 100}%`, - } + }; } } @@ -22,7 +22,7 @@ registerValidateRules({ return { type: 'error', message: `${i18n.t('The field value cannot be less than ')}${minValue * 100}%`, - } + }; } } @@ -36,12 +36,12 @@ registerValidateRules({ return { type: 'error', message: `${i18n.t('The field value is not an integer number')}`, - } + }; } return true; - } -}) + }, +}); // registerValidateFormats({ // percentInteger: /^(\d+)(.\d{0,2})?$/, @@ -68,6 +68,7 @@ export const percent: IField = { }, }, }, + availableTypes: ['float'], hasDefaultValue: true, properties: { ...defaultProps, @@ -104,7 +105,9 @@ export const percent: IField = { 'x-reactions': `{{(field) => { const targetValue = field.query('.minimum').value(); field.selfErrors = - !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Maximum must greater than minimum')}' : '' + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t( + 'Maximum must greater than minimum', + )}' : '' }}}`, }, minValue: { @@ -119,7 +122,9 @@ export const percent: IField = { dependencies: ['.maximum'], fulfill: { state: { - selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Minimum must less than maximum')}' : ''}}`, + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t( + 'Minimum must less than maximum', + )}' : ''}}`, }, }, }, @@ -132,10 +137,12 @@ export const percent: IField = { 'x-component-props': { allowClear: true, }, - enum: [{ - label: '{{ t("Integer") }}', - value: 'Integer', - }] + enum: [ + { + label: '{{ t("Integer") }}', + value: 'Integer', + }, + ], }, pattern: { type: 'string', @@ -145,8 +152,8 @@ export const percent: IField = { 'x-component-props': { prefix: '/', suffix: '/', - } + }, }, }; - } + }, }; diff --git a/packages/core/client/src/collection-manager/interfaces/phone.ts b/packages/core/client/src/collection-manager/interfaces/phone.ts index 24055ca8c..491c49085 100644 --- a/packages/core/client/src/collection-manager/interfaces/phone.ts +++ b/packages/core/client/src/collection-manager/interfaces/phone.ts @@ -21,6 +21,7 @@ export const phone: IField = { // 'x-validator': 'phone', }, }, + availableTypes: ['string'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/radioGroup.ts b/packages/core/client/src/collection-manager/interfaces/radioGroup.ts index a7205e3b3..5a097c732 100644 --- a/packages/core/client/src/collection-manager/interfaces/radioGroup.ts +++ b/packages/core/client/src/collection-manager/interfaces/radioGroup.ts @@ -17,6 +17,7 @@ export const radioGroup: IField = { 'x-component': 'Radio.Group', }, }, + availableTypes: ['string'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/richText.ts b/packages/core/client/src/collection-manager/interfaces/richText.ts index c10ba28a4..2f32ff1c8 100644 --- a/packages/core/client/src/collection-manager/interfaces/richText.ts +++ b/packages/core/client/src/collection-manager/interfaces/richText.ts @@ -18,6 +18,7 @@ export const richText: IField = { 'x-component': 'RichText', }, }, + availableTypes: ['text'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/select.ts b/packages/core/client/src/collection-manager/interfaces/select.ts index 26031e80e..7141c4c7d 100644 --- a/packages/core/client/src/collection-manager/interfaces/select.ts +++ b/packages/core/client/src/collection-manager/interfaces/select.ts @@ -18,6 +18,7 @@ export const select: IField = { enum: [], }, }, + availableTypes: ['string'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/subTable.ts b/packages/core/client/src/collection-manager/interfaces/subTable.ts index 502bb1450..8689dec01 100644 --- a/packages/core/client/src/collection-manager/interfaces/subTable.ts +++ b/packages/core/client/src/collection-manager/interfaces/subTable.ts @@ -20,6 +20,7 @@ export const subTable: IField = { 'x-component-props': {}, }, }, + availableTypes: ['hasMany'], schemaInitialize(schema: ISchema, { field, readPretty }) { const association = `${field.collectionName}.${field.name}`; schema['type'] = 'void'; diff --git a/packages/core/client/src/collection-manager/interfaces/textarea.ts b/packages/core/client/src/collection-manager/interfaces/textarea.ts index 3abf3888b..cf50e810c 100644 --- a/packages/core/client/src/collection-manager/interfaces/textarea.ts +++ b/packages/core/client/src/collection-manager/interfaces/textarea.ts @@ -18,6 +18,7 @@ export const textarea: IField = { 'x-component': 'Input.TextArea', }, }, + availableTypes: ['text'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/time.ts b/packages/core/client/src/collection-manager/interfaces/time.ts index 78a1f2bed..e1d6b08ea 100644 --- a/packages/core/client/src/collection-manager/interfaces/time.ts +++ b/packages/core/client/src/collection-manager/interfaces/time.ts @@ -16,6 +16,7 @@ export const time: IField = { 'x-component': 'TimePicker', }, }, + availableTypes: ['time'], hasDefaultValue: true, properties: { ...defaultProps, diff --git a/packages/core/client/src/collection-manager/interfaces/updatedAt.ts b/packages/core/client/src/collection-manager/interfaces/updatedAt.ts index 4498c5ee3..56bae4897 100644 --- a/packages/core/client/src/collection-manager/interfaces/updatedAt.ts +++ b/packages/core/client/src/collection-manager/interfaces/updatedAt.ts @@ -20,6 +20,7 @@ export const updatedAt: IField = { 'x-read-pretty': true, }, }, + availableTypes: ['date'], properties: { ...defaultProps, ...dateTimeProps, diff --git a/packages/core/client/src/collection-manager/interfaces/updatedBy.ts b/packages/core/client/src/collection-manager/interfaces/updatedBy.ts index fdb0b934c..5b58133ae 100644 --- a/packages/core/client/src/collection-manager/interfaces/updatedBy.ts +++ b/packages/core/client/src/collection-manager/interfaces/updatedBy.ts @@ -27,6 +27,7 @@ export const updatedBy: IField = { 'x-read-pretty': true, }, }, + availableTypes: ['belongsTo'], properties: { ...defaultProps, }, diff --git a/packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx b/packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx new file mode 100644 index 000000000..0f27b521d --- /dev/null +++ b/packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx @@ -0,0 +1,216 @@ +import { Cascader } from '@formily/antd'; +import { useField, useForm } from '@formily/react'; +import { Input, Select, Spin, Table, Tag } from 'antd'; +import React, { useContext, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ResourceActionContext, useCompile } from '../../../'; +import { useAPIClient } from '../../../api-client'; +import { getOptions } from '../../Configuration/interfaces'; +import { useCollectionManager } from '../../hooks/useCollectionManager'; + +const getInterfaceOptions = (data, type) => { + const interfaceOptions = []; + data.forEach((item) => { + const options = item.children.filter((h) => h?.availableTypes?.includes(type)); + interfaceOptions.push({ + label: item.label, + key: item.key, + children: options, + }); + }); + return interfaceOptions.filter((v) => v.children.length > 0); +}; +const PreviewCom = (props) => { + const { name, sources, viewName, schema } = props; + const { data: fields } = useContext(ResourceActionContext); + const api = useAPIClient(); + const { t } = useTranslation(); + const [loading, setLoading] = useState(false); + const [dataSource, setDataSource] = useState([]); + const [sourceFields, setSourceFields] = useState([]); + const field: any = useField(); + const form = useForm(); + const { getCollection } = useCollectionManager(); + const compile = useCompile(); + const initOptions = getOptions().filter((v) => !['relation', 'systemInfo'].includes(v.key)); + useEffect(() => { + const data = []; + sources.forEach((item) => { + const collection = getCollection(item); + const children = collection.fields?.map((v) => { + return { value: v.name, label: v.uiSchema?.title }; + }); + data.push({ + value: item, + label: collection.title, + children, + }); + }); + setSourceFields(data); + }, [sources, name]); + + useEffect(() => { + if (name) { + setLoading(true); + api + .resource(`dbViews`) + .get({ filterByTk: viewName, schema }) + .then(({ data }) => { + if (data) { + setLoading(false); + setDataSource([]); + const fieldsData = Object.values(data?.data?.fields)?.map((v: any) => { + if (v.source) { + return v; + } else { + return fields?.data.find((h) => h.name === v.name) || v; + } + }); + field.value = fieldsData; + setDataSource(fieldsData); + form.setValuesIn('sources', data.data?.sources); + } + }); + } + }, [name]); + + const handleFieldChange = (record, index) => { + dataSource.splice(index, 1, record); + setDataSource(dataSource); + field.value = dataSource.map((v) => { + return { + ...v, + source: typeof v.source === 'string' ? v.source : v.source?.join('.'), + }; + }); + }; + const columns = [ + { + title: t('Field name'), + dataIndex: 'name', + key: 'name', + width: 130, + }, + { + title: t('Field source'), + dataIndex: 'source', + key: 'source', + width: 200, + render: (text, record, index) => { + return ( + { + handleFieldChange({ ...record, source: value }, index); + }} + placeholder={t('Select field source')} + /> + ); + }, + }, + { + title: t('Field type'), + dataIndex: 'type', + width: 140, + key: 'type', + render: (text, _, index) => { + const item = dataSource[index]; + return item?.source || !item?.possibleTypes ? ( + {text} + ) : ( + handleFieldChange({ ...item, interface: value }, index)} + > + {data.map((group) => ( + + {group.children.map((item) => ( + + {compile(item.label)} + + ))} + + ))} + + ); + }, + }, + { + title: t('Field display name'), + dataIndex: 'title', + key: 'title', + width: 180, + render: (text, record, index) => { + const item = dataSource[index]; + return item.source ? ( + record?.uiSchema?.title + ) : ( + handleFieldChange({ ...item, uiSchema: { title: e.target.value } }, index)} + /> + ); + }, + }, + ]; + return ( + + {dataSource.length > 0 && ( + <> +
+
+ + + +
+ : +
+ + + )} + + ); +}; + +function areEqual(prevProps, nextProps) { + return nextProps.name === prevProps.name && nextProps.sources === prevProps.sources; +} + +export const PreviewFields = React.memo(PreviewCom, areEqual); diff --git a/packages/core/client/src/collection-manager/templates/components/PreviewTable.tsx b/packages/core/client/src/collection-manager/templates/components/PreviewTable.tsx new file mode 100644 index 000000000..e9de3b70e --- /dev/null +++ b/packages/core/client/src/collection-manager/templates/components/PreviewTable.tsx @@ -0,0 +1,105 @@ +import { RecursionField, useForm } from '@formily/react'; +import { Spin, Table } from 'antd'; +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { EllipsisWithTooltip, useCompile } from '../../../'; +import { useAPIClient } from '../../../api-client'; +import { useCollectionManager } from '../../hooks/useCollectionManager'; + +export const PreviewTable = (props) => { + const { name, viewName, schema, fields } = props; + const [previewColumns, setPreviewColumns] = useState([]); + const [previewData, setPreviewData] = useState([]); + const compile = useCompile(); + const [loading, setLoading] = useState(false); + const { getCollection, getCollectionField, getInterface } = useCollectionManager(); + const api = useAPIClient(); + const { t } = useTranslation(); + const form = useForm(); + useEffect(() => { + if (name) { + getPreviewData(); + } + }, [name]); + + useEffect(() => { + const pColumns = formatPreviewColumns(fields); + setPreviewColumns(pColumns); + }, [form.values.fields]); + + const getPreviewData = () => { + setLoading(true); + api + .resource(`dbViews`) + .query({ filterByTk: viewName, schema }) + .then(({ data }) => { + if (data) { + setLoading(false); + setPreviewData(data?.data || []); + } + }); + }; + + const formatPreviewColumns = (data) => { + return data + .filter((k) => k.source || k.interface) + ?.map((item) => { + const fieldSource = typeof item?.source === 'string' ? item?.source?.split('.') : item?.source; + const sourceField = getCollection(fieldSource?.[0])?.fields.find((v) => v.name === fieldSource?.[1])?.uiSchema + ?.title; + const target = sourceField || item?.uiSchema?.title || item.name; + const schema: any = item.source + ? getCollectionField(typeof item.source === 'string' ? item.source : item.source.join('.'))?.uiSchema + : getInterface(item.interface)?.default?.uiSchema; + return { + title: compile(target), + dataIndex: item.name, + key: item.name, + width: 200, + render: (v, record, index) => { + const content = record[item.name]; + const objSchema: any = { + type: 'object', + properties: { + [item.name]: { ...schema, default: content, 'x-read-pretty': true, title: null }, + }, + }; + return ( + + + + ); + }, + }; + }); + }; + return ( + +
+ {previewColumns?.length > 0 && [ +
+
+ + + +
+ : +
, +
, + ]} + + + ); +}; diff --git a/packages/core/client/src/collection-manager/templates/index.tsx b/packages/core/client/src/collection-manager/templates/index.tsx index 2bf123f94..236eab7b6 100644 --- a/packages/core/client/src/collection-manager/templates/index.tsx +++ b/packages/core/client/src/collection-manager/templates/index.tsx @@ -1,4 +1,4 @@ export * from './calendar'; export * from './general'; export * from './tree'; - +export * from './view'; diff --git a/packages/core/client/src/collection-manager/templates/types.ts b/packages/core/client/src/collection-manager/templates/types.ts index 8528a463b..3d7753cc4 100644 --- a/packages/core/client/src/collection-manager/templates/types.ts +++ b/packages/core/client/src/collection-manager/templates/types.ts @@ -14,6 +14,8 @@ export interface ICollectionTemplate { configurableProperties?: Record; /** 当前模板可用的字段类型 */ availableFieldInterfaces?: AvailableFieldInterfacesInclude | AvailableFieldInterfacesExclude; + /** 是否分割线 */ + divider?: boolean; } interface AvailableFieldInterfacesInclude { @@ -24,7 +26,6 @@ interface AvailableFieldInterfacesExclude { exclude?: any[]; } - interface CollectionOptions { /** * 自动生成 id diff --git a/packages/core/client/src/collection-manager/templates/view.tsx b/packages/core/client/src/collection-manager/templates/view.tsx new file mode 100644 index 000000000..5469e9863 --- /dev/null +++ b/packages/core/client/src/collection-manager/templates/view.tsx @@ -0,0 +1,106 @@ +import { getConfigurableProperties } from './properties'; +import { ICollectionTemplate } from './types'; +import { PreviewFields } from './components/PreviewFields'; +import { PreviewTable } from './components/PreviewTable'; + + +export const view: ICollectionTemplate = { + name: 'view', + title: '{{t("Connect to database view")}}', + order: 4, + color: 'yellow', + default: { + fields: [], + }, + divider: true, + configurableProperties: { + title: { + type: 'string', + title: '{{ t("Collection display name") }}', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + name: { + title: '{{t("Connect to database view")}}', + type: 'single', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Select', + 'x-reactions': ['{{useAsyncDataSource(loadDBViews)}}'], + 'x-disabled': '{{ !createOnly }}', + }, + schema: { + type: 'string', + 'x-hidden': true, + 'x-reactions': { + dependencies: ['name'], + when: "{{isPG}}", + fulfill: { + state: { + value: "{{$deps[0].split('_')?.[0]}}", + }, + }, + otherwise: { + state: { + value: null, + }, + }, + }, + }, + viewName: { + type: 'string', + 'x-hidden': true, + 'x-reactions': { + dependencies: ['name'], + when: "{{isPG}}", + fulfill: { + state: { + value: '{{$deps[0].match(/^([^_]+)_(.*)$/)?.[2]}}', + }, + }, + otherwise: { + state: { + value: '{{$deps[0]}}', + }, + }, + }, + }, + sources: { + type: 'array', + title: '{{ t("Source collections") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Select', + 'x-component-props': { + multiple: true, + }, + 'x-reactions': ['{{useAsyncDataSource(loadCollections)}}'], + 'x-disabled': true, + }, + fields: { + type: 'array', + 'x-component': PreviewFields, + 'x-reactions': { + dependencies: ['name'], + fulfill: { + schema: { + 'x-component-props': '{{$form.values}}', //任意层次属性都支持表达式 + }, + }, + }, + }, + preview: { + type: 'object', + 'x-component': PreviewTable, + 'x-reactions': { + dependencies: ['name','fields'], + fulfill: { + schema: { + 'x-component-props': '{{$form.values}}', //任意层次属性都支持表达式 + }, + }, + }, + }, + ...getConfigurableProperties('category'), + }, +}; diff --git a/packages/core/client/src/locale/en_US.ts b/packages/core/client/src/locale/en_US.ts index 0d5310355..ea0cdbd5f 100644 --- a/packages/core/client/src/locale/en_US.ts +++ b/packages/core/client/src/locale/en_US.ts @@ -180,6 +180,10 @@ export default { "Collection template": "Collection template", "Calendar collection": "Calendar collection", "General collection": "General collection", + "Connect to database view":"Connect to database view", + "Source collections":"Source collections", + "Field source":"Field source", + "Preview":"Preview", "Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.": "Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.", "Storage type": "Storage type", "Edit": "Edit", diff --git a/packages/core/client/src/locale/ja_JP.ts b/packages/core/client/src/locale/ja_JP.ts index fd2bd17b2..ac4f34894 100644 --- a/packages/core/client/src/locale/ja_JP.ts +++ b/packages/core/client/src/locale/ja_JP.ts @@ -171,6 +171,10 @@ export default { "Collection template":"データテーブルテンプレート", "Calendar collection":"カレンダデータテーブル", "General collection":"一般データテーブル", + "Connect to database view":"ビューに接続", + "Source collections":"ソースデータセット", + "Field source":"ソースフィールド", + "Preview":"プレビュー", "Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.": "ランダムに生成され、変更可能です。 アルファベット、数字、アンダースコアをサポートし、アルファベットから始まる必要があります。", "Storage type": "ストレージタイプ", "Edit": "編集", diff --git a/packages/core/client/src/locale/zh_CN.ts b/packages/core/client/src/locale/zh_CN.ts index 6eddcbbb1..968b33eca 100644 --- a/packages/core/client/src/locale/zh_CN.ts +++ b/packages/core/client/src/locale/zh_CN.ts @@ -188,6 +188,10 @@ export default { "Collection template": "数据表模板", "Calendar collection": "日历数据表", "General collection": "普通数据表", + "Connect to database view":"连接数据库视图", + "Source collections":"来源数据表", + "Field source":"来源字段", + "Preview":"预览", "Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.": "随机生成,可修改。支持英文、数字和下划线,必须以英文字母开头。", "Storage type": "存储类型", "Types will be used in database": "数据库使用的类型", diff --git a/packages/core/client/src/schema-initializer/buttons/CalendarActionInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/CalendarActionInitializers.tsx index 73f2cc587..9508b1cce 100644 --- a/packages/core/client/src/schema-initializer/buttons/CalendarActionInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/CalendarActionInitializers.tsx @@ -1,3 +1,5 @@ +import { useCollection } from '../../'; + // 日历的操作配置 export const CalendarActionInitializers = { title: '{{t("Configure actions")}}', @@ -72,6 +74,10 @@ export const CalendarActionInitializers = { skipScopeCheck: true, }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, ], }, diff --git a/packages/core/client/src/schema-initializer/buttons/CalendarFormActionInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/CalendarFormActionInitializers.tsx index 6677f3d2e..f2caff05e 100644 --- a/packages/core/client/src/schema-initializer/buttons/CalendarFormActionInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/CalendarFormActionInitializers.tsx @@ -1,3 +1,5 @@ +import { useCollection } from '../..'; + // 表单的操作配置 export const CalendarFormActionInitializers = { title: '{{t("Configure actions")}}', @@ -21,6 +23,10 @@ export const CalendarFormActionInitializers = { type: 'primary', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -30,6 +36,10 @@ export const CalendarFormActionInitializers = { 'x-component': 'Action', 'x-decorator': 'ACLActionProvider', }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -39,6 +49,10 @@ export const CalendarFormActionInitializers = { 'x-component': 'Action', 'x-decorator': 'ACLActionProvider', }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -130,6 +144,10 @@ export const CalendarFormActionInitializers = { useProps: '{{ useCustomizeUpdateActionProps }}', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -153,6 +171,10 @@ export const CalendarFormActionInitializers = { useProps: '{{ useCustomizeRequestActionProps }}', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, ], }, diff --git a/packages/core/client/src/schema-initializer/buttons/KanbanActionInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/KanbanActionInitializers.tsx index ff22997c0..ad5e8c4a7 100644 --- a/packages/core/client/src/schema-initializer/buttons/KanbanActionInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/KanbanActionInitializers.tsx @@ -1,3 +1,5 @@ +import { useCollection } from '../../'; + export const KanbanActionInitializers = { title: "{{t('Configure actions')}}", icon: 'SettingOutlined', @@ -28,6 +30,10 @@ export const KanbanActionInitializers = { skipScopeCheck: true, }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, ], }, diff --git a/packages/core/client/src/schema-initializer/buttons/ReadPrettyFormActionInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/ReadPrettyFormActionInitializers.tsx index 18b686467..2cca7b01e 100644 --- a/packages/core/client/src/schema-initializer/buttons/ReadPrettyFormActionInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/ReadPrettyFormActionInitializers.tsx @@ -1,3 +1,5 @@ +import { useCollection } from '../..'; + // 表单的操作配置 export const ReadPrettyFormActionInitializers = { title: '{{t("Configure actions")}}', @@ -21,6 +23,10 @@ export const ReadPrettyFormActionInitializers = { type: 'primary', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -30,6 +36,10 @@ export const ReadPrettyFormActionInitializers = { 'x-component': 'Action', 'x-decorator': 'ACLActionProvider', }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -122,6 +132,10 @@ export const ReadPrettyFormActionInitializers = { useProps: '{{ useCustomizeUpdateActionProps }}', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -145,6 +159,10 @@ export const ReadPrettyFormActionInitializers = { useProps: '{{ useCustomizeRequestActionProps }}', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, ], }, diff --git a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx index 5e3608382..e0dd52a3a 100644 --- a/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/RecordBlockInitializers.tsx @@ -166,8 +166,11 @@ export const RecordBlockInitializers = (props: any) => { const { insertPosition, component, actionInitializers } = props; const collection = useCollection(); const { getChildrenCollections } = useCollectionManager(); - const childrenCollections = getChildrenCollections(collection.name); - const hasChildCollection = childrenCollections?.length > 0; + const formChildrenCollections = getChildrenCollections(collection.name); + const hasFormChildCollection = formChildrenCollections?.length > 0; + const detailChildrenCollections = getChildrenCollections(collection.name, true); + const hasDetailChildCollection = detailChildrenCollections?.length > 0; + const modifyFlag = (collection as any).template !== 'view'; return ( { { type: 'itemGroup', title: '{{t("Current record blocks")}}', - children: hasChildCollection - ? [ - { + children: [ + hasDetailChildCollection + ? { key: 'details', type: 'subMenu', title: '{{t("Details")}}', - children: useDetailCollections({ ...props, childrenCollections, collection }), - }, - { - key: 'form', - type: 'subMenu', - title: '{{t("Form")}}', - children: useFormCollections({ ...props, childrenCollections, collection }), - }, - ] - : [ - { + children: useDetailCollections({ + ...props, + childrenCollections: detailChildrenCollections, + collection, + }), + } + : { key: 'details', type: 'item', title: '{{t("Details")}}', component: 'RecordReadPrettyFormBlockInitializer', actionInitializers, }, - { + hasFormChildCollection + ? { + key: 'form', + type: 'subMenu', + title: '{{t("Form")}}', + children: useFormCollections({ + ...props, + childrenCollections: formChildrenCollections, + collection, + }), + } + : modifyFlag && { key: 'form', type: 'item', title: '{{t("Form")}}', component: 'RecordFormBlockInitializer', }, - ], + ], }, { type: 'itemGroup', diff --git a/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx index 669d576a0..ba97bf8b3 100644 --- a/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/TableActionColumnInitializers.tsx @@ -51,7 +51,8 @@ export const TableActionColumnInitializers = (props: any) => { const { refresh } = useDesignable(); const { t } = useTranslation(); const collection = useCollection(); - const { treeTable } = fieldSchema?.parent?.parent['x-decorator-props']||{}; + const { treeTable } = fieldSchema?.parent?.parent['x-decorator-props'] || {}; + const modifyFlag = (collection as any).template !== 'view'; return ( { 'x-action': 'update', 'x-decorator': 'ACLActionProvider', }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, - { + modifyFlag && { type: 'item', title: t('Delete'), component: 'DestroyActionInitializer', @@ -202,6 +207,10 @@ export const TableActionColumnInitializers = (props: any) => { useProps: '{{ useCustomizeUpdateActionProps }}', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -224,6 +233,10 @@ export const TableActionColumnInitializers = (props: any) => { useProps: '{{ useCustomizeRequestActionProps }}', }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, ], }, diff --git a/packages/core/client/src/schema-initializer/buttons/TableActionInitializers.tsx b/packages/core/client/src/schema-initializer/buttons/TableActionInitializers.tsx index 40c6c493d..91e17308f 100644 --- a/packages/core/client/src/schema-initializer/buttons/TableActionInitializers.tsx +++ b/packages/core/client/src/schema-initializer/buttons/TableActionInitializers.tsx @@ -32,6 +32,10 @@ export const TableActionInitializers = { skipScopeCheck: true, }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -41,6 +45,10 @@ export const TableActionInitializers = { 'x-align': 'right', 'x-decorator': 'ACLActionProvider', }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -60,7 +68,7 @@ export const TableActionInitializers = { visible: () => { const schema = useFieldSchema(); const collection = useCollection(); - const { treeTable } = schema?.parent?.['x-decorator-props']||{}; + const { treeTable } = schema?.parent?.['x-decorator-props'] || {}; return collection.tree && treeTable !== false; }, }, @@ -68,6 +76,10 @@ export const TableActionInitializers = { }, { type: 'divider', + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'item', @@ -82,9 +94,17 @@ export const TableActionInitializers = { )?.[1]; return resultSchema; }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'divider', + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, { type: 'subMenu', @@ -135,6 +155,10 @@ export const TableActionInitializers = { }, }, ], + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }, ], }; diff --git a/packages/core/client/src/schema-initializer/items/DetailsBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/DetailsBlockInitializer.tsx index dd2bd7392..8907ef886 100644 --- a/packages/core/client/src/schema-initializer/items/DetailsBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/DetailsBlockInitializer.tsx @@ -1,9 +1,9 @@ -import React from "react"; +import React from 'react'; import { TableOutlined } from '@ant-design/icons'; -import { useCollectionManager } from "../../collection-manager"; -import { createDetailsBlockSchema } from "../utils"; -import { DataBlockInitializer } from "./DataBlockInitializer"; +import { useCollectionManager } from '../../collection-manager'; +import { createDetailsBlockSchema } from '../utils'; +import { DataBlockInitializer } from './DataBlockInitializer'; export const DetailsBlockInitializer = (props) => { const { insert } = props; @@ -15,7 +15,11 @@ export const DetailsBlockInitializer = (props) => { componentType={'Details'} onCreateBlockSchema={async ({ item }) => { const collection = getCollection(item.name); - const schema = createDetailsBlockSchema({ collection: item.name, rowKey: collection.filterTargetKey || 'id' }); + const schema = createDetailsBlockSchema({ + collection: item.name, + rowKey: collection.filterTargetKey || 'id', + actionInitializers: collection.template !== 'view' && 'DetailsActionInitializers', + }); insert(schema); }} /> diff --git a/packages/core/client/src/schema-initializer/items/TableBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/TableBlockInitializer.tsx index 71004f942..bb74cfb15 100644 --- a/packages/core/client/src/schema-initializer/items/TableBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/TableBlockInitializer.tsx @@ -1,9 +1,8 @@ -import React from "react"; +import React from 'react'; import { TableOutlined } from '@ant-design/icons'; - -import { useCollectionManager } from "../../collection-manager"; -import { DataBlockInitializer } from "./DataBlockInitializer"; -import { createTableBlockSchema } from "../utils"; +import { useCollectionManager } from '../../collection-manager'; +import { DataBlockInitializer } from './DataBlockInitializer'; +import { createTableBlockSchema } from '../utils'; export const TableBlockInitializer = (props) => { const { insert } = props; @@ -15,7 +14,10 @@ export const TableBlockInitializer = (props) => { componentType={'Table'} onCreateBlockSchema={async ({ item }) => { const collection = getCollection(item.name); - const schema = createTableBlockSchema({ collection: item.name, rowKey: collection.filterTargetKey || 'id' }); + const schema = createTableBlockSchema({ + collection: item.name, + rowKey: collection.filterTargetKey || 'id', + }); insert(schema); }} /> diff --git a/packages/core/client/src/schema-initializer/utils.ts b/packages/core/client/src/schema-initializer/utils.ts index 5f37f5def..ada43660d 100644 --- a/packages/core/client/src/schema-initializer/utils.ts +++ b/packages/core/client/src/schema-initializer/utils.ts @@ -705,6 +705,8 @@ export const useCollectionDataSourceItems = (componentName) => { return false; } else if (item.autoGenId === false && !item.fields.find((v) => v.primaryKey)) { return false; + } else if (['Kanban', 'FormItem'].includes(componentName) && item.template === 'view') { + return false; } else { return b && !(item?.isThrough && item?.autoCreate); } diff --git a/packages/core/database/src/__tests__/repository.test.ts b/packages/core/database/src/__tests__/repository.test.ts index 6af56a3ff..060a1d434 100644 --- a/packages/core/database/src/__tests__/repository.test.ts +++ b/packages/core/database/src/__tests__/repository.test.ts @@ -311,6 +311,20 @@ describe('repository.update', () => { name: 'post1', userId: user.id, }); + + await User.repository.update({ + filterByTk: user.id, + values: { + posts: [{ name: 'post2' }, { name: 'post3' }], + }, + }); + + const updated2 = await User.repository.findOne({ + filterByTk: user.id, + appends: ['posts'], + }); + + expect(updated2.posts.length).toBe(2); }); it('update2', async () => { diff --git a/packages/core/database/src/__tests__/sql-parser.test.ts b/packages/core/database/src/__tests__/sql-parser.test.ts new file mode 100644 index 000000000..d0bbb2745 --- /dev/null +++ b/packages/core/database/src/__tests__/sql-parser.test.ts @@ -0,0 +1,13 @@ +import sqlParser from '../sql-parser'; + +describe('sql parser', () => { + it('should parse sql', function () { + const sql = `select users.id as id from users`; + const { ast } = sqlParser.parse(sql); + const columns = ast.columns; + const firstColumn = columns[0]; + + expect(firstColumn['expr']['table']).toEqual('users'); + expect(firstColumn['expr']['column']).toEqual('id'); + }); +}); diff --git a/packages/core/database/src/__tests__/view/list-view.test.ts b/packages/core/database/src/__tests__/view/list-view.test.ts new file mode 100644 index 000000000..3b218c0de --- /dev/null +++ b/packages/core/database/src/__tests__/view/list-view.test.ts @@ -0,0 +1,34 @@ +import { Database, mockDatabase } from '@nocobase/database'; + +describe('list view', () => { + let db: Database; + + beforeEach(async () => { + db = mockDatabase({ + tablePrefix: '', + }); + await db.clean({ drop: true }); + }); + + afterEach(async () => { + await db.close(); + }); + + it('should list view', async () => { + const dropViewSQL1 = `DROP VIEW IF EXISTS test1`; + await db.sequelize.query(dropViewSQL1); + + const dropViewSQL2 = `DROP VIEW IF EXISTS test2`; + await db.sequelize.query(dropViewSQL2); + + const sql1 = `CREATE VIEW test1 AS SELECT 1`; + const sql2 = `CREATE VIEW test2 AS SELECT 2`; + + await db.sequelize.query(sql1); + await db.sequelize.query(sql2); + + const results = await db.queryInterface.listViews(); + expect(results.find((item) => item.name === 'test1')).toBeTruthy(); + expect(results.find((item) => item.name === 'test2')).toBeTruthy(); + }); +}); diff --git a/packages/core/database/src/__tests__/view/view-collection.test.ts b/packages/core/database/src/__tests__/view/view-collection.test.ts new file mode 100644 index 000000000..14f3c694c --- /dev/null +++ b/packages/core/database/src/__tests__/view/view-collection.test.ts @@ -0,0 +1,199 @@ +import { Database, mockDatabase } from '@nocobase/database'; +import { uid } from '@nocobase/utils'; +import { ViewCollection } from '../../view-collection'; + +describe('create view', () => { + let db: Database; + + beforeEach(async () => { + db = mockDatabase({ + tablePrefix: '', + }); + await db.clean({ drop: true }); + }); + + afterEach(async () => { + await db.close(); + }); + + it('should create view collection in difference schema', async () => { + if (!db.inDialect('postgres')) return; + const schemaName = `t_${uid(6)}`; + const testSchemaSql = `CREATE SCHEMA IF NOT EXISTS ${schemaName};`; + await db.sequelize.query(testSchemaSql); + + const viewName = 'test_view'; + + const viewSQL = `CREATE OR REPLACE VIEW ${schemaName}.test_view AS SELECT 1+1 as result`; + await db.sequelize.query(viewSQL); + + const viewCollection = db.collection({ + name: viewName, + schema: schemaName, + view: true, + fields: [ + { + type: 'string', + name: 'result', + }, + ], + }); + + const results = await viewCollection.repository.find(); + + expect(results.length).toBe(1); + }); + + it('should create view collection', async () => { + const UserCollection = db.collection({ + name: 'users', + fields: [ + { + type: 'string', + name: 'name', + }, + { + type: 'hasOne', + name: 'profile', + foreignKey: 'user_id', + }, + ], + }); + + const ProfileCollection = db.collection({ + name: 'profiles', + fields: [ + { + type: 'integer', + name: 'age', + }, + { + type: 'belongsTo', + name: 'user', + foreignKey: 'user_id', + }, + ], + }); + + await db.sync(); + + await UserCollection.repository.create({ + values: { + name: 'foo', + profile: { + age: 18, + }, + }, + }); + const schema = UserCollection.collectionSchema(); + const viewName = 'users_with_profile'; + + const appendSchema = db.inDialect('postgres') ? `"${schema}".` : ''; + + const dropViewSQL = `DROP VIEW IF EXISTS ${appendSchema}${viewName}`; + await db.sequelize.query(dropViewSQL); + const viewSql = `CREATE VIEW ${appendSchema}${viewName} AS SELECT users.name, profiles.age FROM ${appendSchema}${UserCollection.model.tableName} as users LEFT JOIN ${appendSchema}${ProfileCollection.model.tableName} as profiles ON users.id = profiles.user_id;`; + + await db.sequelize.query(viewSql); + + db.collection({ + name: viewName, + view: true, + fields: [ + { + type: 'string', + name: 'name', + }, + { + type: 'integer', + name: 'age', + }, + ], + }); + const UserWithProfileView = db.getCollection(viewName); + expect(UserWithProfileView).toBeInstanceOf(ViewCollection); + + const fooData = await UserWithProfileView.repository.findOne({ + filter: { + name: 'foo', + }, + }); + + console.log(fooData); + expect(fooData.get('name')).toBe('foo'); + expect(fooData.get('age')).toBe(18); + }); + + it('should not sync view collection', async () => { + const dropViewSQL = `DROP VIEW IF EXISTS test_view`; + await db.sequelize.query(dropViewSQL); + + const viewSql = `CREATE VIEW test_view AS SELECT 1+1 as result`; + + await db.sequelize.query(viewSql); + const viewCollection = db.collection({ + name: 'view_collection', + viewName: 'test_view', + fields: [ + { + type: 'string', + name: 'result', + }, + ], + }); + + const jestFn = jest.fn(); + + db.on('beforeSync', jestFn); + + await viewCollection.sync(); + expect(jestFn).not.toBeCalled(); + }); + + it('should create view collection with source field options', async () => { + const UserCollection = db.collection({ + name: 'users', + fields: [ + { + name: 'name', + type: 'string', + patterns: [ + { + type: 'integer', + options: { key: 1 }, + }, + ], + }, + ], + }); + + await db.sync(); + + const viewName = 'users_view'; + + const dropViewSQL = `DROP VIEW IF EXISTS ${viewName}`; + await db.sequelize.query(dropViewSQL); + + const viewSQL = ` + CREATE VIEW ${viewName} as SELECT users.* FROM ${UserCollection.quotedTableName()} as users + `; + + await db.sequelize.query(viewSQL); + + // create view collection + const ViewCollection = db.collection({ + name: viewName, + view: true, + fields: [ + { + name: 'name', + type: 'string', + source: 'users.name', + }, + ], + }); + + const viewNameField = ViewCollection.getField('name'); + expect(viewNameField.options.patterns).toEqual(UserCollection.getField('name').options.patterns); + }); +}); diff --git a/packages/core/database/src/__tests__/view/view-inference.test.ts b/packages/core/database/src/__tests__/view/view-inference.test.ts new file mode 100644 index 000000000..f5e9f5052 --- /dev/null +++ b/packages/core/database/src/__tests__/view/view-inference.test.ts @@ -0,0 +1,103 @@ +import { Database, mockDatabase } from '@nocobase/database'; +import { ViewFieldInference } from '../../view/view-inference'; + +describe('view inference', function () { + let db: Database; + + beforeEach(async () => { + db = mockDatabase({ + tablePrefix: '', + }); + await db.clean({ drop: true }); + }); + + afterEach(async () => { + await db.close(); + }); + + it('should infer collection fields', async () => { + const UserCollection = db.collection({ + name: 'users', + fields: [ + { + name: 'name', + type: 'string', + interface: 'test', + }, + { + name: 'age', + type: 'integer', + interface: 'test', + }, + { + name: 'profile', + type: 'json', + interface: 'test', + }, + { + name: 'posts', + type: 'hasMany', + interface: 'test', + }, + ], + }); + + const PostCollection = db.collection({ + name: 'posts', + fields: [ + { + name: 'title', + type: 'string', + interface: 'test', + }, + { + name: 'user', + type: 'belongsTo', + interface: 'test', + }, + ], + }); + + await db.sync(); + + const viewName = 'user_posts'; + + const dropViewSQL = `DROP VIEW IF EXISTS ${viewName}`; + await db.sequelize.query(dropViewSQL); + + const viewSQL = ` + CREATE VIEW ${viewName} as SELECT 1 as const_field, users.* FROM ${UserCollection.quotedTableName()} as users + `; + + await db.sequelize.query(viewSQL); + + const inferredFields = await ViewFieldInference.inferFields({ + db, + viewName, + viewSchema: 'public', + }); + + const createdAt = UserCollection.model.rawAttributes['createdAt'].field; + expect(inferredFields[createdAt]['type']).toBe('date'); + + if (db.options.dialect == 'sqlite') { + expect(inferredFields['name']).toMatchObject({ + name: 'name', + type: 'string', + }); + } else { + expect(inferredFields['name']).toMatchObject({ + name: 'name', + type: 'string', + source: 'users.name', + }); + + expect(inferredFields['const_field']).toMatchObject({ + name: 'const_field', + type: 'integer', + }); + } + + await db.sequelize.query(dropViewSQL); + }); +}); diff --git a/packages/core/database/src/__tests__/view/view-repository.test.ts b/packages/core/database/src/__tests__/view/view-repository.test.ts new file mode 100644 index 000000000..66dd29c03 --- /dev/null +++ b/packages/core/database/src/__tests__/view/view-repository.test.ts @@ -0,0 +1,67 @@ +import { Database, mockDatabase } from '@nocobase/database'; +import { uid } from '@nocobase/utils'; + +describe('view repository', () => { + let db: Database; + + beforeEach(async () => { + db = mockDatabase({ + tablePrefix: '', + }); + await db.clean({ drop: true }); + }); + + afterEach(async () => { + await db.close(); + }); + + it('should support find view without primary key', async () => { + const UserCollection = await db.collection({ + name: 'users', + fields: [ + { + type: 'string', + name: 'name', + }, + ], + }); + + await db.sync(); + + await UserCollection.repository.create({ + values: [{ name: 'a' }, { name: 'b' }, { name: 'c' }, { name: 'd' }], + }); + + const viewName = `t_${uid(6)}`; + const dropSQL = `DROP VIEW IF EXISTS ${viewName};`; + await db.sequelize.query(dropSQL); + + const viewSQL = `CREATE VIEW ${viewName} AS select id as aaa, name from ${UserCollection.quotedTableName()}`; + + await db.sequelize.query(viewSQL); + + const viewCollection = db.collection({ + name: viewName, + view: true, + schema: db.inDialect('postgres') ? 'public' : undefined, + fields: [ + { + type: 'string', + name: 'name', + }, + { + type: 'integer', + name: 'aaa', + }, + ], + }); + + const results = await viewCollection.repository.findAndCount({ + offset: 1, + limit: 1, + }); + + expect(results[0].length).toBe(1); + expect(results[1]).toBe(4); + }); +}); diff --git a/packages/core/database/src/collection.ts b/packages/core/database/src/collection.ts index aca9aa543..f65973479 100644 --- a/packages/core/database/src/collection.ts +++ b/packages/core/database/src/collection.ts @@ -34,6 +34,8 @@ export interface CollectionOptions extends Omit tableName?: string; inherits?: string[] | string; + viewName?: string; + filterTargetKey?: string; fields?: FieldOptions[]; model?: string | ModelStatic; @@ -69,7 +71,12 @@ export class Collection< repository: Repository; get filterTargetKey() { - return lodash.get(this.options, 'filterTargetKey', this.model.primaryKeyAttribute); + let targetKey = lodash.get(this.options, 'filterTargetKey', this.model.primaryKeyAttribute); + if (!targetKey && this.model.rawAttributes['id']) { + return 'id'; + } + + return targetKey; } get name() { @@ -111,7 +118,11 @@ export class Collection< this.modelInit(); this.db.modelCollection.set(this.model, this); - this.db.tableNameCollectionMap.set(this.model.tableName, this); + + // set tableName to collection map + // the form of key is `${schema}.${tableName}` if schema exists + // otherwise is `${tableName}` + this.db.tableNameCollectionMap.set(this.getTableNameWithSchemaAsString(), this); if (!options.inherits) { this.setFields(options.fields); @@ -141,7 +152,7 @@ export class Collection< return this.db.options.underscored ? snakeCase(tName) : tName; } - private sequelizeModelOptions() { + protected sequelizeModelOptions() { const { name } = this.options; return { ..._.omit(this.options, ['name', 'fields', 'model', 'targetKey']), @@ -261,6 +272,17 @@ export class Collection< this.checkFieldType(name, options); const { database } = this.context; + + if (options.source) { + const [sourceCollectionName, sourceFieldName] = options.source.split('.'); + const sourceCollection = this.db.collections.get(sourceCollectionName); + if (!sourceCollection) { + throw new Error(`source collection "${sourceCollectionName}" not found`); + } + const sourceField = sourceCollection.fields.get(sourceFieldName); + options = { ...sourceField.options, ...options }; + } + this.emit('field.beforeAdd', name, options, { collection: this }); const field = database.buildField( @@ -334,9 +356,10 @@ export class Collection< async removeFromDb(options?: QueryInterfaceDropTableOptions) { if ( - await this.existsInDb({ + !this.isView() && + (await this.existsInDb({ transaction: options?.transaction, - }) + })) ) { const queryInterface = this.db.sequelize.getQueryInterface(); await queryInterface.dropTable(this.getTableNameWithSchema(), options); @@ -575,13 +598,23 @@ export class Collection< public getTableNameWithSchema() { const tableName = this.model.tableName; - if (this.collectionSchema()) { + if (this.collectionSchema() && this.db.inDialect('postgres')) { return this.db.utils.addSchema(tableName, this.collectionSchema()); } return tableName; } + public getTableNameWithSchemaAsString() { + const tableName = this.model.tableName; + + if (this.collectionSchema() && this.db.inDialect('postgres')) { + return `${this.collectionSchema()}.${tableName}`; + } + + return tableName; + } + public quotedTableName() { return this.db.utils.quoteTable(this.getTableNameWithSchema()); } @@ -601,4 +634,8 @@ export class Collection< return undefined; } + + public isView() { + return false; + } } diff --git a/packages/core/database/src/database-utils/index.ts b/packages/core/database/src/database-utils/index.ts index 8e2d656c8..46c3906b8 100644 --- a/packages/core/database/src/database-utils/index.ts +++ b/packages/core/database/src/database-utils/index.ts @@ -5,6 +5,7 @@ export default class DatabaseUtils { constructor(public db: Database) {} addSchema(tableName, schema?) { + if (!this.db.inDialect('postgres')) return tableName; if (this.db.options.schema && !schema) { schema = this.db.options.schema; } diff --git a/packages/core/database/src/database.ts b/packages/core/database/src/database.ts index 33c10d76d..5e8a66af1 100644 --- a/packages/core/database/src/database.ts +++ b/packages/core/database/src/database.ts @@ -15,7 +15,7 @@ import { Sequelize, SyncOptions, Transactionable, - Utils + Utils, } from 'sequelize'; import { SequelizeStorage, Umzug } from 'umzug'; import { Collection, CollectionOptions, RepositoryType } from './collection'; @@ -58,7 +58,7 @@ import { SyncListener, UpdateListener, UpdateWithAssociationsListener, - ValidateListener + ValidateListener, } from './types'; import { patchSequelizeQueryInterface, snakeCase } from './utils'; @@ -69,6 +69,7 @@ import buildQueryInterface from './query-interface/query-interface-builder'; import QueryInterface from './query-interface/query-interface'; import { Logger } from '@nocobase/logger'; import { CollectionGroupManager } from './collection-group-manager'; +import { ViewCollection } from './view-collection'; export interface MergeOptions extends merge.Options {} @@ -221,7 +222,7 @@ export class Database extends EventEmitter implements AsyncEmitter { } this.options = opts; - this.sequelize = new Sequelize(opts); + this.sequelize = new Sequelize(this.sequelizeOptions(this.options)); this.queryInterface = buildQueryInterface(this); @@ -297,6 +298,17 @@ export class Database extends EventEmitter implements AsyncEmitter { this.logger = logger; } + sequelizeOptions(options) { + if (options.dialect === 'postgres') { + options.hooks = { + afterConnect: async (connection) => { + await connection.query('SET search_path TO public;'); + }, + }; + } + return options; + } + initListener() { this.on('beforeDefine', (model, options) => { if (this.options.underscored) { @@ -416,14 +428,21 @@ export class Database extends EventEmitter implements AsyncEmitter { return options.inherits && lodash.castArray(options.inherits).length > 0; })(); - const collection = hasValidInheritsOptions - ? new InheritedCollection(options, { - database: this, - }) - : new Collection(options, { - database: this, - }); + const hasViewOptions = options.viewName || options.view; + const collectionKlass = (() => { + if (hasValidInheritsOptions) { + return InheritedCollection; + } + + if (hasViewOptions) { + return ViewCollection; + } + + return Collection; + })(); + + const collection = new collectionKlass(options, { database: this }); this.collections.set(collection.name, collection); this.emit('afterDefineCollection', collection); @@ -647,7 +666,7 @@ export class Database extends EventEmitter implements AsyncEmitter { return; } - await this.sequelize.getQueryInterface().dropAllTables(others); + await this.queryInterface.dropAll(options); } async collectionExistsInDb(name: string, options?: Transactionable) { diff --git a/packages/core/database/src/fields/field.ts b/packages/core/database/src/fields/field.ts index e78e391e1..8011a44bf 100644 --- a/packages/core/database/src/fields/field.ts +++ b/packages/core/database/src/fields/field.ts @@ -157,6 +157,11 @@ export abstract class Field { // return; // } + if (this.collection.isView()) { + this.remove(); + return; + } + const columnReferencesCount = _.filter( this.collection.model.rawAttributes, (attr) => attr.field == this.columnName(), @@ -232,6 +237,7 @@ export abstract class Field { if (this.dataType) { Object.assign(opts, { type: this.dataType }); } + return opts; } diff --git a/packages/core/database/src/fields/json-field.ts b/packages/core/database/src/fields/json-field.ts index 19ea21cdb..a1b89be2f 100644 --- a/packages/core/database/src/fields/json-field.ts +++ b/packages/core/database/src/fields/json-field.ts @@ -20,6 +20,7 @@ export class JsonbField extends Field { return DataTypes.JSON; } } + export interface JsonbFieldOptions extends BaseColumnFieldOptions { type: 'jsonb'; } diff --git a/packages/core/database/src/index.ts b/packages/core/database/src/index.ts index d379a4676..3162fad03 100644 --- a/packages/core/database/src/index.ts +++ b/packages/core/database/src/index.ts @@ -21,3 +21,5 @@ export * from './update-associations'; export { snakeCase } from './utils'; export * from './value-parsers'; export * from './collection-group-manager'; +export * from './view-collection'; +export * from './view/view-inference'; diff --git a/packages/core/database/src/mock-database.ts b/packages/core/database/src/mock-database.ts index 137f7a927..7abc8b4b5 100644 --- a/packages/core/database/src/mock-database.ts +++ b/packages/core/database/src/mock-database.ts @@ -14,7 +14,7 @@ export class MockDatabase extends Database { } export function getConfigByEnv() { - return { + const options = { username: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE, @@ -33,10 +33,14 @@ export function getConfigByEnv() { timezone: process.env.DB_TIMEZONE, underscored: process.env.DB_UNDERSCORED === 'true', schema: process.env.DB_SCHEMA !== 'public' ? process.env.DB_SCHEMA : undefined, - dialectOptions: { - application_name: process.env.DB_DIALECT == 'postgres' ? 'nocobase.main' : undefined, - }, + dialectOptions: {}, }; + + if (process.env.DB_DIALECT == 'postgres') { + options.dialectOptions['application_name'] = 'nocobase.main'; + } + + return options; } function customLogger(queryString, queryObject) { diff --git a/packages/core/database/src/model.ts b/packages/core/database/src/model.ts index e5224f8b9..c549e09a1 100644 --- a/packages/core/database/src/model.ts +++ b/packages/core/database/src/model.ts @@ -151,6 +151,10 @@ export class Model 0; } + + async listViews() { + const sql = `SELECT TABLE_NAME as name, VIEW_DEFINITION as definition + FROM information_schema.views + WHERE TABLE_SCHEMA = DATABASE() + ORDER BY TABLE_NAME;`; + + return await this.db.sequelize.query(sql, { type: 'SELECT' }); + } + + async viewColumnUsage(options: { viewName: string; schema?: string }): Promise< + Array<{ + column_name: string; + table_name: string; + table_schema?: string; + }> + > { + try { + const viewDefinition = await this.db.sequelize.query(`SHOW CREATE VIEW ${options.viewName}`, { type: 'SELECT' }); + const createView = viewDefinition[0]['Create View']; + const regex = /(?<=AS\s)([\s\S]*)/i; + const match = createView.match(regex); + const sql = match[0]; + + const { ast } = sqlParser.parse(sql); + + const columns = ast.columns; + + const results = []; + for (const column of columns) { + if (column.expr.type === 'column_ref') { + results.push({ + column_name: column.expr.column, + table_name: column.expr.table, + }); + } + } + + return results; + } catch (e) { + this.db.logger.warn(e); + + return []; + } + } } diff --git a/packages/core/database/src/query-interface/postgres-query-interface.ts b/packages/core/database/src/query-interface/postgres-query-interface.ts index c01fe9509..eb5e054e8 100644 --- a/packages/core/database/src/query-interface/postgres-query-interface.ts +++ b/packages/core/database/src/query-interface/postgres-query-interface.ts @@ -12,11 +12,35 @@ export default class PostgresQueryInterface extends QueryInterface { const tableName = collection.model.tableName; const schema = collection.collectionSchema() || 'public'; - const sql = `SELECT EXISTS(SELECT 1 FROM information_schema.tables - WHERE table_schema = '${schema}' - AND table_name = '${tableName}')`; + const sql = `SELECT EXISTS(SELECT 1 + FROM information_schema.tables + WHERE table_schema = '${schema}' + AND table_name = '${tableName}')`; const results = await this.db.sequelize.query(sql, { type: 'SELECT', transaction }); return results[0]['exists']; } + + async listViews() { + const sql = ` + SELECT viewname as name, definition, schemaname as schema + FROM pg_views + WHERE schemaname NOT IN ('pg_catalog', 'information_schema') + ORDER BY viewname; + `; + + return await this.db.sequelize.query(sql, { type: 'SELECT' }); + } + + async viewColumnUsage(options) { + const { viewName, schema = 'public' } = options; + const sql = ` + SELECT * + FROM information_schema.view_column_usage + WHERE view_schema = '${schema}' + AND view_name = '${viewName}'; + `; + + return (await this.db.sequelize.query(sql, { type: 'SELECT' })) as any; + } } diff --git a/packages/core/database/src/query-interface/query-interface.ts b/packages/core/database/src/query-interface/query-interface.ts index 311da005a..8792a24cc 100644 --- a/packages/core/database/src/query-interface/query-interface.ts +++ b/packages/core/database/src/query-interface/query-interface.ts @@ -4,9 +4,40 @@ import { QueryInterface as SequelizeQueryInterface, Transactionable } from 'sequ export default abstract class QueryInterface { sequelizeQueryInterface: SequelizeQueryInterface; + protected constructor(public db: Database) { this.sequelizeQueryInterface = db.sequelize.getQueryInterface(); } abstract collectionTableExists(collection: Collection, options?: Transactionable): Promise; + + abstract listViews(); + + abstract viewColumnUsage(options: { viewName: string; schema?: string }): Promise< + Array<{ + column_name: string; + table_name: string; + table_schema?: string; + }> + >; + + async dropAll(options) { + if (options.drop !== true) return; + + const views = await this.listViews(); + + for (const view of views) { + let removeSql; + + if (view.schema) { + removeSql = `DROP VIEW IF EXISTS "${view.schema}"."${view.name}"`; + } else { + removeSql = `DROP VIEW IF EXISTS ${view.name}`; + } + + await this.db.sequelize.query(removeSql, { transaction: options.transaction }); + } + + await this.db.sequelize.getQueryInterface().dropAllTables(options); + } } diff --git a/packages/core/database/src/query-interface/sqlite-query-interface.ts b/packages/core/database/src/query-interface/sqlite-query-interface.ts index 9ac5e8a77..137b75789 100644 --- a/packages/core/database/src/query-interface/sqlite-query-interface.ts +++ b/packages/core/database/src/query-interface/sqlite-query-interface.ts @@ -1,5 +1,6 @@ import QueryInterface from './query-interface'; import { Collection } from '../collection'; +import sqlParser from '../sql-parser'; export default class SqliteQueryInterface extends QueryInterface { constructor(db) { @@ -11,8 +12,65 @@ export default class SqliteQueryInterface extends QueryInterface { const tableName = collection.model.tableName; - const sql = `SELECT name FROM sqlite_master WHERE type='table' AND name='${tableName}';`; + const sql = `SELECT name + FROM sqlite_master + WHERE type = 'table' + AND name = '${tableName}';`; const results = await this.db.sequelize.query(sql, { type: 'SELECT', transaction }); return results.length > 0; } + + async listViews() { + const sql = ` + SELECT name , sql as definition + FROM sqlite_master + WHERE type = 'view' + ORDER BY name; + `; + + return await this.db.sequelize.query(sql, { + type: 'SELECT', + }); + } + + async viewColumnUsage(options: { viewName: string; schema?: string }): Promise< + Array<{ + column_name: string; + table_name: string; + table_schema?: string; + }> + > { + try { + const viewDefinition = await this.db.sequelize.query( + `SELECT sql FROM sqlite_master WHERE name = '${options.viewName}' AND type = 'view'`, + { + type: 'SELECT', + }, + ); + + const createView = viewDefinition[0]['sql']; + const regex = /(?<=AS\s)([\s\S]*)/i; + const match = createView.match(regex); + const sql = match[0]; + + const { ast } = sqlParser.parse(sql); + + const columns = ast.columns; + + const results = []; + for (const column of columns) { + if (column.expr.type === 'column_ref') { + results.push({ + column_name: column.expr.column, + table_name: column.expr.table, + }); + } + } + + return results; + } catch (e) { + this.db.logger.warn(e); + return []; + } + } } diff --git a/packages/core/database/src/repository.ts b/packages/core/database/src/repository.ts index d58d0f37d..4a9821aa5 100644 --- a/packages/core/database/src/repository.ts +++ b/packages/core/database/src/repository.ts @@ -11,7 +11,7 @@ import { Op, Transactionable, UpdateOptions as SequelizeUpdateOptions, - WhereOperators + WhereOperators, } from 'sequelize'; import { Collection } from './collection'; import { Database } from './database'; @@ -340,7 +340,9 @@ export class Repository targetLength) { return str; } + targetLength -= str.length; + padString += padString.repeat(targetLength); + return str + padString.slice(0, targetLength); +} + +peg$SyntaxError.prototype.format = function(sources) { + var str = "Error: " + this.message; + if (this.location) { + var src = null; + var k; + for (k = 0; k < sources.length; k++) { + if (sources[k].source === this.location.source) { + src = sources[k].text.split(/\r\n|\n|\r/g); + break; + } + } + var s = this.location.start; + var offset_s = (this.location.source && (typeof this.location.source.offset === "function")) + ? this.location.source.offset(s) + : s; + var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column; + if (src) { + var e = this.location.end; + var filler = peg$padEnd("", offset_s.line.toString().length, ' '); + var line = src[s.line - 1]; + var last = s.line === e.line ? e.column : line.length + 1; + var hatLen = (last - s.column) || 1; + str += "\n --> " + loc + "\n" + + filler + " |\n" + + offset_s.line + " | " + line + "\n" + + filler + " | " + peg$padEnd("", s.column - 1, ' ') + + peg$padEnd("", hatLen, "^"); + } else { + str += "\n at " + loc; + } + } + return str; +}; + +peg$SyntaxError.buildMessage = function(expected, found) { + var DESCRIBE_EXPECTATION_FNS = { + literal: function(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + + class: function(expectation) { + var escapedParts = expectation.parts.map(function(part) { + return Array.isArray(part) + ? classEscape(part[0]) + "-" + classEscape(part[1]) + : classEscape(part); + }); + + return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]"; + }, + + any: function() { + return "any character"; + }, + + end: function() { + return "end of input"; + }, + + other: function(expectation) { + return expectation.description; + } + }; + + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + function literalEscape(s) { + return s + .replace(/\\/g, "\\\\") + .replace(/"/g, "\\\"") + .replace(/\0/g, "\\0") + .replace(/\t/g, "\\t") + .replace(/\n/g, "\\n") + .replace(/\r/g, "\\r") + .replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); }); + } + + function classEscape(s) { + return s + .replace(/\\/g, "\\\\") + .replace(/\]/g, "\\]") + .replace(/\^/g, "\\^") + .replace(/-/g, "\\-") + .replace(/\0/g, "\\0") + .replace(/\t/g, "\\t") + .replace(/\n/g, "\\n") + .replace(/\r/g, "\\r") + .replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); }); + } + + function describeExpectation(expectation) { + return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); + } + + function describeExpected(expected) { + var descriptions = expected.map(describeExpectation); + var i, j; + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } + } + descriptions.length = j; + } + + switch (descriptions.length) { + case 1: + return descriptions[0]; + + case 2: + return descriptions[0] + " or " + descriptions[1]; + + default: + return descriptions.slice(0, -1).join(", ") + + ", or " + + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found) { + return found ? "\"" + literalEscape(found) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; +}; + +function peg$parse(input, options) { + options = options !== undefined ? options : {}; + + var peg$FAILED = {}; + var peg$source = options.grammarSource; + + var peg$startRuleFunctions = { start: peg$parsestart }; + var peg$startRuleFunction = peg$parsestart; + + var peg$c0 = "("; + var peg$c1 = ")"; + var peg$c2 = "="; + var peg$c3 = "!"; + var peg$c4 = ">="; + var peg$c5 = ">"; + var peg$c6 = "<="; + var peg$c7 = "<>"; + var peg$c8 = "<"; + var peg$c9 = "!="; + var peg$c10 = "+"; + var peg$c11 = "-"; + var peg$c12 = "*"; + var peg$c13 = "/"; + var peg$c14 = "%"; + var peg$c15 = "\""; + var peg$c16 = "'"; + var peg$c17 = "`"; + var peg$c18 = ":"; + var peg$c19 = "\\'"; + var peg$c20 = "\\\""; + var peg$c21 = "\\\\"; + var peg$c22 = "\\/"; + var peg$c23 = "\\b"; + var peg$c24 = "\\f"; + var peg$c25 = "\\n"; + var peg$c26 = "\\r"; + var peg$c27 = "\\t"; + var peg$c28 = "\\u"; + var peg$c29 = "."; + var peg$c30 = "null"; + var peg$c31 = "true"; + var peg$c32 = "false"; + var peg$c33 = "show"; + var peg$c34 = "drop"; + var peg$c35 = "select"; + var peg$c36 = "update"; + var peg$c37 = "create"; + var peg$c38 = "delete"; + var peg$c39 = "insert"; + var peg$c40 = "RECURSIVE"; + var peg$c41 = "replace"; + var peg$c42 = "explain"; + var peg$c43 = "into"; + var peg$c44 = "from"; + var peg$c45 = "set"; + var peg$c46 = "as"; + var peg$c47 = "table"; + var peg$c48 = "on"; + var peg$c49 = "left"; + var peg$c50 = "right"; + var peg$c51 = "full"; + var peg$c52 = "inner"; + var peg$c53 = "join"; + var peg$c54 = "outer"; + var peg$c55 = "union"; + var peg$c56 = "values"; + var peg$c57 = "using"; + var peg$c58 = "where"; + var peg$c59 = "with"; + var peg$c60 = "group"; + var peg$c61 = "by"; + var peg$c62 = "order"; + var peg$c63 = "having"; + var peg$c64 = "limit"; + var peg$c65 = "asc"; + var peg$c66 = "desc"; + var peg$c67 = "all"; + var peg$c68 = "distinct"; + var peg$c69 = "between"; + var peg$c70 = "in"; + var peg$c71 = "is"; + var peg$c72 = "like"; + var peg$c73 = "exists"; + var peg$c74 = "not"; + var peg$c75 = "and"; + var peg$c76 = "or"; + var peg$c77 = "count"; + var peg$c78 = "max"; + var peg$c79 = "min"; + var peg$c80 = "sum"; + var peg$c81 = "avg"; + var peg$c82 = "case"; + var peg$c83 = "when"; + var peg$c84 = "then"; + var peg$c85 = "else"; + var peg$c86 = "end"; + var peg$c87 = "cast"; + var peg$c88 = "char"; + var peg$c89 = "varchar"; + var peg$c90 = "numeric"; + var peg$c91 = "decimal"; + var peg$c92 = "signed"; + var peg$c93 = "unsigned"; + var peg$c94 = "int"; + var peg$c95 = "integer"; + var peg$c96 = "json"; + var peg$c97 = "smallint"; + var peg$c98 = "date"; + var peg$c99 = "time"; + var peg$c100 = "timestamp"; + var peg$c101 = "user"; + var peg$c102 = "current_date"; + var peg$c103 = "adddate"; + var peg$c104 = "interval"; + var peg$c105 = "year"; + var peg$c106 = "month"; + var peg$c107 = "day"; + var peg$c108 = "hour"; + var peg$c109 = "minute"; + var peg$c110 = "second"; + var peg$c111 = "current_time"; + var peg$c112 = "current_timestamp"; + var peg$c113 = "current_user"; + var peg$c114 = "session_user"; + var peg$c115 = "system_user"; + var peg$c116 = "$"; + var peg$c117 = "return"; + var peg$c118 = ":="; + var peg$c119 = "dual"; + var peg$c120 = "sql_calc_found_rows"; + var peg$c121 = "sql_cache"; + var peg$c122 = "sql_no_cache"; + var peg$c123 = "sql_small_result"; + var peg$c124 = "sql_big_result"; + var peg$c125 = "sql_buffer_result"; + var peg$c126 = ","; + var peg$c127 = "["; + var peg$c128 = "]"; + var peg$c129 = ";"; + var peg$c130 = "/*"; + var peg$c131 = "*/"; + var peg$c132 = "--"; + + var peg$r0 = /^[^"]/; + var peg$r1 = /^[^']/; + var peg$r2 = /^[^`]/; + var peg$r3 = /^[A-Za-z_]/; + var peg$r4 = /^[A-Za-z0-9_]/; + var peg$r5 = /^[A-Za-z0-9_:]/; + var peg$r6 = /^[^"\\\0-\x1F\x7F]/; + var peg$r7 = /^[^'\\\0-\x1F\x7F]/; + var peg$r8 = /^[\n\r]/; + var peg$r9 = /^[0-9]/; + var peg$r10 = /^[1-9]/; + var peg$r11 = /^[0-9a-fA-F]/; + var peg$r12 = /^[eE]/; + var peg$r13 = /^[+\-]/; + var peg$r14 = /^[ \t\n\r]/; + + var peg$e0 = peg$literalExpectation("(", false); + var peg$e1 = peg$literalExpectation(")", false); + var peg$e2 = peg$literalExpectation("=", false); + var peg$e3 = peg$literalExpectation("!", false); + var peg$e4 = peg$literalExpectation(">=", false); + var peg$e5 = peg$literalExpectation(">", false); + var peg$e6 = peg$literalExpectation("<=", false); + var peg$e7 = peg$literalExpectation("<>", false); + var peg$e8 = peg$literalExpectation("<", false); + var peg$e9 = peg$literalExpectation("!=", false); + var peg$e10 = peg$literalExpectation("+", false); + var peg$e11 = peg$literalExpectation("-", false); + var peg$e12 = peg$literalExpectation("*", false); + var peg$e13 = peg$literalExpectation("/", false); + var peg$e14 = peg$literalExpectation("%", false); + var peg$e15 = peg$literalExpectation("\"", false); + var peg$e16 = peg$classExpectation(["\""], true, false); + var peg$e17 = peg$literalExpectation("'", false); + var peg$e18 = peg$classExpectation(["'"], true, false); + var peg$e19 = peg$literalExpectation("`", false); + var peg$e20 = peg$classExpectation(["`"], true, false); + var peg$e21 = peg$classExpectation([["A", "Z"], ["a", "z"], "_"], false, false); + var peg$e22 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_"], false, false); + var peg$e23 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_", ":"], false, false); + var peg$e24 = peg$literalExpectation(":", false); + var peg$e25 = peg$classExpectation(["\"", "\\", ["\0", "\x1F"], "\x7F"], true, false); + var peg$e26 = peg$classExpectation(["'", "\\", ["\0", "\x1F"], "\x7F"], true, false); + var peg$e27 = peg$literalExpectation("\\'", false); + var peg$e28 = peg$literalExpectation("\\\"", false); + var peg$e29 = peg$literalExpectation("\\\\", false); + var peg$e30 = peg$literalExpectation("\\/", false); + var peg$e31 = peg$literalExpectation("\\b", false); + var peg$e32 = peg$literalExpectation("\\f", false); + var peg$e33 = peg$literalExpectation("\\n", false); + var peg$e34 = peg$literalExpectation("\\r", false); + var peg$e35 = peg$literalExpectation("\\t", false); + var peg$e36 = peg$literalExpectation("\\u", false); + var peg$e37 = peg$classExpectation(["\n", "\r"], false, false); + var peg$e38 = peg$literalExpectation(".", false); + var peg$e39 = peg$classExpectation([["0", "9"]], false, false); + var peg$e40 = peg$classExpectation([["1", "9"]], false, false); + var peg$e41 = peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false); + var peg$e42 = peg$classExpectation(["e", "E"], false, false); + var peg$e43 = peg$classExpectation(["+", "-"], false, false); + var peg$e44 = peg$literalExpectation("NULL", true); + var peg$e45 = peg$literalExpectation("TRUE", true); + var peg$e46 = peg$literalExpectation("FALSE", true); + var peg$e47 = peg$literalExpectation("SHOW", true); + var peg$e48 = peg$literalExpectation("DROP", true); + var peg$e49 = peg$literalExpectation("SELECT", true); + var peg$e50 = peg$literalExpectation("UPDATE", true); + var peg$e51 = peg$literalExpectation("CREATE", true); + var peg$e52 = peg$literalExpectation("DELETE", true); + var peg$e53 = peg$literalExpectation("INSERT", true); + var peg$e54 = peg$literalExpectation("RECURSIVE", false); + var peg$e55 = peg$literalExpectation("REPLACE", true); + var peg$e56 = peg$literalExpectation("EXPLAIN", true); + var peg$e57 = peg$literalExpectation("INTO", true); + var peg$e58 = peg$literalExpectation("FROM", true); + var peg$e59 = peg$literalExpectation("SET", true); + var peg$e60 = peg$literalExpectation("AS", true); + var peg$e61 = peg$literalExpectation("TABLE", true); + var peg$e62 = peg$literalExpectation("ON", true); + var peg$e63 = peg$literalExpectation("LEFT", true); + var peg$e64 = peg$literalExpectation("RIGHT", true); + var peg$e65 = peg$literalExpectation("FULL", true); + var peg$e66 = peg$literalExpectation("INNER", true); + var peg$e67 = peg$literalExpectation("JOIN", true); + var peg$e68 = peg$literalExpectation("OUTER", true); + var peg$e69 = peg$literalExpectation("UNION", true); + var peg$e70 = peg$literalExpectation("VALUES", true); + var peg$e71 = peg$literalExpectation("USING", true); + var peg$e72 = peg$literalExpectation("WHERE", true); + var peg$e73 = peg$literalExpectation("WITH", true); + var peg$e74 = peg$literalExpectation("GROUP", true); + var peg$e75 = peg$literalExpectation("BY", true); + var peg$e76 = peg$literalExpectation("ORDER", true); + var peg$e77 = peg$literalExpectation("HAVING", true); + var peg$e78 = peg$literalExpectation("LIMIT", true); + var peg$e79 = peg$literalExpectation("ASC", true); + var peg$e80 = peg$literalExpectation("DESC", true); + var peg$e81 = peg$literalExpectation("ALL", true); + var peg$e82 = peg$literalExpectation("DISTINCT", true); + var peg$e83 = peg$literalExpectation("BETWEEN", true); + var peg$e84 = peg$literalExpectation("IN", true); + var peg$e85 = peg$literalExpectation("IS", true); + var peg$e86 = peg$literalExpectation("LIKE", true); + var peg$e87 = peg$literalExpectation("EXISTS", true); + var peg$e88 = peg$literalExpectation("NOT", true); + var peg$e89 = peg$literalExpectation("AND", true); + var peg$e90 = peg$literalExpectation("OR", true); + var peg$e91 = peg$literalExpectation("COUNT", true); + var peg$e92 = peg$literalExpectation("MAX", true); + var peg$e93 = peg$literalExpectation("MIN", true); + var peg$e94 = peg$literalExpectation("SUM", true); + var peg$e95 = peg$literalExpectation("AVG", true); + var peg$e96 = peg$literalExpectation("CASE", true); + var peg$e97 = peg$literalExpectation("WHEN", true); + var peg$e98 = peg$literalExpectation("THEN", true); + var peg$e99 = peg$literalExpectation("ELSE", true); + var peg$e100 = peg$literalExpectation("END", true); + var peg$e101 = peg$literalExpectation("CAST", true); + var peg$e102 = peg$literalExpectation("CHAR", true); + var peg$e103 = peg$literalExpectation("VARCHAR", true); + var peg$e104 = peg$literalExpectation("NUMERIC", true); + var peg$e105 = peg$literalExpectation("DECIMAL", true); + var peg$e106 = peg$literalExpectation("SIGNED", true); + var peg$e107 = peg$literalExpectation("UNSIGNED", true); + var peg$e108 = peg$literalExpectation("INT", true); + var peg$e109 = peg$literalExpectation("INTEGER", true); + var peg$e110 = peg$literalExpectation("JSON", true); + var peg$e111 = peg$literalExpectation("SMALLINT", true); + var peg$e112 = peg$literalExpectation("DATE", true); + var peg$e113 = peg$literalExpectation("TIME", true); + var peg$e114 = peg$literalExpectation("TIMESTAMP", true); + var peg$e115 = peg$literalExpectation("USER", true); + var peg$e116 = peg$literalExpectation("CURRENT_DATE", true); + var peg$e117 = peg$literalExpectation("ADDDATE", true); + var peg$e118 = peg$literalExpectation("INTERVAL", true); + var peg$e119 = peg$literalExpectation("YEAR", true); + var peg$e120 = peg$literalExpectation("MONTH", true); + var peg$e121 = peg$literalExpectation("DAY", true); + var peg$e122 = peg$literalExpectation("HOUR", true); + var peg$e123 = peg$literalExpectation("MINUTE", true); + var peg$e124 = peg$literalExpectation("SECOND", true); + var peg$e125 = peg$literalExpectation("CURRENT_TIME", true); + var peg$e126 = peg$literalExpectation("CURRENT_TIMESTAMP", true); + var peg$e127 = peg$literalExpectation("CURRENT_USER", true); + var peg$e128 = peg$literalExpectation("SESSION_USER", true); + var peg$e129 = peg$literalExpectation("SYSTEM_USER", true); + var peg$e130 = peg$literalExpectation("$", false); + var peg$e131 = peg$literalExpectation("return", true); + var peg$e132 = peg$literalExpectation(":=", false); + var peg$e133 = peg$literalExpectation("DUAL", true); + var peg$e134 = peg$literalExpectation("SQL_CALC_FOUND_ROWS", true); + var peg$e135 = peg$literalExpectation("SQL_CACHE", true); + var peg$e136 = peg$literalExpectation("SQL_NO_CACHE", true); + var peg$e137 = peg$literalExpectation("SQL_SMALL_RESULT", true); + var peg$e138 = peg$literalExpectation("SQL_BIG_RESULT", true); + var peg$e139 = peg$literalExpectation("SQL_BUFFER_RESULT", true); + var peg$e140 = peg$literalExpectation(",", false); + var peg$e141 = peg$literalExpectation("[", false); + var peg$e142 = peg$literalExpectation("]", false); + var peg$e143 = peg$literalExpectation(";", false); + var peg$e144 = peg$literalExpectation("/*", false); + var peg$e145 = peg$literalExpectation("*/", false); + var peg$e146 = peg$literalExpectation("--", false); + var peg$e147 = peg$anyExpectation(); + var peg$e148 = peg$classExpectation([" ", "\t", "\n", "\r"], false, false); + + var peg$f0 = function(head, tail) { + const cur = [head && head.ast || head]; + for (let i = 0; i < tail.length; i++) { + if(!tail[i][3] || tail[i][3].length === 0) continue; + cur.push(tail[i][3] && tail[i][3].ast || tail[i][3]); + } + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: cur + } + }; + var peg$f1 = function(head, tail) { + let cur = head; + for (let i = 0; i < tail.length; i++) { + cur._next = tail[i][3]; + cur = cur._next + } + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: head + } + }; + var peg$f2 = function(s) { + return s[2]; + }; + var peg$f3 = function(head, tail) { + return createList(head, tail); + }; + var peg$f4 = function(cte) { + cte.recursive = true; + return [cte] + }; + var peg$f5 = function(name, columns, stmt) { + return { name, stmt, columns }; + }; + var peg$f6 = function(head, tail) { + return createList(head, tail); + }; + var peg$f7 = function(cte, opts, d, c, f, w, g, h, o, l) { + if(f) f.forEach(info => info.table && tableList.add(`select::${info.db}::${info.table}`)); + return { + with: cte, + type: 'select', + options: opts, + distinct: d, + columns: c, + from: f, + where: w, + groupby: g, + having: h, + orderby: o, + limit: l + }; + }; + var peg$f8 = function(head, tail) { + const opts = [head]; + for (let i = 0, l = tail.length; i < l; ++i) { + opts.push(tail[i][1]); + } + return opts; + }; + var peg$f9 = function(option) { return option; }; + var peg$f10 = function() { + columnList.add('select::null::(.*)'); + return '*'; + }; + var peg$f11 = function(head, tail) { + return createList(head, tail); + }; + var peg$f12 = function(tbl) { + columnList.add(`select::${tbl}::(.*)`); + return { + expr: { + type: 'column_ref', + table: tbl, + column: '*' + }, + as: null + }; + }; + var peg$f13 = function(e, alias) { + return { expr: e, as: alias }; + }; + var peg$f14 = function(i) { return i; }; + var peg$f15 = function(i) { return i; }; + var peg$f16 = function(l) { return l; }; + var peg$f17 = function(head, tail) { + tail.unshift(head); + return tail; + }; + var peg$f18 = function(t) { return t; }; + var peg$f19 = function(t) { return t; }; + var peg$f20 = function(op, t, head, tail) { + t.join = op; + t.using = createList(head, tail); + return t; + }; + var peg$f21 = function(op, t, expr) { + t.join = op; + t.on = expr; + return t; + }; + var peg$f22 = function(op, stmt, alias, expr) { + stmt.parentheses = true; + return { + expr: stmt, + as: alias, + join: op, + on: expr + }; + }; + var peg$f23 = function() { + return { + type: 'dual' + }; + }; + var peg$f24 = function(t, alias) { + if (t.type === 'var') { + t.as = alias; + return t; + } else { + return { + db: t.db, + table: t.table, + as: alias + }; + } + }; + var peg$f25 = function(stmt, alias) { + stmt.parentheses = true; + return { + expr: stmt, + as: alias + }; + }; + var peg$f26 = function() { return 'LEFT JOIN'; }; + var peg$f27 = function() { return 'RIGHT JOIN'; }; + var peg$f28 = function() { return 'FULL JOIN'; }; + var peg$f29 = function() { return 'INNER JOIN'; }; + var peg$f30 = function(dt, tail) { + const obj = { db: null, table: dt }; + if (tail !== null) { + obj.db = dt; + obj.table = tail[3]; + } + return obj; + }; + var peg$f31 = function(v) { + v.db = null; + v.table = v.name; + return v; + }; + var peg$f32 = function(e) { return e; }; + var peg$f33 = function(e) { return e; }; + var peg$f34 = function(l) { return l; }; + var peg$f35 = function(head, tail) { + return createList(head, tail); + }; + var peg$f36 = function(e) { return e; }; + var peg$f37 = function(l) { return l; }; + var peg$f38 = function(head, tail) { + return createList(head, tail); + }; + var peg$f39 = function(e, d) { + const obj = { expr: e, type: 'ASC' }; + if (d === 'DESC') obj.type = 'DESC'; + return obj; + }; + var peg$f40 = function(i1, tail) { + const res = [i1]; + if (tail === null) res.unshift({ type: 'number', value: 0 }); + else res.push(tail[2]); + return res; + }; + var peg$f41 = function(t, l, w) { + if(t.table) tableList.add(`update::${t.db}::${t.table}`); + if(l) l.forEach(col => columnList.add(`update::${t.table}::${col.column}`)); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: 'update', + db: t.db, + table: t.table, + set: l, + where: w + } + }; + }; + var peg$f42 = function(t, f, w) { + if(f) f.forEach(info => { + info.table && tableList.add(`delete::${info.db}::${info.table}`); + columnList.add(`delete::${info.table}::(.*)`); + }); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: 'delete', + tables: t, + from: f, + where: w + } + }; + }; + var peg$f43 = function(head, tail) { + return createList(head, tail); + }; + var peg$f44 = function(tbl, c, v) { + return { column: c, value: v, table: tbl && tbl[0] }; + }; + var peg$f45 = function(ri, t, c, v) { + if (t.table) tableList.add(`insert::${t.db}::${t.table}`); + if (c) c.forEach(c => columnList.add(`insert::${t.table}::${c}`)); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: ri, + db: t.db, + table: t.table, + columns: c, + values: v + } + }; + }; + var peg$f46 = function(ri, t, v) { + if (t.table) tableList.add(`insert::${t.db}::${t.table}`); + columnList.add(`insert::${t.table}::(.*)`); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: ri, + db: t.db, + table: t.table, + columns: null, + values: v + } + }; + }; + var peg$f47 = function() { return 'insert'; }; + var peg$f48 = function() { return 'replace'; }; + var peg$f49 = function(l) { return l; }; + var peg$f50 = function(head, tail) { + return createList(head, tail); + }; + var peg$f51 = function(l) { + return l; + }; + var peg$f52 = function(head, tail) { + const el = { type: 'expr_list' }; + el.value = createList(head, tail); + return el; + }; + var peg$f53 = function(n, u) { + return { + type: 'interval', + value: [n, u] + } + }; + var peg$f54 = function(expr, condition_list, otherwise) { + if (otherwise) condition_list.push(otherwise); + return { + type: 'case', + expr: expr || null, + args: condition_list + }; + }; + var peg$f55 = function(condition, result) { + return { + type: 'when', + cond: condition, + result: result + }; + }; + var peg$f56 = function(result) { + return { type: 'else', result: result }; + }; + var peg$f57 = function(head, tail) { + return createBinaryExprChain(head, tail); + }; + var peg$f58 = function(head, tail) { + return createBinaryExprChain(head, tail); + }; + var peg$f59 = function(expr) { + return createUnaryExpr('NOT', expr); + }; + var peg$f60 = function(left, rh) { + if (rh === null) return left; + else if (rh.type === 'arithmetic') return createBinaryExprChain(left, rh.tail); + else return createBinaryExpr(rh.op, left, rh.right); + }; + var peg$f61 = function(op, stmt) { + stmt.parentheses = true; + return createUnaryExpr(op, stmt); + }; + var peg$f62 = function(nk) { return nk[0] + ' ' + nk[2]; }; + var peg$f63 = function(l) { + return { type: 'arithmetic', tail: l }; + }; + var peg$f64 = function(right) { + return { op: 'IS', right: right }; + }; + var peg$f65 = function(right) { + return { op: 'IS NOT', right: right }; + }; + var peg$f66 = function(op, begin, end) { + return { + op: op, + right: { + type: 'expr_list', + value: [begin, end] + } + }; + }; + var peg$f67 = function(nk) { return nk[0] + ' ' + nk[2]; }; + var peg$f68 = function(nk) { return nk[0] + ' ' + nk[2]; }; + var peg$f69 = function(nk) { return nk[0] + ' ' + nk[2]; }; + var peg$f70 = function(op, right) { + return { op: op, right: right }; + }; + var peg$f71 = function(op, l) { + return { op: op, right: l }; + }; + var peg$f72 = function(op, e) { + return { op: op, right: e }; + }; + var peg$f73 = function(head, tail) { + return createBinaryExprChain(head, tail); + }; + var peg$f74 = function(head, tail) { + return createBinaryExprChain(head, tail) + }; + var peg$f75 = function(e) { + e.parentheses = true; + return e; + }; + var peg$f76 = function(list) { + list.parentheses = true; + return list; + }; + var peg$f77 = function(tbl, col) { + columnList.add(`select::${tbl}::${col}`); + return { + type: 'column_ref', + table: tbl, + column: col + }; + }; + var peg$f78 = function(col) { + columnList.add(`select::null::${col}`); + return { + type: 'column_ref', + table: null, + column: col + }; + }; + var peg$f79 = function(head, tail) { + return createList(head, tail); + }; + var peg$f80 = function(name) { return reservedMap[name.toUpperCase()] === true; }; + var peg$f81 = function(name) { + return name; + }; + var peg$f82 = function(name) { + return name; + }; + var peg$f83 = function(name) { + if (reservedMap[name.toUpperCase()] === true) throw new Error("Error: "+ JSON.stringify(name)+" is a reserved word, can not as alias clause"); + return false + }; + var peg$f84 = function(name) { + return name; + }; + var peg$f85 = function(name) { + return name; + }; + var peg$f86 = function(chars) { return chars.join(''); }; + var peg$f87 = function(chars) { return chars.join(''); }; + var peg$f88 = function(chars) { return chars.join(''); }; + var peg$f89 = function(name) { return reservedMap[name.toUpperCase()] === true; }; + var peg$f90 = function(name) { return name; }; + var peg$f91 = function(start, parts) { return start + parts.join(''); }; + var peg$f92 = function(start, parts) { return start + parts.join(''); }; + var peg$f93 = function(l) { + return { type: 'param', value: l[1] }; + }; + var peg$f94 = function(name, e) { + return { + type: 'aggr_func', + name: name, + args: { + expr: e + } + }; + }; + var peg$f95 = function(name, arg) { + return { + type: 'aggr_func', + name: name, + args: arg + }; + }; + var peg$f96 = function(e) { return { expr: e }; }; + var peg$f97 = function(d, c) { return { distinct: d, expr: c }; }; + var peg$f98 = function() { return { type: 'star', value: '*' }; }; + var peg$f99 = function(name, l) { + return { + type: 'function', + name: name, + args: l ? l: { type: 'expr_list', value: [] } + }; + }; + var peg$f100 = function(name) { + return { + type: 'function', + name: name, + args: { type: 'expr_list', value: [] } + }; + }; + var peg$f101 = function(e, t) { + return { + type: 'cast', + expr: e, + target: t + }; + }; + var peg$f102 = function(e, precision) { + return { + type: 'cast', + expr: e, + target: { + dataType: 'DECIMAL(' + precision + ')' + } + }; + }; + var peg$f103 = function(e, precision, scale) { + return { + type: 'cast', + expr: e, + target: { + dataType: 'DECIMAL(' + precision + ', ' + scale + ')' + } + }; + }; + var peg$f104 = function(e, s, t) { /* MySQL cast to un-/signed integer */ + return { + type: 'cast', + expr: e, + target: { + dataType: s + (t ? ' ' + t: '') + } + }; + }; + var peg$f105 = function(head, tail) { + return createList(head, tail); + }; + var peg$f106 = function() { + return { type: 'null', value: null }; + }; + var peg$f107 = function() { + return { type: 'bool', value: true }; + }; + var peg$f108 = function() { + return { type: 'bool', value: false }; + }; + var peg$f109 = function(ca) { + return { + type: 'string', + value: ca[1].join('') + }; + }; + var peg$f110 = function(ca) { + return { + type: 'string', + value: ca[1].join('') + }; + }; + var peg$f111 = function(type, ca) { + return { + type: type.toLowerCase(), + value: ca[1].join('') + }; + }; + var peg$f112 = function() { return "'"; }; + var peg$f113 = function() { return '"'; }; + var peg$f114 = function() { return "\\"; }; + var peg$f115 = function() { return "/"; }; + var peg$f116 = function() { return "\b"; }; + var peg$f117 = function() { return "\f"; }; + var peg$f118 = function() { return "\n"; }; + var peg$f119 = function() { return "\r"; }; + var peg$f120 = function() { return "\t"; }; + var peg$f121 = function(h1, h2, h3, h4) { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); + }; + var peg$f122 = function(n) { + return { type: 'number', value: n }; + }; + var peg$f123 = function(int_, frac, exp) { return parseFloat(int_ + frac + exp); }; + var peg$f124 = function(int_, frac) { return parseFloat(int_ + frac); }; + var peg$f125 = function(int_, exp) { return parseFloat(int_ + exp); }; + var peg$f126 = function(int_) { return parseFloat(int_); }; + var peg$f127 = function(digit19, digits) { return digit19 + digits; }; + var peg$f128 = function(op, digit19, digits) { return "-" + digit19 + digits; }; + var peg$f129 = function(op, digit) { return "-" + digit; }; + var peg$f130 = function(digits) { return "." + digits; }; + var peg$f131 = function(e, digits) { return e + digits; }; + var peg$f132 = function(digits) { return digits.join(""); }; + var peg$f133 = function(e, sign) { return e + (sign !== null ? sign: ''); }; + var peg$f134 = function() { return 'ASC'; }; + var peg$f135 = function() { return 'DESC'; }; + var peg$f136 = function() { return 'ALL'; }; + var peg$f137 = function() { return 'DISTINCT';}; + var peg$f138 = function() { return 'BETWEEN'; }; + var peg$f139 = function() { return 'IN'; }; + var peg$f140 = function() { return 'IS'; }; + var peg$f141 = function() { return 'LIKE'; }; + var peg$f142 = function() { return 'EXISTS'; }; + var peg$f143 = function() { return 'NOT'; }; + var peg$f144 = function() { return 'AND'; }; + var peg$f145 = function() { return 'OR'; }; + var peg$f146 = function() { return 'COUNT'; }; + var peg$f147 = function() { return 'MAX'; }; + var peg$f148 = function() { return 'MIN'; }; + var peg$f149 = function() { return 'SUM'; }; + var peg$f150 = function() { return 'AVG'; }; + var peg$f151 = function() { return 'CHAR'; }; + var peg$f152 = function() { return 'VARCHAR';}; + var peg$f153 = function() { return 'NUMERIC'; }; + var peg$f154 = function() { return 'DECIMAL'; }; + var peg$f155 = function() { return 'SIGNED'; }; + var peg$f156 = function() { return 'UNSIGNED'; }; + var peg$f157 = function() { return 'INT'; }; + var peg$f158 = function() { return 'INTEGER'; }; + var peg$f159 = function() { return 'JSON'; }; + var peg$f160 = function() { return 'SMALLINT'; }; + var peg$f161 = function() { return 'DATE'; }; + var peg$f162 = function() { return 'TIME'; }; + var peg$f163 = function() { return 'TIMESTAMP'; }; + var peg$f164 = function() { return 'USER'; }; + var peg$f165 = function() { return 'CURRENT_DATE'; }; + var peg$f166 = function() { return 'ADDDATE'; }; + var peg$f167 = function() { return 'INTERVAL'; }; + var peg$f168 = function() { return 'YEAR'; }; + var peg$f169 = function() { return 'MONTH'; }; + var peg$f170 = function() { return 'DAY'; }; + var peg$f171 = function() { return 'HOUR'; }; + var peg$f172 = function() { return 'MINUTE'; }; + var peg$f173 = function() { return 'SECOND'; }; + var peg$f174 = function() { return 'CURRENT_TIME'; }; + var peg$f175 = function() { return 'CURRENT_TIMESTAMP'; }; + var peg$f176 = function() { return 'CURRENT_USER'; }; + var peg$f177 = function() { return 'SESSION_USER'; }; + var peg$f178 = function() { return 'SYSTEM_USER'; }; + var peg$f179 = function() { varList = []; return true; }; + var peg$f180 = function(s) { + return { stmt: s, vars: varList }; + }; + var peg$f181 = function(va, e) { + return { + type: 'assign', + left: va, + right: e + }; + }; + var peg$f182 = function(e) { + return { type: 'return', expr: e }; + }; + var peg$f183 = function(head, tail) { + return createBinaryExprChain(head, tail); + }; + var peg$f184 = function(head, tail) { + return createBinaryExprChain(head, tail); + }; + var peg$f185 = function(lt, op, rt, expr) { + return { + type: 'join', + ltable: lt, + rtable: rt, + op: op, + on: expr + }; + }; + var peg$f186 = function(e) { + e.parentheses = true; + return e; + }; + var peg$f187 = function(name, l) { + //compatible with original func_call + return { + type: 'function', + name: name, + args: { + type: 'expr_list', + value: l + } + }; + }; + var peg$f188 = function(head, tail) { + return createList(head, tail); + }; + var peg$f189 = function(l) { + return { type: 'array', value: l }; + }; + var peg$f190 = function(name, m) { + //push for analysis + varList.push(name); + return { + type: 'var', + name: name, + members: m + }; + }; + var peg$f191 = function(l) { + const s = []; + for (let i = 0; i < l.length; i++) { + s.push(l[i][1]); + } + return s; + }; + var peg$f192 = function(t, l) { + return { dataType: t, length: parseInt(l.join(''), 10) }; + }; + var peg$f193 = function(t) { return { dataType: t }; }; + var peg$f194 = function(t) { return { dataType: t }; }; + var peg$f195 = function(t) { return { dataType: t }; }; + var peg$f196 = function(t) { return { dataType: t }; }; + var peg$f197 = function(t) { return { dataType: t }; }; + var peg$currPos = 0; + var peg$savedPos = 0; + var peg$posDetailsCache = [{ line: 1, column: 1 }]; + var peg$maxFailPos = 0; + var peg$maxFailExpected = []; + var peg$silentFails = 0; + + var peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$savedPos, peg$currPos); + } + + function offset() { + return peg$savedPos; + } + + function range() { + return { + source: peg$source, + start: peg$savedPos, + end: peg$currPos + }; + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description, location) { + location = location !== undefined + ? location + : peg$computeLocation(peg$savedPos, peg$currPos); + + throw peg$buildStructuredError( + [peg$otherExpectation(description)], + input.substring(peg$savedPos, peg$currPos), + location + ); + } + + function error(message, location) { + location = location !== undefined + ? location + : peg$computeLocation(peg$savedPos, peg$currPos); + + throw peg$buildSimpleError(message, location); + } + + function peg$literalExpectation(text, ignoreCase) { + return { type: "literal", text: text, ignoreCase: ignoreCase }; + } + + function peg$classExpectation(parts, inverted, ignoreCase) { + return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; + } + + function peg$anyExpectation() { + return { type: "any" }; + } + + function peg$endExpectation() { + return { type: "end" }; + } + + function peg$otherExpectation(description) { + return { type: "other", description: description }; + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos]; + var p; + + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column + }; + + while (p < pos) { + if (input.charCodeAt(p) === 10) { + details.line++; + details.column = 1; + } else { + details.column++; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + + return details; + } + } + + function peg$computeLocation(startPos, endPos, offset) { + var startPosDetails = peg$computePosDetails(startPos); + var endPosDetails = peg$computePosDetails(endPos); + + var res = { + source: peg$source, + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + if (offset && peg$source && (typeof peg$source.offset === "function")) { + res.start = peg$source.offset(res.start); + res.end = peg$source.offset(res.end); + } + return res; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildSimpleError(message, location) { + return new peg$SyntaxError(message, null, null, location); + } + + function peg$buildStructuredError(expected, found, location) { + return new peg$SyntaxError( + peg$SyntaxError.buildMessage(expected, found), + expected, + found, + location + ); + } + + function peg$parsestart() { + var s0; + + s0 = peg$parsemultiple_stmt(); + if (s0 === peg$FAILED) { + s0 = peg$parsecrud_stmt(); + } + + return s0; + } + + function peg$parsecrud_stmt() { + var s0; + + s0 = peg$parseunion_stmt(); + if (s0 === peg$FAILED) { + s0 = peg$parseupdate_stmt(); + if (s0 === peg$FAILED) { + s0 = peg$parsereplace_insert_stmt(); + if (s0 === peg$FAILED) { + s0 = peg$parseinsert_no_columns_stmt(); + if (s0 === peg$FAILED) { + s0 = peg$parsedelete_stmt(); + if (s0 === peg$FAILED) { + s0 = peg$parseproc_stmts(); + } + } + } + } + } + + return s0; + } + + function peg$parsemultiple_stmt() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsecrud_stmt(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseSEMICOLON(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecrud_stmt(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseSEMICOLON(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecrud_stmt(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f0(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseunion_stmt() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseselect_stmt(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseKW_UNION(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseselect_stmt(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseKW_UNION(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseselect_stmt(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f1(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseselect_stmt() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$parseselect_stmt_nake(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 40) { + s2 = peg$c0; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e0); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseselect_stmt(); + if (s4 !== peg$FAILED) { + s5 = peg$parse__(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c1; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + if (s6 !== peg$FAILED) { + s2 = [s2, s3, s4, s5, s6]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f2(s1); + } + s0 = s1; + } + + return s0; + } + + function peg$parsewith_clause() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + s0 = peg$currPos; + s1 = peg$parseKW_WITH(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsecte_definition(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$currPos; + s6 = peg$parse__(); + s7 = peg$parseCOMMA(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsecte_definition(); + if (s9 !== peg$FAILED) { + s6 = [s6, s7, s8, s9]; + s5 = s6; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$currPos; + s6 = peg$parse__(); + s7 = peg$parseCOMMA(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsecte_definition(); + if (s9 !== peg$FAILED) { + s6 = [s6, s7, s8, s9]; + s5 = s6; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f3(s3, s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parse__(); + s2 = peg$parseKW_WITH(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseKW_RECURSIVE(); + if (s4 !== peg$FAILED) { + s5 = peg$parse__(); + s6 = peg$parsecte_definition(); + if (s6 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f4(s6); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsecte_definition() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; + + s0 = peg$currPos; + s1 = peg$parseident_name(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsecte_column_definition(); + if (s3 === peg$FAILED) { + s3 = null; + } + s4 = peg$parse__(); + s5 = peg$parseKW_AS(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseLPAREN(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parseunion_stmt(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parseRPAREN(); + if (s11 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f5(s1, s3, s9); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsecte_column_definition() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + s0 = peg$currPos; + s1 = peg$parseLPAREN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsecolumn(); + if (s3 !== peg$FAILED) { + s4 = []; + s5 = peg$currPos; + s6 = peg$parse__(); + s7 = peg$parseCOMMA(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsecolumn(); + if (s9 !== peg$FAILED) { + s6 = [s6, s7, s8, s9]; + s5 = s6; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + while (s5 !== peg$FAILED) { + s4.push(s5); + s5 = peg$currPos; + s6 = peg$parse__(); + s7 = peg$parseCOMMA(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsecolumn(); + if (s9 !== peg$FAILED) { + s6 = [s6, s7, s8, s9]; + s5 = s6; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } + s5 = peg$parse__(); + s6 = peg$parseRPAREN(); + if (s6 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f6(s3, s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseselect_stmt_nake() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21; + + s0 = peg$currPos; + s1 = peg$parsewith_clause(); + if (s1 === peg$FAILED) { + s1 = null; + } + s2 = peg$parse__(); + s3 = peg$parseKW_SELECT(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseoption_clause(); + if (s5 === peg$FAILED) { + s5 = null; + } + s6 = peg$parse__(); + s7 = peg$parseKW_DISTINCT(); + if (s7 === peg$FAILED) { + s7 = null; + } + s8 = peg$parse__(); + s9 = peg$parsecolumn_clause(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parsefrom_clause(); + if (s11 === peg$FAILED) { + s11 = null; + } + s12 = peg$parse__(); + s13 = peg$parsewhere_clause(); + if (s13 === peg$FAILED) { + s13 = null; + } + s14 = peg$parse__(); + s15 = peg$parsegroup_by_clause(); + if (s15 === peg$FAILED) { + s15 = null; + } + s16 = peg$parse__(); + s17 = peg$parsehaving_clause(); + if (s17 === peg$FAILED) { + s17 = null; + } + s18 = peg$parse__(); + s19 = peg$parseorder_by_clause(); + if (s19 === peg$FAILED) { + s19 = null; + } + s20 = peg$parse__(); + s21 = peg$parselimit_clause(); + if (s21 === peg$FAILED) { + s21 = null; + } + peg$savedPos = s0; + s0 = peg$f7(s1, s5, s7, s9, s11, s13, s15, s17, s19, s21); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseoption_clause() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parsequery_option(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parsequery_option(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parsequery_option(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f8(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsequery_option() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseOPT_SQL_CALC_FOUND_ROWS(); + if (s1 === peg$FAILED) { + s1 = peg$parseOPT_SQL_CACHE(); + if (s1 === peg$FAILED) { + s1 = peg$parseOPT_SQL_NO_CACHE(); + } + if (s1 === peg$FAILED) { + s1 = peg$parseOPT_SQL_BIG_RESULT(); + if (s1 === peg$FAILED) { + s1 = peg$parseOPT_SQL_SMALL_RESULT(); + if (s1 === peg$FAILED) { + s1 = peg$parseOPT_SQL_BUFFER_RESULT(); + } + } + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f9(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsecolumn_clause() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseKW_ALL(); + if (s1 === peg$FAILED) { + s1 = peg$currPos; + s2 = peg$parseSTAR(); + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + peg$silentFails++; + s4 = peg$parseident_start(); + peg$silentFails--; + if (s4 === peg$FAILED) { + s3 = undefined; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s2 = [s2, s3]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 === peg$FAILED) { + s1 = peg$parseSTAR(); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f10(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsecolumn_list_item(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecolumn_list_item(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecolumn_list_item(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f11(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsecolumn_list_item() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseident(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseDOT(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseSTAR(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f12(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseexpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsealias_clause(); + if (s3 === peg$FAILED) { + s3 = null; + } + peg$savedPos = s0; + s0 = peg$f13(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsealias_clause() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_AS(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsealias_ident(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f14(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_AS(); + if (s1 === peg$FAILED) { + s1 = null; + } + s2 = peg$parse__(); + s3 = peg$parseident(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f15(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsefrom_clause() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_FROM(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsetable_ref_list(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f16(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsetable_ref_list() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parsetable_base(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsetable_ref(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsetable_ref(); + } + peg$savedPos = s0; + s0 = peg$f17(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsetable_ref() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$parse__(); + s2 = peg$parseCOMMA(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parsetable_base(); + if (s4 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f18(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parse__(); + s2 = peg$parsetable_join(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f19(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsetable_join() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15; + + s0 = peg$currPos; + s1 = peg$parsejoin_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsetable_base(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseKW_USING(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseLPAREN(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parseident_name(); + if (s9 !== peg$FAILED) { + s10 = []; + s11 = peg$currPos; + s12 = peg$parse__(); + s13 = peg$parseCOMMA(); + if (s13 !== peg$FAILED) { + s14 = peg$parse__(); + s15 = peg$parseident_name(); + if (s15 !== peg$FAILED) { + s12 = [s12, s13, s14, s15]; + s11 = s12; + } else { + peg$currPos = s11; + s11 = peg$FAILED; + } + } else { + peg$currPos = s11; + s11 = peg$FAILED; + } + while (s11 !== peg$FAILED) { + s10.push(s11); + s11 = peg$currPos; + s12 = peg$parse__(); + s13 = peg$parseCOMMA(); + if (s13 !== peg$FAILED) { + s14 = peg$parse__(); + s15 = peg$parseident_name(); + if (s15 !== peg$FAILED) { + s12 = [s12, s13, s14, s15]; + s11 = s12; + } else { + peg$currPos = s11; + s11 = peg$FAILED; + } + } else { + peg$currPos = s11; + s11 = peg$FAILED; + } + } + s11 = peg$parse__(); + s12 = peg$parseRPAREN(); + if (s12 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f20(s1, s3, s9, s10); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsejoin_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsetable_base(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseon_clause(); + if (s5 === peg$FAILED) { + s5 = null; + } + peg$savedPos = s0; + s0 = peg$f21(s1, s3, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsejoin_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseunion_stmt(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsealias_clause(); + if (s9 === peg$FAILED) { + s9 = null; + } + s10 = peg$parse__(); + s11 = peg$parseon_clause(); + if (s11 === peg$FAILED) { + s11 = null; + } + peg$savedPos = s0; + s0 = peg$f22(s1, s5, s9, s11); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + + return s0; + } + + function peg$parsetable_base() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseKW_DUAL(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f23(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsetable_name(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsealias_clause(); + if (s3 === peg$FAILED) { + s3 = null; + } + peg$savedPos = s0; + s0 = peg$f24(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseLPAREN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseunion_stmt(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseRPAREN(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsealias_clause(); + if (s7 === peg$FAILED) { + s7 = null; + } + peg$savedPos = s0; + s0 = peg$f25(s3, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + + return s0; + } + + function peg$parsejoin_op() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseKW_LEFT(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_OUTER(); + if (s3 === peg$FAILED) { + s3 = null; + } + s4 = peg$parse__(); + s5 = peg$parseKW_JOIN(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f26(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_RIGHT(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_OUTER(); + if (s3 === peg$FAILED) { + s3 = null; + } + s4 = peg$parse__(); + s5 = peg$parseKW_JOIN(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f27(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_FULL(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_OUTER(); + if (s3 === peg$FAILED) { + s3 = null; + } + s4 = peg$parse__(); + s5 = peg$parseKW_JOIN(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f28(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseKW_INNER(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s2 = [s2, s3]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 === peg$FAILED) { + s1 = null; + } + s2 = peg$parseKW_JOIN(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f29(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + + return s0; + } + + function peg$parsetable_name() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$parseident(); + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + s3 = peg$parse__(); + s4 = peg$parseDOT(); + if (s4 !== peg$FAILED) { + s5 = peg$parse__(); + s6 = peg$parseident(); + if (s6 !== peg$FAILED) { + s3 = [s3, s4, s5, s6]; + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 === peg$FAILED) { + s2 = null; + } + peg$savedPos = s0; + s0 = peg$f30(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsevar_decl(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f31(s1); + } + s0 = s1; + } + + return s0; + } + + function peg$parseon_clause() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_ON(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f32(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsewhere_clause() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_WHERE(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f33(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsegroup_by_clause() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseKW_GROUP(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_BY(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parsecolumn_ref_list(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f34(s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsecolumn_ref_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsecolumn_ref(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecolumn_ref(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecolumn_ref(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f35(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsehaving_clause() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_HAVING(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f36(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseorder_by_clause() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseKW_ORDER(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_BY(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseorder_by_list(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f37(s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseorder_by_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseorder_by_element(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseorder_by_element(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseorder_by_element(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f38(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseorder_by_element() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseexpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_DESC(); + if (s3 === peg$FAILED) { + s3 = peg$parseKW_ASC(); + } + if (s3 === peg$FAILED) { + s3 = null; + } + peg$savedPos = s0; + s0 = peg$f39(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsenumber_or_param() { + var s0; + + s0 = peg$parseliteral_numeric(); + if (s0 === peg$FAILED) { + s0 = peg$parseparam(); + } + + return s0; + } + + function peg$parselimit_clause() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8; + + s0 = peg$currPos; + s1 = peg$parseKW_LIMIT(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsenumber_or_param(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$currPos; + s6 = peg$parseCOMMA(); + if (s6 !== peg$FAILED) { + s7 = peg$parse__(); + s8 = peg$parsenumber_or_param(); + if (s8 !== peg$FAILED) { + s6 = [s6, s7, s8]; + s5 = s6; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + if (s5 === peg$FAILED) { + s5 = null; + } + peg$savedPos = s0; + s0 = peg$f40(s3, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseupdate_stmt() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; + + s0 = peg$currPos; + s1 = peg$parseKW_UPDATE(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsetable_name(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseKW_SET(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseset_list(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsewhere_clause(); + if (s9 === peg$FAILED) { + s9 = null; + } + peg$savedPos = s0; + s0 = peg$f41(s3, s7, s9); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsedelete_stmt() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseKW_DELETE(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsetable_ref_list(); + if (s3 === peg$FAILED) { + s3 = null; + } + s4 = peg$parse__(); + s5 = peg$parsefrom_clause(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsewhere_clause(); + if (s7 === peg$FAILED) { + s7 = null; + } + peg$savedPos = s0; + s0 = peg$f42(s3, s5, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseset_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseset_item(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseset_item(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseset_item(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f43(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseset_item() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseident(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseDOT(); + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 === peg$FAILED) { + s1 = null; + } + s2 = peg$parse__(); + s3 = peg$parsecolumn_name(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (input.charCodeAt(peg$currPos) === 61) { + s5 = peg$c2; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e2); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseadditive_expr(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f44(s1, s3, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsereplace_insert_stmt() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13; + + s0 = peg$currPos; + s1 = peg$parsereplace_insert(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_INTO(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parsetable_name(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseLPAREN(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsecolumn_list(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parseRPAREN(); + if (s11 !== peg$FAILED) { + s12 = peg$parse__(); + s13 = peg$parsevalue_clause(); + if (s13 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f45(s1, s5, s9, s13); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseinsert_no_columns_stmt() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsereplace_insert(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_INTO(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parsetable_name(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsevalue_clause(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f46(s1, s5, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsereplace_insert() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseKW_INSERT(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f47(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_REPLACE(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f48(); + } + s0 = s1; + } + + return s0; + } + + function peg$parsevalue_clause() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_VALUES(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsevalue_list(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f49(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsevalue_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsevalue_item(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsevalue_item(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsevalue_item(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f50(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsevalue_item() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseLPAREN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr_list(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseRPAREN(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f51(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseexpr_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseexpr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseexpr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseexpr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f52(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseinterval_expr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseKW_INTERVAL(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsenumber(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseinterval_unit(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f53(s3, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsecase_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; + + s0 = peg$currPos; + s1 = peg$parseKW_CASE(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr(); + if (s3 === peg$FAILED) { + s3 = null; + } + s4 = peg$parse__(); + s5 = []; + s6 = peg$parsecase_when_then(); + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsecase_when_then(); + } + } else { + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecase_else(); + if (s7 === peg$FAILED) { + s7 = null; + } + s8 = peg$parse__(); + s9 = peg$parseKW_END(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parseKW_CASE(); + if (s11 === peg$FAILED) { + s11 = null; + } + peg$savedPos = s0; + s0 = peg$f54(s3, s5, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsecase_when_then() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8; + + s0 = peg$currPos; + s1 = peg$parseKW_WHEN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseKW_THEN(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseexpr(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + peg$savedPos = s0; + s0 = peg$f55(s3, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsecase_else() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_ELSE(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f56(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseexpr() { + var s0; + + s0 = peg$parseor_expr(); + if (s0 === peg$FAILED) { + s0 = peg$parseselect_stmt(); + } + + return s0; + } + + function peg$parseor_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseand_expr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseKW_OR(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseand_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseKW_OR(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseand_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f57(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseand_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsenot_expr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseKW_AND(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsenot_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseKW_AND(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsenot_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f58(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsenot_expr() { + var s0, s1, s2, s3, s4; + + s0 = peg$parsecomparison_expr(); + if (s0 === peg$FAILED) { + s0 = peg$parseexists_expr(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_NOT(); + if (s1 === peg$FAILED) { + s1 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 33) { + s2 = peg$c3; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e3); } + } + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + peg$silentFails++; + if (input.charCodeAt(peg$currPos) === 61) { + s4 = peg$c2; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e2); } + } + peg$silentFails--; + if (s4 === peg$FAILED) { + s3 = undefined; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + s2 = [s2, s3]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsenot_expr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f59(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + + return s0; + } + + function peg$parsecomparison_expr() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseadditive_expr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsecomparison_op_right(); + if (s3 === peg$FAILED) { + s3 = null; + } + peg$savedPos = s0; + s0 = peg$f60(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseexists_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseexists_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseunion_stmt(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f61(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseexists_op() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseKW_NOT(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseKW_EXISTS(); + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f62(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$parseKW_EXISTS(); + } + + return s0; + } + + function peg$parsecomparison_op_right() { + var s0; + + s0 = peg$parsearithmetic_op_right(); + if (s0 === peg$FAILED) { + s0 = peg$parsein_op_right(); + if (s0 === peg$FAILED) { + s0 = peg$parsebetween_op_right(); + if (s0 === peg$FAILED) { + s0 = peg$parseis_op_right(); + if (s0 === peg$FAILED) { + s0 = peg$parselike_op_right(); + } + } + } + } + + return s0; + } + + function peg$parsearithmetic_op_right() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + s3 = peg$parse__(); + s4 = peg$parsearithmetic_comparison_operator(); + if (s4 !== peg$FAILED) { + s5 = peg$parse__(); + s6 = peg$parseadditive_expr(); + if (s6 !== peg$FAILED) { + s3 = [s3, s4, s5, s6]; + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + s3 = peg$parse__(); + s4 = peg$parsearithmetic_comparison_operator(); + if (s4 !== peg$FAILED) { + s5 = peg$parse__(); + s6 = peg$parseadditive_expr(); + if (s6 !== peg$FAILED) { + s3 = [s3, s4, s5, s6]; + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f63(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsearithmetic_comparison_operator() { + var s0; + + if (input.substr(peg$currPos, 2) === peg$c4) { + s0 = peg$c4; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e4); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 62) { + s0 = peg$c5; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e5); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c6) { + s0 = peg$c6; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e6); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c7) { + s0 = peg$c7; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 60) { + s0 = peg$c8; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e8); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 61) { + s0 = peg$c2; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e2); } + } + if (s0 === peg$FAILED) { + if (input.substr(peg$currPos, 2) === peg$c9) { + s0 = peg$c9; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e9); } + } + } + } + } + } + } + } + + return s0; + } + + function peg$parseis_op_right() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$parseKW_IS(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseadditive_expr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f64(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseKW_IS(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseKW_NOT(); + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseadditive_expr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f65(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsebetween_op_right() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsebetween_or_not_between_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseadditive_expr(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseKW_AND(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseadditive_expr(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f66(s1, s3, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsebetween_or_not_between_op() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseKW_NOT(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseKW_BETWEEN(); + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f67(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$parseKW_BETWEEN(); + } + + return s0; + } + + function peg$parselike_op() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseKW_NOT(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseKW_LIKE(); + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f68(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$parseKW_LIKE(); + } + + return s0; + } + + function peg$parsein_op() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$currPos; + s2 = peg$parseKW_NOT(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + s4 = peg$parseKW_IN(); + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f69(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$parseKW_IN(); + } + + return s0; + } + + function peg$parselike_op_right() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parselike_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsecomparison_expr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f70(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsein_op_right() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsein_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseexpr_list(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f71(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsein_op(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsevar_decl(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f72(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parseadditive_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsemultiplicative_expr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseadditive_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsemultiplicative_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseadditive_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsemultiplicative_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f73(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseadditive_operator() { + var s0; + + if (input.charCodeAt(peg$currPos) === 43) { + s0 = peg$c10; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 45) { + s0 = peg$c11; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + } + + return s0; + } + + function peg$parsemultiplicative_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseprimary(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parsemultiplicative_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseprimary(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parsemultiplicative_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseprimary(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f74(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsemultiplicative_operator() { + var s0; + + if (input.charCodeAt(peg$currPos) === 42) { + s0 = peg$c12; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e12); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 47) { + s0 = peg$c13; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e13); } + } + if (s0 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 37) { + s0 = peg$c14; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e14); } + } + } + } + + return s0; + } + + function peg$parseprimary() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$parseliteral(); + if (s0 === peg$FAILED) { + s0 = peg$parsecast_expr(); + if (s0 === peg$FAILED) { + s0 = peg$parseaggr_func(); + if (s0 === peg$FAILED) { + s0 = peg$parsefunc_call(); + if (s0 === peg$FAILED) { + s0 = peg$parsecase_expr(); + if (s0 === peg$FAILED) { + s0 = peg$parseinterval_expr(); + if (s0 === peg$FAILED) { + s0 = peg$parsecolumn_ref(); + if (s0 === peg$FAILED) { + s0 = peg$parseparam(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseLPAREN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseRPAREN(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f75(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseLPAREN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseexpr_list(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseRPAREN(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f76(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parsevar_decl(); + } + } + } + } + } + } + } + } + } + } + + return s0; + } + + function peg$parsecolumn_ref() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseident(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseDOT(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parsecolumn(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f77(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsecolumn(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f78(s1); + } + s0 = s1; + } + + return s0; + } + + function peg$parsecolumn_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsecolumn(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecolumn(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parsecolumn(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f79(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseident() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$parseident_name(); + if (s1 !== peg$FAILED) { + peg$savedPos = peg$currPos; + s2 = peg$f80(s1); + if (s2) { + s2 = peg$FAILED; + } else { + s2 = undefined; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f81(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsequoted_ident(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f82(s1); + } + s0 = s1; + } + + return s0; + } + + function peg$parsealias_ident() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$parseident_name(); + if (s1 !== peg$FAILED) { + peg$savedPos = peg$currPos; + s2 = peg$f83(s1); + if (s2) { + s2 = peg$FAILED; + } else { + s2 = undefined; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f84(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsequoted_ident(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f85(s1); + } + s0 = s1; + } + + return s0; + } + + function peg$parsequoted_ident() { + var s0; + + s0 = peg$parsedouble_quoted_ident(); + if (s0 === peg$FAILED) { + s0 = peg$parsesingle_quoted_ident(); + if (s0 === peg$FAILED) { + s0 = peg$parsebackticks_quoted_ident(); + } + } + + return s0; + } + + function peg$parsedouble_quoted_ident() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c15; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$r0.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$r0.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c15; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f86(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsesingle_quoted_ident() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 39) { + s1 = peg$c16; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$r1.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$r1.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s3 = peg$c16; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f87(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsebackticks_quoted_ident() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 96) { + s1 = peg$c17; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e19); } + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$r2.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$r2.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 96) { + s3 = peg$c17; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e19); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f88(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsecolumn() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$parsecolumn_name(); + if (s1 !== peg$FAILED) { + peg$savedPos = peg$currPos; + s2 = peg$f89(s1); + if (s2) { + s2 = peg$FAILED; + } else { + s2 = undefined; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f90(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parsequoted_ident(); + } + + return s0; + } + + function peg$parsecolumn_name() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseident_start(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsecolumn_part(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsecolumn_part(); + } + peg$savedPos = s0; + s0 = peg$f91(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseident_name() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseident_start(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseident_part(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseident_part(); + } + peg$savedPos = s0; + s0 = peg$f92(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseident_start() { + var s0; + + if (peg$r3.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e21); } + } + + return s0; + } + + function peg$parseident_part() { + var s0; + + if (peg$r4.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e22); } + } + + return s0; + } + + function peg$parsecolumn_part() { + var s0; + + if (peg$r5.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e23); } + } + + return s0; + } + + function peg$parseparam() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 58) { + s2 = peg$c18; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parseident_name(); + if (s3 !== peg$FAILED) { + s2 = [s2, s3]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f93(s1); + } + s0 = s1; + + return s0; + } + + function peg$parseaggr_func() { + var s0; + + s0 = peg$parseaggr_fun_count(); + if (s0 === peg$FAILED) { + s0 = peg$parseaggr_fun_smma(); + } + + return s0; + } + + function peg$parseaggr_fun_smma() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseKW_SUM_MAX_MIN_AVG(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseadditive_expr(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f94(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SUM_MAX_MIN_AVG() { + var s0; + + s0 = peg$parseKW_SUM(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_MAX(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_MIN(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_AVG(); + } + } + } + + return s0; + } + + function peg$parseaggr_fun_count() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseKW_COUNT(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parsecount_arg(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f95(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsecount_arg() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parsestar_expr(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f96(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_DISTINCT(); + if (s1 === peg$FAILED) { + s1 = null; + } + s2 = peg$parse__(); + s3 = peg$parsecolumn_ref(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f97(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsestar_expr() { + var s0, s1; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 42) { + s1 = peg$c12; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e12); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f98(); + } + s0 = s1; + + return s0; + } + + function peg$parsefunc_call() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseident(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseexpr_list(); + if (s5 === peg$FAILED) { + s5 = null; + } + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f99(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsescalar_func(); + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + s3 = peg$parse__(); + s4 = peg$parseLPAREN(); + if (s4 !== peg$FAILED) { + s5 = peg$parseRPAREN(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s3 = [s3, s4, s5, s6]; + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 === peg$FAILED) { + s2 = null; + } + peg$savedPos = s0; + s0 = peg$f100(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parsescalar_func() { + var s0; + + s0 = peg$parseKW_CURRENT_DATE(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_CURRENT_TIME(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_CURRENT_TIMESTAMP(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_CURRENT_USER(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_USER(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_SESSION_USER(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_SYSTEM_USER(); + } + } + } + } + } + } + + return s0; + } + + function peg$parsecast_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21; + + s0 = peg$currPos; + s1 = peg$parseKW_CAST(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseexpr(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseKW_AS(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsedata_type(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parseRPAREN(); + if (s11 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f101(s5, s9); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_CAST(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseexpr(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseKW_AS(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parseKW_DECIMAL(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parseLPAREN(); + if (s11 !== peg$FAILED) { + s12 = peg$parse__(); + s13 = peg$parseint(); + if (s13 !== peg$FAILED) { + s14 = peg$parse__(); + s15 = peg$parseRPAREN(); + if (s15 !== peg$FAILED) { + s16 = peg$parse__(); + s17 = peg$parseRPAREN(); + if (s17 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f102(s5, s13); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_CAST(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseexpr(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseKW_AS(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parseKW_DECIMAL(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parseLPAREN(); + if (s11 !== peg$FAILED) { + s12 = peg$parse__(); + s13 = peg$parseint(); + if (s13 !== peg$FAILED) { + s14 = peg$parse__(); + s15 = peg$parseCOMMA(); + if (s15 !== peg$FAILED) { + s16 = peg$parse__(); + s17 = peg$parseint(); + if (s17 !== peg$FAILED) { + s18 = peg$parse__(); + s19 = peg$parseRPAREN(); + if (s19 !== peg$FAILED) { + s20 = peg$parse__(); + s21 = peg$parseRPAREN(); + if (s21 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f103(s5, s13, s17); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_CAST(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseexpr(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseKW_AS(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + s9 = peg$parsesignedness(); + if (s9 !== peg$FAILED) { + s10 = peg$parse__(); + s11 = peg$parseKW_INTEGER(); + if (s11 === peg$FAILED) { + s11 = null; + } + s12 = peg$parse__(); + s13 = peg$parseRPAREN(); + if (s13 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f104(s5, s9, s11); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + + return s0; + } + + function peg$parsesignedness() { + var s0; + + s0 = peg$parseKW_SIGNED(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_UNSIGNED(); + } + + return s0; + } + + function peg$parseliteral() { + var s0; + + s0 = peg$parseliteral_string(); + if (s0 === peg$FAILED) { + s0 = peg$parseliteral_numeric(); + if (s0 === peg$FAILED) { + s0 = peg$parseliteral_bool(); + if (s0 === peg$FAILED) { + s0 = peg$parseliteral_null(); + if (s0 === peg$FAILED) { + s0 = peg$parseliteral_datetime(); + } + } + } + } + + return s0; + } + + function peg$parseliteral_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseliteral(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseliteral(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseliteral(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f105(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseliteral_null() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseKW_NULL(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f106(); + } + s0 = s1; + + return s0; + } + + function peg$parseliteral_bool() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseKW_TRUE(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f107(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_FALSE(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f108(); + } + s0 = s1; + } + + return s0; + } + + function peg$parseliteral_string() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 39) { + s2 = peg$c16; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsesingle_char(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsesingle_char(); + } + if (input.charCodeAt(peg$currPos) === 39) { + s4 = peg$c16; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f109(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s2 = peg$c15; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$parsesingle_quote_char(); + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$parsesingle_quote_char(); + } + if (input.charCodeAt(peg$currPos) === 34) { + s4 = peg$c15; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s4 !== peg$FAILED) { + s2 = [s2, s3, s4]; + s1 = s2; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f110(s1); + } + s0 = s1; + } + + return s0; + } + + function peg$parseliteral_datetime() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$parseKW_TIME(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_DATE(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_TIMESTAMP(); + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 39) { + s4 = peg$c16; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s4 !== peg$FAILED) { + s5 = []; + s6 = peg$parsesingle_char(); + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = peg$parsesingle_char(); + } + if (input.charCodeAt(peg$currPos) === 39) { + s6 = peg$c16; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s6 !== peg$FAILED) { + s4 = [s4, s5, s6]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f111(s1, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsesingle_quote_char() { + var s0; + + if (peg$r6.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s0 === peg$FAILED) { + s0 = peg$parseescape_char(); + } + + return s0; + } + + function peg$parsesingle_char() { + var s0; + + if (peg$r7.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e26); } + } + if (s0 === peg$FAILED) { + s0 = peg$parseescape_char(); + } + + return s0; + } + + function peg$parseescape_char() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c19) { + s1 = peg$c19; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e27); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f112(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c20) { + s1 = peg$c20; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e28); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f113(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c21) { + s1 = peg$c21; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e29); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f114(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c22) { + s1 = peg$c22; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e30); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f115(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c23) { + s1 = peg$c23; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e31); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f116(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c24) { + s1 = peg$c24; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e32); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f117(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c25) { + s1 = peg$c25; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e33); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f118(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c26) { + s1 = peg$c26; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e34); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f119(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c27) { + s1 = peg$c27; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e35); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f120(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c28) { + s1 = peg$c28; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e36); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsehexDigit(); + if (s2 !== peg$FAILED) { + s3 = peg$parsehexDigit(); + if (s3 !== peg$FAILED) { + s4 = peg$parsehexDigit(); + if (s4 !== peg$FAILED) { + s5 = peg$parsehexDigit(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f121(s2, s3, s4, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + } + } + } + } + } + } + + return s0; + } + + function peg$parseline_terminator() { + var s0; + + if (peg$r8.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e37); } + } + + return s0; + } + + function peg$parseliteral_numeric() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parsenumber(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f122(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsenumber() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$parseint(); + if (s1 !== peg$FAILED) { + s2 = peg$parsefrac(); + if (s2 !== peg$FAILED) { + s3 = peg$parseexp(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + peg$savedPos = s0; + s0 = peg$f123(s1, s2, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseint(); + if (s1 !== peg$FAILED) { + s2 = peg$parsefrac(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + peg$savedPos = s0; + s0 = peg$f124(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseint(); + if (s1 !== peg$FAILED) { + s2 = peg$parseexp(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + peg$savedPos = s0; + s0 = peg$f125(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseint(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + peg$savedPos = s0; + s0 = peg$f126(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + + return s0; + } + + function peg$parseint() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parsedigit19(); + if (s1 !== peg$FAILED) { + s2 = peg$parsedigits(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f127(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parsedigit(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 45) { + s1 = peg$c11; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + if (s1 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 43) { + s1 = peg$c10; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsedigit19(); + if (s2 !== peg$FAILED) { + s3 = peg$parsedigits(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f128(s1, s2, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 45) { + s1 = peg$c11; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + if (s1 === peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 43) { + s1 = peg$c10; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsedigit(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f129(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + + return s0; + } + + function peg$parsefrac() { + var s0, s1, s2; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s1 = peg$c29; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e38); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parsedigits(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f130(s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseexp() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$parsee(); + if (s1 !== peg$FAILED) { + s2 = peg$parsedigits(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f131(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsedigits() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parsedigit(); + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parsedigit(); + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f132(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsedigit() { + var s0; + + if (peg$r9.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e39); } + } + + return s0; + } + + function peg$parsedigit19() { + var s0; + + if (peg$r10.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e40); } + } + + return s0; + } + + function peg$parsehexDigit() { + var s0; + + if (peg$r11.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e41); } + } + + return s0; + } + + function peg$parsee() { + var s0, s1, s2; + + s0 = peg$currPos; + if (peg$r12.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e42); } + } + if (s1 !== peg$FAILED) { + if (peg$r13.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e43); } + } + if (s2 === peg$FAILED) { + s2 = null; + } + peg$savedPos = s0; + s0 = peg$f133(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_NULL() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c30) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e44); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_TRUE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c31) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e45); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_FALSE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c32) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e46); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SHOW() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c33) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_DROP() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c34) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e48); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SELECT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c35) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e49); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UPDATE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c36) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e50); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CREATE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c37) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e51); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_DELETE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c38) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e52); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_INSERT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c39) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e53); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_RECURSIVE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 9) === peg$c40) { + s1 = peg$c40; + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e54); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_REPLACE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c41) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e55); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_EXPLAIN() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c42) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e56); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_INTO() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c43) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e57); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_FROM() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c44) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e58); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SET() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c45) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e59); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_AS() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2).toLowerCase() === peg$c46) { + s1 = input.substr(peg$currPos, 2); + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e60); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_TABLE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c47) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e61); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_ON() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2).toLowerCase() === peg$c48) { + s1 = input.substr(peg$currPos, 2); + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e62); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_LEFT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c49) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e63); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_RIGHT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c50) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e64); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_FULL() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c51) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e65); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_INNER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c52) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e66); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_JOIN() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c53) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e67); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_OUTER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c54) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e68); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNION() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c55) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e69); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_VALUES() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c56) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e70); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_USING() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c57) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e71); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_WHERE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c58) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e72); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_WITH() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c59) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e73); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_GROUP() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c60) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e74); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_BY() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2).toLowerCase() === peg$c61) { + s1 = input.substr(peg$currPos, 2); + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e75); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_ORDER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c62) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e76); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_HAVING() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c63) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e77); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_LIMIT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c64) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e78); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_ASC() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c65) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e79); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f134(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_DESC() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c66) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e80); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f135(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_ALL() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c67) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e81); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f136(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_DISTINCT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c68) { + s1 = input.substr(peg$currPos, 8); + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e82); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f137(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_BETWEEN() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c69) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e83); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f138(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_IN() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2).toLowerCase() === peg$c70) { + s1 = input.substr(peg$currPos, 2); + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e84); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f139(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_IS() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2).toLowerCase() === peg$c71) { + s1 = input.substr(peg$currPos, 2); + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e85); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f140(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_LIKE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c72) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e86); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f141(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_EXISTS() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c73) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e87); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f142(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_NOT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c74) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e88); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f143(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_AND() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c75) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e89); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f144(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_OR() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2).toLowerCase() === peg$c76) { + s1 = input.substr(peg$currPos, 2); + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e90); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f145(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_COUNT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c77) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e91); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f146(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_MAX() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c78) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e92); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f147(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_MIN() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c79) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e93); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f148(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SUM() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c80) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e94); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f149(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_AVG() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c81) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e95); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f150(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CASE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c82) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e96); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_WHEN() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c83) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e97); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_THEN() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c84) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e98); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_ELSE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c85) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e99); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_END() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c86) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e100); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CAST() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c87) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e101); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CHAR() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c88) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e102); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f151(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_VARCHAR() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c89) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e103); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f152(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_NUMERIC() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c90) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e104); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f153(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_DECIMAL() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c91) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e105); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f154(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SIGNED() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c92) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e106); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f155(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNSIGNED() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c93) { + s1 = input.substr(peg$currPos, 8); + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e107); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f156(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_INT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c94) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e108); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f157(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_INTEGER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c95) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e109); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f158(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_JSON() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c96) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e110); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f159(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SMALLINT() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c97) { + s1 = input.substr(peg$currPos, 8); + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e111); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f160(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_DATE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c98) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e112); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f161(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_TIME() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c99) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e113); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f162(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_TIMESTAMP() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c100) { + s1 = input.substr(peg$currPos, 9); + peg$currPos += 9; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e114); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f163(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_USER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c101) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e115); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f164(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CURRENT_DATE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 12).toLowerCase() === peg$c102) { + s1 = input.substr(peg$currPos, 12); + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e116); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f165(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_ADD_DATE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 7).toLowerCase() === peg$c103) { + s1 = input.substr(peg$currPos, 7); + peg$currPos += 7; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e117); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f166(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_INTERVAL() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 8).toLowerCase() === peg$c104) { + s1 = input.substr(peg$currPos, 8); + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e118); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f167(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNIT_YEAR() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c105) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e119); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f168(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNIT_MONTH() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 5).toLowerCase() === peg$c106) { + s1 = input.substr(peg$currPos, 5); + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e120); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f169(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNIT_DAY() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 3).toLowerCase() === peg$c107) { + s1 = input.substr(peg$currPos, 3); + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e121); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f170(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNIT_HOUR() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c108) { + s1 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e122); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f171(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNIT_MINUTE() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c109) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e123); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f172(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_UNIT_SECOND() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c110) { + s1 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e124); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f173(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CURRENT_TIME() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 12).toLowerCase() === peg$c111) { + s1 = input.substr(peg$currPos, 12); + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e125); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f174(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CURRENT_TIMESTAMP() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 17).toLowerCase() === peg$c112) { + s1 = input.substr(peg$currPos, 17); + peg$currPos += 17; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e126); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f175(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_CURRENT_USER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 12).toLowerCase() === peg$c113) { + s1 = input.substr(peg$currPos, 12); + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e127); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f176(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SESSION_USER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 12).toLowerCase() === peg$c114) { + s1 = input.substr(peg$currPos, 12); + peg$currPos += 12; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e128); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f177(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_SYSTEM_USER() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 11).toLowerCase() === peg$c115) { + s1 = input.substr(peg$currPos, 11); + peg$currPos += 11; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e129); } + } + if (s1 !== peg$FAILED) { + s2 = peg$currPos; + peg$silentFails++; + s3 = peg$parseident_start(); + peg$silentFails--; + if (s3 === peg$FAILED) { + s2 = undefined; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f178(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKW_VAR_PRE() { + var s0; + + if (input.charCodeAt(peg$currPos) === 36) { + s0 = peg$c116; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e130); } + } + + return s0; + } + + function peg$parseKW_RETURN() { + var s0; + + if (input.substr(peg$currPos, 6).toLowerCase() === peg$c117) { + s0 = input.substr(peg$currPos, 6); + peg$currPos += 6; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e131); } + } + + return s0; + } + + function peg$parseKW_ASSIGN() { + var s0; + + if (input.substr(peg$currPos, 2) === peg$c118) { + s0 = peg$c118; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e132); } + } + + return s0; + } + + function peg$parseKW_DUAL() { + var s0; + + if (input.substr(peg$currPos, 4).toLowerCase() === peg$c119) { + s0 = input.substr(peg$currPos, 4); + peg$currPos += 4; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e133); } + } + + return s0; + } + + function peg$parseOPT_SQL_CALC_FOUND_ROWS() { + var s0; + + if (input.substr(peg$currPos, 19).toLowerCase() === peg$c120) { + s0 = input.substr(peg$currPos, 19); + peg$currPos += 19; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e134); } + } + + return s0; + } + + function peg$parseOPT_SQL_CACHE() { + var s0; + + if (input.substr(peg$currPos, 9).toLowerCase() === peg$c121) { + s0 = input.substr(peg$currPos, 9); + peg$currPos += 9; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e135); } + } + + return s0; + } + + function peg$parseOPT_SQL_NO_CACHE() { + var s0; + + if (input.substr(peg$currPos, 12).toLowerCase() === peg$c122) { + s0 = input.substr(peg$currPos, 12); + peg$currPos += 12; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e136); } + } + + return s0; + } + + function peg$parseOPT_SQL_SMALL_RESULT() { + var s0; + + if (input.substr(peg$currPos, 16).toLowerCase() === peg$c123) { + s0 = input.substr(peg$currPos, 16); + peg$currPos += 16; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e137); } + } + + return s0; + } + + function peg$parseOPT_SQL_BIG_RESULT() { + var s0; + + if (input.substr(peg$currPos, 14).toLowerCase() === peg$c124) { + s0 = input.substr(peg$currPos, 14); + peg$currPos += 14; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e138); } + } + + return s0; + } + + function peg$parseOPT_SQL_BUFFER_RESULT() { + var s0; + + if (input.substr(peg$currPos, 17).toLowerCase() === peg$c125) { + s0 = input.substr(peg$currPos, 17); + peg$currPos += 17; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e139); } + } + + return s0; + } + + function peg$parseDOT() { + var s0; + + if (input.charCodeAt(peg$currPos) === 46) { + s0 = peg$c29; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e38); } + } + + return s0; + } + + function peg$parseCOMMA() { + var s0; + + if (input.charCodeAt(peg$currPos) === 44) { + s0 = peg$c126; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e140); } + } + + return s0; + } + + function peg$parseSTAR() { + var s0; + + if (input.charCodeAt(peg$currPos) === 42) { + s0 = peg$c12; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e12); } + } + + return s0; + } + + function peg$parseLPAREN() { + var s0; + + if (input.charCodeAt(peg$currPos) === 40) { + s0 = peg$c0; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e0); } + } + + return s0; + } + + function peg$parseRPAREN() { + var s0; + + if (input.charCodeAt(peg$currPos) === 41) { + s0 = peg$c1; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + + return s0; + } + + function peg$parseLBRAKE() { + var s0; + + if (input.charCodeAt(peg$currPos) === 91) { + s0 = peg$c127; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e141); } + } + + return s0; + } + + function peg$parseRBRAKE() { + var s0; + + if (input.charCodeAt(peg$currPos) === 93) { + s0 = peg$c128; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e142); } + } + + return s0; + } + + function peg$parseSEMICOLON() { + var s0; + + if (input.charCodeAt(peg$currPos) === 59) { + s0 = peg$c129; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e143); } + } + + return s0; + } + + function peg$parse__() { + var s0, s1; + + s0 = []; + s1 = peg$parsewhitespace(); + if (s1 === peg$FAILED) { + s1 = peg$parsecomment(); + } + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parsewhitespace(); + if (s1 === peg$FAILED) { + s1 = peg$parsecomment(); + } + } + + return s0; + } + + function peg$parsecomment() { + var s0; + + s0 = peg$parseblock_comment(); + if (s0 === peg$FAILED) { + s0 = peg$parseline_comment(); + } + + return s0; + } + + function peg$parseblock_comment() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c130) { + s1 = peg$c130; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e144); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 2) === peg$c131) { + s5 = peg$c131; + peg$currPos += 2; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e145); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = undefined; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parsechar(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + if (input.substr(peg$currPos, 2) === peg$c131) { + s5 = peg$c131; + peg$currPos += 2; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e145); } + } + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = undefined; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parsechar(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (input.substr(peg$currPos, 2) === peg$c131) { + s3 = peg$c131; + peg$currPos += 2; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e145); } + } + if (s3 !== peg$FAILED) { + s1 = [s1, s2, s3]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseline_comment() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c132) { + s1 = peg$c132; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e146); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseEOL(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = undefined; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parsechar(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$currPos; + peg$silentFails++; + s5 = peg$parseEOL(); + peg$silentFails--; + if (s5 === peg$FAILED) { + s4 = undefined; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + if (s4 !== peg$FAILED) { + s5 = peg$parsechar(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + s1 = [s1, s2]; + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsechar() { + var s0; + + if (input.length > peg$currPos) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e147); } + } + + return s0; + } + + function peg$parseinterval_unit() { + var s0; + + s0 = peg$parseKW_UNIT_YEAR(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_UNIT_MONTH(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_UNIT_DAY(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_UNIT_HOUR(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_UNIT_MINUTE(); + if (s0 === peg$FAILED) { + s0 = peg$parseKW_UNIT_SECOND(); + } + } + } + } + } + + return s0; + } + + function peg$parsewhitespace() { + var s0; + + if (peg$r14.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e148); } + } + + return s0; + } + + function peg$parseEOL() { + var s0, s1; + + s0 = peg$parseEOF(); + if (s0 === peg$FAILED) { + s0 = []; + if (peg$r8.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e37); } + } + if (s1 !== peg$FAILED) { + while (s1 !== peg$FAILED) { + s0.push(s1); + if (peg$r8.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e37); } + } + } + } else { + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parseEOF() { + var s0, s1; + + s0 = peg$currPos; + peg$silentFails++; + if (input.length > peg$currPos) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e147); } + } + peg$silentFails--; + if (s1 === peg$FAILED) { + s0 = undefined; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseproc_stmts() { + var s0, s1; + + s0 = []; + s1 = peg$parseproc_stmt(); + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parseproc_stmt(); + } + + return s0; + } + + function peg$parseproc_stmt() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + peg$savedPos = peg$currPos; + s1 = peg$f179(); + if (s1) { + s1 = undefined; + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseassign_stmt(); + if (s3 === peg$FAILED) { + s3 = peg$parsereturn_stmt(); + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f180(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseassign_stmt() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parsevar_decl(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseKW_ASSIGN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseproc_expr(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f181(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsereturn_stmt() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_RETURN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseproc_expr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f182(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseproc_expr() { + var s0; + + s0 = peg$parseselect_stmt(); + if (s0 === peg$FAILED) { + s0 = peg$parseproc_join(); + if (s0 === peg$FAILED) { + s0 = peg$parseproc_additive_expr(); + if (s0 === peg$FAILED) { + s0 = peg$parseproc_array(); + } + } + } + + return s0; + } + + function peg$parseproc_additive_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseproc_multiplicative_expr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseadditive_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseproc_multiplicative_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseadditive_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseproc_multiplicative_expr(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f183(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseproc_multiplicative_expr() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseproc_primary(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parsemultiplicative_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseproc_primary(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parsemultiplicative_operator(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseproc_primary(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f184(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseproc_join() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parsevar_decl(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parsejoin_op(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parsevar_decl(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseon_clause(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f185(s1, s3, s5, s7); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseproc_primary() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$parseliteral(); + if (s0 === peg$FAILED) { + s0 = peg$parsevar_decl(); + if (s0 === peg$FAILED) { + s0 = peg$parseproc_func_call(); + if (s0 === peg$FAILED) { + s0 = peg$parseparam(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseLPAREN(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseproc_additive_expr(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseRPAREN(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f186(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + } + + return s0; + } + + function peg$parseproc_func_call() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseident(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseproc_primary_list(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f187(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseproc_primary_list() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = peg$parseproc_primary(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseproc_primary(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse__(); + s5 = peg$parseCOMMA(); + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseproc_primary(); + if (s7 !== peg$FAILED) { + s4 = [s4, s5, s6, s7]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f188(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseproc_array() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseLBRAKE(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseproc_primary_list(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = peg$parseRBRAKE(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f189(s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsevar_decl() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = peg$parseKW_VAR_PRE(); + if (s1 !== peg$FAILED) { + s2 = peg$parseident_name(); + if (s2 !== peg$FAILED) { + s3 = peg$parsemem_chain(); + peg$savedPos = s0; + s0 = peg$f190(s2, s3); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parsemem_chain() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = []; + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s3 = peg$c29; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e38); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parseident_name(); + if (s4 !== peg$FAILED) { + s3 = [s3, s4]; + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 46) { + s3 = peg$c29; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e38); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parseident_name(); + if (s4 !== peg$FAILED) { + s3 = [s3, s4]; + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } + peg$savedPos = s0; + s1 = peg$f191(s1); + s0 = s1; + + return s0; + } + + function peg$parsedata_type() { + var s0; + + s0 = peg$parsecharacter_string_type(); + if (s0 === peg$FAILED) { + s0 = peg$parsenumeric_type(); + if (s0 === peg$FAILED) { + s0 = peg$parsedatetime_type(); + if (s0 === peg$FAILED) { + s0 = peg$parsejson_type(); + } + } + } + + return s0; + } + + function peg$parsecharacter_string_type() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8; + + s0 = peg$currPos; + s1 = peg$parseKW_CHAR(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_VARCHAR(); + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + s3 = peg$parseLPAREN(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + s5 = []; + if (peg$r9.test(input.charAt(peg$currPos))) { + s6 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e39); } + } + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + if (peg$r9.test(input.charAt(peg$currPos))) { + s6 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e39); } + } + } + } else { + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s6 = peg$parse__(); + s7 = peg$parseRPAREN(); + if (s7 !== peg$FAILED) { + s8 = peg$parse__(); + peg$savedPos = s0; + s0 = peg$f192(s1, s5); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_CHAR(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f193(s1); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseKW_VARCHAR(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f194(s1); + } + s0 = s1; + } + } + + return s0; + } + + function peg$parsenumeric_type() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseKW_NUMERIC(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_DECIMAL(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_INT(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_INTEGER(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_SMALLINT(); + } + } + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f195(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsedatetime_type() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseKW_DATE(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_TIME(); + if (s1 === peg$FAILED) { + s1 = peg$parseKW_TIMESTAMP(); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f196(s1); + } + s0 = s1; + + return s0; + } + + function peg$parsejson_type() { + var s0, s1; + + s0 = peg$currPos; + s1 = peg$parseKW_JSON(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f197(s1); + } + s0 = s1; + + return s0; + } + + + const reservedMap = { + 'ALL': true, + 'AND': true, + 'AS': true, + 'ASC': true, + + 'BETWEEN': true, + 'BY': true, + + 'CASE': true, + 'CREATE': true, + 'CONTAINS': true, + 'CURRENT_DATE': true, + 'CURRENT_TIME': true, + 'CURRENT_TIMESTAMP': true, + 'CURRENT_USER': true, + + 'DELETE': true, + 'DESC': true, + 'DISTINCT': true, + 'DROP': true, + + 'ELSE': true, + 'END': true, + 'EXISTS': true, + 'EXPLAIN': true, + + 'FALSE': true, + 'FROM': true, + 'FULL': true, + + 'GROUP': true, + + 'HAVING': true, + + 'IN': true, + 'INDEX': true, + 'INNER': true, + 'INSERT': true, + 'INTO': true, + 'IS': true, + + 'JOIN': true, + 'JSON': true, + + 'LEFT': true, + 'LIKE': true, + 'LIMIT': true, + + 'NOT': true, + 'NULL': true, + + 'ON': true, + 'OR': true, + 'ORDER': true, + 'OUTER': true, + + 'RECURSIVE': true, + 'REPLACE': true, + 'RIGHT': true, + + 'SELECT': true, + 'SESSION_USER': true, + 'SET': true, + 'SHOW': true, + 'STATUS': true, // reserved (MySQL) + 'SYSTEM_USER': true, + + 'TABLE': true, + 'THEN': true, + 'TRUE': true, + 'TYPE': true, // reserved (MySQL) + + 'UNION': true, + 'UPDATE': true, + 'USER': true, + 'USING': true, + + 'VALUES': true, + + 'WITH': true, + 'WHEN': true, + 'WHERE': true + }; + + function createUnaryExpr(op, e) { + return { + type: 'unary_expr', + operator: op, + expr: e + }; + } + + function createBinaryExpr(op, left, right) { + return { + type: 'binary_expr', + operator: op, + left: left, + right: right + }; + } + + function createList(head, tail) { + const result = [head]; + for (let i = 0; i < tail.length; i++) { + result.push(tail[i][3]); + } + return result; + } + + function createBinaryExprChain(head, tail) { + let result = head; + for (let i = 0; i < tail.length; i++) { + result = createBinaryExpr(tail[i][1], result, tail[i][3]); + } + return result; + } + + const cmpPrefixMap = { + '+': true, + '-': true, + '*': true, + '/': true, + '>': true, + '<': true, + '!': true, + '=': true, + + //between + 'B': true, + 'b': true, + //for is or in + 'I': true, + 'i': true, + //for like + 'L': true, + 'l': true, + //for not + 'N': true, + 'n': true + }; + + // used for dependency analysis + let varList = []; + + const tableList = new Set(); + const columnList = new Set(); + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail(peg$endExpectation()); + } + + throw peg$buildStructuredError( + peg$maxFailExpected, + peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } +} + +module.exports = { + SyntaxError: peg$SyntaxError, + parse: peg$parse +}; diff --git a/packages/core/database/src/sql-parser/readme.md b/packages/core/database/src/sql-parser/readme.md new file mode 100644 index 000000000..14f4c2b81 --- /dev/null +++ b/packages/core/database/src/sql-parser/readme.md @@ -0,0 +1,2 @@ +use peggy to transform pegjs to sql parser +https://github.com/peggyjs/peggy diff --git a/packages/core/database/src/sql-parser/sql.pegjs b/packages/core/database/src/sql-parser/sql.pegjs new file mode 100644 index 000000000..22a45a4bc --- /dev/null +++ b/packages/core/database/src/sql-parser/sql.pegjs @@ -0,0 +1,1297 @@ +{ + const reservedMap = { + 'ALL': true, + 'AND': true, + 'AS': true, + 'ASC': true, + + 'BETWEEN': true, + 'BY': true, + + 'CASE': true, + 'CREATE': true, + 'CONTAINS': true, + 'CURRENT_DATE': true, + 'CURRENT_TIME': true, + 'CURRENT_TIMESTAMP': true, + 'CURRENT_USER': true, + + 'DELETE': true, + 'DESC': true, + 'DISTINCT': true, + 'DROP': true, + + 'ELSE': true, + 'END': true, + 'EXISTS': true, + 'EXPLAIN': true, + + 'FALSE': true, + 'FROM': true, + 'FULL': true, + + 'GROUP': true, + + 'HAVING': true, + + 'IN': true, + 'INDEX': true, + 'INNER': true, + 'INSERT': true, + 'INTO': true, + 'IS': true, + + 'JOIN': true, + 'JSON': true, + + 'LEFT': true, + 'LIKE': true, + 'LIMIT': true, + + 'NOT': true, + 'NULL': true, + + 'ON': true, + 'OR': true, + 'ORDER': true, + 'OUTER': true, + + 'RECURSIVE': true, + 'REPLACE': true, + 'RIGHT': true, + + 'SELECT': true, + 'SESSION_USER': true, + 'SET': true, + 'SHOW': true, + 'STATUS': true, // reserved (MySQL) + 'SYSTEM_USER': true, + + 'TABLE': true, + 'THEN': true, + 'TRUE': true, + 'TYPE': true, // reserved (MySQL) + + 'UNION': true, + 'UPDATE': true, + 'USER': true, + 'USING': true, + + 'VALUES': true, + + 'WITH': true, + 'WHEN': true, + 'WHERE': true + }; + + function createUnaryExpr(op, e) { + return { + type: 'unary_expr', + operator: op, + expr: e + }; + } + + function createBinaryExpr(op, left, right) { + return { + type: 'binary_expr', + operator: op, + left: left, + right: right + }; + } + + function createList(head, tail) { + const result = [head]; + for (let i = 0; i < tail.length; i++) { + result.push(tail[i][3]); + } + return result; + } + + function createBinaryExprChain(head, tail) { + let result = head; + for (let i = 0; i < tail.length; i++) { + result = createBinaryExpr(tail[i][1], result, tail[i][3]); + } + return result; + } + + const cmpPrefixMap = { + '+': true, + '-': true, + '*': true, + '/': true, + '>': true, + '<': true, + '!': true, + '=': true, + + //between + 'B': true, + 'b': true, + //for is or in + 'I': true, + 'i': true, + //for like + 'L': true, + 'l': true, + //for not + 'N': true, + 'n': true + }; + + // used for dependency analysis + let varList = []; + + const tableList = new Set(); + const columnList = new Set(); +} + +start + = multiple_stmt + / crud_stmt + +crud_stmt + = union_stmt + / update_stmt + / replace_insert_stmt + / insert_no_columns_stmt + / delete_stmt + / proc_stmts + +multiple_stmt + = head:crud_stmt tail:(__ SEMICOLON __ crud_stmt)+ { + const cur = [head && head.ast || head]; + for (let i = 0; i < tail.length; i++) { + if(!tail[i][3] || tail[i][3].length === 0) continue; + cur.push(tail[i][3] && tail[i][3].ast || tail[i][3]); + } + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: cur + } + } + +union_stmt + = head:select_stmt tail:(__ KW_UNION __ select_stmt)* { + let cur = head; + for (let i = 0; i < tail.length; i++) { + cur._next = tail[i][3]; + cur = cur._next + } + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: head + } + } + +select_stmt + = select_stmt_nake + / s:('(' __ select_stmt __ ')') { + return s[2]; + } + +with_clause + = KW_WITH __ head:cte_definition tail:(__ COMMA __ cte_definition)* { + return createList(head, tail); + } + / __ KW_WITH __ KW_RECURSIVE __ cte:cte_definition { + cte.recursive = true; + return [cte] + } + +cte_definition + = name:ident_name __ columns:cte_column_definition? __ KW_AS __ LPAREN __ stmt:union_stmt __ RPAREN { + return { name, stmt, columns }; + } + +cte_column_definition + = LPAREN __ head:column tail:(__ COMMA __ column)* __ RPAREN { + return createList(head, tail); + } + +select_stmt_nake + = cte:with_clause? __ KW_SELECT __ + opts:option_clause? __ + d:KW_DISTINCT? __ + c:column_clause __ + f:from_clause? __ + w:where_clause? __ + g:group_by_clause? __ + h:having_clause? __ + o:order_by_clause? __ + l:limit_clause? { + if(f) f.forEach(info => info.table && tableList.add(`select::${info.db}::${info.table}`)); + return { + with: cte, + type: 'select', + options: opts, + distinct: d, + columns: c, + from: f, + where: w, + groupby: g, + having: h, + orderby: o, + limit: l + }; + } + +// MySQL extensions to standard SQL +option_clause + = head:query_option tail:(__ query_option)* { + const opts = [head]; + for (let i = 0, l = tail.length; i < l; ++i) { + opts.push(tail[i][1]); + } + return opts; + } + +query_option + = option:( + OPT_SQL_CALC_FOUND_ROWS + / (OPT_SQL_CACHE / OPT_SQL_NO_CACHE) + / OPT_SQL_BIG_RESULT + / OPT_SQL_SMALL_RESULT + / OPT_SQL_BUFFER_RESULT + ) { return option; } + +column_clause + = (KW_ALL / (STAR !ident_start) / STAR) { + columnList.add('select::null::(.*)'); + return '*'; + } + / head:column_list_item tail:(__ COMMA __ column_list_item)* { + return createList(head, tail); + } + +column_list_item + = tbl:ident __ DOT __ STAR { + columnList.add(`select::${tbl}::(.*)`); + return { + expr: { + type: 'column_ref', + table: tbl, + column: '*' + }, + as: null + }; + } + / e:expr __ alias:alias_clause? { + return { expr: e, as: alias }; + } + +alias_clause + = KW_AS __ i:alias_ident { return i; } + / KW_AS? __ i:ident { return i; } + +from_clause + = KW_FROM __ l:table_ref_list { return l; } + +table_ref_list + = head:table_base + tail:table_ref* { + tail.unshift(head); + return tail; + } + +table_ref + = __ COMMA __ t:table_base { return t; } + / __ t:table_join { return t; } + + +table_join + = op:join_op __ t:table_base __ KW_USING __ LPAREN __ head:ident_name tail:(__ COMMA __ ident_name)* __ RPAREN { + t.join = op; + t.using = createList(head, tail); + return t; + } + / op:join_op __ t:table_base __ expr:on_clause? { + t.join = op; + t.on = expr; + return t; + } + / op:join_op __ LPAREN __ stmt:union_stmt __ RPAREN __ alias:alias_clause? __ expr:on_clause? { + stmt.parentheses = true; + return { + expr: stmt, + as: alias, + join: op, + on: expr + }; + } + +//NOTE that, the table assigned to `var` shouldn't write in `table_join` +table_base + = KW_DUAL { + return { + type: 'dual' + }; + } + / t:table_name __ alias:alias_clause? { + if (t.type === 'var') { + t.as = alias; + return t; + } else { + return { + db: t.db, + table: t.table, + as: alias + }; + } + } + / LPAREN __ stmt:union_stmt __ RPAREN __ alias:alias_clause? { + stmt.parentheses = true; + return { + expr: stmt, + as: alias + }; + } + +join_op + = KW_LEFT __ KW_OUTER? __ KW_JOIN { return 'LEFT JOIN'; } + / KW_RIGHT __ KW_OUTER? __ KW_JOIN { return 'RIGHT JOIN'; } + / KW_FULL __ KW_OUTER? __ KW_JOIN { return 'FULL JOIN'; } + / (KW_INNER __)? KW_JOIN { return 'INNER JOIN'; } + +table_name + = dt:ident tail:(__ DOT __ ident)? { + const obj = { db: null, table: dt }; + if (tail !== null) { + obj.db = dt; + obj.table = tail[3]; + } + return obj; + } + / v:var_decl { + v.db = null; + v.table = v.name; + return v; + } + +on_clause + = KW_ON __ e:expr { return e; } + +where_clause + = KW_WHERE __ e:expr { return e; } + +group_by_clause + = KW_GROUP __ KW_BY __ l:column_ref_list { return l; } + +column_ref_list + = head:column_ref tail:(__ COMMA __ column_ref)* { + return createList(head, tail); + } + +having_clause + = KW_HAVING __ e:expr { return e; } + +order_by_clause + = KW_ORDER __ KW_BY __ l:order_by_list { return l; } + +order_by_list + = head:order_by_element tail:(__ COMMA __ order_by_element)* { + return createList(head, tail); + } + +order_by_element + = e:expr __ d:(KW_DESC / KW_ASC)? { + const obj = { expr: e, type: 'ASC' }; + if (d === 'DESC') obj.type = 'DESC'; + return obj; + } + +number_or_param + = literal_numeric + / param + +limit_clause + = KW_LIMIT __ i1:(number_or_param) __ tail:(COMMA __ number_or_param)? { + const res = [i1]; + if (tail === null) res.unshift({ type: 'number', value: 0 }); + else res.push(tail[2]); + return res; + } + +update_stmt + = KW_UPDATE __ + t:table_name __ + KW_SET __ + l:set_list __ + w:where_clause? { + if(t.table) tableList.add(`update::${t.db}::${t.table}`); + if(l) l.forEach(col => columnList.add(`update::${t.table}::${col.column}`)); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: 'update', + db: t.db, + table: t.table, + set: l, + where: w + } + }; + } + +delete_stmt + = KW_DELETE __ + t: table_ref_list? __ + f:from_clause __ + w:where_clause? { + if(f) f.forEach(info => { + info.table && tableList.add(`delete::${info.db}::${info.table}`); + columnList.add(`delete::${info.table}::(.*)`); + }); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: 'delete', + tables: t, + from: f, + where: w + } + }; + } +set_list + = head:set_item tail:(__ COMMA __ set_item)* { + return createList(head, tail); + } + +/** + * here only use `additive_expr` to support 'col1 = col1+2' + * if you want to use lower operator, please use '()' like below + * 'col1 = (col2 > 3)' + */ +set_item + = tbl:(ident __ DOT)? __ c:column_name __ '=' __ v:additive_expr { + return { column: c, value: v, table: tbl && tbl[0] }; + } + +replace_insert_stmt + = ri:replace_insert __ + KW_INTO __ + t:table_name __ LPAREN __ + c:column_list __ RPAREN __ + v:value_clause { + if (t.table) tableList.add(`insert::${t.db}::${t.table}`); + if (c) c.forEach(c => columnList.add(`insert::${t.table}::${c}`)); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: ri, + db: t.db, + table: t.table, + columns: c, + values: v + } + }; + } + +insert_no_columns_stmt + = ri:replace_insert __ + KW_INTO __ + t:table_name __ + v:value_clause { + if (t.table) tableList.add(`insert::${t.db}::${t.table}`); + columnList.add(`insert::${t.table}::(.*)`); + return { + tableList: Array.from(tableList), + columnList: Array.from(columnList), + ast: { + type: ri, + db: t.db, + table: t.table, + columns: null, + values: v + } + }; + } + +replace_insert + = KW_INSERT { return 'insert'; } + / KW_REPLACE { return 'replace'; } + +value_clause + = KW_VALUES __ l:value_list { return l; } + +value_list + = head:value_item tail:(__ COMMA __ value_item)* { + return createList(head, tail); + } + +value_item + = LPAREN __ l:expr_list __ RPAREN { + return l; + } + +expr_list + = head:expr tail:(__ COMMA __ expr)* { + const el = { type: 'expr_list' }; + el.value = createList(head, tail); + return el; + } + +interval_expr + = KW_INTERVAL __ + n:number __ + u: interval_unit { + return { + type: 'interval', + value: [n, u] + } + } + +case_expr + = KW_CASE __ + expr:expr? __ + condition_list:case_when_then+ __ + otherwise:case_else? __ + KW_END __ KW_CASE? { + if (otherwise) condition_list.push(otherwise); + return { + type: 'case', + expr: expr || null, + args: condition_list + }; + } + +case_when_then + = KW_WHEN __ condition:expr __ KW_THEN __ result:expr __ { + return { + type: 'when', + cond: condition, + result: result + }; + } + +case_else = KW_ELSE __ result:expr { + return { type: 'else', result: result }; + } + +/** + * Borrowed from PL/SQL ,the priority of below list IS ORDER BY DESC + * --------------------------------------------------------------------------------------------------- + * | +, - | identity, negation | + * | *, / | multiplication, division | + * | +, - | addition, subtraction, concatenation | + * | =, <, >, <=, >=, <>, !=, IS, LIKE, BETWEEN, IN | comparion | + * | !, NOT | logical negation | + * | AND | conjunction | + * | OR | inclusion | + * --------------------------------------------------------------------------------------------------- + */ + +expr + = or_expr + / select_stmt + +or_expr + = head:and_expr tail:(__ KW_OR __ and_expr)* { + return createBinaryExprChain(head, tail); + } + +and_expr + = head:not_expr tail:(__ KW_AND __ not_expr)* { + return createBinaryExprChain(head, tail); + } + +//here we should use `NOT` instead of `comparision_expr` to support chain-expr +not_expr + = comparison_expr + / exists_expr + / (KW_NOT / "!" !"=") __ expr:not_expr { + return createUnaryExpr('NOT', expr); + } + +comparison_expr + = left:additive_expr __ rh:comparison_op_right? { + if (rh === null) return left; + else if (rh.type === 'arithmetic') return createBinaryExprChain(left, rh.tail); + else return createBinaryExpr(rh.op, left, rh.right); + } + +exists_expr + = op:exists_op __ LPAREN __ stmt:union_stmt __ RPAREN { + stmt.parentheses = true; + return createUnaryExpr(op, stmt); + } + +exists_op + = nk:(KW_NOT __ KW_EXISTS) { return nk[0] + ' ' + nk[2]; } + / KW_EXISTS + +comparison_op_right + = arithmetic_op_right + / in_op_right + / between_op_right + / is_op_right + / like_op_right + +arithmetic_op_right + = l:(__ arithmetic_comparison_operator __ additive_expr)+ { + return { type: 'arithmetic', tail: l }; + } + +arithmetic_comparison_operator + = ">=" / ">" / "<=" / "<>" / "<" / "=" / "!=" + +is_op_right + = KW_IS __ right:additive_expr { + return { op: 'IS', right: right }; + } + / (KW_IS __ KW_NOT) __ right:additive_expr { + return { op: 'IS NOT', right: right }; + } + +between_op_right + = op:between_or_not_between_op __ begin:additive_expr __ KW_AND __ end:additive_expr { + return { + op: op, + right: { + type: 'expr_list', + value: [begin, end] + } + }; + } + +between_or_not_between_op + = nk:(KW_NOT __ KW_BETWEEN) { return nk[0] + ' ' + nk[2]; } + / KW_BETWEEN + +like_op + = nk:(KW_NOT __ KW_LIKE) { return nk[0] + ' ' + nk[2]; } + / KW_LIKE + +in_op + = nk:(KW_NOT __ KW_IN) { return nk[0] + ' ' + nk[2]; } + / KW_IN + +like_op_right + = op:like_op __ right:comparison_expr { + return { op: op, right: right }; + } + +in_op_right + = op:in_op __ LPAREN __ l:expr_list __ RPAREN { + return { op: op, right: l }; + } + / op:in_op __ e:var_decl { + return { op: op, right: e }; + } + +additive_expr + = head:multiplicative_expr + tail:(__ additive_operator __ multiplicative_expr)* { + return createBinaryExprChain(head, tail); + } + +additive_operator + = "+" / "-" + +multiplicative_expr + = head:primary + tail:(__ multiplicative_operator __ primary)* { + return createBinaryExprChain(head, tail) + } + +multiplicative_operator + = "*" / "/" / "%" + +primary + = literal + / cast_expr + / aggr_func + / func_call + / case_expr + / interval_expr + / column_ref + / param + / LPAREN __ e:expr __ RPAREN { + e.parentheses = true; + return e; + } + / LPAREN __ list:expr_list __ RPAREN { + list.parentheses = true; + return list; + } + / var_decl + +column_ref + = tbl:ident __ DOT __ col:column { + columnList.add(`select::${tbl}::${col}`); + return { + type: 'column_ref', + table: tbl, + column: col + }; + } + / col:column { + columnList.add(`select::null::${col}`); + return { + type: 'column_ref', + table: null, + column: col + }; + } + +column_list + = head:column tail:(__ COMMA __ column)* { + return createList(head, tail); + } + +ident + = name:ident_name !{ return reservedMap[name.toUpperCase()] === true; } { + return name; + } + / name:quoted_ident { + return name; + } + +alias_ident + = name:ident_name !{ + if (reservedMap[name.toUpperCase()] === true) throw new Error("Error: "+ JSON.stringify(name)+" is a reserved word, can not as alias clause"); + return false + } { + return name; + } + / name:quoted_ident { + return name; + } + +quoted_ident + = double_quoted_ident + / single_quoted_ident + / backticks_quoted_ident + +double_quoted_ident + = '"' chars:[^"]+ '"' { return chars.join(''); } + +single_quoted_ident + = "'" chars:[^']+ "'" { return chars.join(''); } + +backticks_quoted_ident + = "`" chars:[^`]+ "`" { return chars.join(''); } + +column + = name:column_name !{ return reservedMap[name.toUpperCase()] === true; } { return name; } + / quoted_ident + +column_name + = start:ident_start parts:column_part* { return start + parts.join(''); } + +ident_name + = start:ident_start parts:ident_part* { return start + parts.join(''); } + +ident_start = [A-Za-z_] + +ident_part = [A-Za-z0-9_] + +// to support column name like `cf1:name` in hbase +column_part = [A-Za-z0-9_:] + +param + = l:(':' ident_name) { + return { type: 'param', value: l[1] }; + } + +aggr_func + = aggr_fun_count + / aggr_fun_smma + +aggr_fun_smma + = name:KW_SUM_MAX_MIN_AVG __ LPAREN __ e:additive_expr __ RPAREN { + return { + type: 'aggr_func', + name: name, + args: { + expr: e + } + }; + } + +KW_SUM_MAX_MIN_AVG + = KW_SUM / KW_MAX / KW_MIN / KW_AVG + +aggr_fun_count + = name:KW_COUNT __ LPAREN __ arg:count_arg __ RPAREN { + return { + type: 'aggr_func', + name: name, + args: arg + }; + } + +count_arg + = e:star_expr { return { expr: e }; } + / d:KW_DISTINCT? __ c:column_ref { return { distinct: d, expr: c }; } + +star_expr + = "*" { return { type: 'star', value: '*' }; } + +func_call + = name:ident __ LPAREN __ l:expr_list? __ RPAREN { + return { + type: 'function', + name: name, + args: l ? l: { type: 'expr_list', value: [] } + }; + } + / name:scalar_func (__ LPAREN RPAREN __)? { + return { + type: 'function', + name: name, + args: { type: 'expr_list', value: [] } + }; + } + +scalar_func + = KW_CURRENT_DATE + / KW_CURRENT_TIME + / KW_CURRENT_TIMESTAMP + / KW_CURRENT_USER + / KW_USER + / KW_SESSION_USER + / KW_SYSTEM_USER + +cast_expr + = KW_CAST __ LPAREN __ e:expr __ KW_AS __ t:data_type __ RPAREN { + return { + type: 'cast', + expr: e, + target: t + }; + } + / KW_CAST __ LPAREN __ e:expr __ KW_AS __ KW_DECIMAL __ LPAREN __ precision:int __ RPAREN __ RPAREN { + return { + type: 'cast', + expr: e, + target: { + dataType: 'DECIMAL(' + precision + ')' + } + }; + } + / KW_CAST __ LPAREN __ e:expr __ KW_AS __ KW_DECIMAL __ LPAREN __ precision:int __ COMMA __ scale:int __ RPAREN __ RPAREN { + return { + type: 'cast', + expr: e, + target: { + dataType: 'DECIMAL(' + precision + ', ' + scale + ')' + } + }; + } + / KW_CAST __ LPAREN __ e:expr __ KW_AS __ s:signedness __ t:KW_INTEGER? __ RPAREN { /* MySQL cast to un-/signed integer */ + return { + type: 'cast', + expr: e, + target: { + dataType: s + (t ? ' ' + t: '') + } + }; + } + +signedness + = KW_SIGNED + / KW_UNSIGNED + +literal + = literal_string + / literal_numeric + / literal_bool + / literal_null + / literal_datetime + +literal_list + = head:literal tail:(__ COMMA __ literal)* { + return createList(head, tail); + } + +literal_null + = KW_NULL { + return { type: 'null', value: null }; + } + +literal_bool + = KW_TRUE { + return { type: 'bool', value: true }; + } + / KW_FALSE { + return { type: 'bool', value: false }; + } + +literal_string + = ca:("'" single_char* "'") { + return { + type: 'string', + value: ca[1].join('') + }; + } + / ca:("\"" single_quote_char* "\"") { + return { + type: 'string', + value: ca[1].join('') + }; + } + +literal_datetime + = type:(KW_TIME / KW_DATE / KW_TIMESTAMP) __ ca:("'" single_char* "'") { + return { + type: type.toLowerCase(), + value: ca[1].join('') + }; + } + +single_quote_char + = [^"\\\0-\x1F\x7f] + / escape_char + +single_char + = [^'\\\0-\x1F\x7f] + / escape_char + +escape_char + = "\\'" { return "'"; } + / '\\"' { return '"'; } + / "\\\\" { return "\\"; } + / "\\/" { return "/"; } + / "\\b" { return "\b"; } + / "\\f" { return "\f"; } + / "\\n" { return "\n"; } + / "\\r" { return "\r"; } + / "\\t" { return "\t"; } + / "\\u" h1:hexDigit h2:hexDigit h3:hexDigit h4:hexDigit { + return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); + } + +line_terminator + = [\n\r] + +literal_numeric + = n:number { + return { type: 'number', value: n }; + } + +number + = int_:int frac:frac exp:exp __ { return parseFloat(int_ + frac + exp); } + / int_:int frac:frac __ { return parseFloat(int_ + frac); } + / int_:int exp:exp __ { return parseFloat(int_ + exp); } + / int_:int __ { return parseFloat(int_); } + +int + = digit19:digit19 digits:digits { return digit19 + digits; } + / digit:digit + / op:("-" / "+" ) digit19:digit19 digits:digits { return "-" + digit19 + digits; } + / op:("-" / "+" ) digit:digit { return "-" + digit; } + +frac + = "." digits:digits { return "." + digits; } + +exp + = e:e digits:digits { return e + digits; } + +digits + = digits:digit+ { return digits.join(""); } + +digit = [0-9] +digit19 = [1-9] + +hexDigit + = [0-9a-fA-F] + +e + = e:[eE] sign:[+-]? { return e + (sign !== null ? sign: ''); } + + +KW_NULL = "NULL"i !ident_start +KW_TRUE = "TRUE"i !ident_start +KW_FALSE = "FALSE"i !ident_start + +KW_SHOW = "SHOW"i !ident_start +KW_DROP = "DROP"i !ident_start +KW_SELECT = "SELECT"i !ident_start +KW_UPDATE = "UPDATE"i !ident_start +KW_CREATE = "CREATE"i !ident_start +KW_DELETE = "DELETE"i !ident_start +KW_INSERT = "INSERT"i !ident_start +KW_RECURSIVE= "RECURSIVE" !ident_start +KW_REPLACE = "REPLACE"i !ident_start +KW_EXPLAIN = "EXPLAIN"i !ident_start + +KW_INTO = "INTO"i !ident_start +KW_FROM = "FROM"i !ident_start +KW_SET = "SET"i !ident_start + +KW_AS = "AS"i !ident_start +KW_TABLE = "TABLE"i !ident_start + +KW_ON = "ON"i !ident_start +KW_LEFT = "LEFT"i !ident_start +KW_RIGHT = "RIGHT"i !ident_start +KW_FULL = "FULL"i !ident_start +KW_INNER = "INNER"i !ident_start +KW_JOIN = "JOIN"i !ident_start +KW_OUTER = "OUTER"i !ident_start +KW_UNION = "UNION"i !ident_start +KW_VALUES = "VALUES"i !ident_start +KW_USING = "USING"i !ident_start + +KW_WHERE = "WHERE"i !ident_start +KW_WITH = "WITH"i !ident_start + +KW_GROUP = "GROUP"i !ident_start +KW_BY = "BY"i !ident_start +KW_ORDER = "ORDER"i !ident_start +KW_HAVING = "HAVING"i !ident_start + +KW_LIMIT = "LIMIT"i !ident_start + +KW_ASC = "ASC"i !ident_start { return 'ASC'; } +KW_DESC = "DESC"i !ident_start { return 'DESC'; } + +KW_ALL = "ALL"i !ident_start { return 'ALL'; } +KW_DISTINCT = "DISTINCT"i !ident_start { return 'DISTINCT';} + +KW_BETWEEN = "BETWEEN"i !ident_start { return 'BETWEEN'; } +KW_IN = "IN"i !ident_start { return 'IN'; } +KW_IS = "IS"i !ident_start { return 'IS'; } +KW_LIKE = "LIKE"i !ident_start { return 'LIKE'; } +KW_EXISTS = "EXISTS"i !ident_start { return 'EXISTS'; } + +KW_NOT = "NOT"i !ident_start { return 'NOT'; } +KW_AND = "AND"i !ident_start { return 'AND'; } +KW_OR = "OR"i !ident_start { return 'OR'; } + +KW_COUNT = "COUNT"i !ident_start { return 'COUNT'; } +KW_MAX = "MAX"i !ident_start { return 'MAX'; } +KW_MIN = "MIN"i !ident_start { return 'MIN'; } +KW_SUM = "SUM"i !ident_start { return 'SUM'; } +KW_AVG = "AVG"i !ident_start { return 'AVG'; } + +KW_CASE = "CASE"i !ident_start +KW_WHEN = "WHEN"i !ident_start +KW_THEN = "THEN"i !ident_start +KW_ELSE = "ELSE"i !ident_start +KW_END = "END"i !ident_start + +KW_CAST = "CAST"i !ident_start + +KW_CHAR = "CHAR"i !ident_start { return 'CHAR'; } +KW_VARCHAR = "VARCHAR"i !ident_start { return 'VARCHAR';} +KW_NUMERIC = "NUMERIC"i !ident_start { return 'NUMERIC'; } +KW_DECIMAL = "DECIMAL"i !ident_start { return 'DECIMAL'; } +KW_SIGNED = "SIGNED"i !ident_start { return 'SIGNED'; } +KW_UNSIGNED = "UNSIGNED"i !ident_start { return 'UNSIGNED'; } +KW_INT = "INT"i !ident_start { return 'INT'; } +KW_INTEGER = "INTEGER"i !ident_start { return 'INTEGER'; } +KW_JSON = "JSON"i !ident_start { return 'JSON'; } +KW_SMALLINT = "SMALLINT"i !ident_start { return 'SMALLINT'; } +KW_DATE = "DATE"i !ident_start { return 'DATE'; } +KW_TIME = "TIME"i !ident_start { return 'TIME'; } +KW_TIMESTAMP= "TIMESTAMP"i!ident_start { return 'TIMESTAMP'; } +KW_USER = "USER"i !ident_start { return 'USER'; } + +KW_CURRENT_DATE = "CURRENT_DATE"i !ident_start { return 'CURRENT_DATE'; } +KW_ADD_DATE = "ADDDATE"i !ident_start { return 'ADDDATE'; } +KW_INTERVAL = "INTERVAL"i !ident_start { return 'INTERVAL'; } +KW_UNIT_YEAR = "YEAR"i !ident_start { return 'YEAR'; } +KW_UNIT_MONTH = "MONTH"i !ident_start { return 'MONTH'; } +KW_UNIT_DAY = "DAY"i !ident_start { return 'DAY'; } +KW_UNIT_HOUR = "HOUR"i !ident_start { return 'HOUR'; } +KW_UNIT_MINUTE = "MINUTE"i !ident_start { return 'MINUTE'; } +KW_UNIT_SECOND = "SECOND"i !ident_start { return 'SECOND'; } +KW_CURRENT_TIME = "CURRENT_TIME"i !ident_start { return 'CURRENT_TIME'; } +KW_CURRENT_TIMESTAMP= "CURRENT_TIMESTAMP"i !ident_start { return 'CURRENT_TIMESTAMP'; } +KW_CURRENT_USER = "CURRENT_USER"i !ident_start { return 'CURRENT_USER'; } +KW_SESSION_USER = "SESSION_USER"i !ident_start { return 'SESSION_USER'; } +KW_SYSTEM_USER = "SYSTEM_USER"i !ident_start { return 'SYSTEM_USER'; } + +KW_VAR_PRE = '$' +KW_RETURN = 'return'i +KW_ASSIGN = ':=' + +KW_DUAL = "DUAL"i + +// MySQL extensions to SQL +OPT_SQL_CALC_FOUND_ROWS = "SQL_CALC_FOUND_ROWS"i +OPT_SQL_CACHE = "SQL_CACHE"i +OPT_SQL_NO_CACHE = "SQL_NO_CACHE"i +OPT_SQL_SMALL_RESULT = "SQL_SMALL_RESULT"i +OPT_SQL_BIG_RESULT = "SQL_BIG_RESULT"i +OPT_SQL_BUFFER_RESULT = "SQL_BUFFER_RESULT"i + +//special character +DOT = '.' +COMMA = ',' +STAR = '*' +LPAREN = '(' +RPAREN = ')' + +LBRAKE = '[' +RBRAKE = ']' + +SEMICOLON = ';' + +// separator +__ + = (whitespace / comment)* + +comment + = block_comment + / line_comment + +block_comment + = "/*" (!"*/" char)* "*/" + +line_comment + = "--" (!EOL char)* + +char = . + +interval_unit + = KW_UNIT_YEAR + / KW_UNIT_MONTH + / KW_UNIT_DAY + / KW_UNIT_HOUR + / KW_UNIT_MINUTE + / KW_UNIT_SECOND + +whitespace = + [ \t\n\r] + +EOL + = EOF + / [\n\r]+ + +EOF = !. + +//begin procedure extension +proc_stmts + = proc_stmt* + +proc_stmt + = &{ varList = []; return true; } __ s:(assign_stmt / return_stmt) { + return { stmt: s, vars: varList }; + } + +assign_stmt + = va:var_decl __ KW_ASSIGN __ e:proc_expr { + return { + type: 'assign', + left: va, + right: e + }; + } + +return_stmt + = KW_RETURN __ e:proc_expr { + return { type: 'return', expr: e }; + } + +proc_expr + = select_stmt + / proc_join + / proc_additive_expr + / proc_array + +proc_additive_expr + = head:proc_multiplicative_expr + tail:(__ additive_operator __ proc_multiplicative_expr)* { + return createBinaryExprChain(head, tail); + } + +proc_multiplicative_expr + = head:proc_primary + tail:(__ multiplicative_operator __ proc_primary)* { + return createBinaryExprChain(head, tail); + } + +proc_join + = lt:var_decl __ op:join_op __ rt:var_decl __ expr:on_clause { + return { + type: 'join', + ltable: lt, + rtable: rt, + op: op, + on: expr + }; + } + +proc_primary + = literal + / var_decl + / proc_func_call + / param + / LPAREN __ e:proc_additive_expr __ RPAREN { + e.parentheses = true; + return e; + } + +proc_func_call + = name:ident __ LPAREN __ l:proc_primary_list __ RPAREN { + //compatible with original func_call + return { + type: 'function', + name: name, + args: { + type: 'expr_list', + value: l + } + }; + } + +proc_primary_list + = head:proc_primary tail:(__ COMMA __ proc_primary)* { + return createList(head, tail); + } + +proc_array = + LBRAKE __ l:proc_primary_list __ RBRAKE { + return { type: 'array', value: l }; + } + +var_decl + = KW_VAR_PRE name:ident_name m:mem_chain { + //push for analysis + varList.push(name); + return { + type: 'var', + name: name, + members: m + }; + } + +mem_chain + = l:('.' ident_name)* { + const s = []; + for (let i = 0; i < l.length; i++) { + s.push(l[i][1]); + } + return s; + } + +data_type + = character_string_type + / numeric_type + / datetime_type + / json_type + +character_string_type + = t:(KW_CHAR / KW_VARCHAR) __ LPAREN __ l:[0-9]+ __ RPAREN __ { + return { dataType: t, length: parseInt(l.join(''), 10) }; + } + / t:KW_CHAR { return { dataType: t }; } + / t:KW_VARCHAR { return { dataType: t }; } + +numeric_type + = t:(KW_NUMERIC / KW_DECIMAL / KW_INT / KW_INTEGER / KW_SMALLINT) { return { dataType: t }; } + +datetime_type + = t:(KW_DATE / KW_TIME / KW_TIMESTAMP) { return { dataType: t }; } + +json_type + = t:KW_JSON { return { dataType: t }; } diff --git a/packages/core/database/src/view-collection.ts b/packages/core/database/src/view-collection.ts new file mode 100644 index 000000000..ff8f9eafd --- /dev/null +++ b/packages/core/database/src/view-collection.ts @@ -0,0 +1,20 @@ +import { Collection, CollectionContext, CollectionOptions } from './collection'; + +export class ViewCollection extends Collection { + constructor(options: CollectionOptions, context: CollectionContext) { + options.autoGenId = false; + options.timestamps = false; + + super(options, context); + } + + protected sequelizeModelOptions(): any { + const modelOptions = super.sequelizeModelOptions(); + modelOptions.tableName = this.options.viewName || this.options.name; + return modelOptions; + } + + isView() { + return true; + } +} diff --git a/packages/core/database/src/view/field-type-map.ts b/packages/core/database/src/view/field-type-map.ts new file mode 100644 index 000000000..b9ab6b6ac --- /dev/null +++ b/packages/core/database/src/view/field-type-map.ts @@ -0,0 +1,56 @@ +const postgres = { + 'character varying': 'string', + varchar: 'string', + text: 'text', + char: 'string', + + smallint: 'integer', + integer: 'integer', + bigint: 'bigInt', + decimal: 'float', + numeric: 'float', + 'double precision': 'float', + + 'timestamp without time zone': 'date', + 'timestamp with time zone': 'date', + date: 'date', + boolean: 'boolean', + + json: ['json', 'array'], + jsonb: ['jsonb', 'array'], +}; + +const mysql = { + varchar: 'string', + text: 'text', + int: 'integer', + integer: 'integer', + bigint: 'bigInt', + float: 'float', + double: 'float', + boolean: 'boolean', + + tinyint: 'integer', + datetime: 'date', + timestamp: 'date', + json: ['json', 'array'], +}; + +const sqlite = { + text: 'text', + varchar: 'string', + + integer: 'integer', + real: 'real', + + datetime: 'date', + date: 'date', + time: 'time', + + boolean: 'boolean', + + numeric: 'decimal', + json: ['json', 'array'], +}; + +export default { postgres, mysql, sqlite }; diff --git a/packages/core/database/src/view/view-inference.ts b/packages/core/database/src/view/view-inference.ts new file mode 100644 index 000000000..efa08c19e --- /dev/null +++ b/packages/core/database/src/view/view-inference.ts @@ -0,0 +1,106 @@ +import Database from '../database'; +import FieldTypeMap from './field-type-map'; +import { isArray } from 'mathjs'; + +type InferredField = { + name: string; + type: string; + source?: string; +}; + +type InferredFieldResult = { + [key: string]: InferredField; +}; + +export class ViewFieldInference { + static async inferFields(options: { + db: Database; + viewName: string; + viewSchema?: string; + }): Promise { + const { db } = options; + if (!db.inDialect('postgres')) { + options.viewSchema = undefined; + } + + const columns = await db.sequelize.getQueryInterface().describeTable(options.viewName, options.viewSchema); + + const columnUsage = await db.queryInterface.viewColumnUsage({ + viewName: options.viewName, + schema: options.viewSchema, + }); + + // @ts-ignore + return Object.fromEntries( + Object.entries(columns).map(([name, column]) => { + const usage = columnUsage.find((item) => item.column_name === name); + + if (usage) { + const collectionField = (() => { + const tableName = `${usage.table_schema ? `${usage.table_schema}.` : ''}${usage.table_name}`; + const collection = db.tableNameCollectionMap.get(tableName); + if (!collection) return false; + + const fieldValue = Object.values(collection.model.rawAttributes).find( + (field) => field.field === usage.column_name, + ); + + if (!fieldValue) { + return false; + } + + // @ts-ignore + const fieldName = fieldValue?.fieldName; + + return collection.getField(fieldName); + })(); + + if (collectionField && collectionField.options.interface) { + return [ + name, + { + name, + type: collectionField.type, + source: `${collectionField.collection.name}.${collectionField.name}`, + }, + ]; + } + } + + return [ + name, + { + name, + ...this.inferToFieldType({ db, name, type: column.type }), + }, + ]; + }), + ); + } + + static inferToFieldType(options: { db: Database; name: string; type: string }) { + const { db } = options; + const dialect = db.sequelize.getDialect(); + const fieldTypeMap = FieldTypeMap[dialect]; + + if (!options.type) { + return { + possibleTypes: Object.keys(fieldTypeMap), + }; + } + + const queryType = options.type.toLowerCase().replace(/\(\d+\)/, ''); + const mappedType = fieldTypeMap[queryType]; + + if (isArray(mappedType)) { + return { + type: mappedType[0], + possibleTypes: mappedType, + }; + } + + return { + type: mappedType, + }; + } +} diff --git a/packages/plugins/acl/src/__tests__/association-field.test.ts b/packages/plugins/acl/src/__tests__/association-field.test.ts index 95c579c81..5a289391c 100644 --- a/packages/plugins/acl/src/__tests__/association-field.test.ts +++ b/packages/plugins/acl/src/__tests__/association-field.test.ts @@ -1,8 +1,8 @@ -import { ACL } from '@nocobase/acl'; -import { Database, HasManyRepository } from '@nocobase/database'; +import {ACL} from '@nocobase/acl'; +import {Database, HasManyRepository} from '@nocobase/database'; import UsersPlugin from '@nocobase/plugin-users'; -import { MockServer } from '@nocobase/test'; -import { prepareApp } from './prepare'; +import {MockServer} from '@nocobase/test'; +import {prepareApp} from './prepare'; describe('association test', () => { let app: MockServer; @@ -36,6 +36,7 @@ describe('association test', () => { context: {}, }); + await db.getRepository('collections').create({ values: { name: 'comments', diff --git a/packages/plugins/collection-manager/src/__tests__/field-options/indexes.test.ts b/packages/plugins/collection-manager/src/__tests__/field-options/indexes.test.ts index f87046628..9cdeef2ea 100644 --- a/packages/plugins/collection-manager/src/__tests__/field-options/indexes.test.ts +++ b/packages/plugins/collection-manager/src/__tests__/field-options/indexes.test.ts @@ -60,6 +60,7 @@ describe('field indexes', () => { it('field value cannot be duplicated with unique index', async () => { const tableName = 'test1'; + // create a field with unique constraint const field = await agent.resource('collections.fields', tableName).create({ values: { diff --git a/packages/plugins/collection-manager/src/__tests__/http-api/view-collection.test.ts b/packages/plugins/collection-manager/src/__tests__/http-api/view-collection.test.ts new file mode 100644 index 000000000..5e7a3c947 --- /dev/null +++ b/packages/plugins/collection-manager/src/__tests__/http-api/view-collection.test.ts @@ -0,0 +1,381 @@ +import { MockServer } from '@nocobase/test'; +import { createApp } from '../index'; +import { uid } from '@nocobase/utils'; + +describe('view collection', () => { + let app: MockServer; + let agent; + let testViewName; + + beforeEach(async () => { + app = await createApp({ + database: { + tablePrefix: '', + }, + }); + agent = app.agent(); + testViewName = `view_${uid(6)}`; + const dropSQL = `DROP VIEW IF EXISTS ${testViewName}`; + await app.db.sequelize.query(dropSQL); + const viewSQL = (() => { + if (app.db.inDialect('sqlite')) { + return `CREATE VIEW ${testViewName} AS WITH RECURSIVE numbers(n) AS ( + SELECT CAST(1 AS INTEGER) + UNION ALL + SELECT CAST(1 + n AS INTEGER) FROM numbers WHERE n < 20 +) +SELECT * FROM numbers; +`; + } + + return `CREATE VIEW ${testViewName} AS WITH RECURSIVE numbers(n) AS ( + SELECT 1 + UNION ALL + SELECT n + 1 FROM numbers WHERE n < 20 +) +SELECT * FROM numbers; +`; + })(); + await app.db.sequelize.query(viewSQL); + }); + + afterEach(async () => { + await app.destroy(); + }); + + it('should list views', async () => { + const response = await agent.resource('dbViews').list(); + expect(response.status).toBe(200); + expect(response.body.data.find((item) => item.name === testViewName)).toBeTruthy(); + }); + + it('should query views data', async () => { + const response = await agent.resource('dbViews').query({ + filterByTk: testViewName, + pageSize: 20, + }); + + expect(response.status).toBe(200); + expect(response.body.data.length).toBe(20); + }); + + it('should list views fields', async () => { + const response = await agent.resource('dbViews').get({ + filterByTk: testViewName, + schema: 'public', + }); + + expect(response.status).toBe(200); + const data = response.body.data; + if (app.db.options.dialect === 'mysql') { + expect(data.fields.n.type).toBe('bigInt'); + } else if (app.db.options.dialect == 'postgres') { + expect(data.fields.n.type).toBe('integer'); + } + + // cannot get field type in sqlite + if (app.db.options.dialect === 'sqlite') { + expect(data.fields.n.possibleTypes).toBeTruthy(); + } + }); + + it('should return possible types for json fields', async () => { + const jsonViewName = 'json_view'; + const dropSql = `DROP VIEW IF EXISTS ${jsonViewName}`; + await app.db.sequelize.query(dropSql); + + const jsonViewSQL = (() => { + if (app.db.inDialect('postgres')) { + return `CREATE VIEW ${jsonViewName} AS SELECT '{"a": 1}'::json as json_field`; + } + return `CREATE VIEW ${jsonViewName} AS SELECT JSON_OBJECT('key1', 1, 'key2', 'abc') as json_field`; + })(); + + await app.db.sequelize.query(jsonViewSQL); + + const response = await agent.resource('dbViews').get({ + filterByTk: jsonViewName, + schema: app.db.inDialect('postgres') ? 'public' : undefined, + }); + + expect(response.status).toBe(200); + const data = response.body.data; + if (!app.db.inDialect('sqlite')) { + expect(data.fields.json_field.type).toBe('json'); + } + expect(data.fields.json_field.possibleTypes).toBeTruthy(); + }); + + it('should list collections fields with source interface', async () => { + await app.db.getCollection('collections').repository.create({ + values: { + name: 'users', + fields: [ + { + name: 'name', + type: 'string', + interface: 'text', + uiSchema: 'name-uiSchema', + }, + { + name: 'age', + type: 'integer', + interface: 'number', + uiSchema: 'age-uiSchema', + }, + ], + }, + context: {}, + }); + + await app.db.sync(); + const UserCollection = app.db.getCollection('users'); + + const viewName = `t_${uid(6)}`; + const dropSQL = `DROP VIEW IF EXISTS ${viewName}`; + await app.db.sequelize.query(dropSQL); + const viewSQL = `CREATE VIEW ${viewName} AS SELECT * FROM ${UserCollection.quotedTableName()}`; + await app.db.sequelize.query(viewSQL); + + // create view collection + const viewCollection = await app.db.getCollection('collections').repository.create({ + values: { + name: viewName, + view: true, + schema: app.db.inDialect('postgres') ? 'public' : undefined, + fields: [ + { + name: 'name', + type: 'string', + source: 'users.name', + }, + { + name: 'age', + type: 'integer', + source: 'users.age', + }, + ], + }, + context: {}, + }); + + const response = await agent.resource('collections').list({ + appends: ['fields'], + paginate: false, + }); + + const listResult = response.body.data.find((item) => item.name === viewName); + + const fields = listResult.fields; + + const nameField = fields.find((item) => item.name === 'name'); + expect(nameField.interface).toBe('text'); + expect(nameField.uiSchema).toBe('name-uiSchema'); + + const viewFieldsResponse = await agent.resource('collections.fields', viewName).list({ + filter: { + $or: { + 'interface.$not': null, + 'options.source.$notEmpty': true, + }, + }, + }); + + expect(viewFieldsResponse.status).toEqual(200); + const viewFieldsData = viewFieldsResponse.body.data; + expect(viewFieldsData.length).toEqual(2); + + expect(viewFieldsData.find((item) => item.name === 'name').interface).toEqual('text'); + + const fieldDetailResponse = await agent.resource('collections.fields', viewName).get({ + filterByTk: 'name', + }); + + const fieldDetailData = fieldDetailResponse.body.data; + expect(fieldDetailData.interface).toEqual('text'); + + UserCollection.addField('email', { type: 'string' }); + + await app.db.sync(); + + // update view in database + await app.db.sequelize.query(dropSQL); + const viewSQL2 = `CREATE VIEW ${viewName} AS SELECT * FROM ${UserCollection.quotedTableName()}`; + await app.db.sequelize.query(viewSQL2); + + const viewDetailResponse = await agent.resource('dbViews').get({ + filterByTk: viewName, + schema: 'public', + }); + + const viewDetail = viewDetailResponse.body.data; + const viewFields = viewDetail.fields; + + const updateFieldsResponse = await agent.resource('collections').setFields({ + filterByTk: viewName, + values: { + fields: Object.values(viewFields), + }, + }); + + expect(updateFieldsResponse.status).toEqual(200); + + const viewCollectionWithEmail = app.db.getCollection(viewName); + expect(viewCollectionWithEmail.getField('email')).toBeTruthy(); + }); + + it('should access view collection resource', async () => { + const UserCollection = app.db.collection({ + name: 'users', + fields: [ + { + name: 'name', + type: 'string', + }, + ], + }); + + await app.db.sync(); + + await UserCollection.repository.create({ + values: { + name: 'John', + }, + }); + + // create view + const viewName = `t_${uid(6)}`; + const dropSQL = `DROP VIEW IF EXISTS ${viewName}`; + await app.db.sequelize.query(dropSQL); + const viewSQL = `CREATE VIEW ${viewName} AS SELECT * FROM ${UserCollection.quotedTableName()}`; + await app.db.sequelize.query(viewSQL); + + // create view collection + await app.db.getCollection('collections').repository.create({ + values: { + name: viewName, + view: true, + schema: app.db.inDialect('postgres') ? 'public' : undefined, + fields: [ + { + name: 'id', + type: 'integer', + }, + { + name: 'name', + type: 'string', + }, + ], + }, + context: {}, + }); + + const viewCollection = app.db.getCollection(viewName); + + // access view collection list + const listResponse = await agent.resource(viewCollection.name).list({}); + expect(listResponse.status).toEqual(200); + + const item = listResponse.body.data[0]; + + // access detail + const detailResponse = await agent.resource(viewCollection.name).get({ + filterByTk: item['id'], + }); + + expect(detailResponse.status).toEqual(200); + }); + + it('should get view in difference schema', async () => { + if (!app.db.inDialect('postgres')) return; + + const schemaName = `t_${uid(6)}`; + const testSchemaSql = `CREATE SCHEMA IF NOT EXISTS ${schemaName};`; + await app.db.sequelize.query(testSchemaSql); + + const viewName = `v_${uid(6)}`; + + const viewSQL = `CREATE OR REPLACE VIEW ${schemaName}.${viewName} AS SELECT 1+1 as result`; + await app.db.sequelize.query(viewSQL); + + const response = await agent.resource('dbViews').query({ + filterByTk: viewName, + schema: schemaName, + pageSize: 20, + }); + + expect(response.status).toEqual(200); + }); + + it('should edit uiSchema in view collection field', async () => { + await app.db.getCollection('collections').repository.create({ + values: { + name: 'users', + fields: [ + { + name: 'name', + type: 'string', + uiSchema: { + title: 'hello', + }, + }, + ], + }, + context: {}, + }); + + await app.db.sync(); + + const UserCollection = app.db.getCollection('users'); + + // create view + const viewName = `t_${uid(6)}`; + const dropSQL = `DROP VIEW IF EXISTS ${viewName}`; + await app.db.sequelize.query(dropSQL); + const viewSQL = `CREATE VIEW ${viewName} AS SELECT * FROM ${UserCollection.quotedTableName()}`; + await app.db.sequelize.query(viewSQL); + + // create view collection + await app.db.getCollection('collections').repository.create({ + values: { + name: viewName, + view: true, + schema: 'public', + fields: [ + { + name: 'id', + type: 'integer', + }, + { + name: 'name', + type: 'string', + source: 'users.name', + }, + ], + }, + context: {}, + }); + + await app.db.getCollection('fields').repository.update({ + filter: { + name: 'name', + collectionName: viewName, + }, + + values: { + uiSchema: { + title: 'bars', + }, + }, + context: {}, + }); + + const viewCollection = app.db.getCollection(viewName); + + expect(viewCollection.getField('name').options.uiSchema.title).toEqual('bars'); + + const viewFieldsResponse = await agent.resource('collections.fields', viewName).list({}); + const nameField = viewFieldsResponse.body.data.find((item) => item.name === 'name'); + expect(nameField.uiSchema.title).toEqual('bars'); + }); +}); diff --git a/packages/plugins/collection-manager/src/__tests__/view/view-collection.test.ts b/packages/plugins/collection-manager/src/__tests__/view/view-collection.test.ts new file mode 100644 index 000000000..73c841093 --- /dev/null +++ b/packages/plugins/collection-manager/src/__tests__/view/view-collection.test.ts @@ -0,0 +1,122 @@ +import Database, { Repository, ViewCollection } from '@nocobase/database'; +import Application from '@nocobase/server'; +import { createApp } from '../index'; + +describe('view collection', function () { + let db: Database; + let app: Application; + + let collectionRepository: Repository; + + let fieldsRepository: Repository; + + beforeEach(async () => { + app = await createApp({ + database: { + tablePrefix: '', + }, + }); + + db = app.db; + + collectionRepository = db.getCollection('collections').repository; + fieldsRepository = db.getCollection('fields').repository; + }); + + afterEach(async () => { + await app.destroy(); + }); + + it('should support view with dot field', async () => { + const dropViewSQL = `DROP VIEW IF EXISTS test_view`; + await db.sequelize.query(dropViewSQL); + const viewSQL = `CREATE VIEW test_view AS select 1+1 as "dot.results"`; + await db.sequelize.query(viewSQL); + + await collectionRepository.create({ + values: { + name: 'view_collection', + viewName: 'test_view', + fields: [{ type: 'string', name: 'dot_result', field: 'dot.results' }], + schema: db.inDialect('postgres') ? 'public' : undefined, + }, + context: {}, + }); + + const viewCollection = db.getCollection('view_collection'); + + const results = await viewCollection.repository.find(); + expect(results.length).toBe(1); + }); + + it('should create view collection by view name', async () => { + const dropViewSQL = `DROP VIEW IF EXISTS test_view`; + await db.sequelize.query(dropViewSQL); + const viewSQL = `CREATE VIEW test_view AS select 1+1 as result`; + await db.sequelize.query(viewSQL); + + await collectionRepository.create({ + values: { + name: 'view_collection', + viewName: 'test_view', + fields: [{ type: 'string', name: 'result' }], + schema: db.inDialect('postgres') ? 'public' : undefined, + }, + context: {}, + }); + + const viewCollection = db.getCollection('view_collection'); + expect(viewCollection).toBeInstanceOf(ViewCollection); + + const results = await viewCollection.repository.find(); + expect(results.length).toBe(1); + }); + + it('should destroy collection view', async () => { + const dropViewSQL = `DROP VIEW IF EXISTS test_view`; + await db.sequelize.query(dropViewSQL); + const viewSQL = `CREATE VIEW test_view AS select 1+1 as result`; + await db.sequelize.query(viewSQL); + + await collectionRepository.create({ + values: { + name: 'view_collection', + viewName: 'test_view', + fields: [{ type: 'string', name: 'result' }], + }, + context: {}, + }); + + expect( + await fieldsRepository.findOne({ + filter: { + collectionName: 'view_collection', + name: 'result', + }, + }), + ).toBeTruthy(); + + await fieldsRepository.destroy({ + filter: { + collectionName: 'view_collection', + name: 'result', + }, + context: {}, + }); + + expect( + await fieldsRepository.findOne({ + filter: { + collectionName: 'view_collection', + name: 'result', + }, + }), + ).toBeFalsy(); + + await collectionRepository.destroy({ + filterByTk: 'view_collection', + }); + + expect(db.getCollection('view_collection')).toBeUndefined(); + }); +}); diff --git a/packages/plugins/collection-manager/src/hooks/beforeCreateForViewCollection.ts b/packages/plugins/collection-manager/src/hooks/beforeCreateForViewCollection.ts new file mode 100644 index 000000000..d44ea868e --- /dev/null +++ b/packages/plugins/collection-manager/src/hooks/beforeCreateForViewCollection.ts @@ -0,0 +1,16 @@ +import { Database } from '@nocobase/database'; + +export function beforeCreateForViewCollection(db: Database) { + return async (model, { transaction, context }) => { + if (model.get('viewSQL')) { + const name = model.get('name'); + const sql = model.get('viewSQL'); + + await db.sequelize.query(`CREATE OR REPLACE VIEW "${name}" AS ${sql}`, { + transaction, + }); + + model.set('viewName', name); + } + }; +} diff --git a/packages/plugins/collection-manager/src/resourcers/collections.ts b/packages/plugins/collection-manager/src/resourcers/collections.ts new file mode 100644 index 000000000..258241af2 --- /dev/null +++ b/packages/plugins/collection-manager/src/resourcers/collections.ts @@ -0,0 +1,32 @@ +import { Database } from '@nocobase/database'; + +export default { + async ['collections:setFields'](ctx, next) { + const { filterByTk, values } = ctx.action.params; + + // WARN: 删掉 key 才能保存 + const fields = values.fields?.map(f => { + delete f.key; + return f; + }); + + const db = ctx.app.db as Database; + + const collection = await db.getRepository('collections').findOne({ + filter: { + name: filterByTk, + }, + }); + + await db.getRepository('collections').update({ + filterByTk, + values: { + fields, + }, + }); + + await collection.loadFields(); + + await next(); + }, +}; diff --git a/packages/plugins/collection-manager/src/resourcers/views.ts b/packages/plugins/collection-manager/src/resourcers/views.ts new file mode 100644 index 000000000..7676362aa --- /dev/null +++ b/packages/plugins/collection-manager/src/resourcers/views.ts @@ -0,0 +1,55 @@ +import { Database, ViewFieldInference } from '@nocobase/database'; + +export default { + name: 'dbViews', + actions: { + async get(ctx, next) { + const { filterByTk, schema } = ctx.action.params; + const db = ctx.app.db as Database; + + const fields = await ViewFieldInference.inferFields({ + db, + viewName: filterByTk, + viewSchema: schema, + }); + + ctx.body = { + fields, + sources: [ + ...new Set( + Object.values(fields) + .map((field) => field.source) + .filter(Boolean) + .map((source) => source.split('.')[0]), + ), + ], + }; + + await next(); + }, + async list(ctx, next) { + const db = ctx.app.db as Database; + const dbViews = await db.queryInterface.listViews(); + ctx.body = dbViews.map((dbView) => { + return { + ...dbView, + }; + }); + + await next(); + }, + + async query(ctx, next) { + const { filterByTk, schema = 'public', page = 1, pageSize = 10 } = ctx.action.params; + + const offset = (page - 1) * pageSize; + const limit = 1 * pageSize; + + const sql = `SELECT * + FROM ${ctx.app.db.utils.quoteTable(ctx.app.db.utils.addSchema(filterByTk, schema))} LIMIT ${limit} OFFSET ${offset}`; + + ctx.body = await ctx.app.db.sequelize.query(sql, { type: 'SELECT' }); + await next(); + }, + }, +}; diff --git a/packages/plugins/collection-manager/src/server.ts b/packages/plugins/collection-manager/src/server.ts index f989ab999..7d639b4ca 100644 --- a/packages/plugins/collection-manager/src/server.ts +++ b/packages/plugins/collection-manager/src/server.ts @@ -15,9 +15,13 @@ import { } from './hooks'; import { InheritedCollection } from '@nocobase/database'; -import lodash from 'lodash'; +import lodash, { castArray } from 'lodash'; import * as process from 'process'; import { CollectionModel, FieldModel } from './models'; +import collectionActions from './resourcers/collections'; +import viewResourcer from './resourcers/views'; + +import { beforeCreateForViewCollection } from './hooks/beforeCreateForViewCollection'; export class CollectionManagerPlugin extends Plugin { public schema: string; @@ -46,19 +50,17 @@ export class CollectionManagerPlugin extends Plugin { this.app.acl.registerSnippet({ name: `pm.${this.name}.collections`, - actions: [ - 'collections:*', - // 'fields:*', - 'collections.fields:*', - ], + actions: ['collections:*', 'collections.fields:*', 'dbViews:*'], }); this.app.db.on('collections.beforeCreate', async (model) => { - if (this.app.db.inDialect('postgres') && this.schema && model.get('from') != 'db2cm') { + if (this.app.db.inDialect('postgres') && this.schema && model.get('from') != 'db2cm' && !model.get('schema')) { model.set('schema', this.schema); } }); + this.app.db.on('collections.beforeCreate', beforeCreateForViewCollection(this.db)); + this.app.db.on( 'collections.afterCreateWithAssociations', async (model: CollectionModel, { context, transaction }) => { @@ -90,6 +92,13 @@ export class CollectionManagerPlugin extends Plugin { } }); + this.app.db.on('fields.beforeValidate', async (model) => { + if (model.get('name') && model.get('name').includes('.')) { + model.set('field', model.get('name')); + model.set('name', model.get('name').replace(/\./g, '_')); + } + }); + this.app.db.on('fields.beforeCreate', async (model, options) => { const type = model.get('type'); const fn = beforeInitOptions[type]; @@ -261,6 +270,55 @@ export class CollectionManagerPlugin extends Plugin { await next(); }); + this.app.resource(viewResourcer); + this.app.actions(collectionActions); + + const handleFieldSource = (fields) => { + for (const field of castArray(fields)) { + if (field.get('source')) { + const [collectionSource, fieldSource] = field.get('source').split('.'); + const collectionField = this.app.db.getCollection(collectionSource).getField(fieldSource); + + const newOptions = {}; + lodash.merge(newOptions, collectionField.options); + lodash.mergeWith(newOptions, field.get(), (objValue, srcValue) => { + if (srcValue === null) { + return objValue; + } + }); + + field.set('options', newOptions); + } + } + }; + + this.app.resourcer.use(async (ctx, next) => { + await next(); + + // handle collections:list + if ( + ctx.action.resourceName === 'collections' && + ctx.action.actionName == 'list' && + ctx.action.params?.paginate == 'false' + ) { + for (const collection of ctx.body) { + if (collection.get('view')) { + const fields = collection.fields; + handleFieldSource(fields); + } + } + } + + //handle collections:fields:list + if (ctx.action.resourceName == 'collections.fields' && ctx.action.actionName == 'list') { + handleFieldSource(ctx.action.params?.paginate == 'false' ? ctx.body : ctx.body.rows); + } + + if (ctx.action.resourceName == 'collections.fields' && ctx.action.actionName == 'get') { + handleFieldSource(ctx.body); + } + }); + this.app.db.extendCollection({ name: 'collectionCategory', namespace: 'collection-manager', diff --git a/packages/plugins/duplicator/src/server/__tests__/dump-action.test.ts b/packages/plugins/duplicator/src/server/__tests__/dump-action.test.ts index 1f141fcbe..eace87249 100644 --- a/packages/plugins/duplicator/src/server/__tests__/dump-action.test.ts +++ b/packages/plugins/duplicator/src/server/__tests__/dump-action.test.ts @@ -1,8 +1,7 @@ import { mockServer, MockServer } from '@nocobase/test'; -import { Database, Model } from '@nocobase/database'; +import { Database } from '@nocobase/database'; import * as os from 'os'; import path from 'path'; -import lodash from 'lodash'; import fsPromises from 'fs/promises'; import { Dumper } from '../dumper'; import { readLines } from '../utils'; diff --git a/packages/plugins/duplicator/src/server/dumper.ts b/packages/plugins/duplicator/src/server/dumper.ts index 5b7925c61..a7018fe1a 100644 --- a/packages/plugins/duplicator/src/server/dumper.ts +++ b/packages/plugins/duplicator/src/server/dumper.ts @@ -147,17 +147,22 @@ export class Dumper extends AppMigrator { // get user defined views in postgres const views = await db.sequelize.query( - `SELECT table_schema, table_name, pg_get_viewdef("table_name", true) as def - FROM information_schema.views - WHERE table_schema NOT IN ('information_schema', 'pg_catalog') - ORDER BY table_schema, table_name`, + `SELECT n.nspname AS schema_name, + v.viewname AS view_name, + v.definition AS view_definition + FROM pg_views v + JOIN + pg_namespace n ON v.schemaname = n.nspname + WHERE n.nspname NOT IN ('information_schema', 'pg_catalog') + ORDER BY schema_name, + view_name;`, { type: 'SELECT', }, ); for (const v of views) { - sqlContent.push(`CREATE OR REPLACE VIEW ${v['table_name']} AS ${v['def']}`); + sqlContent.push(`CREATE OR REPLACE VIEW ${v['view_name']} AS ${v['view_definition']}`); } } diff --git a/packages/plugins/import/src/client/ImportInitializerProvider.tsx b/packages/plugins/import/src/client/ImportInitializerProvider.tsx index f9990db99..7728cfddd 100644 --- a/packages/plugins/import/src/client/ImportInitializerProvider.tsx +++ b/packages/plugins/import/src/client/ImportInitializerProvider.tsx @@ -1,4 +1,4 @@ -import { SchemaInitializerContext } from '@nocobase/client'; +import { SchemaInitializerContext, useCollection } from '@nocobase/client'; import { useContext } from 'react'; export const ImportInitializerProvider = (props: any) => { @@ -18,6 +18,10 @@ export const ImportInitializerProvider = (props: any) => { skipScopeCheck: true, }, }, + visible: () => { + const collection = useCollection(); + return (collection as any).template !== 'view'; + }, }); return props.children; };