mdb-reader
Version:
JavaScript library to read data from Access databases
69 lines (68 loc) • 2.69 kB
JavaScript
import { Database } from "../../Database.js";
import { Table } from "../../Table.js";
import { ColumnTypes } from "../../types.js";
import { decodeAttachmentFileData } from "./attachment.js";
import { resolveFlatTableForComplexColumn } from "./utils.js";
/** Known attachment type column names; the FK column is the Long that is not one of these. */
const ATTACHMENT_TYPE_COLUMN_NAMES = new Set([
"FileName",
"FileType",
"FileData",
"FileURL",
"FileTimeStamp",
"FileFlags",
]);
/**
* Reads a Complex (attachment) column: resolves the complex value FK to the flat table,
* collects matching rows, and decodes each attachment's FileData.
*/
export function readComplex(buffer, column, database) {
try {
const complexTypeId = column.complex?.typeId;
const tableDefinitionPage = column.complex?.tableDefinitionPage;
if (complexTypeId === undefined || tableDefinitionPage === undefined) {
throw new Error("Complex column is not valid");
}
const complexColumnDefinition = {
...column,
complex: {
typeId: complexTypeId,
tableDefinitionPage,
},
};
const foreignKey = buffer.readInt32LE(0);
if (foreignKey <= 0) {
throw new Error("Foreign key value is not valid");
}
const { tableName: flatTableName, firstPage: flatTableFirstPage } = resolveFlatTableForComplexColumn(database, complexColumnDefinition);
const flatTable = new Table(flatTableName, database, flatTableFirstPage);
const foreignKeyColumn = flatTable
.getColumns()
.find((c) => c.type === ColumnTypes.Long && !c.autoLong && !ATTACHMENT_TYPE_COLUMN_NAMES.has(c.name));
if (!foreignKeyColumn) {
throw new Error("Foreign key column not found");
}
const flatData = flatTable.getData();
const matchingRows = flatData.filter((row) => row[foreignKeyColumn.name] === foreignKey);
return matchingRows.map((row) => {
const attachment = {
name: row.FileName,
type: row.FileType,
data: decodeAttachmentFileData(row.FileData),
};
if (row.FileURL) {
attachment.url = row.FileURL;
}
if (row.FileTimeStamp) {
attachment.timestamp = row.FileTimeStamp;
}
if (row.FileFlags) {
attachment.flags = row.FileFlags;
}
return attachment;
});
}
catch (error) {
throw new Error("Failed to read complex column", { cause: error });
}
}