diff --git a/examples/execRelLiteral.ts b/examples/execRelLiteral.ts new file mode 100644 index 0000000..390b148 --- /dev/null +++ b/examples/execRelLiteral.ts @@ -0,0 +1,74 @@ +/** + * Copyright 2021 RelationalAI, 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. + */ + +import { Command } from 'commander'; + +import { Client, readConfig, ResultTable } from '../index.node'; + +async function run( + database: string, + engine: string, + queryString: string, + readonly: boolean, + tag: string, + profile?: string, +) { + const config = await readConfig(profile); + const client = new Client(config); + const tags = tag ? [tag] : undefined; + const result = await client.exec( + database, + engine, + queryString, + [], + readonly, + tags, + ); + + const literal = + '{\n' + + result.results.map(rel => new ResultTable(rel).toRelLiteral()).join(';\n') + + '\n}'; + console.log(literal); +} + +(async () => { + const program = new Command(); + + const options = program + .requiredOption('-d, --database ', 'database name') + .requiredOption('-e, --engine ', 'engine name') + .requiredOption('-c, --command ', 'rel source string') + .option('-t, --tag ', 'tag', '') + .option('-r, --readonly', 'readonly', false) + .option('--poll', 'poll results', false) + .option('-p, --profile ', 'profile', 'default') + .parse(process.argv) + .opts(); + + try { + await run( + options.database, + options.engine, + options.command, + options.readonly, + options.tag, + options.profile, + ); + } catch (error: any) { + console.error(error.toString()); + } +})(); diff --git a/src/results/resultTable.ts b/src/results/resultTable.ts index 658d17f..dac12c1 100644 --- a/src/results/resultTable.ts +++ b/src/results/resultTable.ts @@ -395,6 +395,28 @@ export class ResultTable implements IteratorOf { arrow() { return this.table; } + + /** + * Return a Rel literal representation of this result table. + * + * @returns String + */ + toRelLiteral(): string { + const typeDefs = this.typeDefs(); + + return this.values() + .map(row => { + const tuple = row + .map((val: RelTypedValue['value'], index: number) => { + const typeDef = typeDefs[index]; + return getDisplayValue(typeDef, val, true); + }) + .join(', '); + + return ` (${tuple})`; + }) + .join(';\n'); + } } function arrowRowToValues(arrowRow: StructRowProxy, colDefs: ColumnDef[]) { diff --git a/src/results/resultUtils.ts b/src/results/resultUtils.ts index 5e5ead8..e29ccac 100644 --- a/src/results/resultUtils.ts +++ b/src/results/resultUtils.ts @@ -462,6 +462,7 @@ export function convertValue( export function getDisplayValue( typeDef: RelTypeDef, value: RelTypedValue['value'], + quoteStrings = false, ): string { const val = { ...typeDef, @@ -474,7 +475,9 @@ export function getDisplayValue( switch (val.type) { case 'String': - return JSON.stringify(val.value).slice(1, -1); + return quoteStrings + ? JSON.stringify(val.value) + : JSON.stringify(val.value).slice(1, -1); case 'Bool': return val.value ? 'true' : 'false'; case 'Char':