diff -r 0ab23958c2a7 Lib/sqlite3/test/dbapi.py --- a/Lib/sqlite3/test/dbapi.py Wed Oct 15 23:58:37 2014 -0400 +++ b/Lib/sqlite3/test/dbapi.py Thu Oct 16 17:59:41 2014 +0200 @@ -443,6 +443,14 @@ row = cur.fetchone() self.assertEqual(row, None) + def CheckWithExisting(self): + self.cu.execute("with bar as (select * from test) select * from bar where name = 'foo'") + self.assertIsNotNone(self.cu.description) + + def CheckWithMissing(self): + self.cu.execute("with bar as (select * from test) select * from bar where name = 'bar'") + self.assertIsNotNone(self.cu.description) + def CheckArraySize(self): # must default ot 1 self.assertEqual(self.cu.arraysize, 1) diff -r 0ab23958c2a7 Modules/_sqlite/cursor.c --- a/Modules/_sqlite/cursor.c Wed Oct 15 23:58:37 2014 -0400 +++ b/Modules/_sqlite/cursor.c Thu Oct 16 17:59:41 2014 +0200 @@ -34,6 +34,7 @@ char buf[20]; const char* src; char* dst; + int state, level; src = statement; /* skip over whitepace */ @@ -51,7 +52,60 @@ } *dst = 0; - + /* skip WITH statement */ + if (!strcmp(buf, "with")) { + state = 0; + /* 0=recursive or name, 1=name, 2=as, 3=(), 4=, or end */ + while (1) { + /* find next token */ + while (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') { + src++; + } + if (*src == 0) + return STATEMENT_INVALID; + if (state==3) { + /* skip (...) with possible subqueries */ + if (*src++ != '(') + return STATEMENT_INVALID; + level = 1; + while (*src && level) { + if (*src == ')') { + level--; + } else if (*src == '(') { + level++; + } + src++; + } + state = 4; + continue; + } else if (state == 4) { + /* next cte-table or end */ + if (*src == ',') { + src++; + state = 1; + continue; + } + } + dst = buf; + *dst = 0; + while (Py_ISALPHA(*src) && (dst - buf) < ((Py_ssize_t)sizeof(buf) - 2)) { + *dst++ = Py_TOLOWER(*src++); + } + *dst = 0; + if (!state) { + if (!strcmp(buf, "recursive")) + state = 1; + else + state = 2; + } else if (state == 2) { + /* as expected */ + if (strcmp(buf, "as")) + return STATEMENT_INVALID; + state = 3; + } else if (state == 4) + break; + } + } if (!strcmp(buf, "select")) { return STATEMENT_SELECT; } else if (!strcmp(buf, "insert")) {