using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using RethinkDb.Driver.Model;
using RethinkDb.Driver.Net;
using RethinkDb.Driver.Proto;
using RethinkDb.Driver.Utils;
namespace RethinkDb.Driver.Ast
{
///
/// Base class for all reql queries.
///
public class ReqlAst
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
protected internal TermType TermType { get; }
protected internal Arguments Args { get; }
protected internal OptArgs OptArgs { get; }
protected internal ReqlAst(TermType termType, Arguments args, OptArgs optargs)
{
this.TermType = termType;
this.Args = args ?? new Arguments();
this.OptArgs = optargs ?? new OptArgs();
}
protected internal virtual object Build()
{
// Create a JSON object from the Ast
JArray list = new JArray();
list.Add(TermType);
if( Args.Count > 0 )
{
var collect = Args.Select(a => { return a.Build(); });
list.Add(new JArray(collect));
}
else
{
list.Add(new JArray());
}
if( OptArgs.Count > 0 )
{
list.Add(BuildOptarg(this.OptArgs));
}
return list;
}
protected internal static JObject BuildOptarg(OptArgs opts)
{
var dict = opts.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Build());
return JObject.FromObject(dict);
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
#region DYNAMIC LANGUAGE RUNTIME (DLR) RUNNERS
///
/// Runs the query on the connection. If you know the response type
/// of your query, T (SUCCESS_ATOM) or Cursor[T] (SUCCESS_SEQUENCE or SUCCESS_PARTIAL)
/// it's recommended to use `.RunAtom`, `.RunCursor` or `.RunResult` helpers
/// as they offer a slight edge in performance since both bypass the
/// dynamic language runtime execution engine.
///
/// Returns T or Cursor[T]
public virtual Task RunAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return conn.RunAsync(this, runOpts, cancelToken);
}
///
/// Runs the query on the connection. If you know the response type
/// of your query, T (SUCCESS_ATOM) or Cursor[T] (SUCCESS_SEQUENCE or SUCCESS_PARTIAL)
/// it's recommended to use `.RunAtom`, `.RunCursor` or `.RunResult` helpers
/// as they offer a slight edge in performance since both bypass the
/// dynamic language runtime execution engine.
///
/// Returns T or Cursor[T]
public virtual Task RunAsync(IConnection conn, CancellationToken cancelToken)
{
return RunAsync(conn, null, cancelToken);
}
///
/// Runs the query on the connection. If you know the response type
/// of your query, T (SUCCESS_ATOM) or Cursor[T] (SUCCESS_SEQUENCE or SUCCESS_PARTIAL)
/// it's recommended to use `.RunAtom`, `.RunCursor` or `.RunResult` helpers
/// as they offer a slight edge in performance since both bypass the
/// dynamic language runtime execution engine.
///
/// Returns T or Cursor[T]
/// /// connection
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return RunAsync(conn, runOpts, cancelToken);
}
///
/// Runs the query on the connection. If you know the response type
/// of your query, T (SUCCESS_ATOM) or Cursor[T] (SUCCESS_SEQUENCE or SUCCESS_PARTIAL)
/// it's recommended to use `.RunAtom`, `.RunCursor` or `.RunResult` helpers
/// as they offer a slight edge in performance since both bypass the
/// dynamic language runtime execution engine.
///
/// Returns T or Cursor[T]
/// /// connection
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunAsync(IConnection conn, CancellationToken cancelToken)
{
return RunAsync(conn, null, cancelToken);
}
///
/// Runs the query on the connection. If you know the response type
/// of your query, T (SUCCESS_ATOM) or Cursor[T] (SUCCESS_SEQUENCE or SUCCESS_PARTIAL)
/// it's recommended to use `.RunAtom`, `.RunCursor` or `.RunResult` helpers
/// as they offer a slight edge in performance since both bypass the
/// dynamic language runtime execution engine.
///
/// Returns T or Cursor[T]
public virtual dynamic Run(IConnection conn, object runOpts = null)
{
return RunAsync(conn, runOpts).WaitSync();
}
///
/// Runs the query on the connection. If you know the response type
/// of your query, T (SUCCESS_ATOM) or Cursor[T] (SUCCESS_SEQUENCE or SUCCESS_PARTIAL)
/// it's recommended to use `.RunAtom`, `.RunCursor` or `.RunResult` helpers
/// as they offer a slight edge in performance since both bypass the
/// dynamic language runtime execution engine.
///
/// Returns T or Cursor[T]
public virtual dynamic Run(IConnection conn, object runOpts = null)
{
return Run(conn, runOpts);
}
#endregion
#region RESPONSE TYPED RUNNERS
///
/// Executes a query with no expected response. Useful for fire-and-forget queries like insert, update.
///
public void RunNoReply(IConnection conn, object runOpts = null)
{
conn.RunNoReply(this, runOpts);
}
///
/// Use this method if you're expecting a cursor (SUCCESS_SEQUENCE or SUCCESS_PARTIAL) response
/// from your query. This method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses.
///
///
/// connection
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
/// A Cursor
public virtual Task> RunCursorAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return conn.RunCursorAsync(this, runOpts, cancelToken);
}
///
/// Use this method if you're expecting a cursor (SUCCESS_SEQUENCE or SUCCESS_PARTIAL) response
/// from your query. This method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses.
///
///
/// connection
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
/// A Cursor
public virtual Task> RunCursorAsync(IConnection conn, CancellationToken cancelToken)
{
return RunCursorAsync(conn, null, cancelToken);
}
///
/// Use this method if you're expecting a cursor (SUCCESS_SEQUENCE or SUCCESS_PARTIAL) response
/// from your query. This method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses.
///
///
/// connection
/// global anonymous type optional arguments
/// A Cursor
public virtual Cursor RunCursor(IConnection conn, object runOpts = null)
{
return RunCursorAsync(conn, runOpts).WaitSync();
}
///
/// Use this method if you're expecting SUCCESS_ATOM response from your query. This
/// method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses.
///
/// connection
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunAtomAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return conn.RunAtomAsync(this, runOpts, cancelToken);
}
///
/// Use this method if you're expecting SUCCESS_ATOM response from your query. This
/// method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses.
///
/// connection
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunAtomAsync(IConnection conn, CancellationToken cancelToken)
{
return RunAtomAsync(conn, null, cancelToken);
}
///
/// Use this method if you're expecting SUCCESS_ATOM response from your query. This
/// method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses.
///
/// connection
/// global anonymous type optional arguments
public virtual T RunAtom(IConnection conn, object runOpts = null)
{
return RunAtomAsync(conn, runOpts).WaitSync();
}
///
/// Use this method if you're expecting SUCCESS_ATOM or SUCCESS_SEQUENCE response from your query. This
/// method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses. Consider using RunAtom or RunCursor if your
/// response is either SUCCESS_ATOM or SUCCESS_SEQUENCE respectively. Exercise caution using this method
/// with large datasets as the server can switch responses from SUCESS_SEQUENCE to SUCCESS_PARTIAL for the
/// same exact query. Refer to the online documentation for this run helper.
///
/// connection
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunResultAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return conn.RunResultAsync(this, runOpts, cancelToken);
}
///
/// Use this method if you're expecting SUCCESS_ATOM or SUCCESS_SEQUENCE response from your query. This
/// method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses. Consider using RunAtom or RunCursor if your
/// response is either SUCCESS_ATOM or SUCCESS_SEQUENCE respectively. Exercise caution using this method
/// with large datasets as the server can switch responses from SUCESS_SEQUENCE to SUCCESS_PARTIAL for the
/// same exact query. Refer to the online documentation for this run helper.
///
/// connection
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunResultAsync(IConnection conn, CancellationToken cancelToken)
{
return RunResultAsync(conn, null, cancelToken);
}
///
/// Use this method if you're expecting SUCCESS_ATOM or SUCCESS_SEQUENCE response from your query. This
/// method offers a slight edge in performance without the need for the
/// dynamic language runtime like the run() method uses. Consider using RunAtom or RunCursor if your
/// response is either SUCCESS_ATOM or SUCCESS_SEQUENCE respectively. Exercise caution using this method
/// with large datasets as the server can switch responses from SUCESS_SEQUENCE to SUCCESS_PARTIAL for the
/// same exact query. Refer to the online documentation for this run helper.
///
/// connection
/// global anonymous type optional arguments
public virtual T RunResult(IConnection conn, object runOpts = null)
{
return RunResultAsync(conn, runOpts).WaitSync();
}
#endregion
#region EXTRA RUN HELPERS
///
/// OBSOLETE: Please use the .RunWriteAsync() method instead.
///
[Obsolete("The .RunResultAsync() method has been renamed to .RunWriteAsync(). Please use the new method name instead.", error: false)]
public virtual Task RunResultAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return RunWriteAsync(conn, runOpts, cancelToken);
}
///
/// OBSOLETE: Please use .RunWriteAsync() method instead.
///
[Obsolete("The .RunResultAsync() method has been renamed to .RunWriteAsync(). Please use the new method name instead.", error: false)]
public virtual Task RunResultAsync(IConnection conn, CancellationToken cancelToken)
{
return RunWriteAsync(conn, null, cancelToken);
}
///
/// OBSOLETE: Please use .RunWrite() method instead.
///
[Obsolete("The .RunResult() method has been renamed to .RunWrite(). Please use the new method name instead.", error: false)]
public virtual Result RunResult(IConnection conn, object runOpts = null)
{
return RunWriteAsync(conn, runOpts).WaitSync();
}
///
/// Helper shortcut for DML type of queries that returns # of inserts, deletes, errors.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// connection
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunWriteAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return conn.RunAtomAsync(this, runOpts, cancelToken);
}
///
/// Helper shortcut for DML type of queries that returns # of inserts, deletes, errors.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// connection
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunWriteAsync(IConnection conn, CancellationToken cancelToken)
{
return RunWriteAsync(conn, null, cancelToken);
}
///
/// Helper shortcut for DML type of queries that returns # of inserts, deletes, errors.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// connection
/// global anonymous type optional arguments
public virtual Result RunWrite(IConnection conn, object runOpts = null)
{
return RunWriteAsync(conn, runOpts).WaitSync();
}
///
/// Runs a query on the server and returns the raw object in an unsafe way
/// with minimal client-side processing. The unbridled use of this method can
/// lead to memory leaks on both the client and server. This method should only
/// be used in well-understood and advanced scenarios.
///
/// The connection object
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task RunUnsafeAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return conn.RunUnsafeAsync(this, runOpts, cancelToken);
}
///
/// Helper shortcut for change feeds, use if your query is expecting an infinite changes() stream.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// The document type of new/old value
/// connection
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task>> RunChangesAsync(IConnection conn, object runOpts = null, CancellationToken cancelToken = default)
{
return conn.RunCursorAsync>(this, runOpts, cancelToken);
}
///
/// Helper shortcut for change feeds, use if your query is expecting an infinite changes() stream.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// The document type of new/old value
/// connection
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task>> RunChangesAsync(IConnection conn, CancellationToken cancelToken)
{
return RunChangesAsync(conn, null, cancelToken);
}
///
/// Helper shortcut for change feeds, use if your query is expecting an infinite changes() stream.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// The document type of new/old value
/// connection
/// global anonymous type optional arguments
public virtual Cursor> RunChanges(IConnection conn, object runOpts = null)
{
return RunChangesAsync(conn, runOpts).WaitSync();
}
#endregion
///
/// Helper shortcut for grouping queries.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// The key type of how items are grouped
/// The type of items
/// connection
/// global anonymous type optional arguments
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual async Task>> RunGroupingAsync(IConnection conn, object runOpts = null,
CancellationToken cancelToken = default)
{
var tsk = await RunAtomAsync>(conn, runOpts, cancelToken).ConfigureAwait(false);
return tsk;
}
///
/// Helper shortcut for grouping queries.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// The key type of how items are grouped
/// The type of items
/// connection
/// Cancellation token used to stop *waiting* for a query response. The cancellation token does not cancel the query's execution on the server.
public virtual Task>> RunGroupingAsync(IConnection conn, CancellationToken cancelToken)
{
return RunGroupingAsync(conn, null, cancelToken);
}
///
/// Helper shortcut for grouping queries.
/// This method bypasses the dynamic language runtime for extra performance.
///
/// The key type of how items are grouped
/// The type of items
/// connection
/// global anonymous type optional arguments
public virtual IEnumerable> RunGrouping(IConnection conn, object runOpts = null)
{
return RunAtomAsync>(conn, runOpts).WaitSync();
}
}
}