From f832ec465f2ba1af27721c2719b0272317d1dd19 Mon Sep 17 00:00:00 2001 From: Pete Vilter Date: Wed, 24 Aug 2022 11:46:40 -0400 Subject: [PATCH 1/5] add toRelLiteral Co-Authored-By: Denis Gursky --- src/results/resultTable.ts | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/results/resultTable.ts b/src/results/resultTable.ts index 658d17f..1a691f7 100644 --- a/src/results/resultTable.ts +++ b/src/results/resultTable.ts @@ -395,6 +395,52 @@ export class ResultTable implements IteratorOf { arrow() { return this.table; } + + /** + * Return a Rel literal representation of this result table. + * + * @returns String + */ + toRelLiteral(): string { + if (this.length === 0) { + return '{}'; + } + + const typeDefs = this.typeDefs(); + + return ( + '{\n' + + this.values() + .map(row => { + const rel = row + .map((val: RelTypedValue['value'], index: number) => { + const typeDef = typeDefs[index]; + + switch (typeDef.type) { + case 'Constant': { + switch (typeDef.value.type) { + case 'String': { + return val; + } + case 'Int64': + return `#(${val})`; + } + break; + } + case 'String': + return `"${val}"`; + case 'Int64': + return val?.toString(); + } + }) + .join(', '); + + return `(${rel})`; + }) + .join(';\n') + + '\n}' + ); + } } function arrowRowToValues(arrowRow: StructRowProxy, colDefs: ColumnDef[]) { From 937c73309dd2d0b94570bafd4a0d413f31c469b6 Mon Sep 17 00:00:00 2001 From: Pete Vilter Date: Wed, 24 Aug 2022 15:12:52 -0400 Subject: [PATCH 2/5] tweak --- src/results/resultTable.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/results/resultTable.ts b/src/results/resultTable.ts index 1a691f7..4efcc4e 100644 --- a/src/results/resultTable.ts +++ b/src/results/resultTable.ts @@ -412,7 +412,7 @@ export class ResultTable implements IteratorOf { '{\n' + this.values() .map(row => { - const rel = row + const tuple = row .map((val: RelTypedValue['value'], index: number) => { const typeDef = typeDefs[index]; @@ -435,7 +435,7 @@ export class ResultTable implements IteratorOf { }) .join(', '); - return `(${rel})`; + return ` (${tuple})`; }) .join(';\n') + '\n}' From d471bd744e127fd4dc00590f957ac9bb3e57ea0e Mon Sep 17 00:00:00 2001 From: Pete Vilter Date: Wed, 24 Aug 2022 15:12:57 -0400 Subject: [PATCH 3/5] add example --- examples/execRelLiteral.ts | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 examples/execRelLiteral.ts diff --git a/examples/execRelLiteral.ts b/examples/execRelLiteral.ts new file mode 100644 index 0000000..3bcc07c --- /dev/null +++ b/examples/execRelLiteral.ts @@ -0,0 +1,72 @@ +/** + * 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, + ); + + result.results + .map(rel => new ResultTable(rel)) + .forEach(resultTable => console.log(resultTable.toRelLiteral())); +} + +(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()); + } +})(); From 10314187080295e823c8e071463dfccbe4226442 Mon Sep 17 00:00:00 2001 From: Pete Vilter Date: Wed, 24 Aug 2022 15:41:09 -0400 Subject: [PATCH 4/5] use getDisplayValue; only surround with curlies before printing --- examples/execRelLiteral.ts | 8 ++++--- src/results/resultTable.ts | 48 ++++++++++---------------------------- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/examples/execRelLiteral.ts b/examples/execRelLiteral.ts index 3bcc07c..390b148 100644 --- a/examples/execRelLiteral.ts +++ b/examples/execRelLiteral.ts @@ -38,9 +38,11 @@ async function run( tags, ); - result.results - .map(rel => new ResultTable(rel)) - .forEach(resultTable => console.log(resultTable.toRelLiteral())); + const literal = + '{\n' + + result.results.map(rel => new ResultTable(rel).toRelLiteral()).join(';\n') + + '\n}'; + console.log(literal); } (async () => { diff --git a/src/results/resultTable.ts b/src/results/resultTable.ts index 4efcc4e..a775a05 100644 --- a/src/results/resultTable.ts +++ b/src/results/resultTable.ts @@ -402,44 +402,20 @@ export class ResultTable implements IteratorOf { * @returns String */ toRelLiteral(): string { - if (this.length === 0) { - return '{}'; - } - const typeDefs = this.typeDefs(); - return ( - '{\n' + - this.values() - .map(row => { - const tuple = row - .map((val: RelTypedValue['value'], index: number) => { - const typeDef = typeDefs[index]; - - switch (typeDef.type) { - case 'Constant': { - switch (typeDef.value.type) { - case 'String': { - return val; - } - case 'Int64': - return `#(${val})`; - } - break; - } - case 'String': - return `"${val}"`; - case 'Int64': - return val?.toString(); - } - }) - .join(', '); - - return ` (${tuple})`; - }) - .join(';\n') + - '\n}' - ); + return this.values() + .map(row => { + const tuple = row + .map((val: RelTypedValue['value'], index: number) => { + const typeDef = typeDefs[index]; + return getDisplayValue(typeDef, val); + }) + .join(', '); + + return ` (${tuple})`; + }) + .join(';\n'); } } From c9abd1c5b896585b6d0a0910e6a08c0803b092bd Mon Sep 17 00:00:00 2001 From: Pete Vilter Date: Wed, 24 Aug 2022 15:44:23 -0400 Subject: [PATCH 5/5] keyword argument to quote strings --- src/results/resultTable.ts | 2 +- src/results/resultUtils.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/results/resultTable.ts b/src/results/resultTable.ts index a775a05..dac12c1 100644 --- a/src/results/resultTable.ts +++ b/src/results/resultTable.ts @@ -409,7 +409,7 @@ export class ResultTable implements IteratorOf { const tuple = row .map((val: RelTypedValue['value'], index: number) => { const typeDef = typeDefs[index]; - return getDisplayValue(typeDef, val); + return getDisplayValue(typeDef, val, true); }) .join(', '); 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':