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 Fri Oct 17 01:43:41 2014 +0200 @@ -443,6 +443,14 @@ row = cur.fetchone() self.assertEqual(row, None) + def CheckWithExisting(self): + self.cu.execute("with bar(id,name,income) 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 Fri Oct 17 01:43:41 2014 +0200 @@ -34,6 +34,7 @@ char buf[20]; const char* src; char* dst; + int state, level; src = statement; /* skip over whitepace */ @@ -52,6 +53,72 @@ *dst = 0; + /* skip WITH statement */ + if (!strcmp(buf, "with")) { + state = 0; + /* 0=recursive or name, 1=name, 2=optional (), 3=as, 4=(), 5=, or end */ + while (1) { + /* find next token */ + while (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') { + src++; + } + if (*src == 0) + return STATEMENT_INVALID; + if (state == 2) { + /* skip (...) */ + if (*src == '(') { + while (*++src) { + if (*src == ')') { + src++; + break; + } + } + } + state = 3; + continue; + } else if (state==4) { + /* skip (...) with possible subqueries */ + if (*src++ != '(') + return STATEMENT_INVALID; + level = 1; + while (*src && level) { + if (*src == ')') { + level--; + } else if (*src == '(') { + level++; + } + src++; + } + state = 5; + continue; + } else if (state == 5) { + /* 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 == 3) { + /* as expected */ + if (strcmp(buf, "as")) + return STATEMENT_INVALID; + state = 4; + } else if (state == 5) + break; + } + } if (!strcmp(buf, "select")) { return STATEMENT_SELECT; } else if (!strcmp(buf, "insert")) {