public static ICreateStatement <TResult> Join <TOuter, TInner, TKey, TResult>(this ICreateStatement <TOuter> outer, ISource <TInner> inner, Expression <Func <TOuter, TKey> > outerKeySelector, Expression <Func <TInner, TKey> > innerKeySelector, Expression <Func <TOuter, TInner, TResult> > resultSelector)
    {
        if (outer == null)
        {
            throw new ArgumentNullException(nameof(outer));
        }
        if (inner == null)
        {
            throw new ArgumentNullException(nameof(inner));
        }
        if (outerKeySelector == null)
        {
            throw new ArgumentNullException(nameof(outerKeySelector));
        }
        if (innerKeySelector == null)
        {
            throw new ArgumentNullException(nameof(innerKeySelector));
        }
        if (resultSelector == null)
        {
            throw new ArgumentNullException(nameof(resultSelector));
        }

        return(outer.Provider.CreateStatement <TResult>(
                   Expression.Call(
                       null,
                       JoinTOuterTInnerTKeyTResult(typeof(TOuter), typeof(TInner), typeof(TKey), typeof(TResult)), outer.Expression, inner.Expression, outerKeySelector, innerKeySelector, resultSelector)));
    }
 public static ICreateStatement <TSource> Take <TSource>(this ICreateStatement <TSource> source, int count)
 {
     return(source.Provider.CreateStatement <TSource>(
                Expression.Call(
                    null,
                    TakeTSource(typeof(TSource)),
                    source.Expression, Expression.Constant(count)
                    )));
 }
    public static string ToStatementString <TSource>(this ICreateStatement <TSource> source)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        var createStatement = source as CreateStatement <TSource>;

        var ksqlQuery = createStatement?.BuildKsql();

        return(ksqlQuery);
    }
    public static ICreateStatement <TSource> Where <TSource>(this ICreateStatement <TSource> source, Expression <Func <TSource, bool> > predicate)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        if (predicate == null)
        {
            throw new ArgumentNullException(nameof(predicate));
        }

        return(source.Provider.CreateStatement <TSource>(
                   Expression.Call(
                       null,
                       WhereTSource(typeof(TSource)),
                       source.Expression, Expression.Quote(predicate)
                       )));
    }
    /// <summary>
    /// Repartition a stream.
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="source"></param>
    /// <param name="selector"></param>
    /// <returns></returns>
    public static ICreateStatement <TResult> PartitionBy <TSource, TResult>(this ICreateStatement <TSource> source, Expression <Func <TSource, TResult> > selector)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        if (selector == null)
        {
            throw new ArgumentNullException(nameof(selector));
        }

        return(source.Provider.CreateStatement <TResult>(
                   Expression.Call(
                       null,
                       PartitionByTSourceTResult(typeof(TSource), typeof(TResult)),
                       source.Expression, Expression.Quote(selector)
                       )));
    }
    public static ICreateStatement <IKSqlGrouping <TKey, TSource> > GroupBy <TSource, TKey>(this ICreateStatement <TSource> source, Expression <Func <TSource, TKey> > keySelector)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }
        if (keySelector == null)
        {
            throw new ArgumentNullException(nameof(keySelector));
        }

        return(source.Provider.CreateStatement <IKSqlGrouping <TKey, TSource> >(
                   Expression.Call(
                       null,
                       GroupByTSourceTKey(typeof(TSource), typeof(TKey)),
                       source.Expression, Expression.Quote(keySelector))
                   ));
    }
    public static ICreateStatement <IWindowedKSql <TKey, TSource> > WindowedBy <TSource, TKey>(this ICreateStatement <IKSqlGrouping <TKey, TSource> > source, TimeWindows timeWindows)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }
        if (timeWindows == null)
        {
            throw new ArgumentNullException(nameof(timeWindows));
        }

        return(source.Provider.CreateStatement <IWindowedKSql <TKey, TSource> >(
                   Expression.Call(null,
                                   WindowedByTSourceTKey(typeof(TSource), typeof(TKey)),
                                   source.Expression, Expression.Constant(timeWindows))));
    }
    public static ICreateStatement <IKSqlGrouping <TKey, TSource> > Having <TSource, TKey>(this ICreateStatement <IKSqlGrouping <TKey, TSource> > source, Expression <Func <IKSqlGrouping <TKey, TSource>, bool> > predicate)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        if (predicate == null)
        {
            throw new ArgumentNullException(nameof(predicate));
        }

        return(source.Provider.CreateStatement <IKSqlGrouping <TKey, TSource> >(
                   Expression.Call(
                       null,
                       HavingTSource(typeof(TSource), typeof(TKey)),
                       source.Expression, Expression.Quote(predicate)
                       )));
    }