@@ -10,15 +10,18 @@ import {
1010} from "./ast-decribe.utils" ;
1111import { ResolvedColumn , SourcesResolver , getSources } from "./ast-get-sources" ;
1212import { PgColRow , PgEnumsMaps , PgTypesMap } from "./generate" ;
13- import { FlattenedRelationWithJoins } from "./utils/get-relations-with-joins" ;
13+ import { getNonNullableColumns } from "./utils/get-nonnullable-columns" ;
14+ import {
15+ FlattenedRelationWithJoins ,
16+ flattenRelationsWithJoinsMap ,
17+ getRelationsWithJoins ,
18+ } from "./utils/get-relations-with-joins" ;
1419
1520type ASTDescriptionOptions = {
1621 parsed : LibPgQueryAST . ParseResult ;
17- relations : FlattenedRelationWithJoins [ ] ;
1822 typesMap : Map < string , { override : boolean ; value : string } > ;
1923 typeExprMap : Map < string , Map < string , Map < string , string > > > ;
2024 overridenColumnTypesMap : Map < string , Map < string , string > > ;
21- nonNullableColumns : Set < string > ;
2225 pgColsBySchemaAndTableName : Map < string , Map < string , PgColRow [ ] > > ;
2326 pgTypes : PgTypesMap ;
2427 pgEnums : PgEnumsMaps ;
@@ -29,6 +32,8 @@ type ASTDescriptionContext = ASTDescriptionOptions & {
2932 select : LibPgQueryAST . SelectStmt ;
3033 resolver : SourcesResolver ;
3134 resolved : WeakMap < LibPgQueryAST . Node , string > ;
35+ nonNullableColumns : Set < string > ;
36+ relations : FlattenedRelationWithJoins [ ] ;
3237 toTypeScriptType : (
3338 params : { oid : number ; baseOid : number | null } | { name : string } ,
3439 ) => ASTDescribedColumnType ;
@@ -43,15 +48,28 @@ export type ASTDescribedColumnType =
4348 | { kind : "type" ; value : string ; type : string ; base ?: string }
4449 | { kind : "literal" ; value : string ; base : ASTDescribedColumnType } ;
4550
46- export function getASTDescription (
47- params : ASTDescriptionOptions ,
48- ) : Map < number , ASTDescribedColumn | undefined > {
51+ export function getASTDescription ( params : ASTDescriptionOptions ) : {
52+ map : Map < number , ASTDescribedColumn | undefined > ;
53+ meta : {
54+ relations : FlattenedRelationWithJoins [ ] ;
55+ nonNullableColumns : Set < string > ;
56+ } ;
57+ } {
4958 const select = params . parsed . stmts [ 0 ] ?. stmt ?. SelectStmt ;
5059
5160 if ( select === undefined ) {
52- return new Map ( ) ;
61+ return {
62+ map : new Map ( ) ,
63+ meta : {
64+ relations : [ ] ,
65+ nonNullableColumns : new Set ( ) ,
66+ } ,
67+ } ;
5368 }
5469
70+ const nonNullableColumns = getNonNullableColumns ( params . parsed ) ;
71+ const relations = flattenRelationsWithJoinsMap ( getRelationsWithJoins ( params . parsed ) ) ;
72+
5573 function getTypeByOid ( oid : number ) {
5674 const name = params . pgTypes . get ( oid ) ?. name ;
5775
@@ -74,10 +92,12 @@ export function getASTDescription(
7492
7593 const context : ASTDescriptionContext = {
7694 ...params ,
95+ nonNullableColumns,
96+ relations,
7797 resolver : getSources ( {
78- relations : params . relations ,
98+ relations : relations ,
7999 select : select ,
80- nonNullableColumns : params . nonNullableColumns ,
100+ nonNullableColumns : nonNullableColumns ,
81101 pgColsBySchemaAndTableName : params . pgColsBySchemaAndTableName ,
82102 } ) ,
83103 select : select ,
@@ -176,7 +196,13 @@ export function getASTDescription(
176196 final . set ( i , result ) ;
177197 }
178198
179- return final ;
199+ return {
200+ map : final ,
201+ meta : {
202+ relations,
203+ nonNullableColumns,
204+ } ,
205+ } ;
180206}
181207
182208function mergeColumns ( columns : ( ASTDescribedColumn | undefined ) [ ] ) : ASTDescribedColumn | undefined {
@@ -247,6 +273,10 @@ function getDescribedNode(params: {
247273 return getDescribedAExpr ( { alias : alias , node : node . A_Expr , context } ) ;
248274 }
249275
276+ if ( node . SelectStmt !== undefined ) {
277+ return getDescribedSelectStmt ( { alias : alias , node : node . SelectStmt , context } ) ;
278+ }
279+
250280 return [ ] ;
251281}
252282
@@ -488,24 +518,74 @@ function getDescribedSubLink({
488518 context,
489519 node,
490520} : GetDescribedParamsOf < LibPgQueryAST . SubLink > ) : ASTDescribedColumn [ ] {
521+ const getSubLinkType = ( ) : ASTDescribedColumnType => {
522+ if ( node . subLinkType === LibPgQueryAST . SubLinkType . EXISTS_SUBLINK ) {
523+ return context . toTypeScriptType ( { name : "bool" } ) ;
524+ }
525+
526+ if ( node . subLinkType === LibPgQueryAST . SubLinkType . EXPR_SUBLINK ) {
527+ const described = node . subselect ?. SelectStmt
528+ ? getDescribedNode ( {
529+ alias : undefined ,
530+ node : { SelectStmt : node . subselect . SelectStmt } ,
531+ context,
532+ } )
533+ : [ ] ;
534+
535+ return described . length > 0
536+ ? described [ 0 ] . type
537+ : context . toTypeScriptType ( { name : "unknown" } ) ;
538+ }
539+
540+ return context . toTypeScriptType ( { name : "unknown" } ) ;
541+ } ;
542+
491543 return [
492544 {
493545 name : alias ?? "exists" ,
494546 type : resolveType ( {
495547 context : context ,
496548 nullable : false ,
497- type : ( ( ) => {
498- if ( node . subLinkType === LibPgQueryAST . SubLinkType . EXISTS_SUBLINK ) {
499- return context . toTypeScriptType ( { name : "bool" } ) ;
500- }
501-
502- return context . toTypeScriptType ( { name : "unknown" } ) ;
503- } ) ( ) ,
549+ type : getSubLinkType ( ) ,
504550 } ) ,
505551 } ,
506552 ] ;
507553}
508554
555+ function getDescribedSelectStmt ( {
556+ alias,
557+ context,
558+ node,
559+ } : GetDescribedParamsOf < LibPgQueryAST . SelectStmt > ) : ASTDescribedColumn [ ] {
560+ const subParsed : LibPgQueryAST . ParseResult = {
561+ version : 0 ,
562+ stmts : [ { stmt : { SelectStmt : node } , stmtLocation : 0 , stmtLen : 0 } ] ,
563+ } ;
564+
565+ const subDescription = getASTDescription ( {
566+ parsed : subParsed ,
567+ typesMap : context . typesMap ,
568+ typeExprMap : context . typeExprMap ,
569+ overridenColumnTypesMap : context . overridenColumnTypesMap ,
570+ pgColsBySchemaAndTableName : context . pgColsBySchemaAndTableName ,
571+ pgTypes : context . pgTypes ,
572+ pgEnums : context . pgEnums ,
573+ pgFns : context . pgFns ,
574+ } ) ;
575+
576+ const firstColumn = subDescription . map . get ( 0 ) ;
577+ if ( firstColumn ) {
578+ return [
579+ {
580+ name : alias ?? firstColumn . name ,
581+ type : firstColumn . type ,
582+ } ,
583+ ] ;
584+ }
585+
586+ return [ ] ;
587+ }
588+
509589function getDescribedCoalesceExpr ( {
510590 alias,
511591 context,
0 commit comments