Skip to content

Commit

Permalink
SNOW-1769573 Add support for describeOnly (#945)
Browse files Browse the repository at this point in the history
Co-authored-by: Gabe Gorelick <[email protected]>
  • Loading branch information
sfc-gh-pmotacki and gabegorelick authored Nov 7, 2024
1 parent 081d28b commit 00e3b95
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 1 deletion.
6 changes: 6 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ declare module 'snowflake-sdk' {
ERR_CONN_EXEC_STMT_INVALID_FETCH_AS_STRING_VALUES = 409012,
ERR_CONN_EXEC_STMT_INVALID_REQUEST_ID = 409013,
ERR_CONN_EXEC_STMT_INVALID_ASYNC_EXEC = 409014,
ERR_CONN_EXEC_STMT_INVALID_DESCRIBE_ONLY = 409015,

// 410001
ERR_CONN_FETCH_RESULT_MISSING_OPTIONS = 410001,
Expand Down Expand Up @@ -652,6 +653,11 @@ declare module 'snowflake-sdk' {
* that is different from the connector directory.
*/
cwd?: string;

/**
* `true` to enable a describe only query.
*/
describeOnly?: boolean;
}

export interface RowStatement {
Expand Down
16 changes: 16 additions & 0 deletions lib/connection/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,12 @@ function createContextPreExec(
ErrorCodes.ERR_CONN_EXEC_STMT_INVALID_ASYNC_EXEC);
}

// if a describeOnly flag is specified, make sure it's boolean
if (Util.exists(statementOptions.describeOnly)) {
Errors.checkArgumentValid(Util.isBoolean(statementOptions.describeOnly),
ErrorCodes.ERR_CONN_EXEC_STMT_INVALID_DESCRIBE_ONLY);
}

// create a statement context
const statementContext = createStatementContext();

Expand Down Expand Up @@ -384,6 +390,11 @@ function createContextPreExec(
statementContext.cwd = statementOptions.cwd;
}

// if the describeOnly flag is specified, add it to the statement context
if (Util.exists(statementOptions.describeOnly)) {
statementContext.describeOnly = statementOptions.describeOnly;
}

// validate non-user-specified arguments
Errors.assertInternal(Util.isObject(services));
Errors.assertInternal(Util.isObject(connectionConfig));
Expand Down Expand Up @@ -1244,6 +1255,11 @@ function sendRequestPreExec(statementContext, onResultAvailable) {
json.asyncExec = statementContext.asyncExec;
}

// include describeOnly flag if a value was specified
if (Util.exists(statementContext.describeOnly)) {
json.describeOnly = statementContext.describeOnly;
}

// use the snowflake service to issue the request
sendSfRequest(statementContext,
{
Expand Down
1 change: 1 addition & 0 deletions lib/constants/error_messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ exports[409011] = 'Invalid fetchAsString value. The specified value must be an A
exports[409012] = 'Invalid fetchAsString type: %s. The supported types are: String, Boolean, Number, Date, Buffer, and JSON.';
exports[409013] = 'Invalid requestId. The specified value must be a string.';
exports[409014] = 'Invalid asyncExec. The specified value must be a boolean.';
exports[409015] = 'Invalid describeOnly. The specified value must be a boolean.';

// 410001
exports[410001] = 'Fetch-result options must be specified.';
Expand Down
1 change: 1 addition & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ codes.ERR_CONN_EXEC_STMT_INVALID_FETCH_AS_STRING = 409011;
codes.ERR_CONN_EXEC_STMT_INVALID_FETCH_AS_STRING_VALUES = 409012;
codes.ERR_CONN_EXEC_STMT_INVALID_REQUEST_ID = 409013;
codes.ERR_CONN_EXEC_STMT_INVALID_ASYNC_EXEC = 409014;
codes.ERR_CONN_EXEC_STMT_INVALID_DESCRIBE_ONLY = 409015;

// 410001
codes.ERR_CONN_FETCH_RESULT_MISSING_OPTIONS = 410001;
Expand Down
48 changes: 48 additions & 0 deletions test/integration/testExecute.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,54 @@ describe('Execute test', function () {
done
);
});

describe('testDescribeOnly', async function () {
const selectWithDescribeOnly = 'SELECT 1.0::NUMBER(30,2) as C1, 2::NUMBER(38,0) AS C2, \'t3\' AS C3, 4.2::DOUBLE AS C4, \'abcd\'::BINARY(8388608) AS C5, true AS C6';
const expectedRows = [{ 'C1': 1, 'C2': 2, 'C3': 't3', 'C4': 4.2, 'C5': { 'type': 'Buffer', 'data': [171, 205] }, 'C6': true }];
const testCases =
[
{
name: 'describeOnly - true',
describeOnly: true,
expectedRows: []
},
{
name: 'describeOnly - false',
describeOnly: false,
expectedRows: expectedRows
},
{
name: 'describeOnly - undefined',
describeOnly: undefined,
expectedRows: expectedRows
},
];

const executeQueryAndVerifyResultDependOnDescribeOnly = async (describeOnly, expectedReturnedRows) => {
return new Promise((resolve, reject) => {
connection.execute({
sqlText: selectWithDescribeOnly,
describeOnly: describeOnly,
complete: (err, stmt, rows) => {
if (err) {
return reject(err);
}
assert.strictEqual(stmt.getColumns().length, 6);
assert.strictEqual(rows.length, expectedReturnedRows.length);
if (rows.length > 0) {
const columnsNamesInMetadata = stmt.getColumns().map(cl => cl.getName());
const columnsNames = Object.keys(rows[0]);
columnsNames.every((element, index) => assert.strictEqual(element, columnsNamesInMetadata[index]));
}
return resolve(rows);
}
});
}
);
};

testCases.forEach(testCase => it(testCase.name, () => executeQueryAndVerifyResultDependOnDescribeOnly(testCase.describeOnly, testCase.expectedRows)));
});
});

describe('Execute test - variant', function () {
Expand Down
12 changes: 11 additions & 1 deletion test/unit/connection/statement_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ describe('Statement.execute()', function () {
connectionConfig: null
},
errorCode: ErrorCodes.ERR_CONN_EXEC_STMT_MISSING_SQL_TEXT
},
{
name: 'execute() invalid describeOnly',
options: {
statementOptions: {
sqlText: '',
describeOnly: 1,
},
},
errorCode: ErrorCodes.ERR_CONN_EXEC_STMT_INVALID_DESCRIBE_ONLY
}
];

Expand Down Expand Up @@ -404,4 +414,4 @@ describe('Statement.fetchResult()', function () {
testCase = testCases[index];
it(testCase.name, createItCallback(testCase));
}
});
});

0 comments on commit 00e3b95

Please sign in to comment.