orderedfind.patch0100644000076400001440000000312210274462650013100 0ustar patusers--- python/PyView.cpp.orig 2005-08-03 17:00:14.000000000 -0400 +++ python/PyView.cpp 2005-08-04 14:59:46.000000000 -0400 @@ -498,7 +498,12 @@ static PyObject *PyView_find(PyView *o, PyObject *_args, PyObject* _kwargs) { PWONumber start(0); - PWOMapping crit; + // Make crit a Python object instead of a mapping. This allows us to use + // a sequence as well as a dictionary for search criteria since makeRow + // supports both. + //PWOMapping crit; + PyObject *crit; + try { PWOSequence args(_args); if (_kwargs) { @@ -514,7 +519,7 @@ if (PyNumber_Check((PyObject*)args[i])) start = args[i]; else - crit = args[i]; + crit = (PyObject*)args[i]; } c4_Row temp; o->makeRow(temp, crit, false); @@ -1111,9 +1116,22 @@ void PyView::makeRowFromDict(c4_Row& tmp, PyObject* o, bool useDefaults) { PWOMapping dict(o); PWOList keys = dict.keys(); - for (int i=0; i -1) { const c4_Property& prop = NthProperty(ndx); PyRowRef::setFromPython(tmp, prop, dict[(const char*)key]); orderedfind.py0100644000076400001440000000750210274457556012450 0ustar patusersimport os from metakit import * import md5 sequence_guid_index_desc = 'sequence_guid_index[_B[sequence:I,encoded_guid:B]]' guid_sequence_index_desc = 'guid_sequence_index[_B[encoded_guid:B,sequence:I]]' def commit (): """Do a commit on the database.""" db.commit(1) def create_database (): global sgi_raw, sgi_ordered, gsi_raw, gsi_ordered sgi_raw = db.getas(sequence_guid_index_desc) sgi_ordered = sgi_raw.blocked().ordered(2) gsi_raw = db.getas(guid_sequence_index_desc) gsi_ordered = gsi_raw.blocked().ordered(2) commit() def structure (view, title=None): if title : print title for p in view.structure(): print "(name:%s, id:%s, type:%s)" % (p.name, p.id, p.type) def do_find (view, criteria, title): result = view.find( criteria ) print title, result try: os.remove('test.db') except: pass db = storage('test.db',1) create_database() print """Demonstrate a defect with ordered view.find() using criteria containing multiple properties. The underlying C++ ordered view expects properties in the cursor to be in the order they are in the ordered view's key. The Python PyView wrapper presents the properties to the C++ code in an order depending on Python's dictionary hash algorithm. The following code demonstrates find() working or failing depending on whether or not the hash ordering agrees with the key property order.\n""" print """Fixes are to either have PyView_find() construct the criteria row with properties in the order required by the underlying view (requiring it to determine the view's structure and match property names with criteria dictionary keys), or to have c4_OrderedViewer::KeyCompare compare keys using property ids rather than assuming the properties will be presented in the same order in both the view to be searched and in the cursor representing the criteria.\n""" print "metakit version", version print "\nview descriptions" print "sgi", db.description('sequence_guid_index') print "gsi", db.description('guid_sequence_index') print "\nview structures" structure( sgi_ordered, 'sgi_ordered (sequence_guid_index.blocked().ordered(2))') print '' structure( gsi_ordered, 'gsi_ordered (guid_sequence_index.blocked().ordered(2))') print '' print '' for i in range(20): guid = "ID%s" % md5.md5("abc%s" % i).hexdigest() sgi_ordered.append( sequence = i, encoded_guid = guid) gsi_ordered.append( sequence = i, encoded_guid = guid) commit () print "sgi criteria are contents of sgi_ordered[10]" r = sgi_ordered[10] sgi_criteria = {'sequence': r.sequence, 'encoded_guid' : r.encoded_guid } del r print "Iterate over criteria dictionary - note hash has the items" print "reversed compared to the property order in gsi_ordered" for items in sgi_criteria.items(): print items print sgi_criteria sgi_seq = (sgi_criteria['sequence'], sgi_criteria['encoded_guid']) print sgi_seq print "\ngsi criteria are contents of gsi_ordered[10]" r = gsi_ordered[10] gsi_criteria = {'sequence': r.sequence, 'encoded_guid' : r.encoded_guid } del r print "Iterate over criteria dictionary - note hash has the items" print "correctly ordered compared to the property order in sgi_ordered" for items in gsi_criteria.items(): print items print gsi_criteria print "Following test will return -1 without patch, 10 with patch" do_find( sgi_ordered, sgi_criteria, 'find sgi criteria in sgi') try: do_find(sgi_ordered, sgi_seq, 'find tuple in sgi') except: print "Tried to find with tuple on Mk4py without patch" print 'search sgi criteria in sgi', sgi_ordered.search(sgi_criteria) print "Following tests demonstrate old behavior working because the Python" print "function has the keys in the same order as the view description" print 'find gsi criteria in gsi', gsi_ordered.find(gsi_criteria) print 'search gsi criteria in gsi', gsi_ordered.search(gsi_criteria)