import { pipe , replace , trim , trimCharsEnd , template } from "lodash/fp" ; import { parse } from "path" ; import * as db from "./db" ; import { splitLines , execPromise } from "./utility" ; import { getObjectInfoFromPath } from "./dbobject" ; import { dbConfig } from "./config" ; const U_AUTO = "<Auto>" ; /**
 *Extract user info from path and match with DB conn configuration
 */ function matchDbUser ( file , env , user , changeOwner ) { const oinfo = getObjectInfoFromPath ( file ) ; let obj = user === U_AUTO ? oinfo : { ... oinfo , owner : user } ; const connCfg = dbConfig . getConfiguration ( env , obj . owner ) ; if ( changeOwner ) { obj . owner = connCfg . user . toUpperCase ( ) ; } return { obj , connCfg } ; } export const exportFile = async ( code , file , env , ease , getFunctionName , done ) => { let exported = null ; let conn ; let obj , connCfg ; try { ( { obj , connCfg } = matchDbUser ( file , env , U_AUTO , false ) ) ; conn = await db . getConnection ( connCfg ) ; if ( ! ease || ( await db . isDifferentDdlTime ( conn , obj , env ) ) ) { let lob = await db . getObjectDdl ( conn , getFunctionName , obj ) ; lob = pipe ( trim , replace ( /\x00/g , "" ) , replace ( /\nALTER TRIGGER+.*/g , "" ) ) ( lob ) ; done ( null , lob ) ; await db . syncDdlTime ( conn , obj , env ) ; exported = true ; } else { done ( null , code ) ; exported = false ; } } catch ( error ) { console . error ( error . message ) ; done ( null , code ) ; exported = false ; } finally { db . closeConnection ( conn ) ; } return { obj , exported } ; } ; function simpleParse ( code ) { code = pipe ( trim , trimCharsEnd ( "/" ) , trim ) ( code ) ; if ( ! /END(\s*\w*);$/gi . test ( code ) ) { code = trimCharsEnd ( ";" ) ( code ) ; } return code ; } function getLineAndPosition ( code , offset ) { let lines = splitLines ( code . substring ( 0 , offset ) ) ; let line = lines . length ; let position = lines . pop ( ) . length + 1 ; return { line , position } ; } export const compileFile = async ( code , file , env , force , warnings , user = U_AUTO ) => { const { obj , connCfg } = matchDbUser ( file , env , user , true ) ; code = simpleParse ( code ) ; let errors ; let lines = [ ] ; let result = { } ; let conn ; try { conn = await db . getConnection ( connCfg ) ; if ( ( await db . isDifferentDdlTime ( conn , obj , env ) ) && ! force ) { errors = db . getErrorObjectChanged ( ) ; } else { result = await db . compile ( conn , code . toString ( ) , warnings ) ; await db . syncDdlTime ( conn , obj , env ) ; errors = await db . getErrors ( conn , obj ) ; lines = await db . getDbmsOutput ( conn ) ; } } catch ( error ) { const { line , position } = getLineAndPosition ( code , error . offset ) ; let msg = error . message ; errors = db . getErrorSystem ( msg , 1 , line , position ) ; } finally { db . closeConnection ( conn ) ; } return { obj , file , env , errors , result , lines , } ; } ; export const compileSelection = async ( code , file , env , lineOffset , user = U_AUTO ) => { const { obj , connCfg } = matchDbUser ( file , env , user , true ) ; code = simpleParse ( code ) ; let errors ; let lines = [ ] ; let result = { } ; let conn ; try { conn = await db . getConnection ( connCfg ) ; result = await db . compile ( conn , code . toString ( ) ) ; errors = db . createErrorList ( ) ; lines = await db . getDbmsOutput ( conn ) ; } catch ( error ) { const { line , position } = getLineAndPosition ( code , error . offset ) ; let msg = error . message ; errors = db . getErrorSystem ( msg , lineOffset , line , position ) ; } finally { db . closeConnection ( conn ) ; } return { obj , file , env , errors , result , lines , } ; } ; export const runFileAsScript = async ( file , env , user = U_AUTO ) => { const { obj , connCfg } = matchDbUser ( file , env , user , true ) ; const connString = await db . getConnectionString ( connCfg ) ; const cwd = parse ( file ) . dir ; const filename = parse ( file ) . base ; const cliExec = process . env . ORADEW_CLI_EXECUTABLE ; const cliCommand = process . env . ORADEW_CLI_COMMAND ; let cmd ; if ( cliCommand === "null" ) { const isSqlPlus = parse ( cliExec ) . name . toLowerCase ( ) === "sqlplus" ; if ( isSqlPlus ) { cmd = `(echo connect ${ connString } && echo start ${ filename } && echo show errors) | "${ cliExec }" -S /nolog` ; } else { cmd = `exit | "${ cliExec }" -S ${ connString } @"${ filename }"` ; } } else { cmd = template ( cliCommand ) ( { cliExec , connString , filename } ) ; } let stdout = await execPromise ( cmd , { encoding : "buffer" , maxBuffer : 1024 * 5000 , cwd } ) ; return { stdout , obj } ; } ; export const getObjectsInfoByType = async ( env , owner , objectTypes ) => { const connCfg = dbConfig . getConfiguration ( env , owner ) ; let conn ; let result = [ ] ; try { conn = await db . getConnection ( connCfg ) ; for ( let objectType of objectTypes ) { const objects = await db . getObjectsInfo ( conn , { owner , objectType } ) ; result = result . concat ( objects ) ; } } catch ( error ) { throw error ; } finally { db . closeConnection ( conn ) ; } return result ; } ; export const resolveObjectInfo = async ( env , objName , user = U_AUTO , file ) => { let { connCfg } = matchDbUser ( file , env , user , false ) ; let conn ; let result ; let conn1 ; try { let schema , part1 , part2 ; let objectName ; conn = await db . getConnection ( connCfg ) ; for ( let context = 0 ; context < 10 ; context ++ ) { try { ( { schema , part1 , part2 } = await db . getNameResolve ( conn , { name : objName , context , } ) ) ; } catch ( error ) { if ( ! [ 6564 , 4047 ] . includes ( error . errorNum ) ) { throw error ; } } objectName = part1 || part2 ; if ( objectName ) { break ; } } if ( ! objectName ) { throw Error ( `object ${ objName } does not exist for user ${ user }.` ) ; } connCfg = dbConfig . getConfiguration ( env , schema ) ; conn1 = await db . getConnection ( connCfg ) ; result = await db . getObjectsInfo ( conn1 , { owner : schema , objectName , } ) ; } catch ( error ) { throw error ; } finally { db . closeConnection ( conn ) ; db . closeConnection ( conn1 ) ; } return result ; } ; export const getGenerator = async ( { func , file , env , object , user = U_AUTO } ) => { const { obj , connCfg } = matchDbUser ( file , env , user , true ) ; let result = { } ; let conn ; try { conn = await db . getConnection ( connCfg ) ; result = await db . getGeneratorFunction ( conn , func , obj , object ) ; } catch ( error ) { throw error ; } finally { db . closeConnection ( conn ) ; } return { obj , file , env , result , } ; } ;