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; }
public object Translate(TranslationContext context, ASTNode node) { var result = new SQLModel.TableExpression(); // TODO: Handle Cardinality // TODO: Handle whether we are in a FromClause context. var sqlContext = (SQLTranslationContext)context; result.TableName = sqlContext.GetExpressionObjectName(String.Format("{0}.{1}", node.GetAttribute<string>("libraryName", sqlContext.ArtifactName), node.GetAttribute<string>("name"))); return result; }
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; } }