R/StmtJoin.R

#' SQL JOIN statement.
#'
#' This class represents a SQL JOIN statement. It requires two fields on which
#' to join, and the type of join to perform (inner, left, right, or full).
#' The table on which to join is determined by looking at the two fields in
#' order and using the first table name available.
#'
#' @examples
#' # Create an inner join (default join type) between table 'foo' and table
#' # 'bar':
#' join <- StmtJoin$new(ExprField$new("id", "foo"),
#'                      ExprField$new("foo_id", "bar"))
#'
#' # Create a left join between table 'foo' and table 'bar':
#' join <- StmtJoin$new(ExprField$new("id", "foo"),
#'                      ExprField$new("foo_id", "bar"),
#'                      type = "left")
#'
#' @import R6
#' @import chk
#' @include Statement.R
#' @export
StmtJoin <- R6::R6Class("StmtJoin",
  inherit = Statement,
  public = list(

    #' @description
    #' Initializer.
    #' To determine the table on which to join, we look at the both fields in
    #' order and use the first table name available.
    #' @param field1 The first field on which to join.
    #' @param field2 The second field on which to join.
    #' @param type The type of join to perform. One of "inner", "left", "right",
    #'  or "full". Defaults to "inner".
    #' @return Nothing.
    initialize = function(field1, field2, type=c("inner", "left", "right",
                                                 "full")) {
      chk::chk_is(field1, "ExprField")
      chk::chk_is(field2, "ExprField")
      private$field1 <- field1
      private$field2 <- field2
      type <- tolower(type)
      private$type <- match.arg(type)
      return(invisible(NULL))
    },

    #' @description
    #' Generates the list of tokens representing this statement.
    #' @return A list of Token objects.
    getTokens = function() {
      tabl <- NULL
      for (f in c(private$field1, private$field2)) {
        x <- f$getTable()
        if (!is.null(x) && !is.na(x)) {
          tabl <- x
          break
        }
      }
      if (is.null(tabl) || !chk::vld_string(tabl)) {
        stop("Cannot determine table on which to join. No table names were",
          " set into fields.", call. = FALSE)
      }

      # Start with type of JOIN
      tokens <- switch(private$type,
        inner = list(),
        left = list(.left, .spc),
        right = list(.right, .spc),
        full = list(.full, .spc)
      )

      # Add optional inner/outer keyword
      if (!getOption("sqlq_omit_kwd", FALSE)) {
        if (private$type == "inner")
          tokens <- c(tokens, .inner, .spc)
        else
          tokens <- c(tokens, .outer, .spc)
      }

      # Construct the JOIN statement
      tokens <- c(tokens, .join, .spc, TokenIdentifier$new(tabl), .spc, .on,
                  .spc)
      expr <- ExprBinOp$new(private$field1, "=", private$field2)
      expr$enableParenthesis(FALSE)
      tokens <- c(tokens, expr$getTokens())

      return(tokens)
    }
  ),
  private = list(
    field1 = NULL,
    field2 = NULL,
    type = NULL
  )
)

Try the sqlq package in your browser

Any scripts or data that you put into this service are public.

sqlq documentation built on Sept. 16, 2025, 9:10 a.m.