This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git
The following commit(s) were added to refs/heads/master by this push:
new 43cab48d7 [SEDONA-636] Support GEOMETRY in Spark SQL table creation
DDL (#1543)
43cab48d7 is described below
commit 43cab48d73fde648f337bd9d868f7191a7c6863d
Author: Feng Zhang <[email protected]>
AuthorDate: Mon Aug 12 10:58:02 2024 -0700
[SEDONA-636] Support GEOMETRY in Spark SQL table creation DDL (#1543)
* [SEDONA-636] Support geometry data type in create table DDL statement
* add one more test
* [SEDONA-636] Support GEOMETRY in Spark SQL table creation DDL
* add one more unit test
* temporarily remove spark 3.0.3 build
* Support multiple versions of spark
* clean up files
* undo github workflow changes to java.yaml
* add parser to spark-3.0
* add sedona parser to spark-3.0 profile
---
.../org/apache/sedona/spark/SedonaContext.scala | 3 +-
.../org/apache/sedona/sql/ParserRegistrator.scala | 60 ++++++++++++++++++++
.../apache/spark/sql/parser/ParserFactory.scala | 41 ++++++++++++++
.../sedona/sql/parser/SedonaSqlAstBuilder.scala | 40 ++++++++++++++
.../apache/sedona/sql/parser/SedonaSqlParser.scala | 43 +++++++++++++++
.../org/apache/sedona/sql/SQLSyntaxTestScala.scala | 64 ++++++++++++++++++++++
.../sedona/sql/parser/SedonaSqlAstBuilder.scala | 39 +++++++++++++
.../org/sedona/sql/parser/SedonaSqlParser.scala | 42 ++++++++++++++
.../org/apache/sedona/sql/SQLSyntaxTestScala.scala | 57 +++++++++++++++++++
.../sedona/sql/parser/SedonaSqlAstBuilder.scala | 39 +++++++++++++
.../apache/sedona/sql/parser/SedonaSqlParser.scala | 42 ++++++++++++++
.../org/apache/sedona/sql/SQLSyntaxTestScala.scala | 57 +++++++++++++++++++
.../src/main/java/org/apache/sedona/Main.java | 25 +++++++++
.../sedona/sql/parser/SedonaSqlAstBuilder.scala | 39 +++++++++++++
.../apache/sedona/sql/parser/SedonaSqlParser.scala | 42 ++++++++++++++
.../org/apache/sedona/sql/SQLSyntaxTestScala.scala | 57 +++++++++++++++++++
.../sedona/sql/parser/SedonaSqlAstBuilder.scala | 39 +++++++++++++
.../apache/sedona/sql/parser/SedonaSqlParser.scala | 42 ++++++++++++++
.../org/apache/sedona/sql/SQLSyntaxTestScala.scala | 57 +++++++++++++++++++
.../sedona/sql/parser/SedonaSqlAstBuilder.scala | 39 +++++++++++++
.../apache/sedona/sql/parser/SedonaSqlParser.scala | 42 ++++++++++++++
.../org/apache/sedona/sql/SQLSyntaxTestScala.scala | 57 +++++++++++++++++++
22 files changed, 965 insertions(+), 1 deletion(-)
diff --git
a/spark/common/src/main/scala/org/apache/sedona/spark/SedonaContext.scala
b/spark/common/src/main/scala/org/apache/sedona/spark/SedonaContext.scala
index db266c38f..692fe5f72 100644
--- a/spark/common/src/main/scala/org/apache/sedona/spark/SedonaContext.scala
+++ b/spark/common/src/main/scala/org/apache/sedona/spark/SedonaContext.scala
@@ -20,7 +20,7 @@ package org.apache.sedona.spark
import org.apache.sedona.common.utils.TelemetryCollector
import org.apache.sedona.core.serde.SedonaKryoRegistrator
-import org.apache.sedona.sql.RasterRegistrator
+import org.apache.sedona.sql.{ParserRegistrator, RasterRegistrator}
import org.apache.sedona.sql.UDF.UdfRegistrator
import org.apache.sedona.sql.UDT.UdtRegistrator
import org.apache.spark.serializer.KryoSerializer
@@ -65,6 +65,7 @@ object SedonaContext {
RasterRegistrator.registerAll(sparkSession)
UdtRegistrator.registerAll()
UdfRegistrator.registerAll(sparkSession)
+ ParserRegistrator.register(sparkSession)
sparkSession
}
diff --git
a/spark/common/src/main/scala/org/apache/sedona/sql/ParserRegistrator.scala
b/spark/common/src/main/scala/org/apache/sedona/sql/ParserRegistrator.scala
new file mode 100644
index 000000000..db3c623a0
--- /dev/null
+++ b/spark/common/src/main/scala/org/apache/sedona/sql/ParserRegistrator.scala
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql
+
+import org.apache.spark.sql.SparkSession
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.parser.ParserFactory
+
+object ParserRegistrator {
+
+ /**
+ * Register the custom Sedona Spark parser
+ * @param sparkSession
+ */
+ def register(sparkSession: SparkSession): Unit = {
+ // try to register the parser with the new constructor for spark 3.1 and
above
+ try {
+ val parserClassName = "org.apache.sedona.sql.parser.SedonaSqlParser"
+ val delegate: ParserInterface = sparkSession.sessionState.sqlParser
+
+ val parser = ParserFactory.getParser(parserClassName, delegate)
+ val field =
sparkSession.sessionState.getClass.getDeclaredField("sqlParser")
+ field.setAccessible(true)
+ field.set(sparkSession.sessionState, parser)
+ return // return if the new constructor is available
+ } catch {
+ case _: Exception =>
+ }
+
+ // try to register the parser with the legacy constructor for spark 3.0
+ try {
+ val parserClassName = "org.apache.sedona.sql.parser.SedonaSqlParser"
+ val delegate: ParserInterface = sparkSession.sessionState.sqlParser
+
+ val parser =
+ ParserFactory.getParser(parserClassName,
sparkSession.sessionState.conf, delegate)
+ val field =
sparkSession.sessionState.getClass.getDeclaredField("sqlParser")
+ field.setAccessible(true)
+ field.set(sparkSession.sessionState, parser)
+ } catch {
+ case _: Exception =>
+ }
+ }
+}
diff --git
a/spark/common/src/main/scala/org/apache/spark/sql/parser/ParserFactory.scala
b/spark/common/src/main/scala/org/apache/spark/sql/parser/ParserFactory.scala
new file mode 100644
index 000000000..e0ee46ba0
--- /dev/null
+++
b/spark/common/src/main/scala/org/apache/spark/sql/parser/ParserFactory.scala
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.spark.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.execution.SparkSqlParser
+import org.apache.spark.sql.internal.SQLConf
+
+object ParserFactory {
+ def getParser(className: String, delegate: ParserInterface): SparkSqlParser
= {
+ Class
+ .forName(className)
+ .getConstructor(classOf[ParserInterface])
+ .newInstance(delegate)
+ .asInstanceOf[SparkSqlParser]
+ }
+
+ def getParser(className: String, conf: SQLConf, delegate: ParserInterface):
SparkSqlParser = {
+ Class
+ .forName(className)
+ .getConstructor(classOf[SQLConf], classOf[ParserInterface])
+ .newInstance(conf, delegate)
+ .asInstanceOf[SparkSqlParser]
+ }
+}
diff --git
a/spark/spark-3.0/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
b/spark/spark-3.0/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
new file mode 100644
index 000000000..9c9f6b674
--- /dev/null
+++
b/spark/spark-3.0/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.SqlBaseParser._
+import org.apache.spark.sql.execution.SparkSqlAstBuilder
+import org.apache.spark.sql.internal.SQLConf
+import org.apache.spark.sql.sedona_sql.UDT.GeometryUDT
+import org.apache.spark.sql.types.DataType
+
+class SedonaSqlAstBuilder(conf: SQLConf) extends SparkSqlAstBuilder(conf) {
+
+ /**
+ * Override the method to handle the geometry data type
+ * @param ctx
+ * @return
+ */
+ override def visitPrimitiveDataType(ctx: PrimitiveDataTypeContext): DataType
= {
+ ctx.getText.toUpperCase() match {
+ case "GEOMETRY" => GeometryUDT
+ case _ => super.visitPrimitiveDataType(ctx)
+ }
+ }
+}
diff --git
a/spark/spark-3.0/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
b/spark/spark-3.0/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
new file mode 100644
index 000000000..2d270eaa4
--- /dev/null
+++
b/spark/spark-3.0/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.execution.SparkSqlParser
+import org.apache.spark.sql.internal.SQLConf
+
+class SedonaSqlParser(conf: SQLConf, delegate: ParserInterface) extends
SparkSqlParser(conf) {
+
+ // The parser builder for the Sedona SQL AST
+ val parserBuilder = new SedonaSqlAstBuilder(conf)
+
+ /**
+ * Parse the SQL text and return the logical plan.
+ * @param sqlText
+ * @return
+ */
+ override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) {
parser =>
+ parserBuilder.visit(parser.singleStatement()) match {
+ case plan: LogicalPlan => plan
+ case _ =>
+ delegate.parsePlan(sqlText)
+ }
+ }
+}
diff --git
a/spark/spark-3.0/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
b/spark/spark-3.0/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
new file mode 100644
index 000000000..22a6aa5c7
--- /dev/null
+++
b/spark/spark-3.0/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql
+
+import org.scalatest.matchers.must.Matchers.be
+import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
+import org.scalatest.prop.TableDrivenPropertyChecks
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.AnalysisException
+import org.scalatest.matchers.should.Matchers._
+
+/**
+ * Test suite for testing Sedona SQL support.
+ */
+class SQLSyntaxTestScala extends TestBaseScala with TableDrivenPropertyChecks {
+
+ override def beforeAll(): Unit = {
+ super.beforeAll()
+ sparkSession.conf.set("spark.sql.legacy.createHiveTableByDefault", "false")
+ }
+
+ describe("Table creation DDL tests") {
+
+ it("should be able to create a regular table without geometry column
should work") {
+ val parser: ParserInterface = sparkSession.sessionState.sqlParser
+ val plan = parser.parsePlan("CREATE TABLE IF NOT EXISTS T_TEST_REGULAR
(INT_COL INT)")
+
+ plan should not be (null)
+ }
+
+ it(
+ "should be able to create a regular table with geometry column should
work without a workaround") {
+ val parser: ParserInterface = sparkSession.sessionState.sqlParser
+ val plan = parser.parsePlan("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY
(GEO_COL GEOMETRY)")
+
+ plan should not be (null)
+ }
+
+ it(
+ "should be able to create a regular table with regular and geometry
column should work without a workaround") {
+ val parser: ParserInterface = sparkSession.sessionState.sqlParser
+ val plan = parser.parsePlan(
+ "CREATE TABLE T_TEST_EXPLICIT_GEOMETRY_2 (INT_COL INT, GEO_COL
GEOMETRY)")
+
+ plan should not be (null)
+ }
+ }
+}
diff --git
a/spark/spark-3.1/src/main/scala/org/sedona/sql/parser/SedonaSqlAstBuilder.scala
b/spark/spark-3.1/src/main/scala/org/sedona/sql/parser/SedonaSqlAstBuilder.scala
new file mode 100644
index 000000000..2bdd92bd6
--- /dev/null
+++
b/spark/spark-3.1/src/main/scala/org/sedona/sql/parser/SedonaSqlAstBuilder.scala
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.SqlBaseParser._
+import org.apache.spark.sql.execution.SparkSqlAstBuilder
+import org.apache.spark.sql.sedona_sql.UDT.GeometryUDT
+import org.apache.spark.sql.types.DataType
+
+class SedonaSqlAstBuilder extends SparkSqlAstBuilder {
+
+ /**
+ * Override the method to handle the geometry data type
+ * @param ctx
+ * @return
+ */
+ override def visitPrimitiveDataType(ctx: PrimitiveDataTypeContext): DataType
= {
+ ctx.getText.toUpperCase() match {
+ case "GEOMETRY" => GeometryUDT
+ case _ => super.visitPrimitiveDataType(ctx)
+ }
+ }
+}
diff --git
a/spark/spark-3.1/src/main/scala/org/sedona/sql/parser/SedonaSqlParser.scala
b/spark/spark-3.1/src/main/scala/org/sedona/sql/parser/SedonaSqlParser.scala
new file mode 100644
index 000000000..420949ab9
--- /dev/null
+++ b/spark/spark-3.1/src/main/scala/org/sedona/sql/parser/SedonaSqlParser.scala
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.execution.SparkSqlParser
+
+class SedonaSqlParser(delegate: ParserInterface) extends SparkSqlParser {
+
+ // The parser builder for the Sedona SQL AST
+ val parserBuilder = new SedonaSqlAstBuilder
+
+ /**
+ * Parse the SQL text and return the logical plan.
+ * @param sqlText
+ * @return
+ */
+ override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) {
parser =>
+ parserBuilder.visit(parser.singleStatement()) match {
+ case plan: LogicalPlan => plan
+ case _ =>
+ delegate.parsePlan(sqlText)
+ }
+ }
+}
diff --git
a/spark/spark-3.1/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
b/spark/spark-3.1/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
new file mode 100644
index 000000000..72680aacd
--- /dev/null
+++
b/spark/spark-3.1/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql
+
+import org.scalatest.matchers.must.Matchers.be
+import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
+import org.scalatest.prop.TableDrivenPropertyChecks
+
+/**
+ * Test suite for testing Sedona SQL support.
+ */
+class SQLSyntaxTestScala extends TestBaseScala with TableDrivenPropertyChecks {
+
+ override def beforeAll(): Unit = {
+ super.beforeAll()
+ sparkSession.conf.set("spark.sql.legacy.createHiveTableByDefault", "false")
+ }
+
+ describe("Table creation DDL tests") {
+
+ it("should be able to create a regular table without geometry column
should work") {
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.sql("CREATE TABLE IF NOT EXISTS T_TEST_REGULAR (INT_COL
INT)")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(true)
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(false)
+ }
+
+ it(
+ "should be able to create a regular table with geometry column should
work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY (GEO_COL
GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY") should
be(true)
+ }
+
+ it(
+ "should be able to create a regular table with regular and geometry
column should work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY_2 (INT_COL INT,
GEO_COL GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY_2") should
be(true)
+ }
+ }
+}
diff --git
a/spark/spark-3.2/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
b/spark/spark-3.2/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
new file mode 100644
index 000000000..2bdd92bd6
--- /dev/null
+++
b/spark/spark-3.2/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.SqlBaseParser._
+import org.apache.spark.sql.execution.SparkSqlAstBuilder
+import org.apache.spark.sql.sedona_sql.UDT.GeometryUDT
+import org.apache.spark.sql.types.DataType
+
+class SedonaSqlAstBuilder extends SparkSqlAstBuilder {
+
+ /**
+ * Override the method to handle the geometry data type
+ * @param ctx
+ * @return
+ */
+ override def visitPrimitiveDataType(ctx: PrimitiveDataTypeContext): DataType
= {
+ ctx.getText.toUpperCase() match {
+ case "GEOMETRY" => GeometryUDT
+ case _ => super.visitPrimitiveDataType(ctx)
+ }
+ }
+}
diff --git
a/spark/spark-3.2/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
b/spark/spark-3.2/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
new file mode 100644
index 000000000..420949ab9
--- /dev/null
+++
b/spark/spark-3.2/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.execution.SparkSqlParser
+
+class SedonaSqlParser(delegate: ParserInterface) extends SparkSqlParser {
+
+ // The parser builder for the Sedona SQL AST
+ val parserBuilder = new SedonaSqlAstBuilder
+
+ /**
+ * Parse the SQL text and return the logical plan.
+ * @param sqlText
+ * @return
+ */
+ override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) {
parser =>
+ parserBuilder.visit(parser.singleStatement()) match {
+ case plan: LogicalPlan => plan
+ case _ =>
+ delegate.parsePlan(sqlText)
+ }
+ }
+}
diff --git
a/spark/spark-3.2/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
b/spark/spark-3.2/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
new file mode 100644
index 000000000..72680aacd
--- /dev/null
+++
b/spark/spark-3.2/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql
+
+import org.scalatest.matchers.must.Matchers.be
+import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
+import org.scalatest.prop.TableDrivenPropertyChecks
+
+/**
+ * Test suite for testing Sedona SQL support.
+ */
+class SQLSyntaxTestScala extends TestBaseScala with TableDrivenPropertyChecks {
+
+ override def beforeAll(): Unit = {
+ super.beforeAll()
+ sparkSession.conf.set("spark.sql.legacy.createHiveTableByDefault", "false")
+ }
+
+ describe("Table creation DDL tests") {
+
+ it("should be able to create a regular table without geometry column
should work") {
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.sql("CREATE TABLE IF NOT EXISTS T_TEST_REGULAR (INT_COL
INT)")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(true)
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(false)
+ }
+
+ it(
+ "should be able to create a regular table with geometry column should
work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY (GEO_COL
GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY") should
be(true)
+ }
+
+ it(
+ "should be able to create a regular table with regular and geometry
column should work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY_2 (INT_COL INT,
GEO_COL GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY_2") should
be(true)
+ }
+ }
+}
diff --git a/spark/spark-3.3/src/main/java/org/apache/sedona/Main.java
b/spark/spark-3.3/src/main/java/org/apache/sedona/Main.java
new file mode 100644
index 000000000..acb8e3005
--- /dev/null
+++ b/spark/spark-3.3/src/main/java/org/apache/sedona/Main.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
diff --git
a/spark/spark-3.3/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
b/spark/spark-3.3/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
new file mode 100644
index 000000000..2bdd92bd6
--- /dev/null
+++
b/spark/spark-3.3/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.SqlBaseParser._
+import org.apache.spark.sql.execution.SparkSqlAstBuilder
+import org.apache.spark.sql.sedona_sql.UDT.GeometryUDT
+import org.apache.spark.sql.types.DataType
+
+class SedonaSqlAstBuilder extends SparkSqlAstBuilder {
+
+ /**
+ * Override the method to handle the geometry data type
+ * @param ctx
+ * @return
+ */
+ override def visitPrimitiveDataType(ctx: PrimitiveDataTypeContext): DataType
= {
+ ctx.getText.toUpperCase() match {
+ case "GEOMETRY" => GeometryUDT
+ case _ => super.visitPrimitiveDataType(ctx)
+ }
+ }
+}
diff --git
a/spark/spark-3.3/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
b/spark/spark-3.3/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
new file mode 100644
index 000000000..420949ab9
--- /dev/null
+++
b/spark/spark-3.3/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.execution.SparkSqlParser
+
+class SedonaSqlParser(delegate: ParserInterface) extends SparkSqlParser {
+
+ // The parser builder for the Sedona SQL AST
+ val parserBuilder = new SedonaSqlAstBuilder
+
+ /**
+ * Parse the SQL text and return the logical plan.
+ * @param sqlText
+ * @return
+ */
+ override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) {
parser =>
+ parserBuilder.visit(parser.singleStatement()) match {
+ case plan: LogicalPlan => plan
+ case _ =>
+ delegate.parsePlan(sqlText)
+ }
+ }
+}
diff --git
a/spark/spark-3.3/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
b/spark/spark-3.3/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
new file mode 100644
index 000000000..72680aacd
--- /dev/null
+++
b/spark/spark-3.3/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql
+
+import org.scalatest.matchers.must.Matchers.be
+import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
+import org.scalatest.prop.TableDrivenPropertyChecks
+
+/**
+ * Test suite for testing Sedona SQL support.
+ */
+class SQLSyntaxTestScala extends TestBaseScala with TableDrivenPropertyChecks {
+
+ override def beforeAll(): Unit = {
+ super.beforeAll()
+ sparkSession.conf.set("spark.sql.legacy.createHiveTableByDefault", "false")
+ }
+
+ describe("Table creation DDL tests") {
+
+ it("should be able to create a regular table without geometry column
should work") {
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.sql("CREATE TABLE IF NOT EXISTS T_TEST_REGULAR (INT_COL
INT)")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(true)
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(false)
+ }
+
+ it(
+ "should be able to create a regular table with geometry column should
work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY (GEO_COL
GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY") should
be(true)
+ }
+
+ it(
+ "should be able to create a regular table with regular and geometry
column should work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY_2 (INT_COL INT,
GEO_COL GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY_2") should
be(true)
+ }
+ }
+}
diff --git
a/spark/spark-3.4/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
b/spark/spark-3.4/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
new file mode 100644
index 000000000..2bdd92bd6
--- /dev/null
+++
b/spark/spark-3.4/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.SqlBaseParser._
+import org.apache.spark.sql.execution.SparkSqlAstBuilder
+import org.apache.spark.sql.sedona_sql.UDT.GeometryUDT
+import org.apache.spark.sql.types.DataType
+
+class SedonaSqlAstBuilder extends SparkSqlAstBuilder {
+
+ /**
+ * Override the method to handle the geometry data type
+ * @param ctx
+ * @return
+ */
+ override def visitPrimitiveDataType(ctx: PrimitiveDataTypeContext): DataType
= {
+ ctx.getText.toUpperCase() match {
+ case "GEOMETRY" => GeometryUDT
+ case _ => super.visitPrimitiveDataType(ctx)
+ }
+ }
+}
diff --git
a/spark/spark-3.4/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
b/spark/spark-3.4/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
new file mode 100644
index 000000000..420949ab9
--- /dev/null
+++
b/spark/spark-3.4/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.execution.SparkSqlParser
+
+class SedonaSqlParser(delegate: ParserInterface) extends SparkSqlParser {
+
+ // The parser builder for the Sedona SQL AST
+ val parserBuilder = new SedonaSqlAstBuilder
+
+ /**
+ * Parse the SQL text and return the logical plan.
+ * @param sqlText
+ * @return
+ */
+ override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) {
parser =>
+ parserBuilder.visit(parser.singleStatement()) match {
+ case plan: LogicalPlan => plan
+ case _ =>
+ delegate.parsePlan(sqlText)
+ }
+ }
+}
diff --git
a/spark/spark-3.4/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
b/spark/spark-3.4/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
new file mode 100644
index 000000000..72680aacd
--- /dev/null
+++
b/spark/spark-3.4/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql
+
+import org.scalatest.matchers.must.Matchers.be
+import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
+import org.scalatest.prop.TableDrivenPropertyChecks
+
+/**
+ * Test suite for testing Sedona SQL support.
+ */
+class SQLSyntaxTestScala extends TestBaseScala with TableDrivenPropertyChecks {
+
+ override def beforeAll(): Unit = {
+ super.beforeAll()
+ sparkSession.conf.set("spark.sql.legacy.createHiveTableByDefault", "false")
+ }
+
+ describe("Table creation DDL tests") {
+
+ it("should be able to create a regular table without geometry column
should work") {
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.sql("CREATE TABLE IF NOT EXISTS T_TEST_REGULAR (INT_COL
INT)")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(true)
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(false)
+ }
+
+ it(
+ "should be able to create a regular table with geometry column should
work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY (GEO_COL
GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY") should
be(true)
+ }
+
+ it(
+ "should be able to create a regular table with regular and geometry
column should work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY_2 (INT_COL INT,
GEO_COL GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY_2") should
be(true)
+ }
+ }
+}
diff --git
a/spark/spark-3.5/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
b/spark/spark-3.5/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
new file mode 100644
index 000000000..2bdd92bd6
--- /dev/null
+++
b/spark/spark-3.5/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlAstBuilder.scala
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.SqlBaseParser._
+import org.apache.spark.sql.execution.SparkSqlAstBuilder
+import org.apache.spark.sql.sedona_sql.UDT.GeometryUDT
+import org.apache.spark.sql.types.DataType
+
+class SedonaSqlAstBuilder extends SparkSqlAstBuilder {
+
+ /**
+ * Override the method to handle the geometry data type
+ * @param ctx
+ * @return
+ */
+ override def visitPrimitiveDataType(ctx: PrimitiveDataTypeContext): DataType
= {
+ ctx.getText.toUpperCase() match {
+ case "GEOMETRY" => GeometryUDT
+ case _ => super.visitPrimitiveDataType(ctx)
+ }
+ }
+}
diff --git
a/spark/spark-3.5/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
b/spark/spark-3.5/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
new file mode 100644
index 000000000..420949ab9
--- /dev/null
+++
b/spark/spark-3.5/src/main/scala/org/apache/sedona/sql/parser/SedonaSqlParser.scala
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql.parser
+
+import org.apache.spark.sql.catalyst.parser.ParserInterface
+import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
+import org.apache.spark.sql.execution.SparkSqlParser
+
+class SedonaSqlParser(delegate: ParserInterface) extends SparkSqlParser {
+
+ // The parser builder for the Sedona SQL AST
+ val parserBuilder = new SedonaSqlAstBuilder
+
+ /**
+ * Parse the SQL text and return the logical plan.
+ * @param sqlText
+ * @return
+ */
+ override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) {
parser =>
+ parserBuilder.visit(parser.singleStatement()) match {
+ case plan: LogicalPlan => plan
+ case _ =>
+ delegate.parsePlan(sqlText)
+ }
+ }
+}
diff --git
a/spark/spark-3.5/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
b/spark/spark-3.5/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
new file mode 100644
index 000000000..72680aacd
--- /dev/null
+++
b/spark/spark-3.5/src/test/scala/org/apache/sedona/sql/SQLSyntaxTestScala.scala
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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.apache.sedona.sql
+
+import org.scalatest.matchers.must.Matchers.be
+import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
+import org.scalatest.prop.TableDrivenPropertyChecks
+
+/**
+ * Test suite for testing Sedona SQL support.
+ */
+class SQLSyntaxTestScala extends TestBaseScala with TableDrivenPropertyChecks {
+
+ override def beforeAll(): Unit = {
+ super.beforeAll()
+ sparkSession.conf.set("spark.sql.legacy.createHiveTableByDefault", "false")
+ }
+
+ describe("Table creation DDL tests") {
+
+ it("should be able to create a regular table without geometry column
should work") {
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.sql("CREATE TABLE IF NOT EXISTS T_TEST_REGULAR (INT_COL
INT)")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(true)
+ sparkSession.sql("DROP TABLE IF EXISTS T_TEST_REGULAR")
+ sparkSession.catalog.tableExists("T_TEST_REGULAR") should be(false)
+ }
+
+ it(
+ "should be able to create a regular table with geometry column should
work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY (GEO_COL
GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY") should
be(true)
+ }
+
+ it(
+ "should be able to create a regular table with regular and geometry
column should work without a workaround") {
+ sparkSession.sql("CREATE TABLE T_TEST_EXPLICIT_GEOMETRY_2 (INT_COL INT,
GEO_COL GEOMETRY)")
+ sparkSession.catalog.tableExists("T_TEST_EXPLICIT_GEOMETRY_2") should
be(true)
+ }
+ }
+}