## Not to be called by the users, so all functions start with a prefix of dot
## and thus are not exported.
## Check arguments of function to make sure that they are legal
## -----------------------------------------------------------------------
## convert {...} string into an arrayparams$grp.str
arraydb.to.arrayr <- function (str, type = "double", ...)
{
if (is.null(str)) return (NULL)
if (type == "character")
res <- character(0)
else if (type == "integer")
res <- integer(0)
else if (type == "logical")
res <- logical(0)
else
res <- numeric(0)
if (type == "character") {
elm <- matrix(unlist(.regmatches(
str,
gregexpr("[^,\"\\s\\{\\}]+|\"[^\"]*\"",
str, perl=T))), nrow = length(str), byrow = TRUE)
} else {
elm <- matrix(unlist(strsplit(gsub("(\\{|\\})", "", str), ",")),
nrow = length(str), byrow = TRUE)
elm[elm == "NULL"] <- NA
if (type == "integer")
class(elm) <- "integer"
else if (type == "logical") {
elm <- toupper(elm)
class(elm) <- "logical"
} else
class(elm) <- "numeric"
}
elm
}
## -----------------------------------------------------------------------
.is.arg.string <- function (arg)
{
return (!is.null(arg) &&
is.character(arg))
}
## -----------------------------------------------------------------------
.is.conn.id.valid <- function (conn.id)
{
return (length(conn.id) != 0 &&
!is.null(conn.id) &&
!is.na(conn.id) &&
is(conn.id, "numeric") &&
conn.id >= 1 &&
length(.localVars$conn.id) != 0 &&
conn.id %in% .localVars$conn.id[,1])
}
## -----------------------------------------------------------------------
## get the distributed by string
.get.distributed.by.str <- function(conn.id, distributed.by)
{
dbms.str <- (.get.dbms.str(conn.id))$db.str
if (dbms.str != "PostgreSQL") {
if (is.null(distributed.by) ||
identical(distributed.by, character(0)))
dist.str <- "DISTRIBUTED RANDOMLY"
else {
if (!.is.arg.string(distributed.by))
stop("distributed.by must be a string or NULL!")
if (distributed.by == "") # "" means no distributed by
dist.str <- ""
else
dist.str <- paste("DISTRIBUTED BY (",
paste("\"", distributed.by, "\"", sep = ""),
")", sep = "")
}
} else
dist.str <- ""
return (dist.str)
}
## -----------------------------------------------------------------------
## simply return the most direct answer
.db.analyze.table.name <- function (name)
{
parts <- strsplit(name, "\\.")[[1]]
l <- length(parts)
if (l != 1 && l != 2)
stop("The database object name is not valid!")
return (parts)
}
## ----------------------------------------------------------------------
.db.table.schema.str <- function (table, conn.id)
{
warns <- .suppress.warnings(conn.id)
table <- .strip(table, "\"")
l <- length(table)
if (l == 2) {
.restore.warnings(warns)
return (paste("table_name = '", table[2],
"' and table_schema = '",
table[1], "'", sep = ""))
} else if (l == 1) {
schemas <- arraydb.to.arrayr(
db.q("select current_schemas(True)",
conn.id=conn.id, verbose = FALSE),
type = "character")
table_schema <- character(0)
for (schema in schemas)
if (.db.existsTable(c(schema, table), conn.id)) {
table_schema <- c(table_schema, schema)
break
}
.restore.warnings(warns)
if (identical(table_schema, character(0))) {
stop("This table does not exist in the search path!")
} else {
return (paste("table_name = '", table,
"' and table_schema = '", table_schema,
"'", sep = ""))
}
}
}
## -----------------------------------------------------------------------
## Is the object in database a table?
.is.table.or.view <- function (table, conn.id = 1)
{
pick <- .db.getQuery(
paste("select count(*) from information_schema.tables where ",
.db.table.schema.str(table, conn.id), sep = ""), conn.id)
if (pick == 1)
return (TRUE)
else
return (FALSE)
}
## -----------------------------------------------------------------------
## Is the object in database a view?
.is.view <- function (table, conn.id = 1)
{
pick <- .db.getQuery(
paste("select count(*) from information_schema.views where ",
.db.table.schema.str(table, conn.id), sep = ""), conn.id)
if (pick == 1)
return (TRUE)
else
return (FALSE)
}
## -----------------------------------------------------------------------
.unique.string <- function ()
{
hex_digits <- c(as.character(0:9), letters[1:6])
y_digits <- hex_digits[9:12]
s <- paste(
paste(sample(hex_digits, 8), collapse=''),
paste(sample(hex_digits, 4), collapse=''),
## paste('4', sample(hex_digits, 3), collapse=''),
paste(sample(y_digits,1), sample(hex_digits, 3),
collapse='', sep = ''),
paste(sample(hex_digits, 12), collapse=''), sep='_')
s <- paste("gp_temp_", s, sep = "")
s
}
# .unique.pattern <- function()
# "madlib_temp_[a-f\\d]{8}_[a-f\\d]{4}_[a-f\\d]{6}_[a-f\\d]{12}"
.unique.string.short <- function ()
{
hex_digits <- c(as.character(0:9), letters[1:6])
s <- paste(sample(hex_digits, 4), collapse='')
paste("_gp", s, "_", sep = "")
}
# .unique.pattern.short <- function()
# "_mad[a-f\\d]{4}_"
## -----------------------------------------------------------------------
## strip the leading and trailing white spaces
.strip <- function (str, rm = "\\s")
{
rm.str <- paste("^", rm, "*(.*[^", rm, "])", rm, "*$", sep = "")
gsub(rm.str, "\\1", str, perl = TRUE)
}
## ----------------------------------------------------------------------
.prepare.ind.vars <- function(ind.vars)
{
vars <- gsub("::[\\w\\s]+", "", ind.vars, perl = T)
vars <- gsub("\"", "`", vars, perl = T)
vars <- gsub("\\(`([^\\[\\]]*?)`\\)\\[(\\d+?)\\]", "`\"\\1\"[\\2]`",
vars, perl = T)
vars <- gsub("\\s", "", vars, perl = T)
vars <- .reverse.consistent.func(vars)
vars
}
## -----------------------------------------------------------------------
## analyze formula
.analyze.formula <- function (formula, data, fdata = data, refresh = FALSE,
is.factor = NA, cols = NA, suffix = NA,
grp.vars = NULL, grp.expr = NULL, no.factor = FALSE)
{
f.str <- strsplit(paste(deparse(formula), collapse = ""), "\\|")[[1]]
## f.str <- .replace.array(f.str, data)
fstr <- f.str[1]
fstr <- gsub("as\\.factor\\((((?!as\\.factor).)*?)\\)", "factor(\\1)",
fstr, perl = T)
fstr <- gsub("([^\\.]|^)factor\\((((?!as\\.factor).)*?)\\)", "\\1as.factor(\\2)",
fstr, perl = T)
f2 <- f.str[2] # grouping columns, might be NA
## fdata <- .expand.array(fdata)
if (!is.null(grp.vars) && !is.na(f2)) {
f2.labels <- grp.vars
grp.expr <- grp.expr
grp <- paste(f2.labels, collapse = ", ")
} else if (!is.na(f2)) {
f2.terms <- terms(formula(paste("~", f2)))
f2.labels <- attr(f2.terms, "term.labels")
## ## grouping column do not use factor
f2.labels <- gsub("I\\((.*?)\\)", "(\\1)", f2.labels, perl = T)
f2.labels <- gsub("as\\.factor\\((.*?)\\)", "(\\1)", f2.labels, perl = T)
f2.labels <- gsub("factor\\((.*?)\\)", "(\\1)", f2.labels, perl = T)
grp.expr <- f2.labels
for (i in seq_len(length(f2.labels))) {
if (! f2.labels[i] %in% names(data)) {
grp.col <- .unique.string()
data[[grp.col]] <- eval(parse(text = paste("with(data, ",
f2.labels[i], ")", sep = "")))
f2.labels[i] <- grp.col
}
}
grp <- paste(f2.labels, collapse = ", ")
} else {
f2.labels <- NULL
grp <- NULL
}
if (!is.null(f2.labels))
fstr <- paste(fstr, "-", paste("`", f2.labels, "`",
collapse = "-", sep = ""))
## create a fake data.frame only to extract
## terms when there is "." in formula
fake.data <- structure(vector("list", ncol(fdata)), names=names(fdata), class="data.frame")
f1 <- formula(fstr) # formula
f.terms <- terms(f1, data = fake.data) # formula terms
## the 1st row is the dependent variable
f.factors <- attr(f.terms, "factors")
f.labels <- attr(f.terms, "term.labels") # each terms on the right side
## f.labels <- gsub("`([^`]*)(\\[\\d+\\])`", "\"\\1\"\\2", f.labels)
right.hand <- paste(f.labels, collapse = "+")
if (refresh) { # second pass
right.hand <- gsub("as\\.factor\\((((?!as\\.factor).)*?)\\)", "(\\1)", right.hand, perl = T)
if (sum(data@.is.factor) > 0 && !no.factor) {
distinct <- list()
ref <- list()
replace.cols <- cols[is.factor]
suffix <- suffix[is.factor]
the.refs <- data@.factor.ref[is.factor]
max.level <- 0
for (i in seq_len(length(replace.cols))) {
col <- replace.cols[i]
new.col <- gsub(paste("^", col, sep = ""), "",
names(data)[grep(paste(col, suffix[i],
sep=""),
names(data))],
perl = TRUE)
distinct[[col]] <- new.col
ref[[col]] <- paste("`", suffix[i], the.refs[i], "`", sep = "")
if (length(new.col) > max.level)
max.level <- length(new.col)
}
right.hand1 <- right.hand
for (col in names(data)) {
right.hand1 <- gsub(paste("(", col, "\\s*\\[.*\\])", sep=""),
"`\\1`", right.hand1, perl = T)
}
vars <- all.vars(parse(text = right.hand1))
vars <- setdiff(vars, names(data))
l <- length(names(data))
fake <- as.data.frame(array(1, dim = c(max.level, l + length(vars))))
names(fake) <- c(names(data), vars)
for (i in seq_len(l)) {
if (data@.is.factor[i]) {
fake[,i] <- array(paste("`", distinct[[data@.col.name[i]]], "`",
sep = ""), dim = c(max.level, 1))
fake[,i] <- as.factor(fake[,i])
fake[,i] <- relevel(fake[,i],
ref = ref[[data@.col.name[i]]])
}
}
if (attr(f.terms, "intercept") == 0) inter.str <- "-1"
else inter.str <- ""
fterm <- .modeling.formula(formula(paste("~", right.hand1, inter.str)), fake)
if (fterm[1] == "(Intercept)") fterm <- fterm[-1]
right.hand <- paste(fterm, collapse = " + ")
}
} else { # first pass
## find all the factor columns
## right.hand <- gsub("as.factor\\s*\\((.*)\\)",
## "factor(\\1)", right.hand, perl = T)
elm <- .regmatches(right.hand,
gregexpr("as\\.factor\\s*\\([^\\(\\)]+\\)",
right.hand, perl=T))[[1]]
col <- .strip(gsub("as\\.factor\\s*\\(([^\\(\\)]+?)\\)", "(\\1)", elm,
perl = T))
col <- gsub("^\\((.*?)\\)$", "\\1", col)
if (!all(col %in% names(data)))
stop("At least one of the variables cannot be set to be a factor ",
"because either it does not exist in the data table ",
"or it is an element of an array!")
## make sure the returned object is always db.Rquery
for (i in seq_len(length(data@.col.name)))
if (data@.is.factor[i]) data[[i]] <- as.factor(data[[i]])
## factors added by formula
for (cl in col) data[[cl]] <- as.factor(data[[cl]])
right.hand <- gsub("as\\.factor\\((((?!as\\.factor).)*?)\\)", "(\\1)", right.hand, perl = T)
## right.hand <- gsub("factor\\((((?!factor).)*)\\)", "\\1", right.hand, perl = T)
}
f.terms1 <- terms(formula(paste("~", right.hand)), data = fake.data)
f.labels <- attr(f.terms1, "term.labels")
## f.labels <- gsub("`([^`]*)(\\[\\d+\\])`", "\"\\1\"\\2", f.labels)
f.intercept <- attr(f.terms, "intercept")
## labels <- .gsub("\\[(\\d+):(\\d+)\\]", "[\\1@\\2]", f.labels)
## labels <- gsub(":", "*", labels, perl = T) # replace interaction : with *
## labels <- .gsub("\\[(\\d+)@(\\d+)\\]", "[\\1:\\2]", labels)
labels <- .replace.colon(f.labels)
labels <- gsub("I\\((.*?)\\)", "(\\1)", labels, perl = T) # remove I()
## vdata <- .expand.array(data)
vdata <- data
## dependent variable
## factor does not play a role in dependent variable
dep.var <- gsub("I\\((.*?)\\)", "(\\1)", rownames(f.factors)[1], perl = T)
dep.var <- gsub("as\\.factor\\((.*?)\\)", "(\\1)", dep.var, perl = T)
dep.var <- gsub("factor\\((.*?)\\)", "(\\1)", dep.var, perl = T)
## dep.var <- .replace.with.quotes(dep.var, data@.col.name)
origin.dep <- dep.var
tmp <- eval(parse(text = paste("with(vdata, ", dep.var, ")", sep = "")))
dep.var <- tmp@.expr
## dep.var <- gsub("`([^`]*)(\\[\\d+\\])`", "\"\\1\"\\2", dep.var)
## with or without intercept
if (f.intercept == 0)
intercept.str <- ""
else
intercept.str <- "1,"
labels <- gsub("`([^`]*\\[.*\\])`", "\\1", labels, perl = T)
labels <- .is.array(labels, data)
orig.labels <- labels
a <- eval(parse(text = paste("with(vdata, c(",
paste(labels, collapse = ", "), "))",
sep = "")))
a.labels <- unlist(sapply(a, function(x) x[,]@.expr))
## b <- eval(parse(text = paste("with(vdata, c(",
## paste(.gsub("I\\((.*)\\)", "(\\1)",
## setdiff(rownames(f.factors),
## colnames(f.factors))),
## collapse = ", "), "))", sep = "")))
b <- eval(parse(text = paste("with(vdata, c(",
paste(.replace.colon(gsub("I\\((.*?)\\)", "(\\1)",
rownames(f.factors)[rowSums(f.factors) == 0])),
collapse = ", "), "))", sep = "")))
## b2 <- eval(parse(text = paste("with(vdata, c(",
## paste(.replace.colon(.gsub("I\\((.*)\\)", "(\\1)", colnames(f.factors))),
## collapse = ", "), "))", sep = "")))
b.labels <- unlist(sapply(b, function(x) x[,]@.expr))
## b2.labels <- unlist(sapply(b2, function(x) x[,]@.expr))
## remove <- match(b2.labels, b1.labels)
## remove <- remove[!is.na(remove)]
## if (length(remove) >0) b.labels <- b1.labels[-remove]
## else b.labels <- character(0)
## b.labels <- b1.labels[rowSums(f.factors) == 0]
labels <- .strip(setdiff(a.labels, b.labels), "`")
## labels <- .replace.with.quotes(labels, data@.col.name)
## remove grouping columns, when there is no intercept term
if (!is.null(f2.labels) && f.intercept != 0)
labels <- setdiff(labels, .strip(f2.labels, "`"))
ind.var <- paste("array[", intercept.str,
paste(labels, collapse = ","),
"]", sep = "") # independent variable
dep.var <- .consistent.func(dep.var)
ind.var <- .consistent.func(ind.var)
labels <- .consistent.func(labels)
dep.var <- gsub("`", "", dep.var)
ind.var <- gsub("`", "", ind.var)
if (!is.null(grp)) grp <- gsub("`", "", grp)
labels <- gsub("`", "", labels)
factor.full <- rep(TRUE, length(names(data)))
if (!refresh) {
model.vars <- .prepare.ind.vars(orig.labels)
model.vars <- gsub("`\"([^\\[\\]]*?)\"\\[(\\d+?)\\]`", "`\\1[\\2]`", model.vars)
vars <- unique(all.vars(parse(text = model.vars)))
idx <- match(vars, names(data))
for (i in seq_len(length(idx))) {
id <- idx[i]
if (!is.na(id)) {
if (data@.col.data_type[id] %in% c("boolean", .txt.types) &&
!data@.is.factor[id]) {
data[[vars[i]]] <- as.factor(data[[vars[i]]])
}
}
}
}
list(dep.str = dep.var, origin.dep = origin.dep,
origin.ind = orig.labels,
ind.str = ind.var,
grp.str = grp, grp.vars = f2.labels, grp.expr = grp.expr,
ind.vars = labels,
has.intercept = as.logical(f.intercept),
data = data,
factor.full = factor.full,
terms = f.terms)
}
## -----------------------------------------------------------------------
## repeatedly replace all patterns
.gsub <- function(pattern, replace, str, ...)
{
while (TRUE) {
.str <- gsub(pattern, replace, str, ...)
if (identical(.str, str)) return (.str)
str <- .str
}
}
## ----------------------------------------------------------------------
.replace.colon <- function(s)
{
r <- gsub("(\\d+)\\s*:\\s*(\\d+)", "\\1@\\2", s)
r <- gsub(":", "*", r, perl = T)
r <- gsub("(\\d+)@(\\d+)", "\\1:\\2", r)
r
}
## ----------------------------------------------------------------------
.modeling.formula <- function(formula, data)
{
mf <- match.call(expand.dots = FALSE)
m <- match(c("formula", "data"), names(mf), 0L)
mf <- mf[c(1L, m)]
mf$drop.unused.levels <- TRUE
mf[[1L]] <- quote(stats::model.frame)
mf <- eval(mf, parent.frame())
mt <- attr(mf, "terms")
x <- model.matrix(mt, mf, contrasts)
res <- colnames(x)
for (s in names(data)) {
if (all(!grepl(paste("`", s, "`", sep = ""), res, fixed = TRUE))) {
res <- gsub(paste(s, "`(.+)$", sep = ""),
paste("`", s, "\\1", sep = ""),
res, perl = T)
}
}
res
}
## ----------------------------------------------------------------------
## R's log is SQL's log(exp(1.), x)
## R's log10 is SQL's log
.consistent.func <- function (strs)
{
res <- gsub("log\\s*\\(", "ln(", strs)
res <- gsub("log10\\s*\\(", "log(", res)
## res <- gsub("log2\\s*\\(", "log(2.,", res)
## res <- gsub("logb\\s*\\(()", "log(", res)
res
}
## ----------------------------------------------------------------------
## reverse of the above function
.reverse.consistent.func <- function (strs)
{
res <- gsub("log\\s*\\(", "log10(", strs)
res <- gsub("ln\\s*\\(", "log(", res)
res
}
## -----------------------------------------------------------------------
.replace.with.quotes <- function (vars, cols)
{
n.order <- order(nchar(cols), decreasing = TRUE)
cols <- cols[n.order]
for (i in seq_len(length(cols))) {
col <- cols[i]
vars <- gsub(paste(col, "([^_\\w]+?)", sep = ""),
paste("\"", col, "\"\\1", sep = ""),
vars, perl = TRUE)
vars <- gsub(paste("([_\\w]+?)\"", col, "\"", sep = ""),
paste("\\1", col, sep = ""),
vars, perl = TRUE)
vars <- gsub(paste("([^_\\w\"]+?)", col, sep = ""),
paste("\\1\"", col, "\"", sep = ""),
vars, perl = TRUE)
vars <- gsub(paste("\"", col, "\"([_\\w]+?)", sep = ""),
paste(col, "\\1", sep = ""),
vars, perl = TRUE)
vars <- gsub(paste("^", col, "$", sep = ""),
paste("\"", col, "\"", sep = ""),
vars, perl = TRUE)
}
## vars <- gsub("([\\w_]+)", "\"\\1\"", vars, perl = T)
vars
}
## -----------------------------------------------------------------------
## interactively read an input from the user
.read.input <- function (msg, expected.answer = c("yes", "y", "no", "n"))
{
a <- tolower(readline(msg))
while (! a %in% expected.answer)
a <- tolower(readline(msg))
a
}
## -----------------------------------------------------------------------
## set/reset the message level
## returns the old message level
.set.msg.level <- function (level, conn.id)
{
old.level <- .db.getQuery("select setting from pg_settings where name='client_min_messages'", conn.id)
.db.getQuery(paste("set client_min_messages to", level), conn.id)
old.level
}
## ----------------------------------------------------------------------
.db.data.frame2db.Rquery <- function(x)
{
if (is(x, "db.data.frame")) {
if (length(names(x)) == 1 && x@.col.data_type == "array") {
if (array)
x <- db.array(x)
else
x <- x[[names(x)]]
} else
x <- x[,]
}
x
}
## -----------------------------------------------------------------------
## If an independent variable is an array, it needs special treatment
.is.array <- function (labels, data)
{
nlabels <- character(0)
data <- .db.data.frame2db.Rquery(data)
if (data@.parent == data@.source)
tbl <- data@.parent
else
tbl <- paste("(", data@.parent, ") s", sep = "")
if (data@.where != "") where.str <- paste(" where", data@.where)
else where.str <- ""
conn.id <- conn.id(data)
for (i in seq_len(length(labels))) {
if (labels[i] %in% names(data) &&
data@.col.data_type[which(names(data) == labels[i])] == "array") {
n <- .db("select array_upper(\"", labels[i],
"\",1) from ",
tbl, where.str, " limit 1", sep = "",
conn.id = conn.id, verbose = F)[[1]]
n0 <- .db("select array_lower(\"", labels[i],
"\",1) from ",
tbl, where.str, " limit 1", sep = "",
conn.id = conn.id, verbose = F)[[1]]
nlabels <- c(nlabels, paste(labels[i], "[",
seq_len(n-n0+1) -1 + n0,
"]", sep = ""))
} else {
nlabels <- c(nlabels, labels[i])
}
}
nlabels
}
## -----------------------------------------------------------------------
## replace array in the formula
.replace.array <- function (fstr, data)
{
data <- data[,]
if (data@.parent == data@.source)
tbl <- data@.parent
else
tbl <- paste("(", data@.parent, ") s", sep = "")
if (data@.where != "") where.str <- paste(" where", data@.where)
else where.str <- ""
conn.id <- conn.id(data)
for (i in seq_len(length(data@.col.name))) {
if (data@.col.data_type[i] == "array") {
n <- .db.getQuery(paste("select array_upper(\"",
data@.col.name[i], "\",1) from ",
tbl, where.str, " limit 1", sep = ""),
conn.id)[[1]]
n0 <- .db.getQuery(paste("select array_lower(\"",
data@.col.name[i],
"\",1) from ",
tbl, where.str, " limit 1", sep = ""),
conn.id)[[1]]
l <- n - n0 + 1
s <- paste("`", data@.col.name[i], "[", seq_len(l) - 1 + n0,
"]`",
sep = "", collapse = " + ")
fstr <- gsub(paste(data@.col.name[i], "\\s*([^\\[]|$)",
sep = ""),
paste("(", s, ")\\1", sep = ""), fstr)
}
}
fstr
}
## -----------------------------------------------------------------------
## whether two where strings are equivalent
.eql.where <- function (where1, where2)
{
s <- gsub("^not \\((.*?)\\)$", "\\1", where1, perl = TRUE)
t <- gsub("^not \\((.*?)\\)$", "\\1", where2, perl = TRUE)
if (s != where1 && t != where2) {
return (.eql.where(s, t))
} else if ((s != where1 && t == where2) ||
(s == where1 && t != where2)) {
return (FALSE)
}
s1 <- gsub("^\\((.*?)\\) (and|or) \\((.*?)\\)$", "\\1", s, perl = TRUE)
if (s1 == s) return (s == t)
s2 <- gsub("^\\((.*?)\\) (and|or) \\((.*?)\\)$", "\\3", s, perl = TRUE)
ss <- gsub("^\\((.*?)\\) (and|or) \\((.*?)\\)$", "\\2", s, perl = TRUE)
t1 <- gsub("^\\((.*?)\\) (and|or) \\((.*?)\\)$", "\\1", t, perl = TRUE)
if (t1 == t) return (FALSE)
t2 <- gsub("^\\((.*?)\\) (and|or) \\((.*?)\\)$", "\\3", t, perl = TRUE)
tt <- gsub("^\\((.*?)\\) (and|or) \\((.*?)\\)$", "\\2", t, perl = TRUE)
if ((.eql.where(s1, t1) && .eql.where(s2, t2) && ss == tt) ||
(.eql.where(s1, t2) && .eql.where(s2, t1) && ss == tt))
TRUE
else
FALSE
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.