conststatement=connection.execute({sqlText:'CREATE DATABASE testdb',complete:function(err,stmt,rows){if(err){console.error(`Failed to execute statement due to the following error: ${err.message}`);}else{console.log(`Successfully executed statement: ${stmt.getSqlText()}`);}}});
The Snowflake Node.js Driver supports asynchronous queries (that is, queries that return control to the user before the query completes). You can start a query, then use polling to determine when the query has completed. After the query completes, you can read the result set.
letqueryId;// 1. Execute query with asyncExec set to trueawaitnewPromise((resolve)=>{connection.execute({sqlText:"CALL SYSTEM$WAIT(3, 'SECONDS')",asyncExec:true,complete:asyncfunction(err,stmt,rows){queryId=stmt.getQueryId();// Get the query IDresolve();}});});// 2. Get results using the query IDconststatement=awaitconnection.getResultsFromQueryId({queryId:queryId});awaitnewPromise((resolve,reject)=>{conststream=statement.streamRows();stream.on('error',err=>{reject(err);});stream.on('data',row=>{console.log(row);});stream.on('end',()=>{resolve();});});
// 1. Execute query with asyncExec set to trueconnection.execute({sqlText:"CALL SYSTEM$WAIT(3, 'SECONDS')",asyncExec:true,complete:asyncfunction(err,stmt,rows){constqueryId=stmt.getQueryId();// 2. Get results using the query IDconnection.getResultsFromQueryId({queryId:queryId,complete:asyncfunction(err,_stmt,rows){console.log(rows);}});}});
非同期で実行するために送信されたクエリのステータスを確認します。
letqueryId;// 1. Execute query with asyncExec set to trueawaitnewPromise((resolve,reject)=>{conststatement=connection.execute({sqlText:"CALL SYSTEM$WAIT(3, 'SECONDS')",asyncExec:true,complete:asyncfunction(err,stmt,rows){queryId=statement.getQueryId();resolve();}});});// 2. Check query status until it's finished executingconstseconds=2;letstatus=awaitconnection.getQueryStatus(queryId);while(connection.isStillRunning(status)){console.log(`Query status is ${status}, timeout for ${seconds} seconds`);awaitnewPromise((resolve)=>{setTimeout(()=>resolve(),1000*seconds);});status=awaitconnection.getQueryStatus(queryId);}console.log(`Query has finished executing, status is ${status}`);
conststatement=connection.execute({sqlText:'ALTER SESSION SET multi_statement_count=0',complete:function(err,stmt,rows){if(err){console.error(`Failed to execute statement due to the following error: ${err.message}`);}else{testMulti();}}});functiontestMulti(){console.log('select bind execute.');constselectStatement=connection.execute({sqlText:'create or replace table test(n int); insert into test values(1), (2); select * from test order by n',complete:function(err,stmt,rows){if(err){console.error(`Failed to execute statement due to the following error: ${err.message}`);}else{console.log('==== complete');console.log(`==== sqlText=${stmt.getSqlText()}`);if(stmt.hasNext()){stmt.NextResult();}else{// do something else, for example close the connection}}}});}
// connection needs to be already set upconnection.connect((err,conn)=>{if(err){console.error(`Unable to connect: ${err.message}`);}else{console.log(`Successfully connected to Snowflake, connection id ${conn.getId()}`);testMulti();}});functiontestMulti(){console.log('execute multi-statement query');connection.execute({sqlText:'create or replace table test(n int); insert into test values(1), (2); select * from test order by n',parameters:{MULTI_STATEMENT_COUNT:3},complete:function(err,stmt,rows){if(err){console.error(`Failed to execute statement: ${err.message}`);}else{console.log('==== complete');console.log(`==== sqlText=${stmt.getSqlText()}`);if(rows){conststream=stmt.streamRows();console.log(`====QueryId=${stmt.getQueryId()}`);stream.on('data',row=>{console.log(row);});stream.on('end',()=>{console.log('done');});}if('hasNext'instmt&&stmt.hasNext()){stmt.NextResult();}else{connection.destroy(err1=>{if(err1){console.error(`Unable to disconnect: ${err1.message}`);}else{console.log(`Disconnected connection with id: ${connection.getId()}`);}});}}}});}
// standard stuff like defining connection, etcconststatement=connection.execute({// table columns are id: int, foo: variantsqlText:'insert into test_db.public.test select value:id, value:foo from table(flatten(parse_json(?)))',binds:[JSON.stringify([{id:1,foo:[{a:'1',b:'2'}]},{id:2,foo:[{c:'3',d:'4'}]}])],complete:function(err,stmt,rows){if(err){console.error(`Failed to execute statement due to the following error: ${err.message}`);}else{console.log(`[queryID ${statement.getStatementId()}, requestId ${statement.getRequestId()}] Number of rows produced: ${rows.length}`);// rest of the code}}});
statement.cancel((err,stmt)=>{if(err){console.error(`Unable to abort statement due to the following error: ${err.message}`);}else{console.log('Successfully aborted statement');}});
ネットワークエラーまたはタイムアウトなどが原因で、Snowflakeが SQL ステートメントを正常に実行したかどうかが分からない場合は、リクエスト ID を使用して同じステートメントを再送信できます。たとえば、データを追加するために INSERT コマンドを送信したが、確認応答がタイムリーに受信されなかったため、コマンドで何が起こったのかが分からない場合があります。このシナリオでは、コマンドを2回実行してデータの重複が発生する可能性があるため、同じコマンドを新しいコマンドとして実行することは望ましくありません。
SQL ステートメントにリクエスト ID を含めると、データが重複する可能性を回避できます。最初のリクエストからのリクエスト ID を使用してリクエストを再送信すると、最初のリクエストが失敗した場合にのみ、再送信されたコマンドが実行されるようになります。詳細については、 SQL ステートメントの実行リクエストの再送信 をご参照ください。
注釈
リクエスト ID を使用してクエリを再送信するには、リクエスト ID を生成したときと同じ接続を使用する必要があります。別の接続からクエリの結果を取得する場合は、 RESULT_SCAN をご参照ください。
次のコードサンプルは、リクエスト ID を保存して使用し、ステートメントを再送信する方法を示しています。ステートメントを実行すると、 getRequestId() 関数を使用して、送信されたリクエストの ID を取得できます。そうすると、その ID を使用して、後で同じステートメントを実行できます。次の例では、INSERT ステートメントを実行し、そのリクエスト ID を requestId 変数に保存します。
letrequestId;connection.execute({sqlText:'INSERT INTO testTable VALUES (1);',complete:function(err,stmt,rows){conststream=stmt.streamRows();requestId=stmt.getRequestId();// Retrieves the request IDstream.on('data',row=>{console.log(row);});stream.on('end',()=>{console.log('done');});}});
コマンドが正常に実行されたという確認を受信しない場合は、以下に示すように保存されたリクエスト ID を使用してリクエストを再送信できます。
connection.execute({sqlText:'INSERT INTO testTable VALUES (1);',// optionalrequestId:requestId,// Uses the request ID from beforecomplete:function(err,stmt,rows){conststream=stmt.streamRows();stream.on('data',row=>{console.log(row);});stream.on('end',()=>{console.log('done');});}});