From 38d889f20922c39354024eb144cfc95aefcf94d1 Mon Sep 17 00:00:00 2001 From: Aryan Jha Date: Sun, 2 Jul 2023 02:25:09 -0400 Subject: [PATCH] Partial Implementation of aliasing functionality. --- src/RelExpr.js | 9 +++++++++ src/RelOp.js | 13 ++++++++++++- src/modules/data.js | 30 ++++++++++++++++++++++++++++++ src/modules/relexp.js | 14 ++++++++++---- src/modules/relexp.test.js | 14 ++++++++++++++ 5 files changed, 75 insertions(+), 5 deletions(-) diff --git a/src/RelExpr.js b/src/RelExpr.js index a30c0f49b..dae71160d 100644 --- a/src/RelExpr.js +++ b/src/RelExpr.js @@ -1,6 +1,7 @@ // @flow import React, {useRef} from 'react'; import { + Alias, UnaryRelOp, Projection, Rename, @@ -97,6 +98,14 @@ const RelExpr: StatelessFunctionalComponent = (props) => { case 'relation': return ; + case 'alias': + return ( + + ); + case 'order_by': return ( = () => ( ); +export const Alias: StatelessFunctionalComponent<{ + value: string, + alias_value: string, +}> = (props) => { + return ( + + ρ{props.alias_value} {props.value} + + ); +}; + export const OrderBy: StatelessFunctionalComponent<{ columns: Array, relation: Node, @@ -146,7 +157,7 @@ export const OrderBy: StatelessFunctionalComponent<{ .join(', '); return ( - τ{columnSort} {props.relation} + τ{columnSort} {props.relation} ); }; diff --git a/src/modules/data.js b/src/modules/data.js index e81914c48..12cd3aabe 100644 --- a/src/modules/data.js +++ b/src/modules/data.js @@ -5,6 +5,7 @@ import {produce} from 'immer'; import department from '../resources/Department.json'; import doctor from '../resources/Doctor.json'; import patient from '../resources/Patient.json'; +import relation from '../Relation'; export const CHANGE_EXPR = 'CHANGE_EXPR'; export const RESET_EXPR = 'RESET_EXPR'; @@ -86,6 +87,29 @@ function getCombinedColumns(left: {[string]: any}, right: {[string]: any}) { return combinedColumns; } +function getAliasedOutput(relation: {[string]: any}, alias: string) { + const newColumns: Array = []; + const newData: Array<{[string]: any}> = []; + for (const column of relation.columns) { + const newColumnName = alias + '.' + column; + newColumns.push(newColumnName); + } + for (const datum of relation.data) { + let newDatum: {[string]: any} = {}; + for (const column of relation.columns) { + newDatum[alias + '.' + column] = datum[column]; + } + newData.push(newDatum); + } + + const output: Output = { + name: alias, + columns: newColumns, + data: newData, + }; + return output; +} + function getCombinedData( leftName: string, leftRow: {[string]: any}, @@ -327,6 +351,12 @@ function applyExpr( // Make a copy of the data from a source table and return it return {...sourceData[expr.relation]}; + case 'alias': + return getAliasedOutput( + sourceData[expr.alias.value], + expr.alias.alias_value + ); + case 'order_by': let ordData = applyExpr(expr.order_by.children[0], sourceData); diff --git a/src/modules/relexp.js b/src/modules/relexp.js index 70222172b..9ced5d7e5 100644 --- a/src/modules/relexp.js +++ b/src/modules/relexp.js @@ -279,7 +279,6 @@ function convertExpr( } default: - console.log(expr); // Produce an error if the expression is unsupported throw new Error('Invalid expression.'); } @@ -396,9 +395,16 @@ function buildRelExp( case 'TableFactor': // Store this table as one referenced by the query tables.push(sql.value.value); - - return {relation: sql.value.value}; - + if (sql.hasAs) { + return { + alias: { + value: sql.value.value, + alias_value: sql.alias.value, + }, + }; + } else { + return {relation: sql.value.value}; + } case 'InnerCrossJoinTable': // Add the condition if it exists if (sql.condition) { diff --git a/src/modules/relexp.test.js b/src/modules/relexp.test.js index c7ce0db33..d4ae70168 100644 --- a/src/modules/relexp.test.js +++ b/src/modules/relexp.test.js @@ -47,6 +47,20 @@ it('converts a rename', () => { }); }); +/** @test {relexp} */ +it('converts a aliasing operation', () => { + const sql = parser.parse('SELECT bar FROM foo as f'); + const action = exprFromSql(sql.value, {foo: ['bar']}); + expect(reducer({}, action)).toMatchObject({ + expr: { + projection: { + arguments: {project: ['bar']}, + children: [{alias: {alias_value: 'f', value: 'foo'}}], + }, + }, + }); +}); + /** @test {relexp} */ it('converts a difference', () => { const sql = parser.parse('SELECT * FROM foo EXCEPT SELECT * FROM bar');