[CONPY-137] cursor.execute does not work with "indicators" Created: 2020-12-29  Updated: 2020-12-29  Resolved: 2020-12-29

Status: Closed
Project: MariaDB Connector/Python
Component/s: Generic
Affects Version/s: 1.0.5
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: Marcelo Titonelli Pio da Cruz Assignee: Georg Richter
Resolution: Not a Bug Votes: 0
Labels: None
Environment:

WIndows 10 64bits
Server version: 10.5.8-MariaDB - mariadb.org binary distribution



 Description   

Sample modified from Official doc:
Using indicators

from mariadb.constants import *
from my_packages.DatabasePoint import database_on_demand
 
def database_on_demand():
    return mariadb.connect(
        user="root", database="test", host="127.0.0.1", password="test", connect_timeout=180, read_timeout=180, write_timeout=180, autocommit=True)
 
 
conn = database_on_demand()
cursor = conn.cursor()
cursor.execute("CREATE OR REPLACE TABLE cakes(id int, cake varchar(100), price decimal(10,2) default 1.99)")
 
sql= "INSERT INTO cakes (id, cake, price) VALUES (?,?,?)"
data= [(1, "Cherry Cake", 2.10), (2, "Apple Cake", INDICATOR.DEFAULT)]
cursor.execute(sql, data[1]) # does not work
cursor.executemany(sql, data) # works
cursor.execute(sql, data[1]) # after executemany it works

Expected output:
2 Apple Cake 1.99
2 Apple Cake 1.99
1 Cherry Cake 2.10
2 Apple Cake 1.99
2 Apple Cake 1.99
2 Apple Cake 1.99

Current output:
2 Apple Cake
2 Apple Cake
1 Cherry Cake 2.10
2 Apple Cake 1.99
2 Apple Cake 1.99
2 Apple Cake 1.99

Execute does not insert default value for Apple Cake when using execute alone, but it works after one row is inserted through executemany because it buffers the default values.

Executemany is not a full alternative due to this another bug, which breaks trigger, but it may be a temporary work around if used on one row before using multiple execute.
https://jira.mariadb.org/browse/MDEV-24411



 Comments   
Comment by Georg Richter [ 2020-12-29 ]

https://mariadb-corporation.github.io/mariadb-connector-python/usage.html#passing-parameters-to-sql-statements

"When using executemany(), there are a few restrictions: - All tuples must have the same types as in first tuple. E.g. the parameter [(1),(1.0)] or [(1),(None)] are invalid. - Special values like None or column default value needs to be indicated by an indicator."

execute() uses a different client/server protocol (COM_STMT_EXECUTE) and doesn't support indicator variables.

Comment by Marcelo Titonelli Pio da Cruz [ 2020-12-29 ]

Thanks again, Georg.

https://mariadb-corporation.github.io/mariadb-connector-python/usage.html#using-indicators
I didn't get why you quote the that part of executemany, my problem with executemany is not about types, my problem with executemany is only about the trigger(https://jira.mariadb.org/browse/MDEV-24411).
The sample provided by me is correct and it's currently the official docs sample, but fixed, because there's a missing interrogation at docs sample:

Official docs sample below:

from mariadb.constants import *
 
cursor.execute("CREATE TABLE cakes(id int, cake varchar(100), price decimal(10,2) default 1.99)")
 
sql= "INSERT INTO cakes (id, cake, price) VALUES (?,?)"
data= [(1, "Cherry Cake", 2.10), (2, "Apple Cake", INDICATOR.default)]
cursor.executemany(sql, data)

It looks like a bug because if executemany is called, even without indicators, at same session, before execute, execute works correctly with indicators, but if executemany is omitted, indicators will not work with execute.

Note that, in below sample, I'm only passing one row to executemany, with no indicator.

from mariadb.constants import * 
def database_on_demand():
    return mariadb.connect(
        user="root", database="test", host="127.0.0.1", password="test", connect_timeout=180, read_timeout=180, write_timeout=180, autocommit=True)
 
conn = database_on_demand()
cursor = conn.cursor()
cursor.execute("CREATE OR REPLACE TABLE cakes(id int, cake varchar(100) default 'Vanilla Cake', price decimal(10,2) default 1.99)")
 
sql= "INSERT INTO cakes (id, cake, price) VALUES (?,?,?)"
data= [(1, "Cherry Cake", 2.10), (2, "Apple Cake", INDICATOR.DEFAULT), (2, INDICATOR.DEFAULT, INDICATOR.NULL)]
cursor.executemany(sql, [data[0]])
cursor.execute(sql, data[0]) 
cursor.execute(sql, data[1])
cursor.execute(sql, data[2]) 

Can a note be added to docs mentioning execute does not work correctly with indicators?

Generated at Thu Feb 08 03:30:32 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.