/*
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.
*/
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
{
///
/// The base interface to access a collection of IQueryable instances. The
/// DryadLINQ Fork operator returns a value that implements this interface.
///
public interface IMultiQueryable
{
///
/// Gets the element type of the query at a specified index.
///
/// The index
/// A Type that represents the type of the elements
Type ElementType(int index);
///
/// Gets the expression tree that is associated with this instance of IMultiQueryable
///
Expression Expression { get; }
///
/// Gets the query provider that is associated with this instance of IMultiQueryable
///
IQueryProvider Provider { get; }
///
/// Gets the number of queries in this instance of IMultiQueryable
///
UInt32 NumberOfInputs { get; }
}
///
/// The interface to access a collection of two IQueryable{T} instances.
///
/// The element type of the first IQueryable{T}
/// The element type of the second IQueryable{T}
public interface IMultiQueryable : IMultiQueryable
{
///
/// Gets the first IQueryable{T}
///
IQueryable First { get; }
///
/// Gets the second IQueryable{T}
///
IQueryable Second { get; }
}
///
/// The interface to access a collection of three IQueryable{T} instances.
///
/// The element type of the first IQueryable{T}
/// The element type of the second IQueryable{T}
/// The element type of the third IQueryable{T}
public interface IMultiQueryable : IMultiQueryable
{
///
/// Gets the first IQueryable{T}
///
IQueryable First { get; }
///
/// Gets the second IQueryable{T}
///
IQueryable Second { get; }
///
/// Gets the third IQueryable{T}
///
IQueryable Third { get; }
}
///
/// The interface to access a collection of IQueryable{T} instances. Each IQueryable{T}
/// contains only elements of the same key. The IQueryable{T}s are indexed by a set of keys.
///
/// The element type of IQueryable{T}s
/// The key type
public interface IKeyedMultiQueryable : IMultiQueryable
{
///
/// Gets the IQueryable{T} associated with a specified key.
///
/// A key
/// The IQueryable{T} associated with the key
IQueryable this[K key] { get; }
///
/// Gets the keys.
///
K[] Keys { get; }
}
internal 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);
}
throw new DryadLinqException(DryadLinqErrorCode.MultiQueryableKeyOutOfRange,
SR.MultiQueryableKeyOutOfRange);
}
}
}
internal 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
{
throw new DryadLinqException(DryadLinqErrorCode.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);
}
}
}
internal 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
{
throw new DryadLinqException(DryadLinqErrorCode.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);
}
}
}
}