From ec10a4a402e5b6845b247f688fc157be45414cdd Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Mon, 5 Nov 2007 02:32:26 +0000 Subject: [PATCH] Fixes bug 477182 on pybsddb.sf.net. DB objects now load the flags and pay attention to them when opening an existing database. This means that d[] behaves properly even on databases previously created with DB_DUP or DB_DUPSORT flags to allow duplicate keys. http://sourceforge.net/tracker/index.php?func=detail&aid=477182&group_id=13900&atid=113900 Do not backport, this bugfix could be considered an API change. --- Lib/bsddb/test/test_misc.py | 24 ++++++++++++++++++++++++ Misc/NEWS | 8 ++++++++ Modules/_bsddb.c | 17 ++--------------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/Lib/bsddb/test/test_misc.py b/Lib/bsddb/test/test_misc.py index 1212581f1d2..598e62607fc 100644 --- a/Lib/bsddb/test/test_misc.py +++ b/Lib/bsddb/test/test_misc.py @@ -90,6 +90,30 @@ class MiscTestCase(unittest.TestCase): db1.close() os.unlink(self.filename) + def test_DB_set_flags_persists(self): + try: + db1 = db.DB() + db1.set_flags(db.DB_DUPSORT) + db1.open(self.filename, db.DB_HASH, db.DB_CREATE) + db1['a'] = 'eh' + db1['a'] = 'A' + self.assertEqual([('a', 'A')], db1.items()) + db1.put('a', 'Aa') + self.assertEqual([('a', 'A'), ('a', 'Aa')], db1.items()) + db1.close() + db1 = db.DB() + # no set_flags call, we're testing that it reads and obeys + # the flags on open. + db1.open(self.filename, db.DB_HASH) + self.assertEqual([('a', 'A'), ('a', 'Aa')], db1.items()) + # if it read the flags right this will replace all values + # for key 'a' instead of adding a new one. (as a dict should) + db1['a'] = 'new A' + self.assertEqual([('a', 'new A')], db1.items()) + finally: + db1.close() + os.unlink(self.filename) + #---------------------------------------------------------------------- diff --git a/Misc/NEWS b/Misc/NEWS index ff209565673..31898d7fb3b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -822,6 +822,14 @@ Extension Modules - Bug #1233: fix bsddb.dbshelve.DBShelf append method to work as intended for RECNO databases. +- pybsddb.sf.net Bug #477182: Load the database flags at database open + time so that opening a database previously created with the DB_DUP or + DB_DUPSORT flag set will keep the proper behavior on subsequent opens. + Specifically: dictionary assignment to a DB object will replace all + values for a given key when the database allows duplicate values. + DB users should use DB.put(k, v) when they want to store duplicates; not + DB[k] = v. + - Bug #1686475: Support stat'ing open files on Windows again. - Patch #1185447: binascii.b2a_qp() now correctly quotes binary characters diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c index d03f72b8446..95ccb438dd6 100644 --- a/Modules/_bsddb.c +++ b/Modules/_bsddb.c @@ -1836,21 +1836,6 @@ DB_open(DBObject* self, PyObject* args, PyObject* kwargs) return NULL; } -#if 0 && (DBVER >= 41) - if ((!txn) && (txnobj != Py_None) && self->myenvobj - && (self->myenvobj->flags & DB_INIT_TXN)) - { - /* If no 'txn' parameter was supplied (no DbTxn object and None was not - * explicitly passed) but we are in a transaction ready environment: - * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions - * to work on BerkeleyDB 4.1 without needing to modify their - * DBEnv or DB open calls. - * TODO make this behaviour of the library configurable. - */ - flags |= DB_AUTO_COMMIT; - } -#endif - MYDB_BEGIN_ALLOW_THREADS; #if (DBVER >= 41) err = self->db->open(self->db, txn, filename, dbname, type, flags, mode); @@ -1864,6 +1849,8 @@ DB_open(DBObject* self, PyObject* args, PyObject* kwargs) return NULL; } + self->db->get_flags(self->db, &self->setflags); + self->flags = flags; RETURN_NONE(); }