Nothing
commCodes<-c(makeArray=2,makeObj=3,var=10,javascript=11,uuid=169,http=153,error=12,implicitVar=13,db=14,table=15,get=16,getAll=78,eq=17,ne=18,lt=19,le=20,gt=21,ge=22,not=23,add=24,sub=25,mul=26,div=27,mod=28,floor=183,ceil=184,round=185,append=29,prepend=80,difference=95,setInsert=88,setIntersection=89,setUnion=90,setDifference=91,slice=30,skip=70,limit=71,offsetsOf=87,contains=93,getField=31,keys=94,values=186,object=143,hasFields=32,withFields=96,pluck=33,without=34,merge=35,betweenDeprecated=36,between=182,reduce=37,map=38,fold=187,filter=39,concatMap=40,orderBy=41,distinct=42,count=43,isEmpty=86,union=44,nth=45,bracket=170,innerJoin=48,outerJoin=49,eqJoin=50,zip=72,range=173,insertAt=82,deleteAt=83,changeAt=84,spliceAt=85,coerceTo=51,typeOf=52,update=53,delete=54,replace=55,insert=56,dbCreate=57,dbDrop=58,dbList=59,tableCreate=60,tableDrop=61,tableList=62,config=174,status=175,wait=177,reconfigure=176,rebalance=179,sync=138,grant=188,indexCreate=75,indexDrop=76,indexList=77,indexStatus=139,indexWait=140,indexRename=156,setWriteHook=189,getWriteHook=190,funcall=64,branch=65,or=66,and=67,forEach=68,func=69,asc=73,desc=74,info=79,match=97,upcase=141,downcase=142,sample=81,default=92,json=98,toJsonString=172,iso8601=99,toIso8601=100,epochTime=101,toEpochTime=102,now=103,inTimezone=104,during=105,date=106,timeOfDay=126,timezone=127,year=128,month=129,day=130,dayOfWeek=131,dayOfYear=132,hours=133,minutes=134,seconds=135,time=136,monday=107,tuesday=108,wednesday=109,thursday=110,friday=111,saturday=112,sunday=113,january=114,february=115,march=116,april=117,may=118,june=119,july=120,august=121,september=122,october=123,november=124,december=125,literal=137,group=144,sum=145,avg=146,min=147,max=148,split=149,ungroup=150,random=151,changes=152,args=154,binary=155,geojson=157,toGeojson=158,point=159,line=160,polygon=161,distance=162,intersects=163,includes=164,circle=165,getIntersecting=166,fill=167,getNearest=168,polygonSub=171,minval=180,maxval=181);
countArgs<-function(f)
length(as.list(args(f)))-1;
setReqlClass<-function(x){
class(x)<-"reql"; x
}
lockBaseQuery<-function(x){
x$baseQuery<-x$query;
return(x)
}
isReql<-function(x)
inherits(x,"reql");
enc<-function(com)
return(as.numeric(commCodes[com]))
coerceDatum<-function(datum){
if(inherits(datum,"call")){
stop("Datum is a call!")
}
if(inherits(datum,"pairlist")){
stop("Datum is a pairlist!")
}
## Do not process what is already done
if(isReql(datum)){
if(is.environment(datum)){
#Here, we collapse a reql tree into a query;
ans<-setReqlClass(datum$query);
# but this means reql tree is useless, so we can trim it to root,
# in order to make it re-usable (useful when it is r()$var(..))
datum$query<-datum$baseQuery;
return(ans);
}
return(datum);
}
## Fix JSON-unfriendly stuff
#Drop functions
if(is.function(datum))
stop("Functions can only exist as direct term arguments.")
#Environments -> lists
if(is.environment(datum)) datum<-as.list(datum);
#Factors -> character
if(is.factor(datum)) datum<-stats::setNames(as.character(datum),names(datum));
#Named stuff -> lists
if(!is.null(names(datum))&&!is.list(datum)) datum<-as.list(datum);
## Drill down lists
if(is.list(datum))
datum<-lapply(datum,coerceDatum);
## Return time
#Named lists -> those shall be objects, just return
if(is.list(datum)&&!is.null(names(datum)))
return(setReqlClass(datum));
#Un-named stuff with length>1 or a list -> makeArray of elements
if(length(datum)>1||is.list(datum))
return(setReqlClass(list(enc("makeArray"),datum)));
#Single-element vector... scalar
return(setReqlClass(datum));
}
incorporateTerm<-function(argRaw,id,Q){
#Convert NULL argRaw meaning argless-function into list()
if(is.null(argRaw)) argRaw<-list()
## Coerce arguments ##
if(length(argRaw)>0) for(e in 1:length(argRaw)){
#Evalute it now, not before
thisArg<-eval(argRaw[[e]],envir=parent.frame(2),enclos=parent.frame(3));
#Functions got executed with reql arguments
if(inherits(thisArg,"function")){
countArgs(thisArg)->arity;
if(arity==0)
stop("Anonymous functions without parameters are not supported.");
internalArgs<-lapply(1:arity,function(e) lockBaseQuery(r()$var(e)));
body<-do.call(thisArg,internalArgs);
if(is.environment(body))
body<-setReqlClass(body$query);
argRaw[[e]]<-setReqlClass(list(
enc("func"),
list(
list(enc("makeArray"),as.list(1:arity)),
body
)
));
}else{
#Static objects get coerced and makeArray-ied when needed
argRaw[[e]]<-coerceDatum(thisArg);
}
}
#Following operations will finally kill argRaw pairlist structure
if(!is.null(names(argRaw))){
#Some options must be extracted
argRaw[nchar(names(argRaw))>0]->argOpts;
argRaw[nchar(names(argRaw))==0]->argArgs;
names(argArgs)<-NULL;
}else{
#No options at all
argArgs<-argRaw;
argOpts<-NULL;
}
if(!is.null(Q$query)) Q$query<-list(Q$query);
argArgs<-c(Q$query,argArgs);
if(is.null(argOpts)){
Q$query<-list(enc(id),argArgs);
}else{
Q$query<-list(enc(id),argArgs,argOpts);
}
}
funGen<-function(id,Q){
id<-force(id);
function(...){
#This will be used to manipulate with R eval order
argRaw<-match.call(expand.dots=FALSE)$...;
incorporateTerm(argRaw,id,Q);
Q;
}
}
#' ReQL root
#'
#' Creates ReQL root for building a query.
#' @param db DB name; this is optional, and is just a syntax sugar for \code{r()$db(db)}.
#' @param table Table name; this is optional, requires db to be given, and is just a syntax sugar for \code{r()$db(db)$table(table)}
#' @return ReQL root; use \code{$} (or \code{[[]]}) to chain query terms (like \code{r()$db("test")$table("test")}).
#' In general, anonymous attributes are passed as attributes while named as term options.
#' In context of term arguments, named lists are treated as JSON objects (following \code{rjson} package heuristics), unnamed lists and simple vectors as JSON arrays; classes and attributes are ignored.
#' Term options should be called in the snake case form (for instance \code{return_changes} not \code{returnChanges}), as documented for the original Python driver.
#' To finalise, use \code{$run} or \code{$runAsync}.
#' For a comprehensive description of all terms, see RethinkDB API reference; here we give an overview of some:
#' \item{run(connection,...)}{Evaluate the query; the function will block until first response from RethinkDB to this query will be received.
#' May return cursor, an object representing a stream of data on which \code{\link{cursorNext}} and \code{\link{cursorToList}} can be used to extract actual information.
#' \code{...} may be used to specify run options, like \code{profile}, \code{durability} or \code{read_mode}.}
#' \item{runAsync(connection,callback,...)}{Evaluate the query; for each datum received \code{x}, run \code{callback(x)}.
#' Callback should return \code{TRUE} to be re-evaluated on proceeding data; any other response will cause the query to be dropped immediately.
#' This function returns immediately; to ask R to start evaluating async queries, run \code{\link{drainConnection}}.
#' Note that callbacks can be also called while \code{$run()} blocks waiting for other query to execute.}
#' \item{bracket(...)}{Implementation of the JavaScript \code{(...)} and Python \code{[...]} operation.}
#' \item{funcall(function,atts)}{Implementation of the JavaScript \code{.do()}; note that the order of arguments is different.}
#' @note ReQL is implemented as an environment, thus is mutable unlike most R objects.
#' To this end, you can use variables for chaining like this \code{r()->query;} \code{query$db("a");} \code{query$table("b")}; but consequently you can't use variables to make a re-usable stub, i.e., this is invalid: \code{r()->query;} \code{query$db("a")$table("aa")$run(...)} \code{query$db("b")$table("bb")$run(...);}.
#'
#' If you get "trying to apply non-function" error, you likely have misspelled term name or trying to use a non-existent one.
#'
#' To view raw AST (at any depth), use \code{$query}.
#' @author Miron B. Kursa
#' @examples \dontrun{
#' #Connect to the RethinkDB instance
#' cn<-openConnection()
#'
#' #Get document count in some_db's some_table
#' r()$db("some_db")$table("some_table")$count()$run(cn)
#' #...same can be done shorter
#' r("some_db","some_table")$count()$run(cn)
#'
#' #Fetch 5 random docs from some_db's some_table...
#' r("some_db","some_table")$sample(5)$run(cn)->cursor
#' #...and present as a list`
#' cursorToList(cursor)
#'
#' #Insert an element
#' r("some_db","some_table")$insert(list(id="new",a=1:10,b=list(c=1,d=2)))$run(cn)
#'
#' #Close connection
#' close(cn)
#' }
#' @export
r<-function(db,table){
setReqlClass(new.env())->Q;
Q$query<-NULL;
Q$baseQuery<-NULL;
#Populating reql composing environment with functions
for(com in names(commCodes))
Q[[com]]<-funGen(com,Q);
Q$row<-function(...)
stop("Implicit var (row) is not supported by rethinker; use an actual anonymous function.")
Q$run<-function(connection,...)
return(syncQuery(connection,rjson::toJSON(Q$query),list(...)))
Q$runAsync<-function(connection,cb,...)
return(hookQuery(connection,rjson::toJSON(Q$query),cb,list(...)));
Q$expr<-function(x){
if(!is.null(Q$query))
stop("$expr only makes sense as a first term.");
Q$query<-coerceDatum(x);
Q
}
#Applying db and table
if(!missing(db)){
Q<-Q$db(force(db));
if(!missing(table))
Q<-Q$table(force(table));
}else{
if(!missing(table))
stop("You can't give table without specifying db.");
}
#Done
Q
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.