morningman opened a new issue, #67369:
URL: https://github.com/apache/doris/issues/67369

   ### Search before asking
   
   - [X] I had searched in the 
[issues](https://github.com/apache/doris/issues?q=is%3Aissue) and found no 
similar issues.
   
   ### Version
   
   Apache Doris 4.1.3-rc02, commit `31263df4dc1d4d3a27517d264802cd4d6b92c874`
   
   Client: Python + ADBC Flight SQL driver (`adbc_driver_flightsql`), FE 
`arrow_flight_sql_port` = 41070.
   The MySQL/JDBC protocol is used as the control path for comparison.
   
   ### What's Wrong?
   
   Executing a PL/SQL `CALL` that contains an `INSERT` **once** over Python 
ADBC Flight SQL returns an error to the client:
   
   ```
   INTERNAL: getMysqlChannel not in mysql connection
   ```
   
   but the procedure's `INSERT` side effect is actually executed **four 
times**. A single call must execute its side effect at most once.
   
   Two independent ADBC calls (keys `444` and `666`) each produced exactly four 
rows. The JDBC control call (key `555`) succeeded and produced exactly one row.
   
   ### What You Expected?
   
   A single `CALL` should succeed and insert exactly one row. If `CALL` is not 
supported over the Flight SQL protocol, the server must reject it *before* 
executing anything, and must never repeat DML side effects after returning an 
error.
   
   ### How to Reproduce?
   
   1. Create the table and the stored procedure below.
   2. Execute `CALL plsql_variable_insert(444,'adbc444')` **once** over Python 
ADBC.
   3. Observe the `INTERNAL` error returned by ADBC.
   4. Over MySQL/JDBC, count the rows for `id=444`; `COUNT(*)` is 4.
   5. Run the same `CALL` for key `555` over JDBC; `COUNT(*)` is 1.
   
   ```sql
   DROP TABLE IF EXISTS plsql_variable;
   CREATE TABLE plsql_variable (
     id INT,
     name VARCHAR(20)
   ) DUPLICATE KEY(id)
   DISTRIBUTED BY HASH(id) BUCKETS 4
   PROPERTIES ("replication_num"="1");
   
   CREATE OR REPLACE PROCEDURE plsql_variable_insert(IN id INT, IN name STRING)
   BEGIN
     INSERT INTO plsql_variable VALUES(id,name);
   END;
   
   -- Execute this ONCE through Python ADBC Flight SQL.
   CALL plsql_variable_insert(444,'adbc444');
   
   -- Inspect through MySQL/JDBC after the ADBC error.
   SELECT id, name, COUNT(*)
   FROM plsql_variable WHERE id=444 GROUP BY id, name;
   ```
   
   Client side:
   
   ```python
   import adbc_driver_flightsql.dbapi as flight_sql
   
   conn = flight_sql.connect(uri="grpc://127.0.0.1:41070",
                             db_kwargs={"username": "root", "password": ""})
   cur = conn.cursor()
   cur.execute("CALL plsql_variable_insert(444,'adbc444')")
   ```
   
   ### Anything Else?
   
   The error message (`getMysqlChannel not in mysql connection`) shows that the 
PL/SQL executor assumes a MySQL channel is available on the session. On a 
Flight SQL connection that assumption does not hold, and the failure apparently 
happens after the statement has already been executed, and is then retried, so 
the DML lands multiple times.
   
   Data correctness impact: this can silently duplicate writes.
   
   **Workaround:** run PL/SQL `CALL` over the MySQL/JDBC protocol. Clients must 
not auto-retry on this error, since the server may already have applied the 
side effect.
   
   Tracking issue: #65615
   
   ### Are you willing to submit PR?
   
   - [ ] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [X] I agree to follow this project's [Code of 
Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to