Skip to content

RD-10855 RDMBS readers duplicate columns that have the same name #420

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

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
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 @@ -140,7 +140,6 @@ class Rql2JsonWriter(os: OutputStream) {
val index = v.invokeMember("getIndex").asInt()
val actualValue = v.invokeMember("getValue")
writeValue(actualValue, tipes(index).asInstanceOf[Rql2TypeWithProperties])

case _ => throw new RuntimeException("unsupported type")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ package raw.compiler.rql2.tests.truffle.regressions
import raw.client.api.{GetProgramDescriptionSuccess, ProgramEnvironment}
import raw.compiler.rql2.truffle.TruffleCompilerTestContext
import raw.compiler.utils.SnapiInterpolator
import raw.testing.tags.TruffleTests

@TruffleTests
class RD10767Test extends TruffleCompilerTestContext {
private val data = tempFile("""
|[
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* Copyright 2024 RAW Labs S.A.
*
* Use of this software is governed by the Business Source License
* included in the file licenses/BSL.txt.
*
* As of the Change Date specified in that file, in accordance with
* the Business Source License, use of this software will be governed
* by the Apache License, Version 2.0, included in the file
* licenses/APL.txt.
*/

package raw.compiler.rql2.tests.truffle.regressions

import raw.compiler.rql2.truffle.TruffleCompilerTestContext
import raw.creds.jdbc.RDBMSTestCreds
import raw.testing.tags.TruffleTests

@TruffleTests
class RD10855Test extends TruffleCompilerTestContext with RDBMSTestCreds {

// The column y is of type varchar, but we are setting to undefined
// when the value is not null it shows the error "skipping column of type ..."
test(
s"""PostgreSQL.Read(
| "${pgsqlCreds.database}",
| "rdbmstest",
| "tbl1",
| type collection(record(a: int, b: int, c: double, d: double, x: string, y: undefined)),
| host = "${pgsqlCreds.host}",
| username = "${pgsqlCreds.username.get}",
| password = "${pgsqlCreds.password.get}"
|)""".stripMargin
) { it =>
it should evaluateTo(
"""[
| {a: 1, b: 1, c: 1.5, d: 1.5, x: "x1", y: "skipping column of type varchar"},
| {a: 2, b: 2, c: 2.2, d: 2.2, x: "x2", y: "skipping column of type varchar"},
| {a: 3, b: null, c: 3.3, d: null, x: "x3", y: null}
|]""".stripMargin
)
}

// As we are getting items by index, we can rename the columns, as long as the types are correct
test(
s"""PostgreSQL.Read(
| "${pgsqlCreds.database}",
| "rdbmstest",
| "tbl1",
| type collection(record(e: int, f: int, g: double, h: double, xx: string, yy: string)),
| host = "${pgsqlCreds.host}",
| username = "${pgsqlCreds.username.get}",
| password = "${pgsqlCreds.password.get}"
|)""".stripMargin
) { it =>
it should evaluateTo(
"""[
| {e: 1, f: 1, g: 1.5, h: 1.5, xx: "x1", yy: "y1"},
| {e: 2, f: 2, g: 2.2, h: 2.2, xx: "x2", yy: "y2"},
| {e: 3, f: null, g: 3.3, h: null, xx: "x3", yy: null}
|]""".stripMargin
)
}

// table skippable_types has unsupported types, field f: macaddr, field g: cidr
// but are null so no errors will be shown
test(
s"""PostgreSQL.InferAndRead(
| "${pgsqlCreds.database}",
| "rdbmstest",
| "skippable_types",
| host = "${pgsqlCreds.host}",
| username = "${pgsqlCreds.username.get}",
| password = "${pgsqlCreds.password.get}"
|)""".stripMargin
) { it =>
it should evaluateTo(
"""[
| {a: 1, b: "hello", c: 2, d: 3, e: Decimal.From(4.4), f: null, g: null}
|]""".stripMargin
)
}

val ttt = "\"\"\""
// Retrieving columns with repeated names
test(s"""PostgreSQL.InferAndQuery(
| "${pgsqlCreds.database}",
| ${ttt}SELECT t1.a, t2.a, t1.b, t2.x as b
| FROM rdbmstest.tbl1 t1, rdbmstest.tbl1 t2
| WHERE t1.a = t2.a $ttt,
| host = "${pgsqlCreds.host}",
| username = "${pgsqlCreds.username.get}",
| password = "${pgsqlCreds.password.get}"
|)""".stripMargin) { it =>
it should evaluateTo(

Check failure on line 95 in snapi-client/src/test/scala/raw/compiler/rql2/tests/truffle/regressions/RD10855Test.scala

View workflow job for this annotation

GitHub Actions / JUnit Test Report

RD10855Test.PostgreSQL.InferAndQuery( "rawtest", """SELECT t1.a, t2.a, t1.b, t2.x as b FROM rdbmstest.tbl1 t1, rdbmstest.tbl1 t2 WHERE t1.a = t2.a """, host = "test-psql.raw-labs.com", username = "rawtest", password = "f55ba92415" )

org.scalatest.exceptions.TestFailedException: null
Raw output
sbt.ForkMain$ForkError: org.scalatest.exceptions.TestFailedException: null
	at org.scalatest.Assertions.newAssertionFailedException(Assertions.scala:472)
	at org.scalatest.Assertions.newAssertionFailedException$(Assertions.scala:471)
	at org.scalatest.funsuite.FixtureAnyFunSuite.newAssertionFailedException(FixtureAnyFunSuite.scala:230)
	at org.scalatest.Assertions.fail(Assertions.scala:965)
	at org.scalatest.Assertions.fail$(Assertions.scala:961)
	at org.scalatest.funsuite.FixtureAnyFunSuite.fail(FixtureAnyFunSuite.scala:230)
	at raw.compiler.rql2.tests.CompilerTestContext.doValidate(CompilerTestContext.scala:662)
	at raw.compiler.rql2.tests.CompilerTestContext.doValidate$(CompilerTestContext.scala:649)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.doValidate(TruffleCompilerTestContext.scala:18)
	at raw.compiler.rql2.tests.CompilerTestContext.tryExecuteQuery(CompilerTestContext.scala:607)
	at raw.compiler.rql2.tests.CompilerTestContext.tryExecuteQuery$(CompilerTestContext.scala:595)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.tryExecuteQuery(TruffleCompilerTestContext.scala:18)
	at raw.compiler.rql2.tests.CompilerTestContext.executeQuery(CompilerTestContext.scala:589)
	at raw.compiler.rql2.tests.CompilerTestContext.executeQuery$(CompilerTestContext.scala:581)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.executeQuery(TruffleCompilerTestContext.scala:18)
	at raw.compiler.rql2.tests.CompilerTestContext$EvaluateTo.apply(CompilerTestContext.scala:399)
	at raw.compiler.rql2.tests.CompilerTestContext$EvaluateTo.apply(CompilerTestContext.scala:396)
	at org.scalatest.matchers.should.Matchers$ShouldMethodHelperClass.shouldMatcher(Matchers.scala:7291)
	at org.scalatest.matchers.should.Matchers$AnyShouldWrapper.should(Matchers.scala:7347)
	at raw.compiler.rql2.tests.truffle.regressions.RD10855Test.$anonfun$new$4(RD10855Test.scala:95)
	at org.scalatest.FixtureTestSuite$TestFunAndConfigMap.$anonfun$apply$1(FixtureTestSuite.scala:275)
	at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
	at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
	at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
	at org.scalatest.FixtureTestSuite$TestFunAndConfigMap.apply(FixtureTestSuite.scala:275)
	at raw.utils.RawTestSuite.withFixture(RawTestSuite.scala:44)
	at raw.utils.RawTestSuite.withFixture$(RawTestSuite.scala:43)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.withFixture(TruffleCompilerTestContext.scala:18)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.invokeWithFixture$1(FixtureAnyFunSuiteLike.scala:298)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.$anonfun$runTest$1(FixtureAnyFunSuiteLike.scala:309)
	at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTest(FixtureAnyFunSuiteLike.scala:309)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTest$(FixtureAnyFunSuiteLike.scala:290)
	at org.scalatest.funsuite.FixtureAnyFunSuite.runTest(FixtureAnyFunSuite.scala:230)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.$anonfun$runTests$1(FixtureAnyFunSuiteLike.scala:369)
	at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:413)
	at scala.collection.immutable.List.foreach(List.scala:431)
	at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401)
	at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:396)
	at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:475)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTests(FixtureAnyFunSuiteLike.scala:369)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTests$(FixtureAnyFunSuiteLike.scala:368)
	at org.scalatest.funsuite.FixtureAnyFunSuite.runTests(FixtureAnyFunSuite.scala:230)
	at org.scalatest.Suite.run(Suite.scala:1114)
	at org.scalatest.Suite.run$(Suite.scala:1096)
	at org.scalatest.funsuite.FixtureAnyFunSuite.org$scalatest$funsuite$FixtureAnyFunSuiteLike$$super$run(FixtureAnyFunSuite.scala:230)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.$anonfun$run$1(FixtureAnyFunSuiteLike.scala:373)
	at org.scalatest.SuperEngine.runImpl(Engine.scala:535)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.run(FixtureAnyFunSuiteLike.scala:373)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.run$(FixtureAnyFunSuiteLike.scala:372)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.org$scalatest$BeforeAndAfterAll$$super$run(TruffleCompilerTestContext.scala:18)
	at org.scalatest.BeforeAndAfterAll.liftedTree1$1(BeforeAndAfterAll.scala:213)
	at org.scalatest.BeforeAndAfterAll.run(BeforeAndAfterAll.scala:210)
	at org.scalatest.BeforeAndAfterAll.run$(BeforeAndAfterAll.scala:208)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.run(TruffleCompilerTestContext.scala:18)
	at org.scalatest.tools.Framework.org$scalatest$tools$Framework$$runSuite(Framework.scala:321)
	at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:517)
	at sbt.ForkMain$Run.lambda$runTest$1(ForkMain.java:414)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: sbt.ForkMain$ForkError: raw.client.api.CompilerServiceException: SqlQueryInputFormatDescriptor(pgsql,rawtest,SourceCollectionType(SourceRecordType(Vector(SourceAttrType(a,SourceIntType(false)), SourceAttrType(a,SourceIntType(false)), SourceAttrType(b,SourceIntType(true)), SourceAttrType(b,SourceStringType(false))),false),false)) (of class raw.inferrer.api.SqlQueryInputFormatDescriptor)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.$anonfun$getType$1(Rql2TruffleCompilerService.scala:140)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.withTruffleContext(Rql2TruffleCompilerService.scala:719)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.getType(Rql2TruffleCompilerService.scala:130)
	at raw.compiler.rql2.tests.CompilerTestContext.doValidate(CompilerTestContext.scala:656)
	... 55 more
Caused by: sbt.ForkMain$ForkError: scala.MatchError: SqlQueryInputFormatDescriptor(pgsql,rawtest,SourceCollectionType(SourceRecordType(Vector(SourceAttrType(a,SourceIntType(false)), SourceAttrType(a,SourceIntType(false)), SourceAttrType(b,SourceIntType(true)), SourceAttrType(b,SourceStringType(false))),false),false)) (of class raw.inferrer.api.SqlQueryInputFormatDescriptor)
	at raw.compiler.rql2.builtin.SqlTableExtensionHelper.resolveInferType(SqlTableExtensionHelper.scala:132)
	at raw.compiler.rql2.builtin.SqlTableExtensionHelper.resolveInferType$(SqlTableExtensionHelper.scala:122)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.resolveInferType(PostgreSQLPackage.scala:297)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.$anonfun$returnType$5(PostgreSQLPackage.scala:390)
	at scala.util.Either.flatMap(Either.scala:341)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.$anonfun$returnType$4(PostgreSQLPackage.scala:389)
	at scala.util.Either.flatMap(Either.scala:341)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.returnType(PostgreSQLPackage.scala:388)
	at raw.compiler.rql2.api.EntryExtension.returnTypeErrorList(PackageExtension.scala:138)
	at raw.compiler.rql2.SemanticAnalyzer.getFunAppPackageEntryType(SemanticAnalyzer.scala:1226)
	at raw.compiler.rql2.SemanticAnalyzer.raw$compiler$rql2$SemanticAnalyzer$$funAppHasError(SemanticAnalyzer.scala:641)
	at raw.compiler.rql2.SemanticAnalyzer$$anonfun$1.isDefinedAt(SemanticAnalyzer.scala:532)
	at raw.compiler.rql2.SemanticAnalyzer$$anonfun$1.isDefinedAt(SemanticAnalyzer.scala:483)
	at scala.PartialFunction$OrElse.isDefinedAt(PartialFunction.scala:170)
	at raw.compiler.base.SemanticAnalyzer$$anonfun$1.isDefinedAt(SemanticAnalyzer.scala:63)
	at raw.compiler.utils.ExtraRewriters$$anonfun$collectNodes$1.applyOrElse(ExtraRewriters.scala:35)
	at scala.PartialFunction$AndThen.applyOrElse(PartialFunction.scala:194)
	at scala.PartialFunction$AndThen.applyOrElse(PartialFunction.scala:194)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$query$1(Rewriter.scala:215)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$plus$1(Strategy.scala:59)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$times$1(Strategy.scala:44)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1(Rewriter.scala:592)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1$adapted(Rewriter.scala:590)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:196)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:194)
	at scala.collection.Iterator.foreach(Iterator.scala:943)
	at scala.collection.Iterator.foreach$(Iterator.scala:943)
	at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
	at scala.collection.TraversableOnce.foldLeft(TraversableOnce.scala:199)
	at scala.collection.TraversableOnce.foldLeft$(TraversableOnce.scala:192)
	at scala.collection.AbstractIterator.foldLeft(Iterator.scala:1431)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct(Rewriter.scala:590)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct$(Rewriter.scala:583)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$.allProduct(Rewriter.scala:1643)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$all$1(Rewriter.scala:543)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$times$1(Strategy.scala:45)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1(Rewriter.scala:592)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1$adapted(Rewriter.scala:590)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:196)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:194)
	at scala.collection.Iterator.foreach(Iterator.scala:943)
	at scala.collection.Iterator.foreach$(Iterator.scala:943)
	at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
	at scala.collection.TraversableOnce.foldLeft(TraversableOnce.scala:199)
	at scala.collection.TraversableOnce.foldLeft$(TraversableOnce.scala:192)
	at scala.collection.AbstractIterator.foldLeft(Iterator.scala:1431)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct(Rewriter.scala:590)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct$(Rewriter.scala:583)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$.allProduct(Rewriter.scala:1643)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$all$1(Rewriter.scala:543)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$times$1(Strategy.scala:45)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$collect$1(Rewriter.scala:1584)
	at raw.compiler.base.SemanticAnalyzer.collectErrors(SemanticAnalyzer.scala:54)
	at raw.compiler.base.SemanticAnalyzer.errors$lzycompute(SemanticAnalyzer.scala:61)
	at raw.compiler.base.SemanticAnalyzer.errors(SemanticAnalyzer.scala:60)
	at raw.compiler.base.TreeWithPositions.errors$lzycompute(TreeWithPositions.scala:39)
	at raw.compiler.base.TreeWithPositions.errors(TreeWithPositions.scala:47)
	at raw.compiler.base.TreeWithPositions.isTreeValid(TreeWithPositions.scala:61)
	at raw.compiler.base.BaseTree.valid$lzycompute(BaseTree.scala:52)
	at raw.compiler.base.BaseTree.valid(BaseTree.scala:52)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.$anonfun$getType$1(Rql2TruffleCompilerService.scala:134)
	... 58 more
"""[
| {a: 1, a: 1, b: 1, b: "x1"},
| {a: 2, a: 2, b: 2, b: "x2"},
| {a: 3, a: 3, b: null, b: "x3"}
|]""".stripMargin
)
}

// Interval type is not supported, so its skipped
test(s"""PostgreSQL.InferAndQuery(
| "${pgsqlCreds.database}",
| "SELECT * FROM rdbmstest.test_types",
| host = "${pgsqlCreds.host}",
| username = "${pgsqlCreds.username.get}",
| password = "${pgsqlCreds.password.get}"
|)""".stripMargin) { it =>
it should evaluateTo(

Check failure on line 112 in snapi-client/src/test/scala/raw/compiler/rql2/tests/truffle/regressions/RD10855Test.scala

View workflow job for this annotation

GitHub Actions / JUnit Test Report

RD10855Test.PostgreSQL.InferAndQuery( "rawtest", "SELECT * FROM rdbmstest.test_types", host = "test-psql.raw-labs.com", username = "rawtest", password = "f55ba92415" )

org.scalatest.exceptions.TestFailedException: null
Raw output
sbt.ForkMain$ForkError: org.scalatest.exceptions.TestFailedException: null
	at org.scalatest.Assertions.newAssertionFailedException(Assertions.scala:472)
	at org.scalatest.Assertions.newAssertionFailedException$(Assertions.scala:471)
	at org.scalatest.funsuite.FixtureAnyFunSuite.newAssertionFailedException(FixtureAnyFunSuite.scala:230)
	at org.scalatest.Assertions.fail(Assertions.scala:965)
	at org.scalatest.Assertions.fail$(Assertions.scala:961)
	at org.scalatest.funsuite.FixtureAnyFunSuite.fail(FixtureAnyFunSuite.scala:230)
	at raw.compiler.rql2.tests.CompilerTestContext.doValidate(CompilerTestContext.scala:662)
	at raw.compiler.rql2.tests.CompilerTestContext.doValidate$(CompilerTestContext.scala:649)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.doValidate(TruffleCompilerTestContext.scala:18)
	at raw.compiler.rql2.tests.CompilerTestContext.tryExecuteQuery(CompilerTestContext.scala:607)
	at raw.compiler.rql2.tests.CompilerTestContext.tryExecuteQuery$(CompilerTestContext.scala:595)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.tryExecuteQuery(TruffleCompilerTestContext.scala:18)
	at raw.compiler.rql2.tests.CompilerTestContext.executeQuery(CompilerTestContext.scala:589)
	at raw.compiler.rql2.tests.CompilerTestContext.executeQuery$(CompilerTestContext.scala:581)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.executeQuery(TruffleCompilerTestContext.scala:18)
	at raw.compiler.rql2.tests.CompilerTestContext$EvaluateTo.apply(CompilerTestContext.scala:399)
	at raw.compiler.rql2.tests.CompilerTestContext$EvaluateTo.apply(CompilerTestContext.scala:396)
	at org.scalatest.matchers.should.Matchers$ShouldMethodHelperClass.shouldMatcher(Matchers.scala:7291)
	at org.scalatest.matchers.should.Matchers$AnyShouldWrapper.should(Matchers.scala:7347)
	at raw.compiler.rql2.tests.truffle.regressions.RD10855Test.$anonfun$new$5(RD10855Test.scala:112)
	at org.scalatest.FixtureTestSuite$TestFunAndConfigMap.$anonfun$apply$1(FixtureTestSuite.scala:275)
	at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
	at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
	at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
	at org.scalatest.FixtureTestSuite$TestFunAndConfigMap.apply(FixtureTestSuite.scala:275)
	at raw.utils.RawTestSuite.withFixture(RawTestSuite.scala:44)
	at raw.utils.RawTestSuite.withFixture$(RawTestSuite.scala:43)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.withFixture(TruffleCompilerTestContext.scala:18)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.invokeWithFixture$1(FixtureAnyFunSuiteLike.scala:298)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.$anonfun$runTest$1(FixtureAnyFunSuiteLike.scala:309)
	at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTest(FixtureAnyFunSuiteLike.scala:309)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTest$(FixtureAnyFunSuiteLike.scala:290)
	at org.scalatest.funsuite.FixtureAnyFunSuite.runTest(FixtureAnyFunSuite.scala:230)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.$anonfun$runTests$1(FixtureAnyFunSuiteLike.scala:369)
	at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:413)
	at scala.collection.immutable.List.foreach(List.scala:431)
	at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:401)
	at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:396)
	at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:475)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTests(FixtureAnyFunSuiteLike.scala:369)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.runTests$(FixtureAnyFunSuiteLike.scala:368)
	at org.scalatest.funsuite.FixtureAnyFunSuite.runTests(FixtureAnyFunSuite.scala:230)
	at org.scalatest.Suite.run(Suite.scala:1114)
	at org.scalatest.Suite.run$(Suite.scala:1096)
	at org.scalatest.funsuite.FixtureAnyFunSuite.org$scalatest$funsuite$FixtureAnyFunSuiteLike$$super$run(FixtureAnyFunSuite.scala:230)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.$anonfun$run$1(FixtureAnyFunSuiteLike.scala:373)
	at org.scalatest.SuperEngine.runImpl(Engine.scala:535)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.run(FixtureAnyFunSuiteLike.scala:373)
	at org.scalatest.funsuite.FixtureAnyFunSuiteLike.run$(FixtureAnyFunSuiteLike.scala:372)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.org$scalatest$BeforeAndAfterAll$$super$run(TruffleCompilerTestContext.scala:18)
	at org.scalatest.BeforeAndAfterAll.liftedTree1$1(BeforeAndAfterAll.scala:213)
	at org.scalatest.BeforeAndAfterAll.run(BeforeAndAfterAll.scala:210)
	at org.scalatest.BeforeAndAfterAll.run$(BeforeAndAfterAll.scala:208)
	at raw.compiler.rql2.truffle.TruffleCompilerTestContext.run(TruffleCompilerTestContext.scala:18)
	at org.scalatest.tools.Framework.org$scalatest$tools$Framework$$runSuite(Framework.scala:321)
	at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:517)
	at sbt.ForkMain$Run.lambda$runTest$1(ForkMain.java:414)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: sbt.ForkMain$ForkError: raw.client.api.CompilerServiceException: SqlQueryInputFormatDescriptor(pgsql,rawtest,SourceCollectionType(SourceRecordType(Vector(SourceAttrType(smallint1,SourceShortType(true)), SourceAttrType(integer1,SourceIntType(true)), SourceAttrType(bigint1,SourceLongType(true)), SourceAttrType(decimal1,SourceDecimalType(true)), SourceAttrType(real1,SourceFloatType(true)), SourceAttrType(double1,SourceDoubleType(true)), SourceAttrType(money1,SourceDoubleType(true)), SourceAttrType(varchar1,SourceStringType(true)), SourceAttrType(char1,SourceStringType(true)), SourceAttrType(text1,SourceStringType(true)), SourceAttrType(boolean1,SourceBoolType(true)), SourceAttrType(timestamp1,SourceTimestampType(None,true)), SourceAttrType(date1,SourceDateType(None,true)), SourceAttrType(time1,SourceTimeType(None,true)), SourceAttrType(interval1,SourceNullType()), SourceAttrType(bytea1,SourceBinaryType(true)), SourceAttrType(bit1,SourceBoolType(true)), SourceAttrType(integer_array1,SourceNullType()), SourceAttrType(smallserial1,SourceShortType(false)), SourceAttrType(serial1,SourceIntType(false)), SourceAttrType(bigserial1,SourceLongType(false))),false),false)) (of class raw.inferrer.api.SqlQueryInputFormatDescriptor)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.$anonfun$getType$1(Rql2TruffleCompilerService.scala:140)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.withTruffleContext(Rql2TruffleCompilerService.scala:719)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.getType(Rql2TruffleCompilerService.scala:130)
	at raw.compiler.rql2.tests.CompilerTestContext.doValidate(CompilerTestContext.scala:656)
	... 55 more
Caused by: sbt.ForkMain$ForkError: scala.MatchError: SqlQueryInputFormatDescriptor(pgsql,rawtest,SourceCollectionType(SourceRecordType(Vector(SourceAttrType(smallint1,SourceShortType(true)), SourceAttrType(integer1,SourceIntType(true)), SourceAttrType(bigint1,SourceLongType(true)), SourceAttrType(decimal1,SourceDecimalType(true)), SourceAttrType(real1,SourceFloatType(true)), SourceAttrType(double1,SourceDoubleType(true)), SourceAttrType(money1,SourceDoubleType(true)), SourceAttrType(varchar1,SourceStringType(true)), SourceAttrType(char1,SourceStringType(true)), SourceAttrType(text1,SourceStringType(true)), SourceAttrType(boolean1,SourceBoolType(true)), SourceAttrType(timestamp1,SourceTimestampType(None,true)), SourceAttrType(date1,SourceDateType(None,true)), SourceAttrType(time1,SourceTimeType(None,true)), SourceAttrType(interval1,SourceNullType()), SourceAttrType(bytea1,SourceBinaryType(true)), SourceAttrType(bit1,SourceBoolType(true)), SourceAttrType(integer_array1,SourceNullType()), SourceAttrType(smallserial1,SourceShortType(false)), SourceAttrType(serial1,SourceIntType(false)), SourceAttrType(bigserial1,SourceLongType(false))),false),false)) (of class raw.inferrer.api.SqlQueryInputFormatDescriptor)
	at raw.compiler.rql2.builtin.SqlTableExtensionHelper.resolveInferType(SqlTableExtensionHelper.scala:132)
	at raw.compiler.rql2.builtin.SqlTableExtensionHelper.resolveInferType$(SqlTableExtensionHelper.scala:122)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.resolveInferType(PostgreSQLPackage.scala:297)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.$anonfun$returnType$5(PostgreSQLPackage.scala:390)
	at scala.util.Either.flatMap(Either.scala:341)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.$anonfun$returnType$4(PostgreSQLPackage.scala:389)
	at scala.util.Either.flatMap(Either.scala:341)
	at raw.compiler.rql2.builtin.PostgreSQLInferAndQueryEntry.returnType(PostgreSQLPackage.scala:388)
	at raw.compiler.rql2.api.EntryExtension.returnTypeErrorList(PackageExtension.scala:138)
	at raw.compiler.rql2.SemanticAnalyzer.getFunAppPackageEntryType(SemanticAnalyzer.scala:1226)
	at raw.compiler.rql2.SemanticAnalyzer.raw$compiler$rql2$SemanticAnalyzer$$funAppHasError(SemanticAnalyzer.scala:641)
	at raw.compiler.rql2.SemanticAnalyzer$$anonfun$1.isDefinedAt(SemanticAnalyzer.scala:532)
	at raw.compiler.rql2.SemanticAnalyzer$$anonfun$1.isDefinedAt(SemanticAnalyzer.scala:483)
	at scala.PartialFunction$OrElse.isDefinedAt(PartialFunction.scala:170)
	at raw.compiler.base.SemanticAnalyzer$$anonfun$1.isDefinedAt(SemanticAnalyzer.scala:63)
	at raw.compiler.utils.ExtraRewriters$$anonfun$collectNodes$1.applyOrElse(ExtraRewriters.scala:35)
	at scala.PartialFunction$AndThen.applyOrElse(PartialFunction.scala:194)
	at scala.PartialFunction$AndThen.applyOrElse(PartialFunction.scala:194)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$query$1(Rewriter.scala:215)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$plus$1(Strategy.scala:59)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$times$1(Strategy.scala:44)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1(Rewriter.scala:592)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1$adapted(Rewriter.scala:590)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:196)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:194)
	at scala.collection.Iterator.foreach(Iterator.scala:943)
	at scala.collection.Iterator.foreach$(Iterator.scala:943)
	at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
	at scala.collection.TraversableOnce.foldLeft(TraversableOnce.scala:199)
	at scala.collection.TraversableOnce.foldLeft$(TraversableOnce.scala:192)
	at scala.collection.AbstractIterator.foldLeft(Iterator.scala:1431)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct(Rewriter.scala:590)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct$(Rewriter.scala:583)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$.allProduct(Rewriter.scala:1643)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$all$1(Rewriter.scala:543)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$times$1(Strategy.scala:45)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1(Rewriter.scala:592)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$allProduct$1$adapted(Rewriter.scala:590)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:196)
	at scala.collection.TraversableOnce$folder$1.apply(TraversableOnce.scala:194)
	at scala.collection.Iterator.foreach(Iterator.scala:943)
	at scala.collection.Iterator.foreach$(Iterator.scala:943)
	at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
	at scala.collection.TraversableOnce.foldLeft(TraversableOnce.scala:199)
	at scala.collection.TraversableOnce.foldLeft$(TraversableOnce.scala:192)
	at scala.collection.AbstractIterator.foldLeft(Iterator.scala:1431)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct(Rewriter.scala:590)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.allProduct$(Rewriter.scala:583)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$.allProduct(Rewriter.scala:1643)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$all$1(Rewriter.scala:543)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy.$anonfun$$less$times$1(Strategy.scala:45)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:33)
	at org.bitbucket.inkytonik.kiama.rewriting.Strategy$$anon$1.apply(Strategy.scala:31)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:69)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter$$anon$1.apply(Rewriter.scala:67)
	at org.bitbucket.inkytonik.kiama.rewriting.Rewriter.$anonfun$collect$1(Rewriter.scala:1584)
	at raw.compiler.base.SemanticAnalyzer.collectErrors(SemanticAnalyzer.scala:54)
	at raw.compiler.base.SemanticAnalyzer.errors$lzycompute(SemanticAnalyzer.scala:61)
	at raw.compiler.base.SemanticAnalyzer.errors(SemanticAnalyzer.scala:60)
	at raw.compiler.base.TreeWithPositions.errors$lzycompute(TreeWithPositions.scala:39)
	at raw.compiler.base.TreeWithPositions.errors(TreeWithPositions.scala:47)
	at raw.compiler.base.TreeWithPositions.isTreeValid(TreeWithPositions.scala:61)
	at raw.compiler.base.BaseTree.valid$lzycompute(BaseTree.scala:52)
	at raw.compiler.base.BaseTree.valid(BaseTree.scala:52)
	at raw.client.rql2.truffle.Rql2TruffleCompilerService.$anonfun$getType$1(Rql2TruffleCompilerService.scala:134)
	... 58 more
"""[
| {
| smallint1: 1,
| integer1: 2,
| bigint1: 3,
| decimal1: Decimal.From(4.4),
| real1: 5.5f,
| double1: 6.6,
| money1: 7.7,
| varchar1: "string",
| char1: "string ",
| text1: "string",
| boolean1: true,
| timestamp1: Timestamp.Build(1975, 6, 23, 1, 2, seconds=3),
| date1: Date.Build(1975, 6, 23),
| time1: Time.Build(1, 2, seconds=3),
| interval1: "skipping column of type interval",
| bytea1: "eyJhIjogMTIzNCwgImIiOiBbImhlbGxvIiwgIndvcmxkIl19",
| bit1: null,
| integer_array1: null,
| smallserial1: 0,
| serial1: 0,
| bigserial1: 0
| }
|]""".stripMargin
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ trait Rql2TypeUtils {
)
case SourceBinaryType(n) => wrapProps(Rql2BinaryType(), n || makeNullable, makeTryable)
case _: SourceNothingType => wrapProps(Rql2UndefinedType(), makeNullable, makeTryable)
case _: SourceNullType => wrapProps(Rql2UndefinedType(), true, makeTryable)
// (CTM) Null type will be an error if we find a non null value, so we have to make it triable also.
// This is because we use it to skipp unsupported types in databases
case _: SourceNullType => wrapProps(Rql2UndefinedType(), true, true)
case _: SourceAnyType => AnyType()
case SourceOrType(ors) =>
val options = ors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,22 @@

package raw.compiler.rql2.builtin

import com.sun.jdi.BooleanValue
import raw.compiler.base.errors.ErrorCompilerMessage
import raw.compiler.base.source.{AnythingType, BaseNode, Type}
import raw.compiler.common.source._
import raw.compiler.rql2.api._
import raw.compiler.rql2.ProgramContext
import raw.compiler.rql2.source._
import raw.client.api._
import raw.inferrer.api.{SqlQueryInputFormatDescriptor, SqlTableInputFormatDescriptor}
import raw.inferrer.api.{
SourceAttrType,
SourceCollectionType,
SourceNullType,
SourceRecordType,
SqlQueryInputFormatDescriptor,
SqlTableInputFormatDescriptor
}

class MySQLPackage extends PackageExtension {

Expand Down Expand Up @@ -76,6 +84,18 @@ class MySQLInferAndReadEntry extends SugarEntryExtension with SqlTableExtensionH
description =
"""The database user password. Can only to be used together with 'host' and 'username' arguments.""".stripMargin,
isOptional = true
),
ParamDoc(
"byIndex",
typeDoc = TypeDoc(List("bool")),
"""Fetch the fields of the database by index instead of by name""".stripMargin,
isOptional = true
),
ParamDoc(
"skipUnsupportedType",
typeDoc = TypeDoc(List("bool")),
"""will remove unsupported types from the output of the query automatically""".stripMargin,
isOptional = true
)
),
examples = List(ExampleDoc("""MySQL.InferAndRead("database", "table")""")),
Expand All @@ -98,6 +118,8 @@ class MySQLInferAndReadEntry extends SugarEntryExtension with SqlTableExtensionH
case "port" => Right(ValueParam(Rql2IntType()))
case "username" => Right(ValueParam(Rql2StringType()))
case "password" => Right(ValueParam(Rql2StringType()))
case "byIndex" => Right(ValueParam(Rql2BoolType()))
case "skipUnsupportedType" => Right(ValueParam(Rql2BoolType()))
}
}

Expand All @@ -111,7 +133,7 @@ class MySQLInferAndReadEntry extends SugarEntryExtension with SqlTableExtensionH
val db = FunAppArg(StringConst(getStringValue(mandatoryArgs(0))), None)
val table = FunAppArg(StringConst(getStringValue(mandatoryArgs(1))), None)
val readType = FunAppArg(TypeExp(t), None)
val optArgs = optionalArgs.map { case (idn, ValueArg(StringValue(s), _)) => FunAppArg(StringConst(s), Some(idn)) }
val optArgs = optionalArgs.filter(x => x._1 != "skipUnsupportedType").map { case (idn, ValueArg(StringValue(s), _)) => FunAppArg(StringConst(s), Some(idn)) }
FunApp(
Proj(PackageIdnExp("MySQL"), "Read"),
Vector(db, table, readType) ++ optArgs
Expand All @@ -126,9 +148,9 @@ class MySQLInferAndReadEntry extends SugarEntryExtension with SqlTableExtensionH
for (
inferrerProperties <- getTableInferrerProperties(mandatoryArgs, optionalArgs, MySqlVendor());
inputFormatDescriptor <- programContext.infer(inferrerProperties);
SqlTableInputFormatDescriptor(_, _, _, _, tipe) = inputFormatDescriptor
t <- resolveInferType(inputFormatDescriptor, optionalArgs)
) yield {
inferTypeToRql2Type(tipe, false, false)
t
}
}
}
Expand Down Expand Up @@ -183,6 +205,12 @@ class MySQLReadEntry extends SugarEntryExtension with SqlTableExtensionHelper {
description =
"""The database user password. Can only to be used together with 'host' and 'username' arguments.""".stripMargin,
isOptional = true
),
ParamDoc(
"byIndex",
typeDoc = TypeDoc(List("bool")),
"""Fetch the fields of the database by index instead of by name""".stripMargin,
isOptional = true
)
),
examples =
Expand All @@ -207,6 +235,7 @@ class MySQLReadEntry extends SugarEntryExtension with SqlTableExtensionHelper {
case "port" => Right(ExpParam(Rql2IntType()))
case "username" => Right(ExpParam(Rql2StringType()))
case "password" => Right(ExpParam(Rql2StringType()))
case "byIndex" => Right(ExpParam(Rql2BoolType()))
}
}

Expand All @@ -230,7 +259,7 @@ class MySQLReadEntry extends SugarEntryExtension with SqlTableExtensionHelper {
val db = FunAppArg(mandatoryArgs.head.asInstanceOf[ExpArg].e, None)
val table = FunAppArg(mandatoryArgs(1).asInstanceOf[ExpArg].e, None)
val tipe = FunAppArg(TypeExp(mandatoryArgs(2).asInstanceOf[TypeArg].t), None)
val optArgs = optionalArgs.map { case (idn, ExpArg(e, _)) => FunAppArg(e, Some(idn)) }
val optArgs = optionalArgs.map { case (idn, ValueArg(StringValue(s), _)) => FunAppArg(StringConst(s), Some(idn)) }

// MySql needs the table name to be quoted with backticks
def quoted(e: Exp) = BinaryExp(Plus(), BinaryExp(Plus(), StringConst("`"), e), StringConst("`"))
Expand Down Expand Up @@ -288,6 +317,18 @@ class MySQLInferAndQueryEntry extends SugarEntryExtension with SqlTableExtension
description =
"""The database user password. Can only to be used together with 'host' and 'username' arguments.""".stripMargin,
isOptional = true
),
ParamDoc(
"byIndex",
typeDoc = TypeDoc(List("bool")),
"""Fetch the fields of the database by index instead of by name""".stripMargin,
isOptional = true
),
ParamDoc(
"skipUnsupportedType",
typeDoc = TypeDoc(List("bool")),
"""will remove unsupported types from the output of the query automatically""".stripMargin,
isOptional = true
)
),
examples = List(ExampleDoc("""MySQL.InferAndQuery("database", "SELECT * FROM table")""")),
Expand All @@ -310,6 +351,8 @@ class MySQLInferAndQueryEntry extends SugarEntryExtension with SqlTableExtension
case "port" => Right(ValueParam(Rql2IntType()))
case "username" => Right(ValueParam(Rql2StringType()))
case "password" => Right(ValueParam(Rql2StringType()))
case "byIndex" => Right(ValueParam(Rql2BoolType()))
case "skipUnsupportedType" => Right(ValueParam(Rql2BoolType()))
}
}

Expand All @@ -321,9 +364,9 @@ class MySQLInferAndQueryEntry extends SugarEntryExtension with SqlTableExtension
for (
inferrerProperties <- getQueryInferrerProperties(mandatoryArgs, optionalArgs, MySqlVendor());
inputFormatDescriptor <- programContext.infer(inferrerProperties);
SqlQueryInputFormatDescriptor(_, _, tipe) = inputFormatDescriptor
t <- resolveInferType(inputFormatDescriptor, optionalArgs)
) yield {
inferTypeToRql2Type(tipe, false, false)
t
}
}

Expand All @@ -337,7 +380,7 @@ class MySQLInferAndQueryEntry extends SugarEntryExtension with SqlTableExtension
val db = FunAppArg(StringConst(getStringValue(mandatoryArgs(0))), None)
val query = FunAppArg(StringConst(getStringValue(mandatoryArgs(1))), None)
val readType = FunAppArg(TypeExp(t), None)
val optArgs = optionalArgs.map { case (idn, ValueArg(StringValue(s), _)) => FunAppArg(StringConst(s), Some(idn)) }
val optArgs = optionalArgs.filter(x => x._1 != "skipUnsupportedType").map { case (idn, ValueArg(StringValue(s), _)) => FunAppArg(StringConst(s), Some(idn)) }
FunApp(
Proj(PackageIdnExp("MySQL"), "Query"),
Vector(db, query, readType) ++ optArgs
Expand Down Expand Up @@ -396,6 +439,12 @@ class MySQLQueryEntry extends EntryExtension with SqlTableExtensionHelper {
description =
"""The database user password. Can only to be used together with 'host' and 'username' arguments.""".stripMargin,
isOptional = true
),
ParamDoc(
"byIndex",
typeDoc = TypeDoc(List("bool")),
"""Fetch the fields of the database by index instead of by name""".stripMargin,
isOptional = true
)
),
examples = List(
Expand All @@ -413,14 +462,15 @@ class MySQLQueryEntry extends EntryExtension with SqlTableExtensionHelper {
else Right(ExpParam(Rql2StringType()))
}

override def optionalParams: Option[Set[String]] = Some(Set("host", "username", "port", "password"))
override def optionalParams: Option[Set[String]] = Some(Set("host", "username", "port", "password", "byIndex"))

override def getOptionalParam(prevMandatoryArgs: Seq[Arg], idn: String): Either[String, Param] = {
idn match {
case "host" => Right(ExpParam(Rql2StringType()))
case "port" => Right(ExpParam(Rql2IntType()))
case "username" => Right(ExpParam(Rql2StringType()))
case "password" => Right(ExpParam(Rql2StringType()))
case "byIndex" => Right(ExpParam(Rql2BoolType()))
}
}
override def returnTypeErrorList(
Expand Down
Loading
Loading