Fixed bug in KQL translation of `%in%` operator so that it now works when the right hand side is either a vector or a tabular expression.
This commit is contained in:
Alex Kyllo 2023-01-24 23:03:25 -08:00 коммит произвёл GitHub
Родитель 43fab40608
Коммит 56518ce052
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 90 добавлений и 12 удалений

Просмотреть файл

@ -1,6 +1,6 @@
Package: AzureKusto Package: AzureKusto
Title: Interface to 'Kusto'/'Azure Data Explorer' Title: Interface to 'Kusto'/'Azure Data Explorer'
Version: 1.1.0.9000 Version: 1.1.1
Authors@R: c( Authors@R: c(
person("Hong", "Ooi", , "hongooi73@gmail.com", role = "aut"), person("Hong", "Ooi", , "hongooi73@gmail.com", role = "aut"),
person("Alex", "Kyllo", , "jekyllo@microsoft.com", role = c("aut", "cre")), person("Alex", "Kyllo", , "jekyllo@microsoft.com", role = c("aut", "cre")),

Просмотреть файл

@ -1,3 +1,8 @@
# AzureKusto 1.1.1
* Fixed bug in KQL translation of `%in%` operator so that it now works when the
right hand side is either a vector or a tabular expression.
# AzureKusto 1.1.0 # AzureKusto 1.1.0
* New function `export()` to export query results to Azure Storage. * New function `export()` to export query results to Azure Storage.

Просмотреть файл

@ -105,9 +105,14 @@ copy_env <- function(from, to = NULL, parent = parent.env(from))
kql_infix <- function(f) kql_infix <- function(f)
{ {
stopifnot(is.character(f)) stopifnot(is.character(f))
function(x, y) { function(x, y) {
build_kql(x, " ", kql(f), " ", y) # If y is a table/query we need to render and inline it
if (inherits(y, "tbl_kusto_abstract")) {
# KQL requires double parens around queries as RHS of in operator
build_kql(x, " ", kql(f), " ((", kql(kql_render(kql_build(y))), "))")
} else {
build_kql(x, " ", kql(f), " ", y)
}
} }
} }
@ -219,6 +224,8 @@ default_op <- function(x)
} }
#' Scalar operator translations (infix and prefix) #' Scalar operator translations (infix and prefix)
#' @export #' @export
base_scalar <- kql_translator( base_scalar <- kql_translator(
@ -244,13 +251,10 @@ base_scalar <- kql_translator(
`>` = kql_infix(">"), `>` = kql_infix(">"),
`>=` = kql_infix(">="), `>=` = kql_infix(">="),
`%in%` = function(x, table) { `%in%` = kql_infix("in"),
if (is.kql(table) || length(table) > 1) { `%in~%` = kql_infix("in~"),
build_kql(x, " IN ", table) `%!in%` = kql_infix("!in"),
} else { `%!in~%` = kql_infix("!in~"),
build_kql(x, " IN (", table, ")")
}
},
`!` = kql_prefix("not"), `!` = kql_prefix("not"),
`&` = kql_infix("and"), `&` = kql_infix("and"),

Просмотреть файл

@ -5,7 +5,7 @@
\alias{base_scalar} \alias{base_scalar}
\title{Scalar operator translations (infix and prefix)} \title{Scalar operator translations (infix and prefix)}
\format{ \format{
An object of class \code{environment} of length 76. An object of class \code{environment} of length 79.
} }
\usage{ \usage{
base_scalar base_scalar

Просмотреть файл

@ -713,6 +713,7 @@ cluster('local_df').database('local_df').['iris']
expect_equal(expected, cmd) expect_equal(expected, cmd)
}) })
test_that("kusto export command errors if format not in allowed list", test_that("kusto export command errors if format not in allowed list",
{ {
expect_error( expect_error(
@ -725,4 +726,72 @@ test_that("kusto export command errors if format not in allowed list",
distributed = FALSE distributed = FALSE
) )
) )
}) })
test_that("%in% operator works for vectors",
{
q <- tbl_iris |>
filter(Species %in% c("setosa", "versicolor"))
expected <- kql("cluster('local_df').database('local_df').['iris']
| where ['Species'] in ('setosa', 'versicolor')")
q_str <- show_query(q)
expect_equal(q_str, expected)
})
test_that("%!in% operator works for vectors",
{
q <- tbl_iris |>
filter(Species %!in% c("setosa", "versicolor"))
expected <- kql("cluster('local_df').database('local_df').['iris']
| where ['Species'] !in ('setosa', 'versicolor')")
q_str <- show_query(q)
expect_equal(q_str, expected)
})
test_that("%in~% operator works for vectors",
{
q <- tbl_iris |>
filter(Species %in~% c("setosa", "versicolor"))
expected <- kql("cluster('local_df').database('local_df').['iris']
| where ['Species'] in~ ('setosa', 'versicolor')")
q_str <- show_query(q)
expect_equal(q_str, expected)
})
test_that("%in% operator works for tables",
{
rhs <- select(tbl_iris, Species)
q <- tbl_iris |>
filter(Species %in% rhs)
expected <- kql("cluster('local_df').database('local_df').['iris']
| where ['Species'] in ((cluster('local_df').database('local_df').['iris']
| project ['Species']))")
q_str <- show_query(q)
expect_equal(q_str, expected)
})
test_that("%!in% operator works for tables",
{
rhs <- select(tbl_iris, Species)
q <- tbl_iris |>
filter(Species %!in% rhs)
expected <- kql("cluster('local_df').database('local_df').['iris']
| where ['Species'] !in ((cluster('local_df').database('local_df').['iris']
| project ['Species']))")
q_str <- show_query(q)
expect_equal(q_str, expected)
})
test_that("%in~% operator works for tables",
{
rhs <- select(tbl_iris, Species)
q <- tbl_iris |>
filter(Species %in~% rhs)
expected <- kql("cluster('local_df').database('local_df').['iris']
| where ['Species'] in~ ((cluster('local_df').database('local_df').['iris']
| project ['Species']))")
q_str <- show_query(q)
expect_equal(q_str, expected)
})