Skip to content

Commit

Permalink
address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
friendlymatthew committed Feb 16, 2024
1 parent 27f05ef commit effbed4
Show file tree
Hide file tree
Showing 7 changed files with 369 additions and 351 deletions.
27 changes: 19 additions & 8 deletions src/btree/multi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { MemoryPointer } from "./node";
import { PageFile } from "./pagefile";

const PAGE_SIZE_BYTES = 4096;
export const maxUint64 = 2n ** 64n - 1n;

export class LinkedMetaPage {
private resolver: RangeResolver;
private offset: bigint;
private metaPageData: ArrayBuffer | null;
private metaPagePromise: Promise<ArrayBuffer> | null = null;

constructor(resolver: RangeResolver, offset: bigint) {
this.resolver = resolver;
Expand Down Expand Up @@ -57,14 +59,23 @@ export class LinkedMetaPage {
return this.metaPageData;
}

const { data } = await this.resolver({
start: Number(this.offset),
end: Number(this.offset) + PAGE_SIZE_BYTES - 1,
});

this.metaPageData = data;
if (!this.metaPagePromise) {
this.metaPagePromise = this.resolver({
start: Number(this.offset),
end: Number(this.offset) + PAGE_SIZE_BYTES - 1,
})
.then(({ data }) => {
this.metaPageData = data;
this.metaPagePromise = null;
return data;
})
.catch((error) => {
this.metaPagePromise = null;
throw error;
});
}

return data;
return this.metaPagePromise;
}

/**
Expand All @@ -75,7 +86,7 @@ export class LinkedMetaPage {

const view = new DataView(pageData, 12, 8);
const nextOffset = view.getBigUint64(0);
const maxUint64 = 2n ** 64n - 1n;

if (nextOffset === maxUint64) {
return null;
}
Expand Down
12 changes: 8 additions & 4 deletions src/db/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ export type Query<T extends Schema> = {
};

export enum FieldType {
String = 1 << 0,
Number = 1 << 1,
Boolean = 1 << 4,
Null = 1 << 5,
String = 0,
Int64 = 1,
Uint64 = 2,
Float64 = 3,
Object = 4,
Array = 5,
Boolean = 6,
Null = 7,
}

function parseIgnoringSuffix(
Expand Down
22 changes: 11 additions & 11 deletions src/db/query-validation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IndexMeta } from "../index-file/meta";
import { IndexHeader, IndexMeta } from "../index-file/meta";
import {
FieldType,
OrderBy,
Expand All @@ -16,8 +16,8 @@ import {
* @param {FieldType} singleType - The specific type to check for within the compositeType.
* @returns {boolean} - Returns true if singleType is included in compositeType, false otherwise.
*/
function containsType(compositeType: bigint, singleType: FieldType): boolean {
return (compositeType & BigInt(singleType)) !== BigInt(0);
function containsType(compositeType: number[], singleType: number): boolean {
return compositeType.includes(singleType);
}

/**
Expand All @@ -29,7 +29,7 @@ function containsType(compositeType: bigint, singleType: FieldType): boolean {
*/
function validateWhere<T extends Schema>(
where: WhereNode<T>[] | undefined,
headers: IndexMeta[]
headers: IndexHeader[]
): void {
if (!where || !Array.isArray(where) || where.length === 0) {
throw new Error("Missing 'where' clause.");
Expand Down Expand Up @@ -57,27 +57,27 @@ function validateWhere<T extends Schema>(
throw new Error("'value' in 'where' clause is missing.");
}

const headerType = header.fieldType;
const headerType = header.fieldTypes;

if (whereNode.value === null) {
if (!containsType(headerType, FieldType.Null)) {
if (!containsType(headerType, 7)) {
throw new Error(`'key: ${whereNode.key} does not have type: null.`);
}
} else {
function fieldTypeError(
key: string,
actual: FieldType,
expected: bigint
expected: number[]
): string {
return `key: ${key} does not have type: ${actual}. Expected: ${expected}`;
}

switch (typeof whereNode.value) {
case "bigint":
case "number":
if (!containsType(headerType, FieldType.Number)) {
if (!containsType(headerType, FieldType.Int64)) {
throw new Error(
fieldTypeError(whereNode.key, FieldType.Number, headerType)
fieldTypeError(whereNode.key, FieldType.Int64, headerType)
);
}
break;
Expand Down Expand Up @@ -141,7 +141,7 @@ function validateOrderBy<T extends Schema>(
*/
function validateSelect<T extends Schema>(
select: SelectField<T>[] | undefined,
headers: IndexMeta[]
headers: IndexHeader[]
): void {
if (select) {
if (!Array.isArray(select) || select.length === 0) {
Expand Down Expand Up @@ -171,7 +171,7 @@ function validateSelect<T extends Schema>(
*/
export async function validateQuery<T extends Schema>(
query: Query<T>,
headers: IndexMeta[]
headers: IndexHeader[]
): Promise<void> {
validateWhere(query.where, headers);
validateOrderBy(query.orderBy, query.where![0].key as string);
Expand Down
19 changes: 4 additions & 15 deletions src/index-file/index-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,35 +74,24 @@ export class IndexFileV1<T> implements VersionedIndexFile<T> {
const buffer = await tree.metadata();

// unmarshall binary for FileMeta
if (buffer.byteLength < 9) {
if (buffer.byteLength < 10) {
throw new Error(`incorrect byte length! Want: 10, got ${buffer.byteLength}`);
}

const dataView = new DataView(buffer);
const version = dataView.getUint8(0);
const formatByte = dataView.getUint8(1);

let format;
switch (formatByte) {
case FileFormat.CSV:
format = FileFormat.CSV
break
case FileFormat.JSONL:
format = FileFormat.JSONL
break
default:
throw new Error(`invalid format: ${formatByte}`)
}

if (format !== FileFormat.CSV && format !== FileFormat.JSONL) {
throw new Error(`unexpected file format. Got: ${format}`);
if (Object.values(FileFormat).indexOf(formatByte) === -1) {
throw new Error(`unexpected file format. Got: ${formatByte}`);
}

const readOffset = dataView.getBigUint64(2);

return {
version: version,
format: format,
format: formatByte,
readOffset: readOffset,
};
}
Expand Down
9 changes: 5 additions & 4 deletions src/index-file/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@ export async function readFileMeta(buffer: ArrayBuffer): Promise<FileMeta> {
const dataView = new DataView(buffer);

const version = dataView.getUint8(0);
const format = dataView.getUint8(1);
const formatByte = dataView.getUint8(1);

if (format !== FileFormat.CSV && format !== FileFormat.JSONL) {
throw new Error(`unexpected file format. Got: ${format}`);
if (Object.values(FileFormat).indexOf(formatByte) === -1) {
throw new Error(`unexpected file format. Got: ${formatByte}`);
}


const readOffset = dataView.getBigUint64(2);

return {
version,
format,
format: formatByte,
readOffset,
};
}
Expand Down
Loading

0 comments on commit effbed4

Please sign in to comment.