Nothing
#' This class handles an SQL Query.
#'
#' This class represents an SQL query.
#'
#' @examples
#' # No example provided, as this class is abstract.
#'
#' @import R6
#' @export
Query <- R6::R6Class("Query",
public = list(
#' @description
#' Initializer.
#' @param stmts A character vector of statement class names.
#' It describes the accepted statements and their order, using
#' wildcards to indicate if a statement is optional, or if it
#' is allowed to occur multiple times. Example:
#' c("Select", "From", "Join*", "Where?", "Limit?")
#' @return Nothing.
initialize = function(stmts) {
# Statements order
private$set_statements(stmts)
# Initialize list of statement objects
private$stmts <- list()
private$current_card <- rep(0L, length(private$stmt_card))
names(private$current_card) <- names(private$stmt_card)
return(invisible(NULL))
},
#' @description
#' Add a statement.
#' @param stmt The statement to add.
#' @return Nothing.
add = function(stmt) {
chk::chk_is(stmt, "Statement")
# Check if statement is allowed
cls <- class(stmt)
cls <- cls[which(cls %in% private$stmt_order)]
if (length(cls) == 0L)
stop(class(stmt)[1L], " is not in allowed statements: ",
toString(private$stmt_order), ".", call. = FALSE)
else if (length(cls) > 1L)
stop("Multiple classes (", toString(cls), ") of ", class(stmt)[1L],
" matches allowed statements: ",
toString(private$stmt_order), ".", call. = FALSE)
# Check cardinality
if (private$current_card[cls] == 1L && private$stmt_card[cls] != "*")
stop("Statement ", cls, " is not allowed multiple times.",
call. = FALSE)
private$current_card[cls] <- private$current_card[cls] + 1L
private$stmts <- c(private$stmts, stmt)
return(invisible(NULL))
},
#' @description
#' Generates the string representation of this query.
#' @return A string containing the full SQL query.
toString = function() {
# Check required statements
req <- names(private$stmt_card)[private$stmt_card == "1"]
miss <- req[private$current_card[req] == 0L]
if (length(miss) > 0L)
stop("The following required statements are missing: ",
toString(missing), ".", call. = FALSE)
# Sort statements
ordered_stmts <- rep(list(list()), length(private$stmt_order))
names(ordered_stmts) <- private$stmt_order
for (s in private$stmts) {
cls <- class(s)
cls <- cls[which(cls %in% private$stmt_order)]
ordered_stmts[[cls]] <- c(ordered_stmts[[cls]], s)
}
# Convert statements to tokens
tokens <- list()
i <- 0L
for (stmt in unlist(ordered_stmts, recursive=FALSE)) {
if (i > 0L)
tokens <- c(tokens, .spc)
tokens <- c(tokens, stmt$getTokens())
i <- i + 1L
}
tokens <- c(tokens, .semicolon)
return(paste(vapply(tokens, function(x) x$toString(), FUN.VALUE = ""),
collapse = ""))
}
),
private = list(
stmts = NULL,
stmt_order = NULL,
stmt_card = NULL,
current_card = NULL,
set_statements = function(stmts) {
chk::chk_character(stmts)
# Add prefix
stmts <- gsub("^", "Stmt", stmts)
# Get order of statements
private$stmt_order <- gsub("[*?]", "", stmts)
# Get cardinality of statements
card <- gsub("^[A-Za-z]+", "", stmts)
card[!nzchar(card)] <- "1" # Default is 1
names(card) <- private$stmt_order
private$stmt_card <- card
}
)
)
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.