Skip to content

Commit 8a1bade

Browse files
[3.10] gh-79009: sqlite3.iterdump now correctly handles tables with autoincrement (GH-9621) (#94015)
Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com> (cherry picked from commit affa9f2) Co-authored-by: itssme <itssme3000@gmail.com>
1 parent cdf3689 commit 8a1bade

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-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/sqlite3/test/dump.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import unittest
44
import sqlite3 as sqlite
55

6+
67
class DumpTests(unittest.TestCase):
78
def setUp(self):
89
self.cx = sqlite.connect(":memory:")
@@ -49,6 +50,51 @@ def test_table_dump(self):
4950
[self.assertEqual(expected_sqls[i], actual_sqls[i])
5051
for i in range(len(expected_sqls))]
5152

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

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,7 @@ Ron Klatchko
928928
Reid Kleckner
929929
Carsten Klein
930930
Bastian Kleineidam
931+
Joel Klimont
931932
Bob Kline
932933
Matthias Klose
933934
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