From ca2f5e6e49caeafb1f882ab873c3dbab5dde67dc Mon Sep 17 00:00:00 2001 From: Dicky Lau <115660532+sfc-gh-ext-simba-dl@users.noreply.github.com> Date: Fri, 14 Apr 2023 23:18:24 -0700 Subject: [PATCH] Nodejs183, crash when using full table path on array binding (#466) * issue 183, fix failed on array binding using full path * add try catch on write file * add error handle on write file for array binding * update the connection string * add longer timeout for testArrayBind - full path * fix test case --- lib/connection/bind_uploader.js | 10 +++++- lib/connection/statement.js | 47 ++++++++++++++++--------- test/integration/testArrayBind.js | 57 +++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 17 deletions(-) diff --git a/lib/connection/bind_uploader.js b/lib/connection/bind_uploader.js index aa203c459..0135f6ba7 100644 --- a/lib/connection/bind_uploader.js +++ b/lib/connection/bind_uploader.js @@ -101,7 +101,15 @@ function BindUploader(options, services, connectionConfig, requestId) } var putStmt = "PUT file://" + fileName + "'" + stageName + "' overwrite=true auto_compress=false source_compression=gzip"; - fs.writeFileSync(fileName, data); + try + { + fs.writeFileSync(fileName, data); + } + catch(e) + { + Logger.getInstance().debug('Failed to write file: %s', fileName); + throw e; + } this.files.push(fileName); this.datas.push(data); this.puts.push(putStmt); diff --git a/lib/connection/statement.js b/lib/connection/statement.js index a484f8926..32df78ba6 100644 --- a/lib/connection/statement.js +++ b/lib/connection/statement.js @@ -91,24 +91,30 @@ exports.createStatementPreExec = function ( } Logger.getInstance().debug('threshold = %d', threshold); - var isUsingBindUpload = false; // check array binding, if(numBinds > threshold) { var bindUploaderRequestId = uuidv4(); var bind = new Bind.BindUploader(options, services, connectionConfig, bindUploaderRequestId); - var bindData = bind.Upload(context.binds); - + var bindData; + try + { + bindData = bind.Upload(context.binds); + } + catch(e) + { + Logger.getInstance().debug('bind upload error, use normal binding'); + return createRowStatementPreExec( + options, context, services, connectionConfig); + } if(bindData != null) { - isUsingBindUpload = true; - context.bindStage = Bind.GetStageName(bindUploaderRequestId); - Logger.getInstance().debug('context.bindStage = %s', context.bindStage); - createStage(services, connectionConfig, bindData, options, context); + context.bindStage = Bind.GetStageName(bindUploaderRequestId); + Logger.getInstance().debug('context.bindStage = %s', context.bindStage); + return createStage(services, connectionConfig, bindData, options, context); } } - - if (!isUsingBindUpload) + else { return createRowStatementPreExec( options, context, services, connectionConfig); @@ -123,12 +129,21 @@ function createStage(services, connectionConfig, bindData, options, context) { Logger.getInstance().debug('stream'); Logger.getInstance().debug('err '+err); - var stream = stmt.streamRows(); - stream.on('data', function (rows) + if(err) { - Logger.getInstance().debug('stream on data'); - uploadFiles(services, connectionConfig, bindData, options, context); - }); + context.bindStage = null; + return createRowStatementPreExec( + options, context, services, connectionConfig); + } + else + { + var stream = stmt.streamRows(); + stream.on('data', function (rows) + { + Logger.getInstance().debug('stream on data'); + return uploadFiles(services, connectionConfig, bindData, options, context); + }); + } } } Logger.getInstance().debug('CREATE_STAGE_STMT = %s', Bind.GetCreateStageStmt()); @@ -144,8 +159,8 @@ function uploadFiles(services, connectionConfig, bindData, options, context, cur sqlText: bindData.puts[curIndex], complete: function (err, stmt, rows) { if (err) { - Logger.getInstance().debug('err ' + err); - throw err; + return createRowStatementPreExec( + options, context, services, connectionConfig); } Logger.getInstance().debug('uploadFiles done '); var stream = stmt.streamRows(); diff --git a/test/integration/testArrayBind.js b/test/integration/testArrayBind.js index 5a3f02e4c..fd93fbe55 100644 --- a/test/integration/testArrayBind.js +++ b/test/integration/testArrayBind.js @@ -428,3 +428,60 @@ describe('Test Array Bind', function () ); }); }); + +describe('testArrayBind - full path', function () +{ + this.timeout(600000); + var connection; + var createABTable = `create or replace table ${DATABASE_NAME}.${SCHEMA_NAME}.testAB(colA string, colB number, colC date, colD time, colE TIMESTAMP_NTZ, colF TIMESTAMP_TZ)`; + var insertAB = `insert into ${DATABASE_NAME}.${SCHEMA_NAME}.testAB values(?, ?, ?, ?, ?, ?)`; + + before(function (done) + { + connection = snowflake.createConnection({ + accessUrl: connOption.valid.accessUrl, + account: connOption.valid.account, + username: connOption.valid.username, + password: connOption.valid.password, + warehouse: connOption.valid.warehouse, + role: connOption.valid.role, + arrayBindingThreshold: 3 + }); + testUtil.connect(connection, function () + { + connection.execute({ + sqlText: createABTable, + complete: function (err) + { + testUtil.checkError(err); + done(); + } + }); + }); + }); + + it('Full path array bind', function () + { + var arrBind = []; + var count = 100; + for(var i = 0; i