Skip to content

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

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();
		}
		
	}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions