DanielLeens commented on PR #11012:
URL: https://github.com/apache/seatunnel/pull/11012#issuecomment-6368818043

   I downloaded the actual logs for run `30559645732`, attempt **7**, on head 
`bca8da53ff0a8806e69fd010e2dc243c0e84d20c`. They change the diagnosis in the 
earlier thread:
   
   - The current test uses **`ifnazar/sybase_15_7:latest`**, and already 
configures a **five-minute startup timeout**.
   - In [JDK 11 job 
91177773929](https://github.com/lazyfetch/seatunnel/actions/runs/30559645732/job/91177773929),
 ASE reports `Recovery complete`, the container starts in **31.12 seconds**, 
and `testCatalogWithCatalogUtils` passes. This execution is not stuck starting 
`nguoianphu/docker-sybase`.
   - The Flink/Zeta executions then fail with this direct call chain:
   
   ```text
   java.lang.AbstractMethodError
     net.sourceforge.jtds.jdbc.JtdsResultSet.getObject(JtdsResultSet.java:1800)
     JdbcFieldTypeUtils.getLocalDateTime(JdbcFieldTypeUtils.java:129)
     AbstractJdbcRowConverter.toInternal(AbstractJdbcRowConverter.java:119)
   ```
   
   `getLocalDateTime()` first invokes the JDBC 4.2 typed getter and catches 
`SQLException`/`UnsupportedOperationException`, but not the 
`AbstractMethodError` thrown by the JDBC 3 jTDS driver. That shared timestamp 
path was introduced by #10724 (`872077f6480`) and is still present in fetched 
upstream `dev` `14a27ac26a0a71b56722f86cdf8ec2779094ceaf`. The local proposal 
below adds only `AbstractMethodError` to this existing typed-getter fallback; 
modern JDBC 4.2 reads, UTC-calendar fallback ordering, and unrelated 
linkage-error propagation are preserved. It has not been committed or pushed.
   
   The last captured operation before the three-hour cancellation is the Spark 
2 launch. The log does not contain its completed result, so the cause of that 
remaining hang is still unproven. A startup-timeout change or disabling 
`JdbcSybaseIT` would not repair the timestamp exception above. I have not 
disabled tests or rerun the exhausted workflow.
   
   I also checked the current review requests against source: the docs are 
already in `docs/en/connectors/source/Sybase.md` and 
`docs/zh/connectors/source/Sybase.md`; the jTDS dependency in the JDBC E2E POM 
is already **test-scoped**. The attached docs-only patch makes the actual 
type/metadata limitations explicit and calls out the independently unresolved 
`Connection.isValid()` compatibility gap. It changes no driver, dependency or 
production code. Save as `sybase-docs.patch`, then run `git apply --check 
sybase-docs.patch` and `git apply sybase-docs.patch` on the exact head above.
   
   <details><summary>EN/ZH documentation patch</summary>
   
   ```diff
   diff --git a/docs/en/connectors/source/Sybase.md 
b/docs/en/connectors/source/Sybase.md
   index 52abb6470d2..3c9dba6ee04 100644
   --- a/docs/en/connectors/source/Sybase.md
   +++ b/docs/en/connectors/source/Sybase.md
   @@ -50,6 +50,14 @@ Read external data source data through JDBC.
    > Please download the support list corresponding to 'Maven' and copy it to 
the '$SEATUNNEL_HOME/plugins/jdbc/lib/' working directory<br/>
    > For example Sybase datasource: cp jtds-xxx.jar 
$SEATUNNEL_HOME/plugins/jdbc/lib/
    
   +## Current limitations
   +
   +This dialect reads Sybase through the generic JDBC metadata fallback; it 
does not provide a Sybase catalog. Exact `table_path` and `table_list` entries 
use that fallback. Catalog-backed regular-expression table discovery 
(`use_regex`) is not implemented for Sybase; use explicit table entries or 
`query` instead.
   +
   +Only the types in the mapping table below are supported. BINARY, VARBINARY, 
IMAGE, UNICHAR, UNIVARCHAR, UNITEXT, unsigned integer types, BIGDATETIME, 
BIGTIME, and the binary rowversion TIMESTAMP type are not mapped. Select 
supported columns explicitly or cast unsupported columns to a supported type in 
`query`.
   +
   +The examples use plaintext TDS. For encrypted connections, configure a 
driver and database deployment that supports the required encryption and 
certificate validation; this connector does not configure TLS itself. The jTDS 
driver is supplied by the user, and its dependency in this PR is test-scoped. 
The driver does not implement JDBC 4 `Connection.isValid()`, so 
`connection_check_timeout_sec` does not make that operation compatible; 
connection validation compatibility still requires a runtime fix.
   +
    ## Data Type Mapping
    
    |                         Sybase Data type                          | 
Seatunnel Data type |
   diff --git a/docs/zh/connectors/source/Sybase.md 
b/docs/zh/connectors/source/Sybase.md
   index d1db0458163..97b676c60f4 100644
   --- a/docs/zh/connectors/source/Sybase.md
   +++ b/docs/zh/connectors/source/Sybase.md
   @@ -50,6 +50,14 @@ import ChangeLog from '../changelog/connector-jdbc.md';
    > 请下载对应 'Maven' 的支持列表,并将其复制到 '$SEATUNNEL_HOME/plugins/jdbc/lib/' 工作目录<br/>
    > 例如 Sybase 数据源:cp jtds-xxx.jar $SEATUNNEL_HOME/plugins/jdbc/lib/
    
   +## 当前限制
   +
   +该方言通过通用 JDBC 元数据回退路径读取 Sybase,没有提供 Sybase Catalog。精确的 `table_path` 和 
`table_list` 条目使用此回退路径。Sybase 尚未实现依赖 Catalog 的正则表达式表发现(`use_regex`);请使用明确的表条目或 
`query`。
   +
   
+仅支持下方映射表列出的类型。BINARY、VARBINARY、IMAGE、UNICHAR、UNIVARCHAR、UNITEXT、无符号整数、BIGDATETIME、BIGTIME
 和二进制 rowversion TIMESTAMP 尚未映射。请显式选择支持的列,或在 `query` 中将不支持的列转换为支持的类型。
   +
   +示例使用明文 TDS。需要加密连接时,必须配置支持所需加密和证书校验的驱动与数据库部署;连接器本身不配置 TLS。jTDS 驱动由用户提供,本 PR 
中的依赖仅用于测试。该驱动未实现 JDBC 4 `Connection.isValid()`,因此 
`connection_check_timeout_sec` 无法使此操作兼容;连接校验兼容性仍需运行时修复。
   +
    ## 数据类型映射
    
    | Sybase 数据类型 | Seatunnel 数据类型 |
   ```
   
   </details>
   
   Validation: scoped formatting passed for `connector-jdbc` and JDBC E2E part 
3; whitespace and reverse patch applicability checks passed. No local 
compilation/tests/runtime validation were run, and these unpushed patches have 
no CI result. The remaining actions are a reviewed JDBC compatibility 
correction, investigation of the Spark 2 hang, and a fresh successful CI result 
on the contributor's resulting head.
   
   <details><summary>Shared JDBC timestamp proposal with UT/E2E regression 
coverage</summary>
   
   This affects the common JDBC timestamp reader, so please review the generic 
scope before adopting it. The existing utility test class covers the modern 
exact-value path, jTDS-style `AbstractMethodError` fallback with nanosecond 
precision, SQL NULL preservation, and propagation of an unrelated 
`NoClassDefFoundError`. The existing Sybase IT now supplies a fixed timestamp 
and asserts that exact value in its sink; existing 100-row assertions remain 
intact. No tests are disabled or weakened.
   
   Save the patch below as `jdbc3-timestamp.patch` and run `git apply --check 
jdbc3-timestamp.patch` before applying on the exact PR head. Scoped formatting 
and reverse applicability checks passed; these behavioral tests have **not** 
been executed, and fresh CI is required. This proposal addresses the evidenced 
timestamp exception, while the connection-validation gap and unfinished Spark 2 
execution remain separate.
   
   ```diff
   diff --git 
a/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtils.java
 
b/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtils.java
   index 08e875a462e..b77e8961003 100644
   --- 
a/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtils.java
   +++ 
b/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtils.java
   @@ -127,8 +127,8 @@ public final class JdbcFieldTypeUtils {
            // Prefer the modern JDBC 4.2 API — returns wall-clock value 
directly, no TZ involved
            try {
                return resultSet.getObject(columnIndex, LocalDateTime.class);
   -        } catch (SQLException | UnsupportedOperationException ignored) {
   -            // Driver does not support getObject(index, 
LocalDateTime.class) — fall back
   +        } catch (SQLException | UnsupportedOperationException | 
AbstractMethodError ignored) {
   +            // JDBC 3 drivers such as jTDS cannot implement the JDBC 4.2 
typed getter.
            }
            // Try UTC Calendar to avoid JVM-default-timezone influence.
            // A new Calendar is created per call to avoid thread-safety issues 
with a shared instance.
   diff --git 
a/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtilsTest.java
 
b/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtilsTest.java
   index f9ac9cb819b..debc20b3140 100644
   --- 
a/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtilsTest.java
   +++ 
b/seatunnel-connectors-v2/connector-jdbc/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/utils/JdbcFieldTypeUtilsTest.java
   @@ -23,16 +23,64 @@ import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Timestamp;
    import java.time.Instant;
   +import java.time.LocalDateTime;
    import java.time.OffsetDateTime;
    import java.time.ZoneOffset;
   +import java.util.Calendar;
    import java.util.Date;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
   +import static org.junit.jupiter.api.Assertions.assertNull;
   +import static org.junit.jupiter.api.Assertions.assertSame;
   +import static org.junit.jupiter.api.Assertions.assertThrows;
   +import static org.mockito.ArgumentMatchers.any;
   +import static org.mockito.ArgumentMatchers.eq;
    import static org.mockito.Mockito.mock;
    import static org.mockito.Mockito.when;
    
    public class JdbcFieldTypeUtilsTest {
    
   +    @Test
   +    public void testGetLocalDateTimeUsesTypedGetter() throws SQLException {
   +        LocalDateTime expected = LocalDateTime.of(2026, 1, 2, 3, 4, 5, 
123456789);
   +        ResultSet rs = mock(ResultSet.class);
   +        when(rs.getObject(1, LocalDateTime.class)).thenReturn(expected);
   +
   +        assertEquals(expected, JdbcFieldTypeUtils.getLocalDateTime(rs, 1));
   +    }
   +
   +    @Test
   +    public void testGetLocalDateTimeFallsBackForJdbc3Driver() throws 
SQLException {
   +        LocalDateTime expected = LocalDateTime.of(2026, 1, 2, 3, 4, 5, 
123456789);
   +        ResultSet rs = mock(ResultSet.class);
   +        when(rs.getObject(1, LocalDateTime.class)).thenThrow(new 
AbstractMethodError());
   +        when(rs.getTimestamp(eq(1), 
any(Calendar.class))).thenReturn(Timestamp.valueOf(expected));
   +
   +        assertEquals(expected, JdbcFieldTypeUtils.getLocalDateTime(rs, 1));
   +    }
   +
   +    @Test
   +    public void testGetLocalDateTimePreservesNullForJdbc3Driver() throws 
SQLException {
   +        ResultSet rs = mock(ResultSet.class);
   +        when(rs.getObject(1, LocalDateTime.class)).thenThrow(new 
AbstractMethodError());
   +        when(rs.getTimestamp(eq(1), any(Calendar.class))).thenReturn(null);
   +
   +        assertNull(JdbcFieldTypeUtils.getLocalDateTime(rs, 1));
   +    }
   +
   +    @Test
   +    public void testGetLocalDateTimePropagatesUnrelatedLinkageError() 
throws SQLException {
   +        ResultSet rs = mock(ResultSet.class);
   +        NoClassDefFoundError failure = new NoClassDefFoundError("driver 
dependency");
   +        when(rs.getObject(1, LocalDateTime.class)).thenThrow(failure);
   +
   +        assertSame(
   +                failure,
   +                assertThrows(
   +                        NoClassDefFoundError.class,
   +                        () -> JdbcFieldTypeUtils.getLocalDateTime(rs, 1)));
   +    }
   +
        @Test
        public void testGetOffsetDateTimeFromTimestampUsesInstant() throws 
SQLException {
            Instant instant = Instant.parse("2025-01-01T00:00:00Z");
   diff --git 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/JdbcSybaseIT.java
 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/JdbcSybaseIT.java
   index f4711e6a176..f532f35c0dc 100644
   --- 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/JdbcSybaseIT.java
   +++ 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/java/org/apache/seatunnel/connectors/seatunnel/jdbc/JdbcSybaseIT.java
   @@ -158,7 +158,8 @@ public class JdbcSybaseIT extends AbstractJdbcIT {
                                    i % 2 == 0, // BIT_TEST
                                    "CharValue" + i, // CHAR_TEST
                                    java.sql.Date.valueOf(LocalDate.now()), // 
DATE_TEST
   -                                
java.sql.Timestamp.valueOf(LocalDateTime.now()), // DATETIME_TEST
   +                                java.sql.Timestamp.valueOf(
   +                                        LocalDateTime.of(2026, 1, 2, 3, 4, 
5)), // DATETIME_TEST
                                    new BigDecimal("123.45"), // DECIMAL_TEST
                                    3.14d, // FLOAT_TEST
                                    new BigDecimal("567.89"), // MONEY_TEST
   diff --git 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/resources/jdbc_sybase_source_and_assert.conf
 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/resources/jdbc_sybase_source_and_assert.conf
   index a73fb78537e..ed8e0661444 100644
   --- 
a/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/resources/jdbc_sybase_source_and_assert.conf
   +++ 
b/seatunnel-e2e/seatunnel-connector-v2-e2e/connector-jdbc-e2e/connector-jdbc-e2e-part-3/src/test/resources/jdbc_sybase_source_and_assert.conf
   @@ -46,6 +46,19 @@ sink {
              rule_value = 100
            }
          ]
   +      field_rules = [
   +        {
   +          # Exercise jTDS timestamp extraction, not only the number of rows 
emitted.
   +          field_name = DATETIME_TEST
   +          field_type = timestamp
   +          field_value = [
   +            {
   +              rule_type = NOT_NULL
   +              equals_to = "2026-01-02T03:04:05"
   +            }
   +          ]
   +        }
   +      ]
        }
      }
    }
   ```
   </details>
   
   <!-- daniel-fcp-repair-20261023-pr11012 -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to