tests/testthat/test-dbAppendTableAs.R

# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

context(paste(Sys.getenv("PRESTO_TYPE", "Presto"), "dbAppendTableAs"))

test_that("dbAppendTableAs works with simple SELECT query", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas"
  test_origin_table <- "iris"
  
  # Create target table with same structure
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0("SELECT * FROM ", test_origin_table, " WHERE 1 = 0")
  )
  
  # Get initial row count
  initial_nrow <- get_nrow(conn, test_table_name)
  expect_equal(initial_nrow, 0L)
  
  # Append from SELECT query
  test_sql <- paste0(
    "SELECT * FROM ", test_origin_table, " WHERE \"sepal.length\" > 7.0"
  )
  rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = test_sql)
  
  # Verify rows were inserted
  expect_true(rows_inserted > 0L)
  expect_equal(get_nrow(conn, test_table_name), rows_inserted)
})

test_that("dbAppendTableAs works with tbl_presto", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_tbl"
  test_origin_table <- "iris"
  
  # Create target table with same structure
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0("SELECT * FROM ", test_origin_table, " WHERE 1 = 0")
  )
  
  # Append from tbl_presto
  tbl_obj <- dplyr::tbl(conn, test_origin_table) %>%
    dplyr::filter(sepal.length > 7.0)
  
  rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = tbl_obj)
  
  # Verify rows were inserted
  expect_true(rows_inserted > 0L)
  expect_equal(get_nrow(conn, test_table_name), rows_inserted)
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs works with complex queries", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_complex"
  test_origin_table <- "iris"
  
  # Create target table
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0(
      "SELECT \"species\", AVG(\"sepal.length\") AS avg_length ",
      "FROM ", test_origin_table, " GROUP BY \"species\""
    )
  )
  
  # Append aggregated data
  test_sql <- paste0(
    "SELECT \"species\", AVG(\"sepal.width\") AS avg_length ",
    "FROM ", test_origin_table, " ",
    "WHERE \"sepal.length\" > 7.0 ",
    "GROUP BY \"species\""
  )
  initial_nrow <- get_nrow(conn, test_table_name)
  rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = test_sql)
  
  expect_true(rows_inserted > 0L)
  expect_equal(get_nrow(conn, test_table_name), initial_nrow + rows_inserted)
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs works with empty result set", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_empty"
  test_origin_table <- "iris"
  
  # Create target table
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0("SELECT * FROM ", test_origin_table, " WHERE 1 = 0")
  )
  
  # Append from query that returns no rows
  test_sql <- paste0(
    "SELECT * FROM ", test_origin_table, " WHERE 1 = 0"
  )
  rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = test_sql)
  
  # Should return 0 and not error
  expect_equal(rows_inserted, 0L)
  expect_equal(get_nrow(conn, test_table_name), 0L)
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs works with different table name formats", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_formats"
  test_origin_table <- "iris"
  
  # Create target table
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0("SELECT * FROM ", test_origin_table, " WHERE 1 = 0")
  )
  
  test_sql <- paste0(
    "SELECT * FROM ", test_origin_table, " LIMIT 1"
  )
  
  # Character string
  rows1 <- dbAppendTableAs(conn, test_table_name, sql = test_sql)
  expect_true(rows1 > 0L)
  
  # Id()
  rows2 <- dbAppendTableAs(
    conn, DBI::Id(table = test_table_name), sql = test_sql
  )
  expect_true(rows2 > 0L)
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs errors when table doesn't exist", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_nonexistent"
  test_sql <- "SELECT * FROM iris LIMIT 1"
  
  # Ensure table doesn't exist
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  
  # Should error because table doesn't exist
  expect_error(
    dbAppendTableAs(conn, test_table_name, sql = test_sql),
    "Table.*does not exist.*INSERT INTO requires an existing table"
  )
})

test_that("dbAppendTableAs errors on invalid input", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas"
  
  # Invalid: not character or tbl_presto
  expect_error(
    dbAppendTableAs(conn, test_table_name, sql = 123),
    "sql must be a character string or a tbl_presto object"
  )
  
  # Invalid: multiple strings
  expect_error(
    dbAppendTableAs(conn, test_table_name, sql = c("SELECT 1", "SELECT 2")),
    "length\\(sql\\) == 1"
  )
})

test_that("dbAppendTableAs validates column names match", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_validate"
  test_origin_table <- "iris"
  
  # Create target table
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0("SELECT \"sepal.length\", \"sepal.width\" FROM ", test_origin_table, " WHERE 1 = 0")
  )
  
  # Test with different column names
  test_sql <- paste0(
    "SELECT \"petal.length\", \"petal.width\" FROM ", test_origin_table, " LIMIT 1"
  )
  
  expect_error(
    dbAppendTableAs(conn, test_table_name, sql = test_sql),
    "Column mismatch detected"
  )
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs reorders columns when auto_reorder is TRUE", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_reorder"
  test_origin_table <- "iris"
  
  # Create target table with specific column order
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0(
      "SELECT \"sepal.length\", \"sepal.width\", \"petal.length\", \"petal.width\" ",
      "FROM ", test_origin_table, " WHERE 1 = 0"
    )
  )
  
  # Query with different column order
  test_sql <- paste0(
    "SELECT \"petal.width\", \"sepal.length\", \"petal.length\", \"sepal.width\" ",
    "FROM ", test_origin_table, " LIMIT 1"
  )
  
  # Should reorder and show message
  expect_message(
    rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = test_sql, auto_reorder = TRUE),
    "Column order mismatch detected"
  )
  
  expect_true(rows_inserted > 0L)
  expect_equal(get_nrow(conn, test_table_name), rows_inserted)
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs works with SELECT * in SQL string", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_select_star"
  test_origin_table <- "iris"
  
  # Create target table
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0("SELECT * FROM ", test_origin_table, " WHERE 1 = 0")
  )
  
  # Query with SELECT *
  test_sql <- paste0("SELECT * FROM ", test_origin_table, " WHERE \"sepal.length\" > 7.0")
  
  rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = test_sql)
  
  expect_true(rows_inserted > 0L)
  expect_equal(get_nrow(conn, test_table_name), rows_inserted)
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs works with aliases in SQL string", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_aliases"
  test_origin_table <- "iris"
  
  # Create target table
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0(
      "SELECT \"sepal.length\" AS sl, \"sepal.width\" AS sw ",
      "FROM ", test_origin_table, " WHERE 1 = 0"
    )
  )
  
  # Query with aliases
  test_sql <- paste0(
    "SELECT \"sepal.length\" AS sl, \"sepal.width\" AS sw ",
    "FROM ", test_origin_table, " WHERE \"sepal.length\" > 7.0"
  )
  
  rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = test_sql)
  
  expect_true(rows_inserted > 0L)
  expect_equal(get_nrow(conn, test_table_name), rows_inserted)
  
  dbRemoveTable(conn, test_table_name)
})

test_that("dbAppendTableAs respects auto_reorder = FALSE", {
  conn <- setup_live_connection()
  test_table_name <- "test_dbappendtableas_no_reorder"
  test_origin_table <- "iris"
  
  # Create target table with specific column order
  if (dbExistsTable(conn, test_table_name)) {
    dbRemoveTable(conn, test_table_name)
  }
  dbCreateTableAs(
    conn, test_table_name,
    paste0(
      "SELECT \"sepal.length\", \"sepal.width\" ",
      "FROM ", test_origin_table, " WHERE 1 = 0"
    )
  )
  
  # Query with different column order
  test_sql <- paste0(
    "SELECT \"sepal.width\", \"sepal.length\" ",
    "FROM ", test_origin_table, " LIMIT 1"
  )
  
  # Should not show reorder message when auto_reorder = FALSE
  # Note: This test may need adjustment based on Presto's actual behavior
  messages <- capture_messages(
    rows_inserted <- dbAppendTableAs(conn, test_table_name, sql = test_sql, auto_reorder = FALSE)
  )
  
  expect_false(any(grepl("Column order mismatch detected", messages)))
  expect_true(rows_inserted > 0L)
  
  dbRemoveTable(conn, test_table_name)
})

Try the RPresto package in your browser

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

RPresto documentation built on Dec. 2, 2025, 9:07 a.m.