From b451e9020df6414e8c51e4e0acd41f855b8742cd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 29 Aug 2023 00:25:35 +0200 Subject: [3.12] gh-64662: Fix virtual table support in sqlite3.Connection.iterdump (#108340) (#108563) * [3.12] gh-64662: Add virtual table support to sqlite3.Connection.iterdump (#108340) (cherry picked from commit d0160c7c22c8dff0a61c49b5304244df6e36465e) Co-authored-by: Aviv Palivoda * The _quote_value helper is not part of 3.12; spell out the replacement * With quotes * Ok, let's use explicit quoting --------- Co-authored-by: Aviv Palivoda --- Lib/sqlite3/dump.py | 20 +++++++++++++------- Lib/test/test_sqlite3/test_dump.py | 20 ++++++++++++++++++++ .../2023-08-22-22-29-42.gh-issue-64662.jHl_Bt.rst | 2 ++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-08-22-22-29-42.gh-issue-64662.jHl_Bt.rst diff --git a/Lib/sqlite3/dump.py b/Lib/sqlite3/dump.py index 07b9da1..1cf8759 100644 --- a/Lib/sqlite3/dump.py +++ b/Lib/sqlite3/dump.py @@ -16,6 +16,7 @@ def _iterdump(connection): directly but instead called from the Connection method, iterdump(). """ + writeable_schema = False cu = connection.cursor() yield('BEGIN TRANSACTION;') @@ -42,13 +43,15 @@ def _iterdump(connection): yield('ANALYZE "sqlite_master";') elif table_name.startswith('sqlite_'): continue - # NOTE: Virtual table support not implemented - #elif sql.startswith('CREATE VIRTUAL TABLE'): - # qtable = table_name.replace("'", "''") - # yield("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"\ - # "VALUES('table','{0}','{0}',0,'{1}');".format( - # qtable, - # sql.replace("''"))) + elif sql.startswith('CREATE VIRTUAL TABLE'): + if not writeable_schema: + writeable_schema = True + yield('PRAGMA writable_schema=ON;') + yield("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table','{0}','{0}',0,'{1}');".format( + table_name.replace("'", "''"), + sql.replace("'", "''"), + )) else: yield('{0};'.format(sql)) @@ -74,6 +77,9 @@ def _iterdump(connection): for name, type, sql in schema_res.fetchall(): yield('{0};'.format(sql)) + if writeable_schema: + yield('PRAGMA writable_schema=OFF;') + # gh-79009: Yield statements concerning the sqlite_sequence table at the # end of the transaction. for row in sqlite_sequence: diff --git a/Lib/test/test_sqlite3/test_dump.py b/Lib/test/test_sqlite3/test_dump.py index d0c24b9..c3ed3ae 100644 --- a/Lib/test/test_sqlite3/test_dump.py +++ b/Lib/test/test_sqlite3/test_dump.py @@ -117,6 +117,26 @@ class DumpTests(unittest.TestCase): got = list(self.cx.iterdump()) self.assertEqual(expected, got) + def test_dump_virtual_tables(self): + # gh-64662 + expected = [ + "BEGIN TRANSACTION;", + "PRAGMA writable_schema=ON;", + ("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table','test','test',0,'CREATE VIRTUAL TABLE test USING fts4(example)');"), + "CREATE TABLE 'test_content'(docid INTEGER PRIMARY KEY, 'c0example');", + "CREATE TABLE 'test_docsize'(docid INTEGER PRIMARY KEY, size BLOB);", + ("CREATE TABLE 'test_segdir'(level INTEGER,idx INTEGER,start_block INTEGER," + "leaves_end_block INTEGER,end_block INTEGER,root BLOB,PRIMARY KEY(level, idx));"), + "CREATE TABLE 'test_segments'(blockid INTEGER PRIMARY KEY, block BLOB);", + "CREATE TABLE 'test_stat'(id INTEGER PRIMARY KEY, value BLOB);", + "PRAGMA writable_schema=OFF;", + "COMMIT;" + ] + self.cu.execute("CREATE VIRTUAL TABLE test USING fts4(example)") + actual = list(self.cx.iterdump()) + self.assertEqual(expected, actual) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2023-08-22-22-29-42.gh-issue-64662.jHl_Bt.rst b/Misc/NEWS.d/next/Library/2023-08-22-22-29-42.gh-issue-64662.jHl_Bt.rst new file mode 100644 index 0000000..1b4c33a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-22-22-29-42.gh-issue-64662.jHl_Bt.rst @@ -0,0 +1,2 @@ +Fix support for virtual tables in :meth:`sqlite3.Connection.iterdump`. Patch +by Aviv Palivoda. -- cgit v0.12