From f7ba2b9abe6e1688379ecf0ca9dd17b5f991ae14 Mon Sep 17 00:00:00 2001 From: taozhi8833998 Date: Fri, 12 Jul 2024 09:21:21 +0800 Subject: [PATCH] feat: support data type array in pg --- pegjs/noql.pegjs | 10 +++++++--- pegjs/postgresql.pegjs | 11 ++++++++--- pegjs/redshift.pegjs | 10 +++++++--- pegjs/snowflake.pegjs | 10 +++++++--- pegjs/trino.pegjs | 10 +++++++--- src/column.js | 8 +++++++- src/func.js | 15 ++++++++++----- test/postgres.spec.js | 7 +++++++ 8 files changed, 60 insertions(+), 21 deletions(-) diff --git a/pegjs/noql.pegjs b/pegjs/noql.pegjs index 410c41f0..a574218a 100644 --- a/pegjs/noql.pegjs +++ b/pegjs/noql.pegjs @@ -5254,11 +5254,15 @@ data_type array_type = t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE __ LBRAKE __ RBRAKE { /* => data_type */ - return { ...t, array: 'two' } + return { ...t, array: { dimension: 2 } } } - / t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE { + / t:(numeric_type / character_string_type) __ LBRAKE __ l:literal_numeric? __ RBRAKE { /* => data_type */ - return { ...t, array: 'one' } + return { ...t, array: { dimension: 1, length: [l] } } + } + / t:(numeric_type / character_string_type) __ KW_ARRAY { + /* => data_type */ + return { ...t, array: { keyword: 'array' } } } boolean_type diff --git a/pegjs/postgresql.pegjs b/pegjs/postgresql.pegjs index 3ab9cceb..f1d8ba7d 100644 --- a/pegjs/postgresql.pegjs +++ b/pegjs/postgresql.pegjs @@ -5528,12 +5528,17 @@ data_type array_type = t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE __ LBRAKE __ RBRAKE { /* => data_type */ - return { ...t, array: 'two' } + return { ...t, array: { dimension: 2 } } } - / t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE { + / t:(numeric_type / character_string_type) __ LBRAKE __ l:literal_numeric? __ RBRAKE { /* => data_type */ - return { ...t, array: 'one' } + return { ...t, array: { dimension: 1, length: [l] } } } + / t:(numeric_type / character_string_type) __ KW_ARRAY { + /* => data_type */ + return { ...t, array: { keyword: 'array' } } + } + boolean_type = t:(KW_BOOL / KW_BOOLEAN) { /* => data_type */ return { dataType: t }} diff --git a/pegjs/redshift.pegjs b/pegjs/redshift.pegjs index 53861bac..6ad2cfd8 100644 --- a/pegjs/redshift.pegjs +++ b/pegjs/redshift.pegjs @@ -5329,11 +5329,15 @@ data_type array_type = t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE __ LBRAKE __ RBRAKE { /* => data_type */ - return { ...t, array: 'two' } + return { ...t, array: { dimension: 2 } } } - / t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE { + / t:(numeric_type / character_string_type) __ LBRAKE __ l:literal_numeric? __ RBRAKE { /* => data_type */ - return { ...t, array: 'one' } + return { ...t, array: { dimension: 1, length: [l] } } + } + / t:(numeric_type / character_string_type) __ KW_ARRAY { + /* => data_type */ + return { ...t, array: { keyword: 'array' } } } boolean_type diff --git a/pegjs/snowflake.pegjs b/pegjs/snowflake.pegjs index 1260e2a3..ff33aee4 100644 --- a/pegjs/snowflake.pegjs +++ b/pegjs/snowflake.pegjs @@ -4778,11 +4778,15 @@ data_type array_type = t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE __ LBRAKE __ RBRAKE { /* => data_type */ - return { ...t, array: 'two' } + return { ...t, array: { dimension: 2 } } } - / t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE { + / t:(numeric_type / character_string_type) __ LBRAKE __ l:literal_numeric? __ RBRAKE { /* => data_type */ - return { ...t, array: 'one' } + return { ...t, array: { dimension: 1, length: [l] } } + } + / t:(numeric_type / character_string_type) __ KW_ARRAY { + /* => data_type */ + return { ...t, array: { keyword: 'array' } } } boolean_type diff --git a/pegjs/trino.pegjs b/pegjs/trino.pegjs index 532b47cf..ffc8d6c4 100644 --- a/pegjs/trino.pegjs +++ b/pegjs/trino.pegjs @@ -4779,11 +4779,15 @@ data_type array_type = t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE __ LBRAKE __ RBRAKE { /* => data_type */ - return { ...t, array: 'two' } + return { ...t, array: { dimension: 2 } } } - / t:(numeric_type / character_string_type) __ LBRAKE __ RBRAKE { + / t:(numeric_type / character_string_type) __ LBRAKE __ l:literal_numeric? __ RBRAKE { /* => data_type */ - return { ...t, array: 'one' } + return { ...t, array: { dimension: 1, length: [l] } } + } + / t:(numeric_type / character_string_type) __ KW_ARRAY { + /* => data_type */ + return { ...t, array: { keyword: 'array' } } } boolean_type diff --git a/src/column.js b/src/column.js index 016c9fb1..dfbfbcae 100644 --- a/src/column.js +++ b/src/column.js @@ -1,6 +1,6 @@ import { constraintDefinitionToSQL } from './constrain' import { exprToSQL } from './expr' -import { castToSQL } from './func' +import { arrayDimensionToSymbol, castToSQL } from './func' import { tablesToSQL } from './tables' import { autoIncrementToSQL, @@ -61,11 +61,17 @@ function columnRefToSQL(expr) { } function columnDataType(definition) { + if (!definition) return const { dataType, length, suffix, scale, expr } = definition || {} let result = dataType if (length != null) result += `(${[length, scale].filter(val => val != null).join(', ')})` if (suffix && suffix.length) result += ` ${suffix.join(' ')}` if (expr) result += exprToSQL(expr) + if (definition.array) { + const arrayExpr = arrayDimensionToSymbol(definition) + const space = /^\[.*\]$/.test(arrayExpr) ? '' : ' ' + result += [space, arrayExpr].join('') + } return result } diff --git a/src/func.js b/src/func.js index 8f7a6011..0e412b16 100644 --- a/src/func.js +++ b/src/func.js @@ -15,12 +15,16 @@ function anyValueFuncToSQL(stmt) { function arrayDimensionToSymbol(target) { if (!target || !target.array) return '' - switch (target.array) { - case 'one': - return '[]' - case 'two': - return '[][]' + const { keyword } = target.array + if (keyword) return toUpper(keyword) + const { dimension, length } = target.array + const result = [] + for (let i = 0; i < dimension; i++) { + result.push('[') + if (length && length[i]) result.push(literalToSQL(length[i])) + result.push(']') } + return result.join('') } function castToSQL(expr) { @@ -107,6 +111,7 @@ function lambdaToSQL(stmt) { export { anyValueFuncToSQL, + arrayDimensionToSymbol, castToSQL, extractFunToSQL, flattenFunToSQL, diff --git a/test/postgres.spec.js b/test/postgres.spec.js index 0b5acf2c..3ff3779c 100644 --- a/test/postgres.spec.js +++ b/test/postgres.spec.js @@ -1514,6 +1514,13 @@ describe('Postgres', () => { 'CREATE TABLE "Books" (price DECIMAL(10, 2) CHECK (Price > 0))' ] }, + { + title: 'array data type', + sql: [ + `CREATE TABLE "table_0" ("hi" INTEGER ARRAY); CREATE TABLE "table_1" ("hi" INTEGER[3]);`, + `CREATE TABLE "table_0" ("hi" INTEGER ARRAY) ; CREATE TABLE "table_1" ("hi" INTEGER[3])` + ] + }, ] function neatlyNestTestedSQL(sqlList){ sqlList.forEach(sqlInfo => {