Exemple #1
0
 protected virtual void EmitBetweenExpression(BetweenExpression expression)
 {
     Append("(");
     EmitExpression(expression.Expression);
     Append(" between ");
     EmitExpression(expression.LowerExpression);
     Append(" and ");
     EmitExpression(expression.UpperExpression);
     Append(")");
 }
        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 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;
            }
        }