You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.1 KiB
JavaScript

/*
* Copyright DataStax, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const vm = require('vm');
const utils = require('../utils');
const types = require('../types');
/**
* @ignore
*/
class ResultMapper {
/**
* Gets a generated function to adapt the row to a document.
* @param {ModelMappingInfo} info
* @param {ResultSet} rs
* @returns {Function}
*/
static getSelectAdapter(info, rs) {
const columns = rs.columns;
if (!columns) {
throw new Error('Expected ROWS result obtained VOID');
}
let scriptText = '(function rowAdapter(row, info) {\n' +
' const item = info.newInstance();\n';
for (const c of columns) {
scriptText += ` item['${info.getPropertyName(c.name)}'] = `;
if (!info.getToModelFn(c.name)) {
scriptText += `row['${c.name}'];\n`;
} else {
scriptText += `info.getToModelFn('${c.name}')(row['${c.name}']);\n`;
}
}
scriptText += ' return item;\n})';
const script = new vm.Script(scriptText, { filename: 'gen-result-mapper.js'});
return script.runInThisContext();
}
/**
* Gets a function used to adapt VOID results or conditional updates.
* @param {ResultSet} rs
* @returns {Function}
*/
static getMutationAdapter(rs) {
if (rs.columns === null) {
// VOID result
return utils.noop;
}
if (
rs.columns.length === 1 && rs.columns[0].name === '[applied]' &&
rs.columns[0].type.code === types.dataTypes.boolean) {
return utils.noop;
}
return ResultMapper._getConditionalRowAdapter(rs);
}
static _getConditionalRowAdapter(rs) {
return (function conditionalRowAdapter(row, info) {
const item = info.newInstance();
// Skip the first column ("[applied]")
for (let i = 1; i < rs.columns.length; i++) {
const c = rs.columns[i];
item[info.getPropertyName(c.name)] = row[c.name];
}
return item;
});
}
/**
* @param {ModelMappingInfo} info
* @param {ResultSet} rs
* @returns {{canCache: Boolean, fn: Function}}
*/
static getCustomQueryAdapter(info, rs) {
if (rs.columns === null || rs.columns.length === 0) {
// VOID result
return { canCache: true, fn: utils.noop };
}
if (rs.columns[0].name === '[applied]' && rs.columns[0].type.code === types.dataTypes.boolean) {
// Conditional update results adapter functions should not be cached
return { canCache: false, fn: ResultMapper._getConditionalRowAdapter(rs) };
}
return { canCache: true, fn: ResultMapper.getSelectAdapter(info, rs) };
}
}
module.exports = ResultMapper;