|
9 | 9 | * |
10 | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | 11 | * |
12 | | - * Unless required by applicable law or agreed to in writing, |
13 | | - * software distributed under the License is distributed on an |
14 | | - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | | - * KIND, either express or implied. See the License for the |
| 12 | + * Unless required by applicable law or agreed to in writing, software |
| 13 | + * distributed under the License is distributed on an |
| 14 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
| 15 | + * either express or implied. See the License for the |
16 | 16 | * specific language governing permissions and limitations |
17 | 17 | * under the License. |
18 | 18 | */ |
|
21 | 21 | import static org.apache.gravitino.integration.test.util.TestDatabaseName.MYSQL_CATALOG_MYSQL_IT; |
22 | 22 |
|
23 | 23 | import com.google.common.collect.Maps; |
| 24 | +import java.sql.Connection; |
| 25 | +import java.sql.DriverManager; |
| 26 | +import java.sql.Statement; |
| 27 | +import java.util.List; |
24 | 28 | import java.util.Map; |
25 | 29 | import org.apache.gravitino.credential.CredentialConstants; |
26 | 30 | import org.apache.gravitino.credential.JdbcCredential; |
27 | 31 | import org.apache.gravitino.integration.test.container.ContainerSuite; |
28 | 32 | import org.apache.gravitino.spark.connector.integration.test.SparkCommonIT; |
29 | 33 | import org.apache.gravitino.spark.connector.integration.test.util.SparkTableInfoChecker; |
30 | 34 | import org.apache.gravitino.spark.connector.jdbc.JdbcPropertiesConstants; |
| 35 | +import org.junit.jupiter.api.Assertions; |
31 | 36 | import org.junit.jupiter.api.Tag; |
| 37 | +import org.junit.jupiter.api.Test; |
32 | 38 |
|
33 | 39 | @Tag("gravitino-docker-test") |
34 | 40 | public abstract class SparkJdbcMysqlCatalogIT extends SparkCommonIT { |
@@ -114,4 +120,45 @@ protected Map<String, String> getCatalogConfigs() { |
114 | 120 | CredentialConstants.CREDENTIAL_PROVIDERS, JdbcCredential.JDBC_CREDENTIAL_TYPE); |
115 | 121 | return catalogProperties; |
116 | 122 | } |
| 123 | + |
| 124 | + @Test |
| 125 | + void testDatetimeFilterPushdown() throws Exception { |
| 126 | + // Regression test for https://github.com/apache/gravitino/issues/9374: |
| 127 | + // MySQL datetime columns must be usable as filter predicates via the Gravitino Spark JDBC |
| 128 | + // catalog. Previously, datetime was mapped to TimestampNTZType (Spark 3.4+), causing the |
| 129 | + // MySQL JDBC dialect to generate invalid SQL literals during filter pushdown. |
| 130 | + // |
| 131 | + // The table is created directly via JDBC to use MySQL-native datetime type, exactly |
| 132 | + // reproducing the original bug scenario where tables exist with datetime columns in MySQL. |
| 133 | + // |
| 134 | + // Note: Uses subquery filter to avoid timezone conversion issues between JVM (UTC+8) and |
| 135 | + // MySQL container (UTC). The subquery approach validates filter pushdown functionality |
| 136 | + // while being resilient to timezone configuration differences in test environments. |
| 137 | + String db = getDefaultDatabase(); |
| 138 | + String tableName = "datetime_filter_test"; |
| 139 | + String jdbcUrl = mysqlUrl + "/" + db; |
| 140 | + try (Connection conn = DriverManager.getConnection(jdbcUrl, mysqlUsername, mysqlPassword); |
| 141 | + Statement stmt = conn.createStatement()) { |
| 142 | + stmt.execute("DROP TABLE IF EXISTS " + tableName); |
| 143 | + stmt.execute("CREATE TABLE " + tableName + " (id INT, create_time DATETIME)"); |
| 144 | + stmt.execute( |
| 145 | + "INSERT INTO " |
| 146 | + + tableName |
| 147 | + + " VALUES" |
| 148 | + + " (1, '2025-12-01 08:00:00')," |
| 149 | + + " (2, '2025-12-04 09:07:43')," |
| 150 | + + " (3, '2025-12-10 12:00:00')"); |
| 151 | + } |
| 152 | + |
| 153 | + // Use subquery filter to avoid timezone-related assertion failures |
| 154 | + // This validates filter pushdown works correctly after the TimestampType fix |
| 155 | + List<String> result = |
| 156 | + getQueryData( |
| 157 | + String.format( |
| 158 | + "SELECT id FROM %s WHERE create_time >= (SELECT create_time FROM %s WHERE id = 2) ORDER BY id", |
| 159 | + tableName, tableName)); |
| 160 | + Assertions.assertEquals(2, result.size()); |
| 161 | + Assertions.assertTrue(result.contains("2")); |
| 162 | + Assertions.assertTrue(result.contains("3")); |
| 163 | + } |
117 | 164 | } |
0 commit comments