Skip to content

Record ID match fails inside OR for legacy string keys. #1245

@matre

Description

@matre

If a database with IDs stored as strings is opened in version 4.3.2, old records can still be retrieved by ID using a "_id" on top level. However, if the "_id" filter is placed inside an OR (or AND) clause, no document will be returned for documents with string ID. The behavior can be reproduced by storing "_id" as string in a new file database.

Test "ID String search" passes while "OR ID search" fails.

	private static Nitrite open(File file) {
		NitriteBuilder builder = Nitrite.builder();
		MVStoreModuleBuilder mvBuilder = MVStoreModule.withConfig().compress(true);
		mvBuilder.filePath(file);
		builder.loadModule(mvBuilder.build());
		return builder.openOrCreate();
	}

	private void buildDb(File dbFile, Object...docIds) {
		
		try (Nitrite dst = open(dbFile)) {
			
			NitriteCollection to = dst.getCollection("my_table");
			
			for (Object docId : docIds) {
				Document copy = Document.createDocument();
				
				copy.put("_id", docId);
				to.insert(copy);
			}			
			dst.commit();
		}		
	}

	@Test
	public void testIdSearch() throws Exception {

		File tempDb = File.createTempFile("temp_db-", ".db");
		
		try {
			
			buildDb(tempDb, "1840817122658033664", 2041406700293308416L);
			try(Nitrite nitrite = open(tempDb)) {

				NitriteCollection collection = nitrite.getCollection("my_table");
				
				Filter idFilter1 = FluentFilter.where("_id").eq(2041406700293308416L);
				Filter idFilter2 = FluentFilter.where("_id").eq(1840817122658033664L);
				
				Set<Long> ids = new HashSet<>();
				
				for (Document doc : collection.find(idFilter1).toList()) {						
					Long id = doc.getId().getIdValue();
					ids.add(id);		
				}
				
				for (Document doc : collection.find(idFilter2).toList()) {						
					Long id = doc.getId().getIdValue();
					ids.add(id);		
				}
				
				assertTrue("ID Long search", ids.contains(2041406700293308416L));
				assertTrue("ID String search", ids.contains(1840817122658033664L));
				
				Set<Long> orIds = new HashSet<>();
				for (Document doc : collection.find(Filter.or(idFilter1, idFilter2)).toList()) {		
					Long id = doc.getId().getIdValue();
					orIds.add(id);
				}
				
				assertTrue("OR ID Long search", orIds.contains(2041406700293308416L));
				assertTrue("OR ID search", orIds.contains(1840817122658033664L));
			}
			
		} finally {
			tempDb.delete();
		}
		
	}

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions