Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional Functions implementation for Eval Engine #1375

Merged
merged 5 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,7 @@ class PartiQLEngineDefaultTest {

internal fun assert() {
val statement = parser.parse(input).root
val catalogBuilder = MemoryCatalog.builder().name("memory")
val catalogBuilder = MemoryCatalog.PartiQL().name("memory")
globals.forEach { global ->
catalogBuilder.define(global.name, global.type, loader.loadSingleElement(global.value))
}
Expand Down Expand Up @@ -1268,7 +1268,7 @@ class PartiQLEngineDefaultTest {

private fun run(mode: PartiQLEngine.Mode): PartiQLValue {
val statement = parser.parse(input).root
val catalog = MemoryCatalog.builder().name("memory").build()
val catalog = MemoryCatalog.PartiQL().name("memory").build()
val connector = MemoryConnector(catalog)
val connectorSession = object : ConnectorSession {
override fun getQueryId(): String = "q"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1830,11 +1830,18 @@ internal class PartiQLParserDefault : PartiQLParser {
* TODO Add labels to each alternative, https://github.com/partiql/partiql-lang-kotlin/issues/1113
*/
override fun visitOverlay(ctx: GeneratedParser.OverlayContext) = translate(ctx) {
// TODO: figure out why do we have a normalized form for overlay?
if (ctx.PLACING() == null) {
// normal form
val function = "OVERLAY".toIdentifier()
val args = visitOrEmpty<Expr>(ctx.expr())
exprCall(function, args)
val args = arrayOfNulls<Expr>(4).also {
visitOrEmpty<Expr>(ctx.expr()).forEachIndexed { index, expr ->
it[index] = expr
}
}
val e = error(ctx, "overlay function requires at least three args")

exprOverlay(args[0] ?: throw e, args[1] ?: throw e, args[2] ?: throw e, args[3])
} else {
// special form
val value = visitExpr(ctx.expr(0))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,12 +583,52 @@ internal object RexConverter {
return rex(type, call)
}

/**
* SQL Spec 1999: Section 6.18 <string value function>
*
* <character overlay function> ::=
* OVERLAY <left paren> <character value expression>
* PLACING <character value expression>
* FROM <start position>
* [ FOR <string length> ] <right paren>
*
* The <character overlay function> is equivalent to:
*
* SUBSTRING ( CV FROM 1 FOR SP - 1 ) || RS || SUBSTRING ( CV FROM SP + SL )
*
* Where CV is the first <character value expression>,
* SP is the <start position>
* RS is the second <character value expression>,
* SL is the <string length> if specified, otherwise it is char_length(RS).
*/
override fun visitExprOverlay(node: Expr.Overlay, ctx: Env): Rex {
TODO("SQL Special Form OVERLAY")
val cv = visitExprCoerce(node.value, ctx)
val sp = visitExprCoerce(node.start, ctx)
val rs = visitExprCoerce(node.overlay, ctx)
val sl = node.length?.let { visitExprCoerce(it, ctx) } ?: rex(StaticType.ANY, call("char_length", rs))
val p1 = rex(
StaticType.ANY,
call(
"substring",
cv,
rex(StaticType.INT4, rexOpLit(int32Value(1))),
rex(StaticType.ANY, call("minus", sp, rex(StaticType.INT4, rexOpLit(int32Value(1)))))
)
)
val p2 = rex(StaticType.ANY, call("concat", p1, rs))
return rex(
StaticType.ANY,
call(
"concat",
p2,
rex(StaticType.ANY, call("substring", cv, rex(StaticType.ANY, call("plus", sp, sl))))
)
)
}

override fun visitExprExtract(node: Expr.Extract, ctx: Env): Rex {
TODO("SQL Special Form EXTRACT")
val call = call("extract_${node.field.name.lowercase()}", visitExprCoerce(node.source, ctx))
return rex(StaticType.ANY, call)
}

// TODO: Ignoring type parameter now
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class PlanTest {
}

fun buildMetadata(catalogName: String): ConnectorMetadata {
val catalog = MemoryCatalog(catalogName)
val catalog = MemoryCatalog.PartiQL().name(catalogName).build()
// Insert binding
val name = BindingPath(
listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SubsumptionTest {
override fun getQueryId(): String = "query-id"
override fun getUserId(): String = "user-id"
}
private val connector = MemoryConnector.empty()
private val connector = MemoryConnector.partiQL()
}

private fun getExcludeClause(statement: Statement): Rel.Op.Exclude {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ abstract class PartiQLTyperTestBase {
* Build a ConnectorMetadata instance from the list of types.
*/
private fun buildMetadata(catalog: String, types: List<StaticType>): ConnectorMetadata {
val cat = MemoryCatalog(catalog)
val cat = MemoryCatalog.PartiQL().name(catalog).build()
val connector = MemoryConnector(cat)

// define all bindings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class PlanTyperTestsPorted {
}
}
map.entries.map { (catalogName, bindings) ->
val catalog = MemoryCatalog(catalogName)
val catalog = MemoryCatalog.PartiQL().name(catalogName).build()
val connector = MemoryConnector(catalog)
for (binding in bindings) {
val path = binding.first
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.partiql.spi.connector.sql

/* ktlint-disable no-wildcard-imports */
import org.partiql.spi.connector.sql.exts.*
import org.partiql.spi.fn.FnExperimental

/**
* PartiQL built-in functions that are not in the SQL-92 spec
*/
@OptIn(FnExperimental::class)
internal object PartiQLExts {
@JvmStatic
val builtins = listOf(
Fn_EXISTS__BAG__BOOL,
Fn_EXISTS__LIST__BOOL,
Fn_EXISTS__SEXP__BOOL,
Fn_EXISTS__STRUCT__BOOL,
Fn_SIZE__BAG__INT32,
Fn_SIZE__LIST__INT32,
Fn_SIZE__SEXP__INT32,
Fn_SIZE__STRUCT__INT32
)
}
Loading
Loading