From 566cbc53cfad9d54c915fec9cf9435f712278837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Manciot?= Date: Tue, 17 Mar 2026 08:17:55 +0100 Subject: [PATCH 1/2] fix: update healthcheck command for arrow sql in docker-compose to use correct syntax --- demo/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/docker-compose.yml b/demo/docker-compose.yml index e5dccc0c..e1becee5 100644 --- a/demo/docker-compose.yml +++ b/demo/docker-compose.yml @@ -81,7 +81,7 @@ services: networks: - elastic-demo healthcheck: - test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/32010'"] + test: ["CMD-SHELL", "bash -c '>/dev/tcp/localhost/32010'"] interval: 5s timeout: 3s start_period: 15s @@ -170,7 +170,7 @@ services: networks: - elastic-demo healthcheck: - test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/32010'"] + test: ["CMD-SHELL", "bash -c '>/dev/tcp/localhost/32010'"] interval: 5s timeout: 3s start_period: 15s From 1cab5004d23af9aedf6f1537245c6049b747ab80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Manciot?= Date: Tue, 17 Mar 2026 08:18:28 +0100 Subject: [PATCH 2/2] feat: add support for schema-qualified table names in parser Closed Issue #57 --- .github/workflows/release.yml | 8 +-- build.sbt | 2 +- .../elastic/sql/parser/FromParser.scala | 12 +++-- .../elastic/sql/parser/ParserSpec.scala | 52 +++++++++++++++++++ 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d7383ad..965c3bc5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,12 +8,8 @@ name: Release on: workflow_dispatch: push: - branches: - - 'main' -# - '*' # matches every branch that doesn't contain a '/' -# - '*/*' # matches every branch containing a single '/' -# - '**' # matches every branch -# - '!main' # excludes main + tags: + - 'v*' permissions: contents: read diff --git a/build.sbt b/build.sbt index ee25df3b..72e55dde 100644 --- a/build.sbt +++ b/build.sbt @@ -20,7 +20,7 @@ ThisBuild / organization := "app.softnetwork" name := "softclient4es" -ThisBuild / version := "0.19.0" +ThisBuild / version := "0.19.1" ThisBuild / scalaVersion := scala213 diff --git a/sql/src/main/scala/app/softnetwork/elastic/sql/parser/FromParser.scala b/sql/src/main/scala/app/softnetwork/elastic/sql/parser/FromParser.scala index 6d4fd964..6d60635c 100644 --- a/sql/src/main/scala/app/softnetwork/elastic/sql/parser/FromParser.scala +++ b/sql/src/main/scala/app/softnetwork/elastic/sql/parser/FromParser.scala @@ -73,9 +73,15 @@ trait FromParser { } } - def table: PackratParser[Table] = identifierRegex ~ alias.? ~ rep(join) ^^ { case i ~ a ~ js => - Table(i, a, js) - } + // Optional quoted schema prefix: "schema". (ignored — Elasticsearch has no schema concept) + // Only quoted schemas are stripped; unquoted dots are part of ES index names (e.g. logs-2025.03) + private def quotedSchemaPrefix: PackratParser[String] = + ("\"" ~> """([^"\\]|\\.)*""".r <~ "\"") <~ "." + + def table: PackratParser[Table] = + opt(quotedSchemaPrefix) ~ identifierRegex ~ alias.? ~ rep(join) ^^ { case _ ~ i ~ a ~ js => + Table(i, a, js) + } def from: PackratParser[From] = From.regex ~ rep1sep(table, separator) ^^ { case _ ~ tables => From(tables) diff --git a/sql/src/test/scala/app/softnetwork/elastic/sql/parser/ParserSpec.scala b/sql/src/test/scala/app/softnetwork/elastic/sql/parser/ParserSpec.scala index fdd81391..91e63442 100644 --- a/sql/src/test/scala/app/softnetwork/elastic/sql/parser/ParserSpec.scala +++ b/sql/src/test/scala/app/softnetwork/elastic/sql/parser/ParserSpec.scala @@ -976,6 +976,58 @@ class ParserSpec extends AnyFlatSpec with Matchers { .getOrElse("") shouldBe whereFiltersAccordingToScope } + // ── Schema-qualified table names (Issue #57) ──────────────────────────────── + + it should "parse schema-qualified table name with quoted schema" in { + val sql = """SELECT * FROM "default".ecommerce""" + val result = Parser(sql) + result.isRight shouldBe true + val stmt = result.toOption.get + stmt match { + case ss: SingleSearch => + ss.from.mainTable.name shouldBe "ecommerce" + ss.sources shouldBe Seq("ecommerce") + case _ => fail("Expected SingleSearch") + } + } + + it should "preserve dots in unquoted table names (ES index names can contain dots)" in { + val sql = "SELECT * FROM myschema.ecommerce" + val result = Parser(sql) + result.isRight shouldBe true + val stmt = result.toOption.get + stmt match { + case ss: SingleSearch => + ss.from.mainTable.name shouldBe "myschema.ecommerce" + case _ => fail("Expected SingleSearch") + } + } + + it should "parse schema-qualified table name with alias" in { + val sql = """SELECT e.field FROM "default".ecommerce AS e""" + val result = Parser(sql) + result.isRight shouldBe true + val stmt = result.toOption.get + stmt match { + case ss: SingleSearch => + ss.from.mainTable.name shouldBe "ecommerce" + ss.from.mainTable.tableAlias.map(_.alias) shouldBe Some("e") + case _ => fail("Expected SingleSearch") + } + } + + it should "still parse table name without schema prefix" in { + val sql = "SELECT * FROM ecommerce" + val result = Parser(sql) + result.isRight shouldBe true + val stmt = result.toOption.get + stmt match { + case ss: SingleSearch => + ss.from.mainTable.name shouldBe "ecommerce" + case _ => fail("Expected SingleSearch") + } + } + // --- DDL --- behavior of "Parser DDL with Table Statements"