결과 사용하기

인라인 결과 반환하기

결과를 사용하는 가장 일반적인 방법은 complete 콜백을 connection.execute() 로 전달하는 방법입니다. 문의 실행이 종료되고 결과를 사용할 수 있으면, 결과 행이 인라인으로 반환되면서 complete 콜백이 호출됩니다.

connection.execute({
  sqlText: 'SELECT * FROM sometable',
  complete: function(err, stmt, rows) {
    if (err) {
      console.error('Failed to execute statement due to the following error: ' + err.message);
    } else {
      console.log('Number of rows produced: ' + rows.length);
    }
  }
});
Copy

결과 스트리밍하기

statement.streamRows() 메서드를 호출할 때 connection.execute 에서 streamResult 연결 매개 변수를 true 로 설정하여 결과를 행 스트림으로 사용할 수도 있습니다. 이 매개 변수를 활성화하면 메서드가 Node.js Readable 스트림을 반환하게 되며, 행을 수신할 때 스트림을 통해 행을 사용할 수 있습니다. Readable 스트림에 대한 자세한 내용은 Node.js 설명서 를 참조하십시오.

중요

Node의 기본 메모리를 초과할 수 있는 결과 세트의 경우 결과를 스트리밍할 때 streamResult 를 반드시 true 로 설정하는 것이 좋습니다. 기본값(false)을 사용할 경우 커넥터는 결과를 스트리밍하기 전에 모든 행을 배열에 저장합니다. 결과 세트가 더 작을 경우 이 요소는 보통 문제가 되지 않습니다. 하지만 결과 세트가 더 클 경우 모든 결과를 메모리에 저장하면 OOM 오류가 발생할 수 있습니다.

최신 버전의 Snowflake Node.js 드라이버(1.6.23 이상)는 역압 기능을 구현하여 결과를 사용할 때 스트림에서 데이터를 읽는 것보다 더 빠르게 데이터가 스트림으로 푸시되지 않도록 합니다.

예를 들어 다음 코드 조각은 Readable 이벤트를 사용하여 결과를 사용합니다.

var connection = snowflake.createConnection({
    account: process.env.SFACCOUNT,
    username: process.env.SFUSER,
    // ...
    streamResult: true
});

// [..rest of the code..]

connection.execute({
  sqlText: "select L_COMMENT from SNOWFLAKE_SAMPLE_DATA.TPCH_SF100.LINEITEM limit 100000;",
  streamResult: true,
  complete: function (err, stmt)
  {
    var stream = stmt.streamRows();
    // Read data from the stream when it is available
    stream.on('readable', function (row)
    {
      while ((row = this.read()) !== null)
      {
        console.log(row);
      }
    }).on('end', function ()
    {
      console.log('done');
    }).on('error', function (err)
    {
      console.log(err);
    });
  }
});
Copy

일괄 처리 결과

기본적으로 statement.streamRows() 메서드에서는 결과의 모든 행이 포함되는 스트림이 생성됩니다. 그러나 하위 결과 세트만을 사용하거나 결과 행을 일괄적으로 사용하려는 경우에는 startend 인자를 사용하여 streamRows() 를 호출할 수 있습니다. 이러한 추가 옵션이 지정되면 요청된 범위 내의 행만 스트리밍됩니다.

connection.execute({
  sqlText: 'SELECT * FROM sometable',
  streamResult: true, // prevent rows from being returned inline in the complete callback
  complete: function(err, stmt, rows) {
    // no rows returned inline because streamResult was set to true
    console.log('rows: ' + rows); // 'rows: undefined'

    // only consume at most the last 5 rows in the result
    rows = [];
    stmt.streamRows({
      start: Math.max(0, stmt.getNumRows() - 5),
      end: stmt.getNumRows() - 1,
    })
    .on('error', function(err) {
      console.error('Unable to consume requested rows');
    })
    .on('data', function(row) {
      rows.push(row);
    })
    .on('end', function() {
      console.log('Number of rows consumed: ' + rows.length);
    });
  }
})
Copy

데이터 타입 캐스팅

결과 행이 생성되면 드라이버는 SQL 데이터 타입을 해당 JavaScript 데이터 타입으로 자동으로 매핑합니다. 예를 들어, TIMESTAMP 및 DATE 타입의 값은 JavaScript 날짜 오브젝트로 반환됩니다.

JavaScript를 SQL 데이터 타입으로 완전하게 매핑하려면 아래 테이블을 참조하십시오.

SQL 데이터 타입

JavaScript 데이터 타입

참고

VARCHAR, CHAR, CHARACTER, STRING, TEXT

String

INT, INTEGER, BIGINT, SMALLINT

숫자

기본 매핑입니다. 세션 매개 변수 JS_TREAT_INTEGER_AS_BIGINT를 사용하여 JavaScript Bigint로 매핑합니다.

NUMBER(전체 자릿수, 소수 자릿수), DECIMAL(p, s), NUMERIC(p, s), 여기서 scale = 0

숫자

기본 매핑입니다. 세션 매개 변수 JS_TREAT_INTEGER_AS_BIGINT를 사용하여 JavaScript Bigint로 매핑합니다.

NUMBER(전체 자릿수, 소수 자릿수), DECIMAL(p, s), NUMERIC(p, s), 여기서 scale > 0

숫자

FLOAT, FLOAT4, FLOAT8, DOUBLE, DOUBLE PRECISION, REAL

숫자

TIMESTAMP, TIMESTAMP_LTZ, TIMESTAMP_NTZ, TIMESTAMP_TZ

날짜

TIMESTAMP_NTZ 값은 UTC 시간으로 반환됩니다.

DATE

날짜

TIME

String

SQL의 TIME 데이터 타입에 해당하는 타입이 JavaScript에는 없으며, 그러므로 JavaScript 문자열로 매핑됩니다.

BOOLEAN

Boolean

VARIANT, ARRAY, OBJECT

JSON

정수 데이터 타입을 Bigint로 가져오기

기본적으로, Snowflake INTEGER 열(BIGINT, NUMBER(p, 0) 등 포함)은 JavaScript의 Number 데이터 타입으로 변환됩니다. 하지만 가장 큰 올바른 Snowflake 정수 값은 가장 큰 올바른 JavaScript Number 값보다 큽니다. Snowflake INTEGER 열을 JavaScript Number 보다 큰 값을 저장할 수 있는 JavaScript Bigint 로 변환하려면 세션 매개 변수 JS_TREAT_INTEGER_AS_BIGINT 를 설정하십시오.

다음 방법을 사용하여 이러한 매개 변수 값을 설정할 수 있습니다.

  • 아래와 같이 ALTER SESSION 문을 사용합니다.

    connection.execute( {
                        sqlText: 'ALTER SESSION SET JS_TREAT_INTEGER_AS_BIGINT = TRUE',
                        complete: function ...
                        }
                      );
    
    Copy
  • 연결 구성 정보에 매개 변수를 지정합니다.

    var connection = snowflake.createConnection(
          {
          username: 'fakeusername',
          password: 'fakepassword',
          account: 'fakeaccountidentifier',
          jsTreatIntegerAsBigInt: true
          }
        );
    
    Copy

데이터 타입을 문자열로 가져오기

connection.execute() 를 호출할 때 fetchAsString 옵션을 사용하여 Boolean, Number, Date, BufferJSON 데이터 타입을 문자열로 반환할 수 있습니다.

예를 들어 이 옵션을 사용하여 다음을 반환할 수 있습니다.

  • DATE 또는 TIMESTAMP(또는 베리언트) 타입 값의 타입이 지정된 버전.

  • 전체 자릿수가 손실되지 않고 JavaScript 숫자로 변환할 수 없는 숫자 SQL 타입의 문자열 버전.

다음 예에서는 fetchAsString 을 사용하여 고정밀도 Number 값을 문자열로 변환합니다.

connection.execute({
  sqlText: 'SELECT 1.123456789123456789123456789 as "c1"',
  fetchAsString: ['Number'],
  complete: function(err, stmt, rows) {
    if (err) {
      console.error('Failed to execute statement due to the following error: ' + err.message);
    } else {
      console.log('c1: ' + rows[0].c1); // c1: 1.123456789123456789123456789
    }
  }
});
Copy

XML 데이터 구문 분석하기

드라이버 버전 1.7.0부터는 다음 fast-xml-parser 라이브러리 구성 옵션을 사용하여 XML 콘텐츠가 포함된 열을 쿼리할 때 드라이버가 XML 문서 특성을 처리하는 방법을 사용자 지정할 수 있습니다. 지원되는 옵션과 이러한 옵션이 XML 데이터 구문 분석에 미치는 영향에 대한 자세한 내용은 xmlParserConfig 옵션 섹션을 참조하십시오.

기본적으로, Node.js 드라이버는 쿼리에서 XML 데이터를 반환할 때 XML 요소 특성을 무시합니다. 예를 들어 다음 XML 콘텐츠에서 <piece> 요소에는 id 특성이 포함됩니다.

<exhibit name="Art Show">
  <piece id="000001">
    <name>Mona Lisa</name>
    <artist>Leonardo da Vinci</artist>
    <year>1503</year>
  </piece>
  <piece id="000002">
    <name>The Starry Night</name>
    <artist>Vincent van Gogh</artist>
    <year>1889</year>
  </piece>
</exhibit>
Copy

기본적으로, Node.js 드라이버는 결과 세트를 반환할 때 id 특성을 무시하고 다음 출력을 반환합니다. 특성 이름과 값은 포함되지 않습니다.

{
  exhibit: {
    piece: [
      {
        "name": "Mona Lisa",
        "artist": "Leonardo da Vinci",
        "year": "1503",
      },
      {
        "name": "The Starry Night",
        "artist": "Vincent van Gogh",
        "year": "1889",
      }
    ]
  }
}

fast-xml-parser 옵션을 설정하려면 다음 예와 유사한 xmlParserConfig 요소를 만드십시오.

const snowflake = require('snowflake-sdk');
snowflake.configure({
  xmlParserConfig: {
    /*  Parameters that you can override
    *   ignoreAttributes - default true,
    *   attributeNamePrefix - default '@_',
    *   attributesGroupName - default unset,
    *   alwaysCreateTextNode - default false
    */
    ignoreAttributes: false, attributesGroupName: '@', attributeNamePrefix: ''
  }
});
Copy

이러한 설정을 사용할 경우 드라이버는 XML 데이터를 구문 분석하고 다음을 생성합니다.

{
  exhibit: {
    piece: [
      {
        "name": "Mona Lisa",
        "artist": "Leonardo da Vinci",
        "year": "1503",
        '@': { id: '000001' }
      },
      {
        "name": "The Starry Night",
        "artist": "Vincent van Gogh",
        "year": "1889",
        '@': { id: '000002' }
      }
    ],
    '@': { name: 'Art Show' }
  }

중복된 열 이름이 포함된 결과 세트 반환하기

Snowflake Node.js 드라이버 버전 1.8.0에서 드라이버가 중복된 열 이름이 포함된 결과 세트를 반환하는 방식을 지정할 수 있는 새로운 rowMode 구성 옵션을 도입했습니다.

버전 1.8.0 이전에는 Snowflake Node.js 드라이버가 항상 SELECT 명령의 결과 세트를 JavaScript 오브젝트로 반환했습니다. 결과 세트에 중복된 열 이름과 값이 포함된 경우 JavaScript 오브젝트가 중복된 이름을 처리하는 방식으로 인해 일부 요소가 생략될 수 있습니다.

rowMode 옵션을 사용하면 다음을 포함하여 잠재적인 정보 손실을 방지하기 위해 결과 세트 데이터의 반환 방식을 지정할 수 있습니다.

  • array

  • object (기본값)

  • object_with_renamed_duplicated_columns

설명을 위해 다음 쿼리를 제출한다고 가정합니다.

select *
from (select 'a' as key, 1 as foo, 3 as name) as table1
join (select 'a' as key, 2 as foo, 3 as name2) as table2 on table1.key = table2.key
join (select 'a' as key, 3 as foo) as table3 on table1.key = table3.key
Copy

드라이버는 rowMode 값을 기준으로 다음과 같이 결과 세트를 반환합니다.

  • object (또는 설정 해제)

    {KEY: 'a', FOO: 3, NAME: 3, NAME2: 3};
    
  • array

    ['a', 1, 3, 'a', 2, 3, 'a', 3];
    
  • object_with_renamed_duplicated_columns

    {KEY: 'a', FOO: 1, NAME: 3, KEY_2: 'a', FOO_2: 2, NAME2: 3, KEY_3: 'a', FOO_3: 3};
    

아래와 같이 연결 또는 문 구성 수준에서 rowMode 매개 변수를 설정할 수 있습니다. 두 위치에 모두 설정된 경우 문 수준 값이 우선합니다.

  • 구성 수준

    snowflake.createConnection({
      account: account,
      username: username,
      ...
      rowMode: 'array'})
    
    Copy
  • 문 수준

    connection.execute({
      sqlText: sql,
      rowMode: 'array',
      ...
      )}
    
    Copy

결과 세트가 JSON 및 XML 데이터를 처리하는 방식 사용자 지정하기

Snowflake Node.js 드라이버는 결과 세트의 JSON 및 XML 데이터를 처리하기 위해 다음과 같은 기본 파서를 제공합니다.

사용자 지정 파서를 사용하려는 경우 다음 예제를 사용하여 구성할 수 있습니다.

  • 드라이버가 버전 1.6.21 이전에 사용했던 eval JSON 파서를 사용합니다.

    const snowflake = require('snowflake-sdk');
    snowflake.configure({
      jsonColumnVariantParser: rawColumnValue => eval("(" + rawColumnValue + ")")
    })
    
    Copy
  • 모든 옵션을 사용자 지정하는: 기능이 있는 fast-xml-parser 파서를 사용합니다.

    const snowflake = require('snowflake-sdk');
    snowflake.configure({
      xmlColumnVariantParser: rawColumnValue => new (require("fast-xml-parser")).XMLParser().parse(rawColumnValue)
    })
    
    Copy
  • 동일한 선언에서 둘 모두에 대해 사용자 지정 파서를 구성합니다.

    const snowflake = require('snowflake-sdk');
    snowflake.configure({
      jsonColumnVariantParser: rawColumnValue => JSON.parse(rawColumnValue),
      xmlColumnVariantParser: rawColumnValue => new (require("fast-xml-parser")).XMLParser().parse(rawColumnValue)
    })
    
    Copy