Skip to content

Commit 1b793d8

Browse files
Add .map and .reduce on SQLiteCloudRowset
1 parent 9089d08 commit 1b793d8

File tree

5 files changed

+106
-25
lines changed

5 files changed

+106
-25
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sqlitecloud-js",
3-
"version": "0.0.25",
3+
"version": "0.0.26",
44
"description": "SQLiteCloud drivers for Typescript/Javascript in edge, web and node clients",
55
"main": "./lib/index.js",
66
"types": "./lib/index.d.ts",

src/connection.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ function parseRowset(buffer: Buffer, spaceIndex: number): SQLiteCloudRowset {
567567
buffer = fwdBuffer
568568
}
569569

570+
console.assert(data && data.length === metadata.numberOfRows * metadata.numberOfColumns, 'SQLiteCloudConnection.parseRowset - invalid rowset data')
570571
return new SQLiteCloudRowset(metadata, data)
571572
}
572573

@@ -606,6 +607,7 @@ function parseRowsetChunks(buffers: Buffer[]) {
606607
}
607608
}
608609

610+
console.assert(data && data.length === metadata.numberOfRows * metadata.numberOfColumns, 'SQLiteCloudConnection.parseRowsetChunks - invalid rowset data')
609611
return new SQLiteCloudRowset(metadata, data)
610612
}
611613

src/rowset.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,9 @@ export class SQLiteCloudRow {
3030
export class SQLiteCloudRowset extends Array<SQLiteCloudRow> {
3131
constructor(metadata: SQLCloudRowsetMetadata, data: any[]) {
3232
super(metadata.numberOfRows)
33-
console.assert(data.length === metadata.numberOfRows * metadata.numberOfColumns, 'Invalid rowset data')
34-
console.assert(metadata.columns.length === metadata.numberOfColumns, 'Invalid columns metadata')
35-
console.assert(
36-
metadata.numberOfRows >= 0 && metadata.numberOfColumns >= 0,
37-
`Invalid rowset dimensions ${metadata.numberOfRows} x ${metadata.numberOfColumns}`
38-
)
33+
34+
// console.assert(data !== undefined && data.length === metadata.numberOfRows * metadata.numberOfColumns, 'Invalid rowset data')
35+
// console.assert(metadata !== undefined && metadata.columns.length === metadata.numberOfColumns, 'Invalid columns metadata')
3936

4037
this.#metadata = metadata
4138
this.#data = data
@@ -113,6 +110,32 @@ export class SQLiteCloudRowset extends Array<SQLiteCloudRow> {
113110

114111
const slicedMetadata = { ...this.#metadata, numberOfRows: end - start }
115112
const slicedData = this.#data.slice(start * this.numberOfColumns, end * this.numberOfColumns)
113+
114+
console.assert(
115+
slicedData && slicedData.length === slicedMetadata.numberOfRows * slicedMetadata.numberOfColumns,
116+
'SQLiteCloudRowset.slice - invalid rowset data'
117+
)
116118
return new SQLiteCloudRowset(slicedMetadata, slicedData)
117119
}
120+
121+
map(fn: (row: SQLiteCloudRow, index: number, rowset: SQLiteCloudRow[]) => any): any[] {
122+
const results: any[] = []
123+
for (let i = 0; i < this.numberOfRows; i++) {
124+
const row = this[i]
125+
results.push(fn(row, i, this))
126+
}
127+
return results
128+
}
129+
130+
/** Returns an instance of SQLiteCloudRowset where rows have been filtered via given callback */
131+
filter(fn: (row: SQLiteCloudRow, index: number, rowset: SQLiteCloudRow[]) => boolean): SQLiteCloudRow[] {
132+
const filteredData: any[] = []
133+
for (let i = 0; i < this.numberOfRows; i++) {
134+
const row = this[i]
135+
if (fn(row, i, this)) {
136+
filteredData.push(...this.#data.slice(i * this.numberOfColumns, (i + 1) * this.numberOfColumns))
137+
}
138+
}
139+
return new SQLiteCloudRowset({ ...this.#metadata, numberOfRows: filteredData.length / this.numberOfColumns }, filteredData)
140+
}
118141
}

test/connection.test.ts

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -280,25 +280,29 @@ describe('connection', () => {
280280
})
281281

282282
describe('operations', () => {
283-
it('should serialize operations', done => {
284-
const numQueries = 20
285-
let completed = 0
283+
it(
284+
'should serialize operations',
285+
done => {
286+
const numQueries = 20
287+
let completed = 0
286288

287-
for (let i = 0; i < numQueries; i++) {
288-
chinook.sendCommands(`select ${i} as "count", 'hello' as 'string'`, (error, results) => {
289-
expect(error).toBeNull()
290-
expect(results.numberOfColumns).toBe(2)
291-
expect(results.numberOfRows).toBe(1)
292-
expect(results.version == 1 || results.version == 2).toBeTruthy()
293-
expect(results.columnsNames).toEqual(['count', 'string'])
294-
expect(results.getItem(0, 0)).toBe(i)
289+
for (let i = 0; i < numQueries; i++) {
290+
chinook.sendCommands(`select ${i} as "count", 'hello' as 'string'`, (error, results) => {
291+
expect(error).toBeNull()
292+
expect(results.numberOfColumns).toBe(2)
293+
expect(results.numberOfRows).toBe(1)
294+
expect(results.version == 1 || results.version == 2).toBeTruthy()
295+
expect(results.columnsNames).toEqual(['count', 'string'])
296+
expect(results.getItem(0, 0)).toBe(i)
295297

296-
if (++completed >= numQueries) {
297-
done()
298-
}
299-
})
300-
}
301-
})
298+
if (++completed >= numQueries) {
299+
done()
300+
}
301+
})
302+
}
303+
},
304+
LONG_TIMEOUT
305+
)
302306

303307
it('should apply short timeout', done => {
304308
// this operation sends 150 packets and cannot complete in 20ms

test/rowset.test.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* rowset.test.ts - test rowset container
33
*/
44

5-
import { SQLiteCloudRowset } from '../src/index'
5+
import { SQLiteCloudRowset, SQLiteCloudRow } from '../src/index'
66
import { SQLiteCloudConnection } from '../src/connection'
77
import { CHINOOK_DATABASE_URL, getChinookConnection, getChinookConfig } from './shared'
88

@@ -34,6 +34,58 @@ describe('rowset', () => {
3434
})
3535
})
3636

37+
it('implements .map', done => {
38+
const connection = getChinookConnection()
39+
connection.sendCommands('SELECT * FROM tracks LIMIT 10;', (error, rowset) => {
40+
expect(rowset).toBeInstanceOf(SQLiteCloudRowset)
41+
expect(rowset.numberOfColumns).toBe(9)
42+
expect(rowset.numberOfRows).toBe(10)
43+
expect(Array.isArray(rowset)).toBeTruthy()
44+
expect(rowset).toHaveLength(10)
45+
46+
rowset.map((row: SQLiteCloudRow) => {
47+
expect(row).toBeInstanceOf(SQLiteCloudRow)
48+
expect(Object.keys(row)).toHaveLength(9)
49+
})
50+
51+
connection.close()
52+
done()
53+
})
54+
})
55+
56+
it('implements .filter', done => {
57+
const connection = getChinookConnection()
58+
connection.sendCommands('SELECT * FROM tracks LIMIT 10;', (error, rowset) => {
59+
expect(rowset).toBeInstanceOf(SQLiteCloudRowset)
60+
expect(rowset.numberOfColumns).toBe(9)
61+
expect(rowset.numberOfRows).toBe(10)
62+
expect(Array.isArray(rowset)).toBeTruthy()
63+
expect(rowset).toHaveLength(10)
64+
65+
const filtered = rowset.filter((row: SQLiteCloudRow) => row.AlbumId === 1)
66+
expect(filtered).toBeInstanceOf(SQLiteCloudRowset)
67+
expect(filtered.numberOfColumns).toBe(9)
68+
expect(filtered.numberOfRows).toBe(6)
69+
70+
connection.close()
71+
done()
72+
})
73+
})
74+
75+
it('implements .reduce', done => {
76+
const connection = getChinookConnection()
77+
connection.sendCommands('SELECT * FROM invoices;', (error, rowset) => {
78+
expect(rowset).toBeInstanceOf(SQLiteCloudRowset)
79+
80+
// doing "SELECT sum(Total) FROM invoices" the wrong way (not using SQL) to test reduce...
81+
const total = rowset.reduce((acc: number, row: SQLiteCloudRow) => acc + (row?.Total ? (row.Total as number) : 0), 0)
82+
expect(Math.floor(total)).toBe(2328)
83+
84+
connection.close()
85+
done()
86+
})
87+
})
88+
3789
it('can be sliced like an array', done => {
3890
const connection = getChinookConnection()
3991
connection.sendCommands('SELECT * FROM tracks LIMIT 50;', (error, rowset) => {

0 commit comments

Comments
 (0)