feat(congodb): implement CongoDB MongoDB wire-protocol compatible in-memory server and APIs
This commit is contained in:
100
ts/congodb/server/handlers/DeleteHandler.ts
Normal file
100
ts/congodb/server/handlers/DeleteHandler.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import * as plugins from '../../congodb.plugins.js';
|
||||
import type { ICommandHandler, IHandlerContext } from '../CommandRouter.js';
|
||||
import { QueryEngine } from '../../engine/QueryEngine.js';
|
||||
|
||||
/**
|
||||
* DeleteHandler - Handles delete commands
|
||||
*/
|
||||
export class DeleteHandler implements ICommandHandler {
|
||||
async handle(context: IHandlerContext): Promise<plugins.bson.Document> {
|
||||
const { storage, database, command, documentSequences } = context;
|
||||
|
||||
const collection = command.delete;
|
||||
if (typeof collection !== 'string') {
|
||||
return {
|
||||
ok: 0,
|
||||
errmsg: 'delete command requires a collection name',
|
||||
code: 2,
|
||||
codeName: 'BadValue',
|
||||
};
|
||||
}
|
||||
|
||||
// Get deletes from command or document sequences
|
||||
let deletes: plugins.bson.Document[] = command.deletes || [];
|
||||
|
||||
// Check for OP_MSG document sequences
|
||||
if (documentSequences && documentSequences.has('deletes')) {
|
||||
deletes = documentSequences.get('deletes')!;
|
||||
}
|
||||
|
||||
if (!Array.isArray(deletes) || deletes.length === 0) {
|
||||
return {
|
||||
ok: 0,
|
||||
errmsg: 'delete command requires deletes array',
|
||||
code: 2,
|
||||
codeName: 'BadValue',
|
||||
};
|
||||
}
|
||||
|
||||
const ordered = command.ordered !== false;
|
||||
const writeErrors: plugins.bson.Document[] = [];
|
||||
let totalDeleted = 0;
|
||||
|
||||
// Check if collection exists
|
||||
const exists = await storage.collectionExists(database, collection);
|
||||
if (!exists) {
|
||||
// Collection doesn't exist, return success with 0 deleted
|
||||
return { ok: 1, n: 0 };
|
||||
}
|
||||
|
||||
for (let i = 0; i < deletes.length; i++) {
|
||||
const deleteSpec = deletes[i];
|
||||
const filter = deleteSpec.q || deleteSpec.filter || {};
|
||||
const limit = deleteSpec.limit;
|
||||
|
||||
// limit: 0 means delete all matching, limit: 1 means delete one
|
||||
const deleteAll = limit === 0;
|
||||
|
||||
try {
|
||||
// Get all documents
|
||||
const documents = await storage.findAll(database, collection);
|
||||
|
||||
// Apply filter
|
||||
const matchingDocs = QueryEngine.filter(documents, filter);
|
||||
|
||||
if (matchingDocs.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine which documents to delete
|
||||
const docsToDelete = deleteAll ? matchingDocs : matchingDocs.slice(0, 1);
|
||||
|
||||
// Delete the documents
|
||||
const idsToDelete = docsToDelete.map(doc => doc._id);
|
||||
const deleted = await storage.deleteByIds(database, collection, idsToDelete);
|
||||
totalDeleted += deleted;
|
||||
} catch (error: any) {
|
||||
writeErrors.push({
|
||||
index: i,
|
||||
code: error.code || 1,
|
||||
errmsg: error.message || 'Delete failed',
|
||||
});
|
||||
|
||||
if (ordered) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const response: plugins.bson.Document = {
|
||||
ok: 1,
|
||||
n: totalDeleted,
|
||||
};
|
||||
|
||||
if (writeErrors.length > 0) {
|
||||
response.writeErrors = writeErrors;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user