‘fabricQueryR’ helps you work with Microsoft Fabric directly from R.
You can use it to find Fabric workspaces and data items, query Fabric data interfaces (SQL, DAX, KQL, and GraphQL), work with OneLake files and tables, run Spark code, and start or monitor Fabric jobs.
Install the latest CRAN release:
install.packages("fabricQueryR")Install the development version from GitHub:
if (!requireNamespace("remotes", quietly = TRUE)) {
install.packages("remotes")
}
remotes::install_github("kennispunttwente/fabricQueryR")To connect to Microsoft Fabric, set your Microsoft Entra tenant ID and sign in. You can also set a client ID if your tenant does not permit the package’s default public Azure CLI client.
library(fabricQueryR)
Sys.setenv(FABRICQUERYR_TENANT_ID = "your-tenant-id")
# Optional, if your tenant does not permit the public Azure CLI client ID:
# Sys.setenv(FABRICQUERYR_CLIENT_ID = "your-app-client-id")The authentication vignette covers interactive sign-in, app registrations, service principals, and other authentication options.
The examples below focus on the main use of each function group. See the function reference and vignettes for configuration options and more involved workflows.
Find the Fabric resources you can access. Discovery returns R6
objects; package-supported actionable types receive specialized methods,
while other types remain generic FabricItem records. In the
example below, $lakehouses() is the object interface to
fabric_lakehouses(), and $read_table() calls
fabric_lakehouse_read_table().
# Find a workspace & lakehouse, and then read a table
workspace <- fabric_workspaces()[[1L]]
lakehouse <- workspace$lakehouses()[[1L]]
orders <- lakehouse$read_table("orders", limit = 1000)
# Read service fields directly
lakehouse$id
lakehouse$displayName
# Equivalent plain-record interface: as.list(lakehouse)
lakehouse_record <- lakehouse$as_list()Search the preview OneLake catalog when discovery must span all visible workspaces:
sales_items <- fabric_catalog_search(
search = "sales",
types = c("Lakehouse", "Warehouse")
)Open a reusable ‘DBI’ connection with $sql_connect()
(fabric_sql_connect()), or run a single query with
$sql_query() (fabric_sql_query()). These
interfaces work with a Warehouse, SQL Database, or Lakehouse SQL
analytics endpoint.
lakehouse <- workspace$lakehouses()[[1L]]
con <- lakehouse$sql_connect()
DBI::dbListTables(con)
DBI::dbDisconnect(con)
customers <- lakehouse$sql_query(
"SELECT * FROM dbo.Customers WHERE region = 'West'"
)$sql_connect() (fabric_sql_connect())
supports both ODBC and ADBC. The default ODBC backend requires Microsoft
ODBC Driver 18 for SQL Server. The default
numeric_policy = "auto" uses ODBC’s numeric conversion and
warns once per session that precision may be lost. Use
backend = "adbc" for exact conversion, or
numeric_policy = "exact" to reject potentially lossy ODBC
results. Explicit numeric_policy = "driver" accepts
conversion without the warning.
Run a DAX query with $dax_query()
(fabric_pbi_dax_query()) and return the result as a tibble.
$semantic_models() is the workspace method for
fabric_semantic_models().
semantic_model <- workspace$semantic_models()[[1L]]
customers <- semantic_model$dax_query(
dax = "EVALUATE TOPN(1000, 'Customers')"
)The function also supports Arrow streaming for modern semantic models on Premium or Fabric capacity.
Run PySpark, Scala, Spark SQL, or SparkR remotely with
$livy_query() (fabric_livy_query()) and return
the result to the local R session. $lakehouses() is the
workspace method for fabric_lakehouses().
lakehouse <- workspace$lakehouses()[[1L]]
result <- lakehouse$livy_query(
kind = "pyspark",
code = "print(1 + 2)"
)Reusable Livy sessions and independent batch submissions are available for multi-step and application-file workflows. See Working with Livy (Spark) for choosing between one-off queries, reusable sessions, and batch jobs.
Move data between R and managed Delta tables with
$read_table() (fabric_lakehouse_read_table())
and $write_table()
(fabric_lakehouse_write_table()). The writer accepts data
frames as well as lazy Arrow sources; $lakehouses()
corresponds to fabric_lakehouses().
lakehouse <- workspace$lakehouses()[[1L]]
orders <- lakehouse$read_table("orders")
lakehouse$write_table(
table = "orders_from_r",
data = orders
)Use $load_table()
(fabric_lakehouse_load_table()) when the source CSV or
Parquet data already exists under Files/ in the same
Lakehouse. See Working
with Fabric Lakehouses and OneLake for the distinction between
ordinary files and managed Delta tables, table loading, larger reads,
and shortcuts.
When only metadata existence is needed, use
fabric_onelake_schema_exists() or
fabric_onelake_table_exists() with either the Delta or
Iceberg table protocol.
Read and write common file formats directly between R and OneLake
with $onelake_read_file()
(fabric_onelake_read_file()) and
$onelake_write_file()
(fabric_onelake_write_file()). Lakehouse file paths
normally start with Files/; $lakehouses()
corresponds to fabric_lakehouses().
lakehouse <- workspace$lakehouses()[[1L]]
lakehouse$onelake_write_file(
path = "Files/exports/orders.parquet",
data = data.frame(id = 1:3, amount = c(10, 20, 30))
)
orders <- lakehouse$onelake_read_file(
path = "Files/exports/orders.parquet"
)The same function group also lists, inspects, downloads, uploads, and deletes OneLake files. The Fabric Lakehouses and OneLake vignette continues with file discovery, uploads, managed tables, and safe deletion.
Read a Warehouse table with $read_table()
(fabric_warehouse_read_table()) or load an R or Arrow
object with $write_table()
(fabric_warehouse_write_table()). Writes use a Lakehouse as
temporary OneLake staging for Fabric’s COPY INTO.
$warehouses() and $lakehouses() correspond to
fabric_warehouses() and
fabric_lakehouses().
warehouse <- workspace$warehouses()[[1L]]
lakehouse <- workspace$lakehouses()[[1L]]
orders <- warehouse$read_table("orders")
warehouse$write_table(
table = "orders_copy",
data = orders,
staging_lakehouse = lakehouse,
create_if_missing = TRUE
)Warehouse reads use the same numeric policy as SQL queries: driver
conversion with a once-per-session warning for ODBC, or exact conversion
for ADBC. Set numeric_policy = "exact" to reject unsafe
ODBC conversions, or numeric_policy = "driver" to
explicitly accept conversion without a warning.
See Working with Fabric Warehouses for staging, table creation, overwrite behavior, schema matching, and large Arrow inputs.
Use $query() (fabric_kql_query()) to query
an Eventhouse database, or $write_table()
(fabric_kql_write_table()) to write an R or Arrow object to
an existing KQL table. $kql_databases() corresponds to
fabric_kql_databases().
kql_database <- workspace$kql_databases()[[1L]]
events <- kql_database$query(
"Events | where EventType == 'Warning' | take 100"
)
kql_database$write_table(
table = "EventsCopy",
data = events,
create_if_missing = TRUE
)For tracked ingestion from existing storage files and server-side export to OneLake, see Working with Fabric Eventhouses (real-time data).
Call an API for GraphQL item with $query()
(fabric_graphql_query()). Data and GraphQL-level errors
remain separately available in the result; $graphql_apis()
corresponds to fabric_graphql_apis().
graphql_api <- workspace$graphql_apis()[[1L]]
result <- graphql_api$query(
query = "{ customers { items { id name region } } }"
)
result$data$customers$itemsWorking with GraphQL covers schema inspection, cursor pagination, and row collection.
Call published Fabric business logic through its public function URL and inspect the structured result. This API is experimental; its service shapes may change. See the vignette for the current validation limits.
result <- fabric_function_invoke(
Sys.getenv("FABRIC_FUNCTION_URL"),
parameters = list(customerName = "Ada", orderId = 42L)
)
result$outputEnable Public access in Run only mode and copy the URL from the function’s properties. See the User Data Functions vignette for permissions, limits, and retry behavior.
Start a semantic-model refresh with $refresh()
(fabric_pbi_refresh()) and wait with
$refresh_wait() (fabric_pbi_refresh_wait()).
The returned object includes the details needed to inspect failures;
$semantic_models() corresponds to
fabric_semantic_models().
semantic_model <- workspace$semantic_models()[[1L]]
refresh <- semantic_model$refresh()
completed <- semantic_model$refresh_wait(refresh, timeout = 1800)
completed$stateSee Working with Semantic Models (DAX queries) for DAX queries, enhanced refresh, permissions, and refresh diagnostics.
Start a notebook, data pipeline, or Spark job definition with
$run() (fabric_job_run()) and wait with
$wait() (fabric_job_wait()).
$notebooks() corresponds to
fabric_notebooks().
notebook <- workspace$notebooks()[[1L]]
job <- notebook$run(
parameters = list(mode = "incremental")
)
result <- notebook$wait(job, timeout = 900)
result$statusThe job automation vignette covers run history, cancellation, and recurring schedules.
Create a shortcut with $shortcut_create()
(fabric_onelake_shortcut_create()) when data in another
Fabric item should be available without being copied into the current
Lakehouse.
lakehouses <- workspace$lakehouses()
lakehouse <- lakehouses[[1L]]
source_lakehouse <- lakehouses[[2L]]
lakehouse$shortcut_create(
path = "Files",
name = "shared-orders",
target = source_lakehouse,
target_path = "Tables/orders"
)Resume an asynchronous Fabric operation from its ID or
Location URL, wait for completion, and retrieve its
result.
operation <- fabric_operation_status(
"00000000-0000-0000-0000-000000000000"
)
operation <- fabric_operation_wait(operation, timeout = 900)
result <- fabric_operation_result(operation)Microsoft Fabric brings data engineering, data warehousing, real-time analytics, and Power BI together in one platform, with OneLake as its shared storage layer.
When our organization started using Fabric, accessing its data from R was not yet straightforward. This package grew from the helper functions created to make that work easier and more consistent for other R users.
I (Luka Koning) am no longer associated with Kennispunt Twente. I maintain this open-source R package in my personal capacity. The repository remains under the Kennispunt Twente GitHub organization for historical reasons, and because the early development was done while I was affiliated with them.