| Title: | Execute Multi-Step 'SQL' Workflows |
|---|---|
| Description: | Execute multi-step 'SQL' workflows by leveraging specially formatted comments to define and control execution. This enables users to mix queries, commands, and metadata within a single script. Results are returned as named objects for use in downstream workflows. |
| Authors: | Christian Million [aut, cre, cph] |
| Maintainer: | Christian Million <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.3.0.9000 |
| Built: | 2026-06-07 23:24:33 UTC |
| Source: | https://github.com/christian-million/qryflow |
A thin wrapper around paste0(x, collapse = '\\n') to standardize the way
qryflow collapses SQL lines.
collapse_sql_lines(x)collapse_sql_lines(x)
x |
character vector of SQL lines |
a character vector of length 1
path <- example_sql_path() lines <- read_sql_lines(path) sql <- collapse_sql_lines(lines)path <- example_sql_path() lines <- read_sql_lines(path) sql <- collapse_sql_lines(lines)
This function creates a connection to an in-memory SQLite database, with the option to add a table to the database. This function is intended to facilitate examples, vignettes, and package tests.
example_db_connect(df = NULL)example_db_connect(df = NULL)
df |
Optional data.frame to add to the database. |
connection from DBI::dbConnect()
con <- example_db_connect(mtcars) x <- DBI::dbGetQuery(con, "SELECT * FROM mtcars;") head(x) DBI::dbDisconnect(con)con <- example_db_connect(mtcars) x <- DBI::dbGetQuery(con, "SELECT * FROM mtcars;") head(x) DBI::dbDisconnect(con)
qryflow provides example SQL scripts in its inst/sql directory. Use this
function to retrieve the path to an example script. This function is intended
to facilitate examples, vignettes, and package tests.
example_sql_path(path = "mtcars.sql")example_sql_path(path = "mtcars.sql")
path |
filename of the example script. |
path to example SQL script
path <- example_sql_path("mtcars.sql") file.exists(path)path <- example_sql_path("mtcars.sql") file.exists(path)
extract_all_tags() scans SQL for specially formatted comment tags (e.g., -- @tag: value)
and returns them as a named list. This is exported with the intent to be useful for users
extending qryflow. It's typically used against a single SQL chunk, such as one parsed from a
.sql file.
extract_all_tags(text) subset_tags(tags, keep, negate = FALSE)extract_all_tags(text) subset_tags(tags, keep, negate = FALSE)
text |
A character vector of SQL lines or a file path to a SQL script. |
tags |
A named list of tags, typically from |
keep |
A character vector of tag names to keep or exclude in |
negate |
Logical; if |
extract_all_tags(): A named list of all tags found in the SQL chunk.
subset_tags(): A filtered named list of tags or NULL if none remain.
qryflow_parse(), ls_qryflow_types()
filepath <- example_sql_path('mtcars.sql') parsed <- qryflow_parse(filepath) chunk <- parsed[[1]] tags <- extract_all_tags(chunk$sql) subset_tags(tags, keep = c("query"))filepath <- example_sql_path('mtcars.sql') parsed <- qryflow_parse(filepath) chunk <- parsed[[1]] tags <- extract_all_tags(chunk$sql) subset_tags(tags, keep = c("query"))
Checks whether a specially structured comment line if formatted in the way that qryflow expects.
is_tag_line(line)is_tag_line(line)
line |
A character vector to check. It is a vectorized function. |
Tag lines should look like this: -- @key: value
Begins with an inline comment (--)
An @ precedes a tag type (e.g., type, name, query, exec) and is followed by a colon (:)
A value is provided
Logical. Indicating whether each line matches tag specification.
a <- "-- @query: df_mtcars" b <- "-- @exec: prep_tbl" c <- "-- @type: query" lines <- c(a, b, c) is_tag_line(lines)a <- "-- @query: df_mtcars" b <- "-- @exec: prep_tbl" c <- "-- @type: query" lines <- c(a, b, c) is_tag_line(lines)
Helper function to access the names of the currently registered chunk types.
ls_qryflow_types()ls_qryflow_types()
Character vector of registered chunk types
ls_qryflow_types()ls_qryflow_types()
qryflow_chunk classCreate an instance of the qryflow_chunk class
new_qryflow_chunk( type = character(), name = character(), sql = character(), tags = NULL, results = NULL, meta = init_meta() )new_qryflow_chunk( type = character(), name = character(), sql = character(), tags = NULL, results = NULL, meta = init_meta() )
type |
Character indicating the type of chunk (e.g., "query", "exec") |
name |
Name of the chunk |
sql |
SQL statement associated with chunk |
tags |
Optional, additional tags included in chunk |
results |
Optional, filled in after chunk execution |
meta |
Optional, stores meta data on the object |
Exported for users intending to extend qryflow. Subsequent processes rely on the structure of a qryflow_chunk.
An list-like object of class qryflow_chunk
chunk <- new_qryflow_chunk("query", "df_name", "SELECT * FROM mtcars;")chunk <- new_qryflow_chunk("query", "df_name", "SELECT * FROM mtcars;")
qryflow() is high level convenience function. It executes a SQL workflow
defined in a tagged .sql script or character string and returns query results as R objects.
The SQL script can contain multiple-steps (chunks), each tagged with @query or @exec. Query results
are captured and returned as a named list, where names correspond to the @query tags.
qryflow( con, sql, ..., on_error = c("stop", "warn", "collect"), verbose = getOption("qryflow.verbose", FALSE), simplify = TRUE, default_type = getOption("qryflow.default_type", "query") )qryflow( con, sql, ..., on_error = c("stop", "warn", "collect"), verbose = getOption("qryflow.verbose", FALSE), simplify = TRUE, default_type = getOption("qryflow.default_type", "query") )
con |
A database connection from |
sql |
A file path to a |
... |
Additional arguments passed to |
on_error |
Controls behaviour when a chunk fails during execution.
One of |
verbose |
Logical. If |
simplify |
Logical; if |
default_type |
The default chunk type (defaults to "query"). The global default can be set with
|
This is a wrapper around the combination of qryflow_run(), which always provides a list of results and metadata,
and qryflow_results(), which filters the output of qryflow_run() to only include the results of the SQL.
A named list of query results, or a single result if simplify = TRUE and only one chunk exists.
qryflow_run(), qryflow_results()
con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") results <- qryflow(con, filepath) head(results$df_mtcars) DBI::dbDisconnect(con)con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") results <- qryflow(con, filepath) head(results$df_mtcars) DBI::dbDisconnect(con)
qryflow_execute() takes a qryflow object (as returned by qryflow_parse()),
executes each chunk (e.g., @query, @exec), and collects the results and timing metadata.
This function is used internally by qryflow_run(), but can be called directly in concert with qryflow_parse() if you want
to manually control parsing and execution.
qryflow_execute( con, x, ..., on_error = c("stop", "warn", "collect"), verbose = getOption("qryflow.verbose", FALSE) )qryflow_execute( con, x, ..., on_error = c("stop", "warn", "collect"), verbose = getOption("qryflow.verbose", FALSE) )
con |
A database connection from |
x |
A |
... |
Reserved for future use |
on_error |
Controls behaviour when a chunk fails during execution.
One of |
verbose |
Logical. If |
An object of class qryflow, containing executed chunks with results and a meta attribute
that includes timing and source information.
qryflow_run(), qryflow_parse()
con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") parsed <- qryflow_parse(filepath) executed <- qryflow_execute(con, parsed) DBI::dbDisconnect(con)con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") parsed <- qryflow_parse(filepath) executed <- qryflow_execute(con, parsed) DBI::dbDisconnect(con)
Checks whether the specified handler exists in the handler registry environment.
qryflow_handler_exists(type)qryflow_handler_exists(type)
type |
chunk type to check (e.g., "query", "exec") |
Logical. Does type exist in the handler registry?
qryflow_handler_exists("query")qryflow_handler_exists("query")
Extract metadata from qryflow objects
qryflow_meta(x)qryflow_meta(x)
x |
|
con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") parsed <- qryflow_parse(filepath) qryflow_meta(parsed) qryflow_meta(parsed[[1]]) results <- qryflow_execute(con, parsed) qryflow_meta(results) qryflow_meta(results[[1]]) DBI::dbDisconnect(con)con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") parsed <- qryflow_parse(filepath) qryflow_meta(parsed) qryflow_meta(parsed[[1]]) results <- qryflow_execute(con, parsed) qryflow_meta(results) qryflow_meta(results[[1]]) DBI::dbDisconnect(con)
qryflow_parse() reads a SQL file or character vector and parses it into
discrete chunks based on @query, @exec, and other custom markers.
qryflow_parse( sql, ..., default_type = getOption("qryflow.default_type", "query") )qryflow_parse( sql, ..., default_type = getOption("qryflow.default_type", "query") )
sql |
A file path to a SQL workflow file, or a character vector containing SQL lines. |
... |
Reserved for future use. |
default_type |
The default chunk type (defaults to "query"). The global default can be set with
|
This function is used internally by qryflow_run(), but can also be used directly to
preprocess or inspect the structure of a SQL workflow.
An object of class qryflow, which is a structured list of SQL chunks and
metadata.
qryflow(), qryflow_run(), qryflow_execute()
filepath <- example_sql_path("mtcars.sql") parsed <- qryflow_parse(filepath)filepath <- example_sql_path("mtcars.sql") parsed <- qryflow_parse(filepath)
qryflow_workflow objectqryflow_results() retrieves the results from a list returned by qryflow_run(),
typically one that includes parsed and executed SQL chunks.
qryflow_results(x, ..., simplify = FALSE)qryflow_results(x, ..., simplify = FALSE)
x |
Results from |
... |
Reserved for future use. |
simplify |
Logical; if |
A named list of query results, or a single result object if simplify = TRUE and only one result is present.
con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") obj <- qryflow_run(con, filepath) results <- qryflow_results(obj) DBI::dbDisconnect(con)con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") obj <- qryflow_run(con, filepath) results <- qryflow_results(obj) DBI::dbDisconnect(con)
qryflow_run() reads a SQL workflow from a file path or character string, parses it into
tagged statements, and executes those statements against a database connection.
This function might be preferable for those who want a qryflow execution to consistently return a qryflow object. Whereas the qryflow() function
may return a list or other objects, depending on the arguments, qryflow_run() always returns a qryflow object. Results can be extracted using qryflow_results().
qryflow_run( con, sql, ..., on_error = c("stop", "warn", "collect"), verbose = getOption("qryflow.verbose", FALSE), default_type = getOption("qryflow.default_type", "query") )qryflow_run( con, sql, ..., on_error = c("stop", "warn", "collect"), verbose = getOption("qryflow.verbose", FALSE), default_type = getOption("qryflow.default_type", "query") )
con |
A database connection from |
sql |
A character string representing either the path to a |
... |
Additional arguments passed to |
on_error |
Controls behaviour when a chunk fails during execution.
One of |
verbose |
Logical. If |
default_type |
The default chunk type (defaults to "query"). The global default can be set with
|
A qryflow object representing the evaluated workflow, containing query results, execution metadata,
or both, depending on the contents of the SQL script.
qryflow(), qryflow_results(), qryflow_execute(), qryflow_parse()
con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") obj <- qryflow_run(con, filepath) obj$df_mtcars$sql obj$df_mtcars$results results <- qryflow_results(obj) head(results$df_mtcars$results) DBI::dbDisconnect(con)con <- example_db_connect(mtcars) filepath <- example_sql_path("mtcars.sql") obj <- qryflow_run(con, filepath) obj$df_mtcars$sql obj$df_mtcars$results results <- qryflow_results(obj) head(results$df_mtcars$results) DBI::dbDisconnect(con)
This is a generic function to ensure lines read from a file, a single character vector, or already parsed lines return the same format. This helps avoid re-reading entire texts by enabling already read lines to pass easily.
This is useful for folks who may want to extend qryflow.
read_sql_lines(x)read_sql_lines(x)
x |
a filepath or character vector containing SQL |
A qryflow_sql object (inherits from character) with a length equal to the number of lines read
# From a file ##### path <- example_sql_path() read_sql_lines(path) # From a single string ##### sql <- "SELECT * FROM mtcars;" read_sql_lines(sql) # From a character ##### lines <- c("SELECT *", "FROM mtcars;") read_sql_lines(lines)# From a file ##### path <- example_sql_path() read_sql_lines(path) # From a single string ##### sql <- "SELECT * FROM mtcars;" read_sql_lines(sql) # From a character ##### lines <- c("SELECT *", "FROM mtcars;") read_sql_lines(lines)
Use this function to register a custom chunk type with qryflow
register_qryflow_type(type, handler, overwrite = FALSE)register_qryflow_type(type, handler, overwrite = FALSE)
type |
Character indicating the chunk type (e.g., "exec", "query") |
handler |
A function to execute the SQL associated with the type. Must accept arguments "chunk", "con", and "...". |
overwrite |
Logical. Overwrite existing handler, if exists? |
To avoid manually registering your custom type each session, consider adding
the registration code to your .Rprofile or creating a package that leverages
.onLoad()
Logical. Indicating whether types were successfully registered.
# Create custom handler ##### custom_handler <- function(con, chunk, ...){ # Custom execution code will go here... # return(result) } register_qryflow_type("query-send", custom_handler, overwrite = TRUE)# Create custom handler ##### custom_handler <- function(con, chunk, ...){ # Custom execution code will go here... # return(result) } register_qryflow_type("query-send", custom_handler, overwrite = TRUE)
This function checks that the passed object is a function and contains the arguments "con", "chunk", and "..." - in that order. This is to help ensure users only register valid handlers.
validate_qryflow_handler(handler)validate_qryflow_handler(handler)
handler |
object to check |
Logical. Generates an error if the object does not pass all the criteria.
custom_func <- function(con, chunk, ...){ # Parsing Code Goes Here } validate_qryflow_handler(custom_func)custom_func <- function(con, chunk, ...){ # Parsing Code Goes Here } validate_qryflow_handler(custom_func)