public object Translate(TranslationContext context, ASTNode node) { // Use LogicalConnective Model.Expression result = null; foreach (var child in node.Children) { var expression = (Model.Expression)context.TranslateNode(child); if (result == null) { result = expression; } else { var binaryExpression = new Model.BinaryExpression(); binaryExpression.Instruction = GetOperator(); binaryExpression.LeftExpression = result; binaryExpression.RightExpression = expression; result = binaryExpression; } } return result; }
public object Translate(TranslationContext context, ASTNode node) { var result = new Model.BinaryExpression(); result.Instruction = GetOperator(); result.LeftExpression = (Model.Expression)context.TranslateNode(node.Children[0]); result.RightExpression = (Model.Expression)context.TranslateNode(node.Children[1]); return result; }
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; } }
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; }