import { assert , SQLQueryAST , TransformType } from './loader/sql' ; import { IInterpolatedQuery , INestedParameters , IQueryParameters , IScalarArrayParam , IScalarParam , ParamTransform , QueryParam , replaceIntervals , Scalar , } from './preprocessor' ; export const processSQLQueryAST = ( query , passedParams ? ) : IInterpolatedQuery => { const bindings = [ ] ; const paramMapping = [ ] ; const usedParams = query . params . filter ( ( p ) => p . name in query . usedParamSet ) ; const { a : statementStart } = query . statement . loc ; let i = 1 ; const intervals = [ ] ; for ( const usedParam of usedParams ) { const paramLocs = usedParam . codeRefs . used . map ( ( { a , b } ) => ( { a : a - statementStart - 1 , b : b - statementStart , } ) ) ; if ( usedParam . transform . type === TransformType . ArraySpread ) { let sub ; if ( passedParams ) { const paramValue = passedParams [ usedParam . name ] ; sub = ( paramValue as Scalar [ ] ) . map ( ( val ) => { bindings . push ( val ) ; return `$${ i ++ }` ; } ) . join ( ',' ) ; } else { const idx = i ++ ; paramMapping . push ( { name : usedParam . name , type : ParamTransform . Spread , assignedIndex : idx , required : usedParam . required , } as IScalarArrayParam ) ; sub = `$${ idx }` ; } paramLocs . forEach ( ( pl ) => intervals . push ( { ... pl , sub : `(${ sub })` , } ) ) ; continue ; } if ( usedParam . transform . type === TransformType . PickTuple ) { const dict = { } ; const sub = usedParam . transform . keys . map ( ( { name , required } ) => { const idx = i ++ ; dict [ name ] = { name , required , type : ParamTransform . Scalar , assignedIndex : idx , } as IScalarParam ; if ( passedParams ) { const paramValue = passedParams [ usedParam . name ] as INestedParameters ; const val = paramValue [ name ] ; bindings . push ( val ) ; } return `$${ idx }` ; } ) . join ( ',' ) ; if ( ! passedParams ) { paramMapping . push ( { name : usedParam . name , type : ParamTransform . Pick , dict , } ) ; } paramLocs . forEach ( ( pl ) => intervals . push ( { ... pl , sub : `(${ sub })` , } ) ) ; continue ; } if ( usedParam . transform . type === TransformType . PickArraySpread ) { let sub ; if ( passedParams ) { const passedParam = passedParams [ usedParam . name ] as INestedParameters [ ] ; sub = passedParam . map ( ( entity ) => { assert ( usedParam . transform . type === TransformType . PickArraySpread ) ; const ssub = usedParam . transform . keys . map ( ( { name } ) => { const val = entity [ name ] ; bindings . push ( val ) ; return `$${ i ++ }` ; } ) . join ( ',' ) ; return ssub ; } ) . join ( '),(' ) ; } else { const dict = { } ; sub = usedParam . transform . keys . map ( ( { name , required } ) => { const idx = i ++ ; dict [ name ] = { name , required , type : ParamTransform . Scalar , assignedIndex : idx , } as IScalarParam ; return `$${ idx }` ; } ) . join ( ',' ) ; paramMapping . push ( { name : usedParam . name , type : ParamTransform . PickSpread , dict , } ) ; } paramLocs . forEach ( ( pl ) => intervals . push ( { ... pl , sub : `(${ sub })` , } ) ) ; continue ; } const assignedIndex = i ++ ; if ( passedParams ) { const paramValue = passedParams [ usedParam . name ] as Scalar ; bindings . push ( paramValue ) ; } else { paramMapping . push ( { name : usedParam . name , type : ParamTransform . Scalar , assignedIndex , required : usedParam . required , } as IScalarParam ) ; } paramLocs . forEach ( ( pl ) => intervals . push ( { ... pl , sub : `$${ assignedIndex }` , } ) ) ; } const flatStr = replaceIntervals ( query . statement . body , intervals ) ; return { mapping : paramMapping , query : flatStr , bindings , } ; } ;