Skip to content

Commit ee624f6

Browse files
committed
🎉 more tests
1 parent 618da8d commit ee624f6

5 files changed

Lines changed: 127 additions & 45 deletions

File tree

__tests__/ddl.spec.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getDBConfig, getSpace } from './utils';
1+
import { getDBConfig, getSpace, getTable } from './utils';
22
import { QueryResult, SQParam } from '../src/skytable';
33

44
const testSpace = 'ddltestspace';
@@ -24,19 +24,51 @@ describe('DDL', () => {
2424
}
2525
});
2626

27-
// FIXME need to fix
27+
// FIXME need to fix. why need 'ALTER SPACE'?
2828
// it('ALTER SPACE', async () => {
2929
// const spaceName = `${testSpace + Date.now()}`;
3030
// try {
31-
// const isNotCreated = await db.query(`CREATE SPACE IF NOT EXISTS ${spaceName}`);
32-
33-
// if (isNotCreated) {
34-
// await db.query(`CREATE SPACE ${spaceName} WITH { property_name: ? }`, 1234);
35-
// }
31+
// await db.query(`CREATE SPACE IF NOT EXISTS ${spaceName} WITH { property_name: ? }`, 123);
3632

3733
// expect(await db.query(`ALTER SPACE ${spaceName} WITH { property_name: ? }`, 456)).toBe(null);
3834
// } finally {
3935
// await db.query(`DROP SPACE ALLOW NOT EMPTY ${spaceName}`);
4036
// }
4137
// })
38+
39+
it('CREATE MODEL', async () => {
40+
const [space, drop] = await getSpace(db, `${testSpace + Date.now()}`);
41+
const tableName = `${space}.testTable${Date.now()}`;
42+
43+
try {
44+
await db.query(`CREATE MODEL ${tableName}(id: string, name: string)`);
45+
46+
expect(
47+
await db.query(
48+
`CREATE MODEL IF NOT EXISTS ${tableName}(id: string, name: string)`,
49+
),
50+
).toBe(false);
51+
} finally {
52+
await drop();
53+
}
54+
});
55+
56+
it('ALTER MODEL', async () => {
57+
const [tableName, drop] = await getTable(db);
58+
59+
try {
60+
await db.query(`CREATE MODEL ${tableName}(id: string, name: string)`);
61+
await db.query(`ALTER MODEL ${tableName} ADD field { type: uint8 }`);
62+
await db.query(
63+
`ALTER MODEL ${tableName} ADD ( first_field { type: string }, second_field { type: binary } )`,
64+
);
65+
66+
await db.query(`ALTER MODEL ${tableName} UPDATE field { type: uint64 }`);
67+
await db.query(
68+
`ALTER MODEL ${tableName} REMOVE (first_field, second_field)`,
69+
);
70+
} finally {
71+
await drop();
72+
}
73+
});
4274
});

__tests__/dml.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Rows } from '../src/skytable';
12
import { getDBConfig, getTable } from './utils';
23

34
describe('DML', () => {
@@ -90,4 +91,32 @@ describe('DML', () => {
9091
await drop();
9192
}
9293
});
94+
95+
it('Multirow', async () => {
96+
const [tableName, drop] = await getTable(db);
97+
98+
try {
99+
await db.query(`CREATE MODEL ${tableName}(id: string, name: string )`);
100+
for (let i = 0; i < 10; i++) {
101+
await db.query(`INSERT INTO ${tableName}(?, ?)`, String(i), 'test');
102+
}
103+
const rows = (await db.query(
104+
`SELECT ALL * FROM ${tableName} LIMIT ?`,
105+
10,
106+
)) as Rows;
107+
108+
expect(
109+
rows.sort((row1, row2) =>
110+
Number(row1[0] as string) > Number(row2[0] as string) ? 1 : -1,
111+
),
112+
).toEqual([
113+
...Array.from({ length: 10 }).map((_, index) => [
114+
String(index),
115+
'test',
116+
]),
117+
]);
118+
} finally {
119+
await drop();
120+
}
121+
});
93122
});

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
export { Config } from './config';
2+
3+
export * from './skytable';
4+
5+
export * from './protocol';

src/protocol.ts

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -110,63 +110,68 @@ function getFirstSplitOffset(buffer: Buffer, split = '\n'): number {
110110
return -1;
111111
}
112112

113-
function parseNumberNext<T = number>(
113+
function parseNumber<T = number>(
114114
formatFn: (string: string) => T,
115115
buffer: Buffer,
116-
): Column[] {
116+
): [T, Buffer] {
117117
const offset = getFirstSplitOffset(buffer);
118118
const val = formatFn(buffer.subarray(0, offset).toString('utf-8'));
119119

120-
return parseNext(val, buffer.subarray(offset + 1));
120+
return [val, buffer.subarray(offset + 1)];
121121
}
122122

123-
function parseNext(val: any, buffer: Buffer): Column[] {
124-
return [val, ...parseSkytableData(buffer)];
125-
}
123+
function parseNextBySize(size: number, buffer: Buffer): [Column[], Buffer] {
124+
let values = [];
125+
let nextBuffer = buffer;
126126

127-
function parseSkytableData(buffer: Buffer): Column[] {
128-
if (!buffer.length) {
129-
return [];
127+
for (let i = 0; i < size; i++) {
128+
const [value, remainingBuffer] = parseSingleVal(nextBuffer);
129+
values.push(value);
130+
nextBuffer = remainingBuffer;
130131
}
131132

133+
return [values, nextBuffer];
134+
}
135+
136+
function parseSingleVal(buffer: Buffer): [Column, Buffer] {
132137
const type = buffer.readUInt8(0);
133138
buffer = buffer.subarray(1);
134139

135140
switch (type) {
136141
case RESPONSES_RESULT.NULL: // Null
137-
return parseNext(null, buffer.subarray(0));
142+
return [null, buffer.subarray(0)];
138143
case RESPONSES_RESULT.BOOL: // Bool
139-
return parseNext(Boolean(buffer.readUInt8(0)), buffer.subarray(1));
144+
return [Boolean(buffer.readUInt8(0)), buffer.subarray(1)];
140145
case RESPONSES_RESULT.U8INT: // 8-bit Unsigned Integer
141-
return parseNumberNext(Number, buffer);
146+
return parseNumber(Number, buffer);
142147
case RESPONSES_RESULT.U16INT: // 16-bit Unsigned Integer
143-
return parseNumberNext(Number, buffer);
148+
return parseNumber(Number, buffer);
144149
case RESPONSES_RESULT.U32INT: // 32-bit Unsigned Integer
145-
return parseNumberNext(Number, buffer);
150+
return parseNumber(Number, buffer);
146151
case RESPONSES_RESULT.U64INT: // 64-bit Unsigned Integer
147-
return parseNumberNext<bigint>(BigInt, buffer);
152+
return parseNumber<bigint>(BigInt, buffer);
148153
case RESPONSES_RESULT.S8INT: // 8-bit Signed Integer
149-
return parseNumberNext(Number, buffer);
154+
return parseNumber(Number, buffer);
150155
case RESPONSES_RESULT.S16INT: // 16-bit Signed Integer
151-
return parseNumberNext(Number, buffer);
156+
return parseNumber(Number, buffer);
152157
case RESPONSES_RESULT.S32INT: // 32-bit Signed Integer
153-
return parseNumberNext(Number, buffer);
158+
return parseNumber(Number, buffer);
154159
case RESPONSES_RESULT.S64INT: // 64-bit Signed Integer
155-
return parseNumberNext<bigint>(BigInt, buffer);
160+
return parseNumber<bigint>(BigInt, buffer);
156161
case RESPONSES_RESULT.FLOAT32: // f32
157-
return parseNumberNext(Number.parseFloat, buffer);
162+
return parseNumber(Number.parseFloat, buffer);
158163
case RESPONSES_RESULT.FLOAT64: // f64
159-
return parseNumberNext(Number.parseFloat, buffer);
164+
return parseNumber(Number.parseFloat, buffer);
160165
case RESPONSES_RESULT.BINARY: {
161166
// Binary <size>\n<payload>,
162167
const sizeOffset = getFirstSplitOffset(buffer);
163168
const size = Number(buffer.subarray(0, sizeOffset).toString('utf-8'));
164169
if (size === 0) {
165-
return parseNext(Buffer.from([]), buffer.subarray(sizeOffset + 1));
170+
return [Buffer.from([]), buffer.subarray(sizeOffset + 1)];
166171
}
167172
const [start, end] = [sizeOffset + 1, sizeOffset + 1 + Number(size)];
168173

169-
return parseNext(buffer.subarray(start, end), buffer.subarray(end));
174+
return [buffer.subarray(start, end), buffer.subarray(end)];
170175
}
171176
case RESPONSES_RESULT.STRING: {
172177
// String <size>\n<body>
@@ -175,16 +180,20 @@ function parseSkytableData(buffer: Buffer): Column[] {
175180
const [start, end] = [sizeOffset + 1, sizeOffset + 1 + Number(size)];
176181
const str = buffer.subarray(start, end).toString('utf-8');
177182

178-
return parseNext(str, buffer.subarray(end));
183+
return [str, buffer.subarray(end)];
179184
}
180185
case RESPONSES_RESULT.LIST: {
181186
// List <size>\n<body>
182187
const sizeOffset = getFirstSplitOffset(buffer);
183188
const size = Number(buffer.subarray(0, sizeOffset).toString('utf-8'));
184189
if (size === 0) {
185-
return parseNext([], buffer.subarray(sizeOffset + 1));
190+
return [[], buffer.subarray(sizeOffset + 1)];
186191
}
187-
return [parseSkytableData(buffer.subarray(sizeOffset + 1)) as Column];
192+
193+
return parseNextBySize(size, buffer.subarray(sizeOffset + 1)) as [
194+
Column,
195+
Buffer,
196+
];
188197
}
189198
default:
190199
throw new Error(`Unknown data type: ${type}`);
@@ -193,10 +202,12 @@ function parseSkytableData(buffer: Buffer): Column[] {
193202

194203
export function formatRow(buffer: Buffer): Row {
195204
const offset = getFirstSplitOffset(buffer);
196-
// const columnCount = Number(buffer.subarray(0, offset).toString("utf-8"))
205+
const columnCount = Number(buffer.subarray(0, offset).toString('utf-8'));
197206
const dataType = buffer.subarray(offset + 1);
198207

199-
return parseSkytableData(dataType);
208+
const [row] = parseNextBySize(columnCount, dataType);
209+
210+
return row;
200211
}
201212

202213
export function formatRows(buffer: Buffer): Rows {
@@ -209,15 +220,17 @@ export function formatRows(buffer: Buffer): Rows {
209220
const columnCount = Number(
210221
buffer.subarray(0, columnOffset).toString('utf-8'),
211222
);
212-
const tableData: Column[] = parseSkytableData(buffer.subarray(offset + 1));
223+
224+
buffer = buffer.subarray(columnOffset + 1);
213225

214226
const result: Rows = [];
227+
let nextBuffer = buffer;
215228

216229
for (let i = 0; i < rowCount; i++) {
217-
result[i] = [];
218-
for (let j = 0; j < columnCount; j++) {
219-
result[i][j] = tableData[i * columnCount + j];
220-
}
230+
const [row, remainingBuffer] = parseNextBySize(columnCount, nextBuffer);
231+
232+
result[i] = row;
233+
nextBuffer = remainingBuffer;
221234
}
222235

223236
return result;
@@ -239,9 +252,9 @@ export function formatResponse(buffer: Buffer): QueryResult {
239252
);
240253
default:
241254
if (isResponsesResult(type)) {
242-
const result = parseSkytableData(buffer);
243-
// FIXME to be better
244-
return result?.[0];
255+
const [val] = parseSingleVal(buffer);
256+
257+
return val;
245258
}
246259
throw new TypeError('unknown response type');
247260
}

src/skytable.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,19 @@ export type ConnectionOptions = {
1010

1111
export type ConnectionTlsOptions = ConnectionOptions & { certFile: string };
1212

13-
type ColumnBase = string | number | boolean | null | bigint;
13+
export type ColumnBase = string | number | boolean | null | bigint;
1414

1515
export type SQParam<T = ColumnBase> = T | SQParam<T>[];
1616

1717
export type ColumnBinary = typeof Buffer;
1818

1919
export type ColumnList<T> = T | ColumnList<T>[];
2020

21-
export type Column = ColumnBase | ColumnBinary | ColumnList<ColumnBase>;
21+
export type Column =
22+
| Buffer
23+
| ColumnBase
24+
| ColumnBinary
25+
| ColumnList<ColumnBase>;
2226

2327
export type Row = Column[];
2428

0 commit comments

Comments
 (0)