public object Translate(TranslationContext context, ASTNode node) { var result = new SQLModel.TableExpression(); var sqlContext = (SQLTranslationContext)context; result.TableName = sqlContext.GetExpressionObjectName(String.Format("{0}.{1}", node.GetAttribute<string>("libraryName", sqlContext.ArtifactName), node.GetAttribute<string>("name"))); // If the expression being referenced is scalar, it will be automatically promoted to a query by the expression def translation // In this case, it must be demoted back to a scalar expression with a subquery access. if (!(node.ResultType is ListType) && !(node.ResultType is ObjectType)) { var selectExpression = new SQLModel.SelectExpression(); selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.Columns.Add(new SQLModel.ColumnExpression(new SQLModel.QualifiedFieldExpression("value"))); selectExpression.FromClause = new SQLModel.CalculusFromClause(new SQLModel.TableSpecifier(result)); // If the result type is also boolean, the expression will be converted to a 1 or 0, so it must be demoted back to an actual boolean-valued expression if (DataTypes.Equal(node.ResultType, DataTypes.Boolean)) { return SQLTranslationUtilities.DemoteBooleanValuedExpression(selectExpression); } return selectExpression; } return result; }
protected override void EmitSelectExpression(SQL.SelectExpression expression) { AppendFormat("{0} /*+ {1}*/ ", SQL.Keywords.Select, expression is SelectExpression ? ((SelectExpression)expression).OptimizerHints : "FIRST_ROWS(20)"); IncreaseIndent(); EmitSelectClause(expression.SelectClause); EmitFromClause(expression.FromClause); EmitWhereClause(expression.WhereClause); EmitGroupClause(expression.GroupClause); EmitHavingClause(expression.HavingClause); DecreaseIndent(); }
/// <summary> /// Ensures that the given expression, if not a select expression, is promoted to a select expression. /// </summary> /// <param name="expression"></param> /// <returns></returns> public static Model.Expression EnsureSelectExpression(object expression) { if (!(expression is SQLModel.SelectExpression) && !(expression is SQLModel.QueryExpression) && !(expression is SQLModel.SelectStatement) && !(expression is SQLModel.SelectStatementExpression)) { var selectExpression = new SQLModel.SelectExpression(); selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.Columns.Add(new SQLModel.ColumnExpression((Model.Expression)expression, "value")); return(selectExpression); } return(EnsureSelectStatementExpression(expression)); }
/// <summary> /// Ensures that the given expression, if not a select expression, is promoted to a select expression. /// </summary> /// <param name="expression"></param> /// <returns></returns> public static Model.Expression EnsureSelectExpression(object expression) { if (!(expression is SQLModel.SelectExpression) && !(expression is SQLModel.QueryExpression) && !(expression is SQLModel.SelectStatement) && !(expression is SQLModel.SelectStatementExpression)) { var selectExpression = new SQLModel.SelectExpression(); selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.Columns.Add(new SQLModel.ColumnExpression((Model.Expression)expression, "value")); return selectExpression; } return EnsureSelectStatementExpression(expression); }
protected override void EmitSelectExpression(SQL.SelectExpression expression) { AppendFormat("{0} ", Alphora.Dataphor.DAE.Language.SQL.Keywords.Select); IncreaseIndent(); EmitSelectClause(expression.SelectClause); EmitFromClause(expression.FromClause); EmitWhereClause(expression.WhereClause); EmitGroupClause(expression.GroupClause); EmitHavingClause(expression.HavingClause); // Add the "for" clause var pgSelect = expression as SelectExpression; if (pgSelect != null) { EmitForClause(pgSelect.ForSpecifier); } DecreaseIndent(); }
public object Translate(TranslationContext context, ASTNode node) { // In(element, interval)... // In(element, list) // Translate as: // exists (select * from (<list>) T where <element equality condition>) // As long as this is list containment, it can be translated using an Exists(Filter(Collection, Condition(Current = Element))); var elementNode = node.Children[0]; var collectionNode = node.Children[1]; if (elementNode.ResultType is ListType) { throw new NotSupportedException("In translation with an element of type list is not supported because there is no equivalent SQL representation."); } if (collectionNode.ResultType is ListType) { var selectExpression = new SQLModel.SelectExpression(); selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.NonProject = true; selectExpression.FromClause = new SQLModel.CalculusFromClause(new SQLModel.TableSpecifier(SQLTranslationUtilities.EnsureSelectStatementExpression(context.TranslateNode(collectionNode)), "T")); selectExpression.WhereClause = new SQLModel.WhereClause(); Model.Expression condition = null; if (elementNode.ResultType is ObjectType) { foreach (var property in ((ObjectType)elementNode.ResultType).Properties) { // TODO: O is an assumed alias here, need a way to establish the outer context for comparison of the element.... var propertyCondition = new Model.BinaryExpression(new SQLModel.QualifiedFieldExpression(property.Name, "T"), "iEqual", new SQLModel.QualifiedFieldExpression(property.Name, "O")); if (condition == null) { condition = propertyCondition; } else { condition = new Model.BinaryExpression(condition, "iAnd", propertyCondition); } } } else { condition = new Model.BinaryExpression(new SQLModel.QualifiedFieldExpression("value", "T"), "iEqual", (Model.Expression)context.TranslateNode(elementNode)); } selectExpression.WhereClause.Expression = condition; return selectExpression; } else { var betweenExpression = new Model.BetweenExpression(); betweenExpression.Expression = (Model.Expression)context.TranslateNode(elementNode); // TODO: Translate an interval selector.... betweenExpression.LowerExpression = new Model.ValueExpression(1); betweenExpression.UpperExpression = new Model.ValueExpression(1); return betweenExpression; } }
public object Translate(TranslationContext context, ASTNode node) { var selectExpression = new SQLModel.SelectExpression(); selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.NonProject = true; selectExpression.FromClause = new SQLModel.CalculusFromClause(new SQLModel.TableSpecifier(new SQLModel.TableExpression("ValueSet"), "VS")); selectExpression.WhereClause = new SQLModel.WhereClause(); var valueSetName = node.GetAttribute<String>("name"); var valueSetLibraryName = node.GetAttribute<String>("libraryName", ((SQLTranslationContext)context).ArtifactName); var valueSetCondition = new Model.BinaryExpression ( new SQLModel.QualifiedFieldExpression("ValueSetName", "VS"), "iEqual", new Model.ValueExpression(String.Format("{0}.{1}", valueSetLibraryName, valueSetName), Model.TokenType.String) ); selectExpression.WhereClause.Expression = valueSetCondition; return selectExpression; }
public object Translate(TranslationContext context, ASTNode node) { var requestListType = node.ResultType as ListType; var requestType = (requestListType == null ? node.ResultType : requestListType.ElementType) as ObjectType; if (requestType == null) { throw new InvalidOperationException(String.Format("Unable to determine request type from source type: '{0}'.", node.ResultType.Name)); } Model.Expression condition = null; // Translate Codes var codes = node.Children.Where(n => n.Name == "codes").FirstOrDefault(); if (codes != null) { var codesResult = context.TranslateNode(codes); // codesResult will be a select statement returning the list of codes // So the retrieve must include a where condition limiting the code property to the set of codes (same as InValueSet translation) var codeExpression = SQLTranslationUtilities.ResolvePath(node.GetAttribute<string>("codeProperty"), "T"); var selectExpression = (SQLModel.SelectExpression)codesResult; // This assumes the codes element is a ValueSetRef... selectExpression.WhereClause.Expression = new Model.BinaryExpression ( selectExpression.WhereClause.Expression, "iAnd", new Model.BinaryExpression(codeExpression, "iEqual", new SQLModel.QualifiedFieldExpression("Code", "VS")) ); var codeCondition = new Model.UnaryExpression("iExists", selectExpression); if (condition != null) { condition = new Model.BinaryExpression(condition, "iAnd", codeCondition); } else { condition = codeCondition; } } // Translate DateRange var dateRange = node.Children.Where(n => n.Name == "dateRange").FirstOrDefault(); if (dateRange != null) { var dateRangeResult = context.TranslateNode(dateRange); var dateExpression = SQLTranslationUtilities.ResolvePath(node.GetAttribute<string>("dateProperty"), "T"); // dateRangeResult will be an interval-valued expression // So the retrieve must include a where condition limiting the date range property to the interval (same as In(date, interval) translation) var dateRangeCondition = new Model.BetweenExpression(); dateRangeCondition.Expression = dateExpression; // TODO: //dateRangeCondition.LowerExpression = // dateRangeResult.Low... //dateRangeCondition.UpperExpression = // dateRangeResult.High... //if (condition != null) //{ // condition = new Model.BinaryExpression(condition, "iAnd", dateRangeCondition); //} //else //{ // condition = codeCondition; //} } // For FHIR, there will also potentially need to be profile filters... // This depends on how the FHIR model is realized within the SQL structures... var inQueryContext = ((SQLTranslationContext)context).InQueryContext(); // Within a Query Context, a retrieve is part of a FromClause var tableExpression = new SQLModel.TableExpression(requestType.Name); if (inQueryContext && (condition == null)) { return tableExpression; } else { var selectExpression = new SQLModel.SelectExpression(); selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.Distinct = false; selectExpression.SelectClause.NonProject = true; selectExpression.FromClause = new SQLModel.CalculusFromClause(new SQLModel.TableSpecifier(tableExpression, "T")); if (condition != null) { selectExpression.WhereClause = new SQLModel.WhereClause(); selectExpression.WhereClause.Expression = condition; } return selectExpression; } }
private Model.Expression TranslateRelationshipClause(TranslationContext context, Node relationship) { var relatedTableSpecifier = TranslateAliasedQuerySource(context, relationship); var relatedConditionNode = (ASTNode)relationship.Children.Where(n => n.Name == "suchThat").Single(); var relatedCondition = (Model.Expression)context.TranslateNode(relatedConditionNode); var relatedSelect = new SQLModel.SelectExpression(); relatedSelect.SelectClause = new SQLModel.SelectClause(); relatedSelect.SelectClause.NonProject = true; relatedSelect.SelectClause.Distinct = false; relatedSelect.FromClause = new SQLModel.CalculusFromClause(relatedTableSpecifier); relatedSelect.WhereClause = new SQLModel.WhereClause(relatedCondition); var relatedExists = new Model.UnaryExpression("iExists", relatedSelect); if (relationship.NodeType.GetLocalName() == "Without") { return new Model.UnaryExpression("iNot", relatedExists); } else { return relatedExists; } }
public object Translate(TranslationContext context, ASTNode node) { var selectExpression = new SQLModel.SelectExpression(); var fromClause = new SQLModel.CalculusFromClause(); selectExpression.FromClause = fromClause; var queryExpression = new SQLModel.QueryExpression(); queryExpression.SelectExpression = selectExpression; var selectStatement = new SQLModel.SelectStatement(); selectStatement.QueryExpression = queryExpression; // 1..* source: AliasedQuerySource foreach (var child in ((Node)node).Children.Where(n => n.Name == "source")) { var tableSpecifier = TranslateAliasedQuerySource(context, child); fromClause.TableSpecifiers.Add(tableSpecifier); } // 0..* define: DefineClause foreach (var child in ((Node)node).Children.Where(n => n.Name == "define")) { // TODO: This would need to be nested to be accessible within context in the SQL query throw new NotImplementedException("Define clause translation is not yet implemented"); } // 0..* relationship: With | Without Model.Expression relationshipConditions = null; foreach (var child in ((Node)node).Children.Where(n => n.Name == "relationship")) { var relationshipCondition = TranslateRelationshipClause(context, child); if (relationshipConditions != null) { relationshipConditions = new Model.BinaryExpression(relationshipConditions, "iAnd", relationshipCondition); } else { relationshipConditions = relationshipCondition; } } // 0..1 where: Expression Model.Expression whereCondition = null; var whereConditionNode = node.Children.SingleOrDefault(n => n.Name == "where"); if (whereConditionNode != null) { whereCondition = (Model.Expression)context.TranslateNode(whereConditionNode); } // 0..1 return: ReturnClause var returnClause = ((Node)node).Children.SingleOrDefault(n => n.Name == "return"); if (returnClause != null) { var selectClause = TranslateReturnClause(context, returnClause); selectExpression.SelectClause = selectClause; } if (selectExpression.SelectClause == null) { selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.NonProject = true; } // 0..1 sort: SortClause var sortClause = ((Node)node).Children.SingleOrDefault(n => n.Name == "sort"); if (sortClause != null) { var orderClause = TranslateSortClause(context, sortClause); selectStatement.OrderClause = orderClause; } return selectStatement; }
public object Translate(TranslationContext context, ASTNode node) { // If the property has a source // select propertyName as value from (<source>) // Else // If the property has a scope // It's a qualified field expression // Else // It's an identifier expression // TODO: Handle nested and indexed paths... var path = node.GetAttribute<string>("path"); var source = node.Children.Where(c => c.Name == "source").FirstOrDefault(); if (source != null) { var selectExpression = new SQLModel.SelectExpression(); selectExpression.SelectClause = new SQLModel.SelectClause(); selectExpression.SelectClause.Columns.Add(new SQLModel.ColumnExpression(SQLTranslationUtilities.ResolvePath(path, "T"), "value")); selectExpression.FromClause = new SQLModel.CalculusFromClause(new SQLModel.TableSpecifier(SQLTranslationUtilities.EnsureExpression(context.TranslateNode(source)), "T")); return selectExpression; } else { var scope = node.GetAttribute<string>("scope", VerificationContext.Current); if (scope != VerificationContext.Current) { return SQLTranslationUtilities.ResolvePath(path, "T"); } else { return SQLTranslationUtilities.ResolvePath(path, null); } } //var sourceType = node.GetAttribute<ObjectType>("sourceType"); // Translate path information //return context.TransformModelPath(sourceType, node, node.GetAttribute<string>("path")); }