Skip to content

Commit

Permalink
Fix for CONPY-133:
Browse files Browse the repository at this point in the history
Extended parser for supporting MariaDB comment syntax
(https://mariadb.com/kb/en/comment-syntax/)
  • Loading branch information
9EOR9 committed Nov 24, 2020
1 parent 6a83209 commit a1c709b
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 4 deletions.
3 changes: 2 additions & 1 deletion include/mariadb_python.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ typedef struct st_parser {
char* value_ofs;
enum enum_paramstyle paramstyle;
MrdbString *keys;
MYSQL *mysql;
} MrdbParser;

struct mrdb_pool;
Expand Down Expand Up @@ -415,7 +416,7 @@ mariadb_param_update(void *data, MYSQL_BIND *bind, uint32_t row_nr);

/* parser prototypes */
MrdbParser *
MrdbParser_init(const char *statement, size_t length);
MrdbParser_init(MYSQL *mysql, const char *statement, size_t length);

void
MrdbParser_end(MrdbParser *p);
Expand Down
4 changes: 2 additions & 2 deletions mariadb/mariadb_cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ PyObject *MrdbCursor_execute(MrdbCursor *self,

if (!self->parser)
{
self->parser= MrdbParser_init(statement, statement_len);
self->parser= MrdbParser_init(self->connection->mysql, statement, statement_len);
if (MrdbParser_parse(self->parser, 0, errmsg, 128))
{
PyErr_SetString(Mariadb_ProgrammingError, errmsg);
Expand Down Expand Up @@ -1364,7 +1364,7 @@ MrdbCursor_executemany(MrdbCursor *self,

if (!self->parser)
{
if (!(self->parser= MrdbParser_init(statement, (size_t)statement_len)))
if (!(self->parser= MrdbParser_init(self->connection->mysql, statement, (size_t)statement_len)))
{
exit(-1);
}
Expand Down
45 changes: 44 additions & 1 deletion mariadb/mariadb_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ MrdbParser_end(MrdbParser* p)
}

MrdbParser *
MrdbParser_init(const char *statement, size_t length)
MrdbParser_init(MYSQL *mysql, const char *statement, size_t length)
{
MrdbParser *p;

Expand All @@ -91,6 +91,7 @@ MrdbParser_init(const char *statement, size_t length)
}
memcpy(p->statement.str, statement, length);
p->statement.length= length;
p->mysql= mysql;
}
return p;
}
Expand Down Expand Up @@ -155,6 +156,48 @@ MrdbParser_parse(MrdbParser *p, uint8_t is_batch,
if (*a == '/' && *(a + 1) == '*')
{
a+= 2;
if (a+1 < end && *a == '!')
{
/* check special syntax: 1. comment followed by '!' and whitespace */
if (isspace(*(a+1)))
{
a+= 2;
continue;
}
/* check special syntax: 3. comment followed by '!' 5 or 6 digit version number */
if (a + 7 < end && isdigit(*(a+1)))
{
char *x;
ulong version_number= strtol(a+1, &x, 10);
a= x;
if ((version_number >= 50700 && version_number <= 99999) ||
!(version_number <= mysql_get_server_version(p->mysql)))
{
p->in_comment= 1;
}
continue;
}
}
if (a+2 < end && *a == 'M' && *(a+1) == '!')
{
a+= 2;
/* check special syntax: 2. comment followed by 'M! ' (MariaDB only) */
if (isspace(*(a)))
continue;

/* check special syntax: 2. comment followed by 'M!' and version number */
if (a + 6 < end && isdigit(*a))
{
char *x;
ulong version_number= strtol(a, &x, 10);
a= x;
if (!(version_number <= mysql_get_server_version(p->mysql)))
{
p->in_comment= 1;
}
continue;
}
}
p->in_comment= 1;
continue;
}
Expand Down
43 changes: 43 additions & 0 deletions testing/test/integration/test_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,49 @@ def test_conpy129(self):
self.assertEqual(conn.server_version_info, (major, minor, patch))
self.assertEqual(conn.get_server_version(), (major, minor, patch))

def test_conpy133(self):
if is_mysql():
self.skipTest("Skip (MySQL)")
conn= create_connection()

cursor= conn.cursor()
cursor.execute("SELECT /*! ? */", (1,))
row= cursor.fetchone()
self.assertEqual(row[0], 1)
del cursor

cursor= conn.cursor()
cursor.execute("SELECT /*M! ? */", (1,))
row= cursor.fetchone()
self.assertEqual(row[0], 1)
del cursor

cursor= conn.cursor()
cursor.execute("SELECT /*M!50601 ? */", (1,))
row= cursor.fetchone()
self.assertEqual(row[0], 1)
del cursor

cursor= conn.cursor()
cursor.execute("SELECT /*!40301 ? */", (1,))
row= cursor.fetchone()
self.assertEqual(row[0], 1)
del cursor

cursor= conn.cursor()
try:
cursor.execute("SELECT /*!50701 ? */", (1,))
except mariadb.DataError:
pass
del cursor

cursor= conn.cursor()
try:
cursor.execute("SELECT /*!250701 ? */", (1,))
except mariadb.DataError:
pass
del cursor

def test_conpy91(self):
with create_connection() as connection:
with connection.cursor() as cursor:
Expand Down

0 comments on commit a1c709b

Please sign in to comment.