Skip to content

Commit 5abe4cb

Browse files
gh-79009: sqlite3.iterdump now correctly handles tables with autoincrement (GH-9621)
Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com> (cherry picked from commit affa9f2) Co-authored-by: itssme <itssme3000@gmail.com>
1 parent b99f398 commit 5abe4cb

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

Lib/sqlite3/dump.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,16 @@ def _iterdump(connection):
2828
ORDER BY "name"
2929
"""
3030
schema_res = cu.execute(q)
31+
sqlite_sequence = []
3132
for table_name, type, sql in schema_res.fetchall():
3233
if table_name == 'sqlite_sequence':
33-
yield('DELETE FROM "sqlite_sequence";')
34+
rows = cu.execute('SELECT * FROM "sqlite_sequence";').fetchall()
35+
sqlite_sequence = ['DELETE FROM "sqlite_sequence"']
36+
sqlite_sequence += [
37+
f'INSERT INTO "sqlite_sequence" VALUES(\'{row[0]}\',{row[1]})'
38+
for row in rows
39+
]
40+
continue
3441
elif table_name == 'sqlite_stat1':
3542
yield('ANALYZE "sqlite_master";')
3643
elif table_name.startswith('sqlite_'):
@@ -67,4 +74,9 @@ def _iterdump(connection):
6774
for name, type, sql in schema_res.fetchall():
6875
yield('{0};'.format(sql))
6976

77+
# gh-79009: Yield statements concerning the sqlite_sequence table at the
78+
# end of the transaction.
79+
for row in sqlite_sequence:
80+
yield('{0};'.format(row))
81+
7082
yield('COMMIT;')

Lib/test/test_sqlite3/test_dump.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import unittest
44
import sqlite3 as sqlite
5+
from .test_dbapi import memory_database
6+
57

68
class DumpTests(unittest.TestCase):
79
def setUp(self):
@@ -49,6 +51,51 @@ def test_table_dump(self):
4951
[self.assertEqual(expected_sqls[i], actual_sqls[i])
5052
for i in range(len(expected_sqls))]
5153

54+
def test_dump_autoincrement(self):
55+
expected = [
56+
'CREATE TABLE "t1" (id integer primary key autoincrement);',
57+
'INSERT INTO "t1" VALUES(NULL);',
58+
'CREATE TABLE "t2" (id integer primary key autoincrement);',
59+
]
60+
self.cu.executescript("".join(expected))
61+
62+
# the NULL value should now be automatically be set to 1
63+
expected[1] = expected[1].replace("NULL", "1")
64+
expected.insert(0, "BEGIN TRANSACTION;")
65+
expected.extend([
66+
'DELETE FROM "sqlite_sequence";',
67+
'INSERT INTO "sqlite_sequence" VALUES(\'t1\',1);',
68+
'COMMIT;',
69+
])
70+
71+
actual = [stmt for stmt in self.cx.iterdump()]
72+
self.assertEqual(expected, actual)
73+
74+
def test_dump_autoincrement_create_new_db(self):
75+
self.cu.execute("BEGIN TRANSACTION")
76+
self.cu.execute("CREATE TABLE t1 (id integer primary key autoincrement)")
77+
self.cu.execute("CREATE TABLE t2 (id integer primary key autoincrement)")
78+
self.cu.executemany("INSERT INTO t1 VALUES(?)", ((None,) for _ in range(9)))
79+
self.cu.executemany("INSERT INTO t2 VALUES(?)", ((None,) for _ in range(4)))
80+
self.cx.commit()
81+
82+
with memory_database() as cx2:
83+
query = "".join(self.cx.iterdump())
84+
cx2.executescript(query)
85+
cu2 = cx2.cursor()
86+
87+
dataset = (
88+
("t1", 9),
89+
("t2", 4),
90+
)
91+
for table, seq in dataset:
92+
with self.subTest(table=table, seq=seq):
93+
res = cu2.execute("""
94+
SELECT "seq" FROM "sqlite_sequence" WHERE "name" == ?
95+
""", (table,))
96+
rows = res.fetchall()
97+
self.assertEqual(rows[0][0], seq)
98+
5299
def test_unorderable_row(self):
53100
# iterdump() should be able to cope with unorderable row types (issue #15545)
54101
class UnorderableRow:

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ Ron Klatchko
934934
Reid Kleckner
935935
Carsten Klein
936936
Bastian Kleineidam
937+
Joel Klimont
937938
Bob Kline
938939
Matthias Klose
939940
Jeremy Kloth
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:meth:`sqlite3.Connection.iterdump` now handles databases that use ``AUTOINCREMENT`` in one or more tables.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy