1- import type { Attribute , BuiltinType } from '@zenstackhq/language/ast' ;
2- import { DataFieldAttributeFactory } from '@zenstackhq/language/factory' ;
1+ import type { Attribute , BuiltinType , Enum , Expression } from '@zenstackhq/language/ast' ;
2+ import { AstFactory , DataFieldAttributeFactory , ExpressionBuilder } from '@zenstackhq/language/factory' ;
33import { Client } from 'pg' ;
44import { getAttributeRef , getDbName , getFunctionRef } from '../utils' ;
55import type { IntrospectedEnum , IntrospectedSchema , IntrospectedTable , IntrospectionProvider } from './provider' ;
6+ import type { ZModelServices } from '@zenstackhq/language' ;
67
78export const postgresql : IntrospectionProvider = {
89 isSupportedFeature ( feature ) {
@@ -112,46 +113,16 @@ export const postgresql: IntrospectionProvider = {
112113 getDefaultValue ( { defaultValue, fieldType, services, enums } ) {
113114 const val = defaultValue . trim ( ) ;
114115
115- // Handle type casts early (PostgreSQL-specific pattern like 'value'::type)
116- if ( val . includes ( '::' ) ) {
117- const [ value , type ] = val
118- . replace ( / ' / g, '' )
119- . split ( '::' )
120- . map ( ( s ) => s . trim ( ) ) as [ string , string ] ;
121- switch ( type ) {
122- case 'character varying' :
123- case 'uuid' :
124- case 'json' :
125- case 'jsonb' :
126- case 'text' :
127- if ( value === 'NULL' ) return null ;
128- return ( ab ) => ab . StringLiteral . setValue ( value ) ;
129- case 'real' :
130- return ( ab ) => ab . NumberLiteral . setValue ( value ) ;
131- default : {
132- const enumDef = enums . find ( ( e ) => getDbName ( e , true ) === type ) ;
133- if ( ! enumDef ) {
134- return ( ab ) =>
135- ab . InvocationExpr . setFunction ( getFunctionRef ( 'dbgenerated' , services ) ) . addArg ( ( a ) =>
136- a . setValue ( ( v ) => v . StringLiteral . setValue ( val ) ) ,
137- ) ;
138- }
139- const enumField = enumDef . fields . find ( ( v ) => getDbName ( v ) === value ) ;
140- if ( ! enumField ) {
141- throw new Error (
142- `Enum value ${ value } not found in enum ${ type } for default value ${ defaultValue } ` ,
143- ) ;
144- }
145- return ( ab ) => ab . ReferenceExpr . setTarget ( enumField ) ;
146- }
147- }
148- }
149-
150116 switch ( fieldType ) {
151117 case 'DateTime' :
152118 if ( val === 'CURRENT_TIMESTAMP' || val === 'now()' ) {
153119 return ( ab ) => ab . InvocationExpr . setFunction ( getFunctionRef ( 'now' , services ) ) ;
154120 }
121+
122+ if ( val . includes ( '::' ) ) {
123+ return typeCastingConvert ( { defaultValue, enums, val, services} ) ;
124+ }
125+
155126 // Fallback to string literal for other DateTime defaults
156127 return ( ab ) => ab . StringLiteral . setValue ( val ) ;
157128
@@ -160,12 +131,21 @@ export const postgresql: IntrospectionProvider = {
160131 if ( val . startsWith ( 'nextval(' ) ) {
161132 return ( ab ) => ab . InvocationExpr . setFunction ( getFunctionRef ( 'autoincrement' , services ) ) ;
162133 }
134+
135+ if ( val . includes ( '::' ) ) {
136+ return typeCastingConvert ( { defaultValue, enums, val, services} ) ;
137+ }
138+
163139 if ( / ^ - ? \d + $ / . test ( val ) ) {
164140 return ( ab ) => ab . NumberLiteral . setValue ( val ) ;
165141 }
166142 break ;
167143
168144 case 'Float' :
145+ if ( val . includes ( '::' ) ) {
146+ return typeCastingConvert ( { defaultValue, enums, val, services} ) ;
147+ }
148+
169149 if ( / ^ - ? \d + \. \d + $ / . test ( val ) ) {
170150 const numVal = parseFloat ( val ) ;
171151 return ( ab ) => ab . NumberLiteral . setValue ( numVal === Math . floor ( numVal ) ? numVal . toFixed ( 1 ) : String ( numVal ) ) ;
@@ -176,6 +156,10 @@ export const postgresql: IntrospectionProvider = {
176156 break ;
177157
178158 case 'Decimal' :
159+ if ( val . includes ( '::' ) ) {
160+ return typeCastingConvert ( { defaultValue, enums, val, services} ) ;
161+ }
162+
179163 if ( / ^ - ? \d + \. \d + $ / . test ( val ) ) {
180164 const numVal = parseFloat ( val ) ;
181165 if ( numVal === Math . floor ( numVal ) ) {
@@ -198,12 +182,20 @@ export const postgresql: IntrospectionProvider = {
198182 break ;
199183
200184 case 'String' :
185+ if ( val . includes ( '::' ) ) {
186+ return typeCastingConvert ( { defaultValue, enums, val, services} ) ;
187+ }
188+
201189 if ( val . startsWith ( "'" ) && val . endsWith ( "'" ) ) {
202190 return ( ab ) => ab . StringLiteral . setValue ( val . slice ( 1 , - 1 ) . replace ( / ' ' / g, "'" ) ) ;
203191 }
204192 break ;
205193 }
206194
195+ if ( val . includes ( '::' ) ) {
196+ return typeCastingConvert ( { defaultValue, enums, val, services} ) ;
197+ }
198+
207199 // Fallback handlers for values that don't match field type-specific patterns
208200 if ( val === 'CURRENT_TIMESTAMP' || val === 'now()' ) {
209201 return ( ab ) => ab . InvocationExpr . setFunction ( getFunctionRef ( 'now' , services ) ) ;
@@ -447,3 +439,37 @@ WHERE
447439 AND "cls"."relname" !~ '_prisma_migrations'
448440 ORDER BY "ns"."nspname", "cls"."relname" ASC;
449441` ;
442+
443+ function typeCastingConvert ( { defaultValue, enums, val, services} :{ val : string , enums : Enum [ ] , defaultValue :string , services :ZModelServices } ) : ( ( builder : ExpressionBuilder ) => AstFactory < Expression > ) | null {
444+ const [ value , type ] = val
445+ . replace ( / ' / g, '' )
446+ . split ( '::' )
447+ . map ( ( s ) => s . trim ( ) ) as [ string , string ] ;
448+ switch ( type ) {
449+ case 'character varying' :
450+ case 'uuid' :
451+ case 'json' :
452+ case 'jsonb' :
453+ case 'text' :
454+ if ( value === 'NULL' ) return null ;
455+ return ( ab ) => ab . StringLiteral . setValue ( value ) ;
456+ case 'real' :
457+ return ( ab ) => ab . NumberLiteral . setValue ( value ) ;
458+ default : {
459+ const enumDef = enums . find ( ( e ) => getDbName ( e , true ) === type ) ;
460+ if ( ! enumDef ) {
461+ return ( ab ) =>
462+ ab . InvocationExpr . setFunction ( getFunctionRef ( 'dbgenerated' , services ) ) . addArg ( ( a ) =>
463+ a . setValue ( ( v ) => v . StringLiteral . setValue ( val ) ) ,
464+ ) ;
465+ }
466+ const enumField = enumDef . fields . find ( ( v ) => getDbName ( v ) === value ) ;
467+ if ( ! enumField ) {
468+ throw new Error (
469+ `Enum value ${ value } not found in enum ${ type } for default value ${ defaultValue } ` ,
470+ ) ;
471+ }
472+ return ( ab ) => ab . ReferenceExpr . setTarget ( enumField ) ;
473+ }
474+ }
475+ }
0 commit comments