@@ -40,6 +40,7 @@ import type {
4040 UniqueConstraint ,
4141 View ,
4242} from '../serializer/pgSchema' ;
43+ import { parse as parsePostgresArray } from 'postgres-array' ;
4344import { type DB , escapeSingleQuotes , isPgArrayType } from '../utils' ;
4445import { getColumnCasing , sqlToStr } from './utils' ;
4546
@@ -1934,7 +1935,91 @@ WHERE
19341935 } ;
19351936} ;
19361937
1937- const defaultForColumn = ( column : any , internals : PgKitInternals , tableName : string ) => {
1938+ /**
1939+ * Formats a single array element based on the PostgreSQL column data type.
1940+ * Handles cleaning up quotes and spaces from postgres-array parsed elements,
1941+ * and applies appropriate formatting for different data types.
1942+ */
1943+ const formatArrayElement = ( element : any , dataType : string ) : string | null => {
1944+ if ( element === null ) return element ;
1945+
1946+ // Remove outer quotes from postgres-array parsed elements if present
1947+ // First trim spaces since postgres-array includes leading spaces in array elements
1948+ let cleanElement = typeof element === 'string' ? element . trim ( ) : element ;
1949+ if ( typeof cleanElement === 'string' && ( ( cleanElement . startsWith ( "'" ) && cleanElement . endsWith ( "'" ) ) || ( cleanElement . startsWith ( '"' ) && cleanElement . endsWith ( '"' ) ) ) ) {
1950+ cleanElement = cleanElement . slice ( 1 , - 1 ) ;
1951+ }
1952+
1953+ // remove [] from dataType if it exists
1954+ if ( ! dataType . endsWith ( "[]" ) ) {
1955+ throw new Error ( `array dataType ${ dataType } does not end with '[]'` ) ;
1956+ }
1957+
1958+ const baseDataType = dataType . slice ( 0 , - "[]" . length ) ;
1959+
1960+ if ( [ 'integer' , 'smallint' , 'bigint' , 'double precision' , 'real' ] . includes ( baseDataType ) ) {
1961+ return cleanElement ;
1962+ } else if ( dataType . startsWith ( 'timestamp' ) ) {
1963+ return `"${ cleanElement } "` ;
1964+ } else if ( baseDataType === 'interval' ) {
1965+ return `"${ cleanElement . replaceAll ( '"' , `\"` ) } "` ;
1966+ } else if ( baseDataType === 'boolean' ) {
1967+ return cleanElement === 't' || cleanElement === 'true' ? 'true' : 'false' ;
1968+ } else if ( [ 'json' , 'jsonb' ] . includes ( baseDataType ) ) {
1969+ // For JSON/JSONB arrays, cleanElement is already a JSON string
1970+ // We just need to ensure it's properly quoted
1971+
1972+ // First, try to parse it to validate it's valid JSON
1973+ const parsed = JSON . parse ( cleanElement ) ;
1974+ // Then stringify it back to ensure consistent formatting
1975+ return `"${ JSON . stringify ( parsed ) . replaceAll ( '"' , '\\"' ) } "` ;
1976+ } else {
1977+ return `"${ cleanElement } "` ;
1978+ }
1979+ } ;
1980+
1981+ /**
1982+ * Handles the default value formatting for array columns.
1983+ * Converts various array formats to PostgreSQL array notation and formats elements.
1984+ */
1985+ const handleArrayDefault = ( columnDefaultAsString : string, dataType : string) : string => {
1986+ // Handle common simple cases
1987+ if ( columnDefaultAsString === '{}' || columnDefaultAsString === "'{}'" ) {
1988+ return "'{}'" ;
1989+ } else if ( columnDefaultAsString === '{""}' || columnDefaultAsString === "'{\"\"}'" ) {
1990+ return "'{\"\"}'" ;
1991+ }
1992+
1993+ // Convert ARRAY constructor syntax to PostgreSQL bracket notation that postgres-array can parse
1994+ let normalizedArrayString = columnDefaultAsString ;
1995+
1996+ if ( columnDefaultAsString . startsWith ( 'ARRAY[' ) && columnDefaultAsString . endsWith ( ']' ) ) {
1997+ // Convert ARRAY['a'::text, 'b', 'c'::varchar] -> {'a', 'b', 'c'}
1998+ const content = columnDefaultAsString . slice ( 6 , - 1 ) ; // Remove 'ARRAY[' and ']'
1999+
2000+ // Remove type casting from individual elements (::text, ::varchar, etc.)
2001+ const cleanContent = content . replace ( / : : \w + / g, '' ) ;
2002+ normalizedArrayString = `{${ cleanContent } }` ;
2003+ }
2004+
2005+ // Handle various bracket notation formats to ensure compatibility with postgres-array
2006+ if ( normalizedArrayString . startsWith ( "'{" ) && normalizedArrayString . endsWith ( "}'" ) ) {
2007+ normalizedArrayString = normalizedArrayString . slice ( 1 , - 1 ) ; // Remove outer quotes
2008+ } else if ( ! normalizedArrayString . startsWith ( "{" ) && ! normalizedArrayString . startsWith ( "'" ) && normalizedArrayString !== '{}' ) {
2009+ // Handle cases where array string doesn't have proper brackets
2010+ normalizedArrayString = `{${ normalizedArrayString } }` ;
2011+ }
2012+
2013+ // Use postgres-array library to parse the normalized string
2014+ const parsedArray = [ ...parsePostgresArray ( normalizedArrayString ) ] ;
2015+
2016+ // Format elements according to data type
2017+ const formattedElements = parsedArray . map ( ( element ) => formatArrayElement ( element , dataType ) ) ;
2018+
2019+ return `'{${ formattedElements . join ( ',' ) } }'` ;
2020+ } ;
2021+
2022+ export const defaultForColumn = ( column : any , internals : PgKitInternals , tableName : string ) => {
19382023 const columnName = column . column_name ;
19392024 const isArray = internals ?. tables [ tableName ] ?. columns [ columnName ] ?. isArray ?? false ;
19402025
@@ -1961,27 +2046,7 @@ const defaultForColumn = (column: any, internals: PgKitInternals, tableName: str
19612046 const columnDefaultAsString : string = column . column_default . toString ( ) ;
19622047
19632048 if ( isArray ) {
1964- return `'{${
1965- columnDefaultAsString
1966- . slice ( 2 , - 2 )
1967- . split ( / \s * , \s * / g)
1968- . map ( ( value ) => {
1969- if ( [ 'integer' , 'smallint' , 'bigint' , 'double precision' , 'real' ] . includes ( column . data_type . slice ( 0 , - 2 ) ) ) {
1970- return value ;
1971- } else if ( column . data_type . startsWith ( 'timestamp' ) ) {
1972- return `${ value } ` ;
1973- } else if ( column . data_type . slice ( 0 , - 2 ) === 'interval' ) {
1974- return value . replaceAll ( '"' , `\"` ) ;
1975- } else if ( column . data_type . slice ( 0 , - 2 ) === 'boolean' ) {
1976- return value === 't' ? 'true' : 'false' ;
1977- } else if ( [ 'json' , 'jsonb' ] . includes ( column . data_type . slice ( 0 , - 2 ) ) ) {
1978- return JSON . stringify ( JSON . stringify ( JSON . parse ( JSON . parse ( value ) ) , null , 0 ) ) ;
1979- } else {
1980- return `\"${ value } \"` ;
1981- }
1982- } )
1983- . join ( ',' )
1984- } }'`;
2049+ return handleArrayDefault ( columnDefaultAsString , column . data_type ) ;
19852050 }
19862051
19872052 if ( [ 'integer' , 'smallint' , 'bigint' , 'double precision' , 'real' ] . includes ( column . data_type ) ) {
0 commit comments