Skip to content

Commit

Permalink
Adds tests for DML statements
Browse files Browse the repository at this point in the history
Adds links to removed DML statements

Removes ExprRow in favor of ExprRowValue
  • Loading branch information
johnedquinn committed Dec 2, 2024
1 parent 4035919 commit a8e9c1c
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 96 deletions.
22 changes: 1 addition & 21 deletions partiql-ast/api/partiql-ast.api
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public final class org/partiql/ast/Ast {
public static final fun exprPathStepField (Lorg/partiql/ast/Identifier;Lorg/partiql/ast/expr/PathStep;)Lorg/partiql/ast/expr/PathStep$Field;
public static final fun exprPosition (Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/expr/ExprPosition;
public static final fun exprQuerySet (Lorg/partiql/ast/QueryBody;Lorg/partiql/ast/OrderBy;Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/expr/ExprQuerySet;
public static final fun exprRow (ZLjava/util/List;)Lorg/partiql/ast/expr/ExprRow;
public static final fun exprRowValue (Ljava/util/List;)Lorg/partiql/ast/expr/ExprRowValue;
public static final fun exprRowValue (Ljava/util/List;Z)Lorg/partiql/ast/expr/ExprRowValue;
public static final fun exprSessionAttribute (Lorg/partiql/ast/expr/SessionAttribute;)Lorg/partiql/ast/expr/ExprSessionAttribute;
public static final fun exprStruct (Ljava/util/List;)Lorg/partiql/ast/expr/ExprStruct;
public static final fun exprStructField (Lorg/partiql/ast/expr/Expr;Lorg/partiql/ast/expr/Expr;)Lorg/partiql/ast/expr/ExprStruct$Field;
Expand Down Expand Up @@ -326,7 +326,6 @@ public abstract class org/partiql/ast/AstVisitor {
public fun visitExprPath (Lorg/partiql/ast/expr/ExprPath;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitExprPosition (Lorg/partiql/ast/expr/ExprPosition;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitExprQuerySet (Lorg/partiql/ast/expr/ExprQuerySet;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitExprRow (Lorg/partiql/ast/expr/ExprRow;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitExprRowValue (Lorg/partiql/ast/expr/ExprRowValue;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitExprSessionAttribute (Lorg/partiql/ast/expr/ExprSessionAttribute;Ljava/lang/Object;)Ljava/lang/Object;
public fun visitExprStruct (Lorg/partiql/ast/expr/ExprStruct;Ljava/lang/Object;)Ljava/lang/Object;
Expand Down Expand Up @@ -2102,25 +2101,6 @@ public class org/partiql/ast/expr/ExprQuerySet$Builder {
public fun toString ()Ljava/lang/String;
}

public class org/partiql/ast/expr/ExprRow : org/partiql/ast/expr/Expr {
public field isExplicit Z
public final field values Ljava/util/List;
public fun <init> (ZLjava/util/List;)V
public fun accept (Lorg/partiql/ast/AstVisitor;Ljava/lang/Object;)Ljava/lang/Object;
public static fun builder ()Lorg/partiql/ast/expr/ExprRow$Builder;
protected fun canEqual (Ljava/lang/Object;)Z
public fun children ()Ljava/util/Collection;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
}

public class org/partiql/ast/expr/ExprRow$Builder {
public fun build ()Lorg/partiql/ast/expr/ExprRow;
public fun isExplicit (Z)Lorg/partiql/ast/expr/ExprRow$Builder;
public fun toString ()Ljava/lang/String;
public fun values (Ljava/util/List;)Lorg/partiql/ast/expr/ExprRow$Builder;
}

public class org/partiql/ast/expr/ExprRowValue : org/partiql/ast/expr/Expr {
public field isExplicit Z
public final field values Ljava/util/List;
Expand Down
5 changes: 0 additions & 5 deletions partiql-ast/src/main/java/org/partiql/ast/AstVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.partiql.ast.expr.ExprPath;
import org.partiql.ast.expr.ExprPosition;
import org.partiql.ast.expr.ExprQuerySet;
import org.partiql.ast.expr.ExprRow;
import org.partiql.ast.expr.ExprRowValue;
import org.partiql.ast.expr.ExprSessionAttribute;
import org.partiql.ast.expr.ExprStruct;
Expand Down Expand Up @@ -262,10 +261,6 @@ public R visitExprArray(ExprArray node, C ctx) {
return defaultVisit(node, ctx);
}

public R visitExprRow(ExprRow node, C ctx) {
return defaultVisit(node, ctx);
}

public R visitExprBag(ExprBag node, C ctx) {
return defaultVisit(node, ctx);
}
Expand Down
52 changes: 0 additions & 52 deletions partiql-ast/src/main/java/org/partiql/ast/expr/ExprRow.java

This file was deleted.

11 changes: 5 additions & 6 deletions partiql-ast/src/main/kotlin/org/partiql/ast/Ast.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import org.partiql.ast.expr.ExprParameter
import org.partiql.ast.expr.ExprPath
import org.partiql.ast.expr.ExprPosition
import org.partiql.ast.expr.ExprQuerySet
import org.partiql.ast.expr.ExprRow
import org.partiql.ast.expr.ExprRowValue
import org.partiql.ast.expr.ExprSessionAttribute
import org.partiql.ast.expr.ExprStruct
Expand Down Expand Up @@ -66,11 +65,6 @@ public object Ast {
return ExprArray(values)
}

@JvmStatic
public fun exprRow(isExplicit: Boolean, values: List<Expr>): ExprRow {
return ExprRow(isExplicit, values)
}

@JvmStatic
public fun exprBag(values: List<Expr>): ExprBag {
return ExprBag(values)
Expand Down Expand Up @@ -224,6 +218,11 @@ public object Ast {
return ExprRowValue(values)
}

@JvmStatic
public fun exprRowValue(values: List<Expr>, isExplicit: Boolean): ExprRowValue {
return ExprRowValue(isExplicit, values)
}

@JvmStatic
public fun exprVariant(value: String, encoding: String): ExprVariant {
return ExprVariant(value, encoding)
Expand Down
10 changes: 3 additions & 7 deletions partiql-parser/src/main/antlr/DML.g4
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ options {
//
//
// STATEMENTS
// TODO: What is REMOVE?
// TODO: What is the RETURNING clause?
// TODO: What are the DML statements with the preceding FROM?
// TODO: Determine future of REMOVE DML statement: https://github.com/partiql/partiql-lang-kotlin/issues/1668
// TODO: Determine future of FROM (INSERT, SET, REMOVE) statements: https://github.com/partiql/partiql-lang-kotlin/issues/1669
// TODO: Implement the RETURNING clause for INSERT/UPDATE. See https://github.com/partiql/partiql-lang-kotlin/issues/1667
//
//

Expand Down Expand Up @@ -49,15 +49,11 @@ replaceStatement: REPLACE INTO tblName=qualifiedName asIdent? insertSource;

insertSource
: insertFromSubquery
| insertFromConstructor
| insertFromDefault
;

insertFromSubquery: insertColumnList? expr;

// TODO
insertFromConstructor: insertColumnList?;

insertFromDefault: DEFAULT VALUES;

insertColumnList: PAREN_LEFT names+=symbolPrimitive ( COMMA names+=symbolPrimitive )* PAREN_RIGHT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ import org.partiql.ast.Ast.exprPathStepElement
import org.partiql.ast.Ast.exprPathStepField
import org.partiql.ast.Ast.exprPosition
import org.partiql.ast.Ast.exprQuerySet
import org.partiql.ast.Ast.exprRow
import org.partiql.ast.Ast.exprRowValue
import org.partiql.ast.Ast.exprSessionAttribute
import org.partiql.ast.Ast.exprStruct
import org.partiql.ast.Ast.exprStructField
Expand Down Expand Up @@ -1507,11 +1507,11 @@ internal class PartiQLParserDefault : PartiQLParser {
override fun visitRowValueConstructor(ctx: GeneratedParser.RowValueConstructorContext) = translate(ctx) {
val isExplicit = ctx.ROW() != null
val expressions = visitOrEmpty<Expr>(ctx.expr())
exprRow(isExplicit, expressions)
exprRowValue(expressions, isExplicit)
}

override fun visitTableValueConstructor(ctx: GeneratedParser.TableValueConstructorContext) = translate(ctx) {
val rows = visitOrEmpty<ExprArray>(ctx.rowValueExpressionList().expr())
val rows = visitOrEmpty<Expr>(ctx.rowValueExpressionList().expr())
exprTable(rows)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at:
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/

package org.partiql.parser.internal

import org.junit.jupiter.api.extension.ExtensionContext
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.ArgumentsProvider
import java.util.stream.Stream

/**
* Reduces some of the boilerplate associated with the style of parameterized testing frequently
* utilized in this package.
*
* Since JUnit5 requires `@JvmStatic` on its `@MethodSource` argument factory methods, this requires all
* of the argument lists to reside in the companion object of a test class. This can be annoying since it
* forces the test to be separated from its tests cases.
*
* Classes that derive from this class can be defined near the `@ParameterizedTest` functions instead.
*/
abstract class ArgumentsProviderBase : ArgumentsProvider {

abstract fun getParameters(): List<Any>

@Throws(Exception::class)
override fun provideArguments(extensionContext: ExtensionContext): Stream<out Arguments>? {
return getParameters().map { Arguments.of(it) }.stream()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.partiql.parser.internal

import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ArgumentsSource

class DeleteStatementTests {

@ParameterizedTest
@ArgumentsSource(SuccessTestCases::class)
fun success(tc: PTestDef) {
tc.assert()
}

@ParameterizedTest
@ArgumentsSource(FailureTestCases::class)
fun failure(tc: PTestDef) {
tc.assert()
}

object SuccessTestCases : ArgumentsProviderBase() {
override fun getParameters(): List<ParserTestCaseSimple> {
val m = mapOf(
"Simplest test" to "DELETE FROM tbl",
"Simplest deletion with condition" to "DELETE FROM tbl WHERE a = 2",
"Namespaced table name" to "DELETE FROM \"CaT1\".schema1.\"TBL_1\"",
"Namespaced table name with condition" to "DELETE FROM \"CaT1\".schema1.\"TBL_1\" WHERE y < x",
).entries.map { ParserTestCaseSimple(it.key, it.value, isValid = true) }
return m
}
}

object FailureTestCases : ArgumentsProviderBase() {
override fun getParameters(): List<ParserTestCaseSimple> {
val m = mapOf(
"Lack of table name" to "DELETE FROM WHERE a = 2",
"Lack of condition" to "DELETE FROM tbl WHERE",
).entries.map { ParserTestCaseSimple(it.key, it.value, isValid = false) }
return m
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.partiql.parser.internal

import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ArgumentsSource

class InsertStatementTests {

@ParameterizedTest
@ArgumentsSource(SuccessTestCases::class)
fun success(tc: PTestDef) {
tc.assert()
}

@ParameterizedTest
@ArgumentsSource(FailureTestCases::class)
fun failure(tc: PTestDef) {
tc.assert()
}

object SuccessTestCases : ArgumentsProviderBase() {
override fun getParameters(): List<ParserTestCaseSimple> {
val m = mapOf(
"Simplest insert of a row" to "INSERT INTO tbl VALUES (1, 2, 3)",
"Column definitions" to "INSERT INTO tbl (a, b, c) VALUES (1, 2, 3)",
"Multiple rows" to "INSERT INTO tbl VALUES (1, 2, 3), (4, 5, 6), (7, 8, 8)",
"Multiple non-row values" to "INSERT INTO tbl VALUES 1, 2, 3",
"Using DEFAULT VALUES" to "INSERT INTO tbl DEFAULT VALUES",
"Explicit bag" to "INSERT INTO tbl << 1, 2, 3 >>",
"Explicit array" to "INSERT INTO tbl [ 1, 2, 3 ]",
"Namespaced table name with delimited alias" to "INSERT INTO \"CaT1\".schema1.\"TBL_1\" AS \"myt\" VALUES (1, 2, 3)",
"Namespaced table name with regular alias" to "INSERT INTO \"CaT1\".schema1.\"TBL_1\" AS myt VALUES (1, 2, 3)",
"Do nothing on conflict" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT DO NOTHING",
"Do nothing on conflict with target index" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT (a, b) DO NOTHING",
"Do nothing on conflict with named constraint" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT ON CONSTRAINT my_constraint DO NOTHING",
"Do replace excluded on conflict" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT DO REPLACE EXCLUDED",
"Do replace excluded on conflict with condition" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT DO REPLACE EXCLUDED WHERE a < 2",
"Do replace excluded on conflict with target index" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT (a, b) DO REPLACE EXCLUDED",
"Do replace excluded on conflict with target index with condition" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT (a, b) DO REPLACE EXCLUDED WHERE a < 2",
"Do replace excluded on conflict with named constraint" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT ON CONSTRAINT my_constraint DO REPLACE EXCLUDED",
"Do replace excluded on conflict with named constraint with condition" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT ON CONSTRAINT my_constraint DO REPLACE EXCLUDED WHERE a < 2",
"Do update excluded on conflict" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT DO UPDATE EXCLUDED",
"Do update excluded on conflict with condition" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT DO UPDATE EXCLUDED WHERE a < 2",
"Do update excluded on conflict with target index" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT (a, b) DO UPDATE EXCLUDED",
"Do update excluded on conflict with target index with condition" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT (a, b) DO UPDATE EXCLUDED WHERE a < 2",
"Do update excluded on conflict with named constraint" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT ON CONSTRAINT my_constraint DO UPDATE EXCLUDED",
"Do update excluded on conflict with named constraint with condition" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT ON CONSTRAINT my_constraint DO UPDATE EXCLUDED WHERE a < 2",
).entries.map { ParserTestCaseSimple(it.key, it.value, isValid = true) }
return m
}
}

object FailureTestCases : ArgumentsProviderBase() {
override fun getParameters(): List<ParserTestCaseSimple> {
val m = mapOf(
"Lack of table name" to "INSERT INTO VALUES (1, 2, 3)",
"Trailing comma for VALUES" to "INSERT INTO tbl VALUES (1, 2, 3), (4, 5, 6),",
"Not DEFAULT VALUES" to "INSERT INTO tbl DEFAULT VALUE",
"Bad column definitions" to "INSERT INTO tbl (a.b, b, c) VALUES (1, 2, 3)",
"Empty column definitions" to "INSERT INTO tbl () VALUES (1, 2, 3)",
"No values" to "INSERT INTO tbl (a, b) VALUES",
"Bad alias" to "INSERT INTO tbl AS alias1.alias2 (a, b) VALUES",
"Do something on conflict" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT DO SOMETHING",
"No parenthesis on conflict with target index" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT a, b DO NOTHING",
"Bad reference for index on conflict with target index" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT (a, b.c) DO NOTHING",
"Do nothing on conflict with no named constraint" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT ON CONSTRAINT DO NOTHING",
"Do update excluded on conflict with condition in wrong spot" to "INSERT INTO tbl << 1, 2, 3 >> ON CONFLICT WHERE a < 2 DO UPDATE EXCLUDED",
).entries.map { ParserTestCaseSimple(it.key, it.value, isValid = false) }
return m
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ class ParserTestCaseSimple(
}
}
}

override fun toString(): String {
return name
}
}
Loading

0 comments on commit a8e9c1c

Please sign in to comment.