Exemplo n.º 1
0
        public override Resultset Get(QueryContext queryContext, object[] parameters)
        {
            if (ChildNodes.Count != 2)
                throw new InvalidOperationException();

            Resultset rs1 = null;
            Resultset rs2 = null;

            Iterator.Invoke(new Action[] {
                () => rs1 = ChildNodes[0].Get(queryContext, parameters),
                () => rs2 = ChildNodes[1].Get(queryContext, parameters)
            });

            if (!rs1.RowType.RowTypeEquals(rs2.RowType))
                throw new ESQLException(Properties.Resources.IncorrectSubqueries);

            RowType.TypeInfo[] typeInfo = new RowType.TypeInfo[rs1.RowType.Fields.Length];
            for (int k = 0; k < typeInfo.Length; k++)
                if (_type == ConnectorType.ComplexUnion)
                    typeInfo[k] = rs1.RowType.Fields[k];
                else
                    typeInfo[k] = new RowType.TypeInfo(k,
                        rs1.RowType.Fields[k], rs2.RowType.Fields[k]);

            DemandProcessingContext context;
            if (_type == ConnectorType.Union && _allTag)
            {
                context = new DataConcateContext(rs1, rs2);
                return new Resultset(new RowType(typeInfo), context);
            }
            else
            {
                if (_allTag)
                    throw new NotImplementedException();
                Resultset rs = new Resultset(new RowType(typeInfo), null);
                IEqualityComparer<Row> comp;
                if (_type == ConnectorType.ComplexUnion)
                    comp = new RowEqualityComplexComparer();
                else
                    comp = new RowEqualityComparer();
                HashSet<Row> set1 = new HashSet<Row>(comp);
                HashSet<Row> set2 = new HashSet<Row>(comp);
                Iterator.Invoke(new Action[] {
                () => {
                    while (rs1.Begin != null)
                        set1.Add(rs1.Dequeue()); },
                () => {
                    while (rs2.Begin != null)
                        set2.Add(rs2.Dequeue()); }});
                switch (_type)
                {
                    case ConnectorType.Union:
                    case ConnectorType.ComplexUnion:
                        set1.UnionWith(set2);
                        break;

                    case ConnectorType.Except:
                        set1.ExceptWith(set2);
                        break;

                    case ConnectorType.Intersect:
                        set1.IntersectWith(set2);
                        break;
                }
                foreach (Row row in set1)
                    rs.Enqueue(row);
                return rs;
            }

        }
Exemplo n.º 2
0
 public override Resultset Get(QueryContext queryContext, object[] parameters)
 {
     // Prepare bindings
     Resultset source = ChildNodes[0].Get(queryContext, parameters);
     List<ColumnBinding> bindings = new List<ColumnBinding>();            
     ExpressionTransformer transformer = new ExpressionTransformer(bindings);
     foreach (RowType.TypeInfo ti in source.RowType.Fields)
         foreach (RowType.TypeInfo nested_ti in ti.NestedType.Fields)
             if (!nested_ti.IsHidden && nested_ti.IsNatural)
             {
                 ColumnBinding b = new ColumnBinding();
                 b.typecode = Type.GetTypeCode(nested_ti.DataType);
                 b.rnum = ti.Ordinal;
                 b.TableName = ti.Name;
                 b.Name = nested_ti.Name;
                 b.fieldType = nested_ti;
                 b.natural = nested_ti.IsNatural;
                 b.container = nested_ti.IsContainer;
                 b.caseSensitive = nested_ti.IsCaseSensitive;
                 b.data = new SymbolLink(nested_ti.DataType);
                 bindings.Add(b);
                 if (nested_ti.IsContainer)
                     transformer.NeedTransform = true;
             }
     foreach (RowType.TypeInfo ti in source.RowType.Fields)
         foreach (RowType.TypeInfo nested_ti in ti.NestedType.Fields)
             if (!nested_ti.IsHidden && !nested_ti.IsNatural)
             {
                 ColumnBinding b = new ColumnBinding();
                 b.typecode = Type.GetTypeCode(nested_ti.DataType);
                 b.rnum = ti.Ordinal;
                 b.TableName = ti.Name;
                 b.Name = nested_ti.Name;
                 b.fieldType = nested_ti;
                 b.natural = nested_ti.IsNatural;
                 b.container = nested_ti.IsContainer;
                 b.caseSensitive = nested_ti.IsCaseSensitive;
                 b.data = new SymbolLink(nested_ti.DataType);
                 bindings.Add(b);
                 if (nested_ti.IsContainer)
                     transformer.NeedTransform = true;
             }
     // Expand columns.
     // On this step we transform select table.* and select * to select field1,...
     List<Column> columns = new List<Column>();
     if (_targets == null) // Select fields from all selected tables
     {
         foreach (ColumnBinding b in bindings)
             columns.Add(new Column(ATOM.Create(null, new string[] { b.TableName, b.Name }, false)));
     }
     else
         foreach (Column col in _targets)
         {
             if (Lisp.IsFunctor(col.Expr, Table)) // Select fields from specified table
             {
                 bool found = false;
                 String name = (String)Lisp.Second(col.Expr);
                 var tableBindings =
                         from b in bindings
                         where b.TableName == name
                         select b;
                 foreach (ColumnBinding b in tableBindings)
                 {
                     columns.Add(new Column(ATOM.Create(null, new string[] { b.TableName, b.Name }, false)));
                     found = true;
                 }
                 if (!found)
                     throw new ESQLException(Properties.Resources.InvalidIdentifier, name);
             }
             else // Select expression specified
                 if (transformer.NeedTransform)
                 {
                     Column c = new Column();
                     c.Alias = col.Alias;
                     c.Expr = transformer.Process(col.Expr);
                     columns.Add(c);
                 }
                 else
                     columns.Add(col);
         }
     // Create demand context   
     FunctionLink[] compiledBody = new FunctionLink[columns.Count];
     SelectorResolver resolver = new SelectorResolver(new Binder(bindings));
     SelectorContext context = new SelectorContext(this, _distinct, columns.ToArray(),
         resolver, source, queryContext, parameters, compiledBody);
     // Create columns type info and generate unique column names by field name and alias
     RowType.TypeInfo[] fields = new RowType.TypeInfo[columns.Count];
     List<String> fieldNames = new List<string>();
     int p = 1;
     for (int k = 0; k < fields.Length; k++)
     {
         String name;
         RowType.TypeInfo fieldType = null;                
         object expr = columns[k].Expr;
         compiledBody[k] = new FunctionLink();
         Type resType = context.LispExecutive.Compile(null, expr, compiledBody[k]);                
         if (Lisp.IsAtom(expr))
         {
             ColumnBinding b = resolver.GetBinding(expr);
             if (b != null)
                 fieldType = b.fieldType;
         }
         else if (Lisp.IsNode(expr) && expr is String)
         {
             fieldType = new RowType.TypeInfo(null, typeof(String),
                 TypeConverter.GetValueSize(expr));
         }
         else if (Lisp.IsFunctor(expr, ID.ParamRef))
         {
             object value = parameters[(int)Lisp.Arg1(expr)];
             fieldType = new RowType.TypeInfo(null, value.GetType(),
                 TypeConverter.GetValueSize(value));
         }
         else if (Lisp.IsFunctor(expr, ID.ToString))
         {
             if (Lisp.Length(expr) == 3)
                 fieldType = new RowType.TypeInfo(null, typeof(String), (int)Lisp.Arg2(expr));
             else
                 fieldType = new RowType.TypeInfo(null, typeof(String), 0);
         }
         else if (Lisp.IsFunctor(expr, ID.ToInt16))
             fieldType = new RowType.TypeInfo(null, typeof(Int16), 0);
         else if (Lisp.IsFunctor(expr, ID.ToInt32))
             fieldType = new RowType.TypeInfo(null, typeof(Int32), 0);
         else if (Lisp.IsFunctor(expr, ID.ToInt64))
             fieldType = new RowType.TypeInfo(null, typeof(Int64), 0);
         else if (Lisp.IsFunctor(expr, ID.ToSingle))
             fieldType = new RowType.TypeInfo(null, typeof(Single), 0);
         else if (Lisp.IsFunctor(expr, ID.ToDouble))
             fieldType = new RowType.TypeInfo(null, typeof(Double), 0);
         else if (Lisp.IsFunctor(expr, ID.ToDecimal))
             fieldType = new RowType.TypeInfo(null, typeof(Decimal), 0);
         else if (Lisp.IsFunctor(expr, ID.ToDateTime))
             fieldType = new RowType.TypeInfo(null, typeof(DateTime), 0);
         else
             fieldType = new RowType.TypeInfo(null, resType, 0);
         if (!String.IsNullOrEmpty(columns[k].Alias))
             name = columns[k].Alias;
         else
             if (fieldType.Name == null)
                 name = String.Format("Expr{0}", p++);
             else
                 name = fieldType.Name;                
         fields[k] = new RowType.TypeInfo(k, 
             Util.CreateUniqueName(fieldNames, name), fieldType);                
     }
     ScanDynatableAccessors(ChildNodes[0], resolver);
     return new Resultset(new RowType(fields), context);            
 }