/* Copyright (c) Microsoft Corporation All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ // // © Microsoft Corporation. All rights reserved. // using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Globalization; using System.Reflection; using System.Linq.Expressions; using System.Linq; using System.Diagnostics; using Microsoft.Research.DryadLinq.Internal; namespace Microsoft.Research.DryadLinq { public interface IMultiQueryable { Type ElementType(int index); Expression Expression { get; } IQueryProvider Provider { get; } UInt32 NumberOfInputs { get; } } public interface IKeyedMultiQueryable : IMultiQueryable { IQueryable this[K key] { get; } K[] Keys { get; } } public interface IMultiQueryable : IMultiQueryable { IQueryable First { get; } IQueryable Second { get; } } public interface IMultiQueryable : IMultiQueryable { IQueryable First { get; } IQueryable Second { get; } IQueryable Third { get; } } public class MultiQueryable : IKeyedMultiQueryable { private IQueryable m_source; private Expression m_queryExpression; private IMultiEnumerable m_enumerables; private K[] m_keys; private Dictionary m_keyMap; public MultiQueryable(IQueryable source, K[] keys, IMultiEnumerable enumerables) { this.m_source = source; this.m_queryExpression = null; this.m_enumerables = enumerables; this.m_keys = new K[keys.Length]; this.m_keyMap = new Dictionary(keys.Length); for (int i = 0; i < keys.Length; i++) { this.m_keys[i] = keys[i]; this.m_keyMap.Add(keys[i], i); } } public MultiQueryable(IQueryable source, K[] keys, Expression queryExpr) { this.m_source = source; this.m_queryExpression = queryExpr; this.m_enumerables = null; this.m_keys = new K[keys.Length]; this.m_keyMap = new Dictionary(keys.Length); for (int i = 0; i < keys.Length; i++) { this.m_keys[i] = keys[i]; this.m_keyMap.Add(keys[i], i); } } public Type ElementType(int index) { return typeof(T); } public Expression Expression { get { return this.m_queryExpression; } } public IQueryProvider Provider { get { return this.m_source.Provider; } } public UInt32 NumberOfInputs { get { if (this.m_enumerables != null) { return (UInt32)this.m_enumerables.NumberOfInputs; } return (UInt32)this.m_keys.Length; } } public K[] Keys { get { return this.m_keys; } } public IQueryable this[K key] { get { int index; if (this.m_keyMap.TryGetValue(key, out index)) { if (this.m_enumerables != null) { var q = this.m_enumerables[index].AsQueryable(); return new DryadLinqLocalQuery(this.Provider, q); } return this.ForkChoose(index); } //@@TODO: throw ArgumentOutOfRangeException? throw new DryadLinqException(HpcLinqErrorCode.MultiQueryableKeyOutOfRange, SR.MultiQueryableKeyOutOfRange); } } } public class MultiQueryable : IMultiQueryable { private IQueryable m_source; private Expression m_queryExpression; private IMultiEnumerable m_enumerables; public MultiQueryable(IQueryable source, IMultiEnumerable enumerables) { this.m_source = source; this.m_queryExpression = null; this.m_enumerables = enumerables; } public MultiQueryable(IQueryable source, Expression queryExpr) { this.m_source = source; this.m_queryExpression = queryExpr; this.m_enumerables = null; } public Type ElementType(int index) { if (index == 0) { return typeof(R1); } else if (index == 1) { return typeof(R2); } else { //@@TODO: throw ArgumentOutOfRangeException? throw new DryadLinqException(HpcLinqErrorCode.IndexOutOfRange, SR.IndexOutOfRange); } } public Expression Expression { get { return this.m_queryExpression; } } public IQueryProvider Provider { get { return this.m_source.Provider; } } public UInt32 NumberOfInputs { get { return 2; } } public IQueryable First { get { if (this.m_enumerables != null) { var q = this.m_enumerables.First.AsQueryable(); return new DryadLinqLocalQuery(this.Provider, q); } return this.ForkChoose(0); } } public IQueryable Second { get { if (this.m_enumerables != null) { var q = this.m_enumerables.Second.AsQueryable(); return new DryadLinqLocalQuery(this.Provider, q); } return this.ForkChoose(1); } } } public class MultiQueryable : IMultiQueryable { private IQueryable m_source; private Expression m_queryExpression; private IMultiEnumerable m_enumerables; public MultiQueryable(IQueryable source, Expression queryExpr) { this.m_source = source; this.m_queryExpression = queryExpr; this.m_enumerables = null; } public MultiQueryable(IQueryable source, IMultiEnumerable enumerables) { this.m_source = source; this.m_queryExpression = null; this.m_enumerables = enumerables; } public Type ElementType(int index) { if (index == 0) { return typeof(R1); } else if (index == 1) { return typeof(R2); } else if (index == 2) { return typeof(R3); } else { //@@TODO: throw ArgumentOutOfRangeException? throw new DryadLinqException(HpcLinqErrorCode.IndexOutOfRange, SR.IndexOutOfRange); } } public Expression Expression { get { return this.m_queryExpression; } } public IQueryProvider Provider { get { return this.m_source.Provider; } } public UInt32 NumberOfInputs { get { return 3; } } public IQueryable First { get { if (this.m_enumerables != null) { var q = this.m_enumerables.First.AsQueryable(); return new DryadLinqLocalQuery(this.Provider, q); } return this.ForkChoose(0); } } public IQueryable Second { get { if (this.m_enumerables != null) { var q = this.m_enumerables.Second.AsQueryable(); return new DryadLinqLocalQuery(this.Provider, q); } return this.ForkChoose(1); } } public IQueryable Third { get { if (this.m_enumerables != null) { var q = this.m_enumerables.Third.AsQueryable(); return new DryadLinqLocalQuery(this.Provider, q); } return this.ForkChoose(2); } } } }