Skip to content

Commit

Permalink
Merge pull request #14 from CRBroughton/enforce-alphabetical-order-fo…
Browse files Browse the repository at this point in the history
…r-responses-from-db

fix: 🐛 ensure insert re-corrects ordering of inputs
  • Loading branch information
CRBroughton authored Mar 10, 2024
2 parents d614469 + 7faf40f commit ff99c59
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 8 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ To create a new table (at the moment, it is recommended to only use one table),
use the `createTable` command:

```typescript
createTable('id int, name char, sex char, job char')
createTable('id int, job char, name char, sex char')
```

`createTable` takes a single argument; This argument will create the specified
columns for your database; It is vitally important that your columns match that of
your specified table row type you supply to Sibyl's root function, otherwise
you'll be unable to get data from your database, or crash your program.
your specified table row type you supply to Sibyl's root function, and that the entries
are in alphabetical order, otherwise
you'll be unable to get data from your database, have malformed data, or crash your program.

### Inserting entries into the DB

Expand Down
2 changes: 1 addition & 1 deletion playground/src/components/HelloWorld.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const { createTable, Insert, Select, All } = await Sibyl<tableRowType>(db, 'test
const myResults = ref<QueryExecResult>()
const selection = ref<tableRowType[]>()
createTable('id int, name char, sex char, job char')
createTable('id int, name char, job char, sex char')
let insertions: tableRowType[] = []
for (let index = 0; index < 1000; index++) {
Expand Down
15 changes: 14 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,20 @@ export async function Sibyl<T extends Record<string, any>>(db: Database, table:
db.run(`CREATE TABLE ${table} (${columns});`)
}

function sortKeys<T extends { [key: string]: any }>(arr: T[]): T[] {
return arr.map(obj => {
const sortedKeys = Object.keys(obj).sort()
const sortedObj: { [key: string]: any } = {}
sortedKeys.forEach(key => {
sortedObj[key] = obj[key]
})
return sortedObj as T
})
}

function Insert(table: string, structs: T[]) {
const flattenedInsert = structs.map(obj => Object.values(obj))
const sortedStructs = sortKeys(structs)
const flattenedInsert = sortedStructs.map(obj => Object.values(obj))
let insertions: string = ''
for (const insert of flattenedInsert) {
let row: T | string[] = []
Expand Down Expand Up @@ -106,5 +118,6 @@ export async function Sibyl<T extends Record<string, any>>(db: Database, table:
objectToWhereClause,
buildSelectQuery,
convertToObjects,
sortKeys,
}
}
4 changes: 2 additions & 2 deletions src/tests/all.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Sibyl } from '../index'

interface TableRow {
id: number
name: string
location: string
name: string
}

describe('all tests', () => {
Expand All @@ -19,7 +19,7 @@ describe('all tests', () => {
const db = new SQL.Database()
const { createTable, Insert, All } = await Sibyl<TableRow>(db, 'testingDB')

createTable('id int, name char, location char')
createTable('id int, location char, name char')
const insertion = Insert(DBName, [
{
id: 1,
Expand Down
26 changes: 25 additions & 1 deletion src/tests/insert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Sibyl } from '../index'

interface TableRow {
id: number
name: string
location: string
name: string
}

describe('insert tests', () => {
Expand Down Expand Up @@ -50,6 +50,30 @@ describe('insert tests', () => {
},
])

expect(actual).toStrictEqual('INSERT INTO test VALUES (1,"Brighton","Craig"); INSERT INTO test VALUES (2,"Cornwall","Bob");')
})
it('catches incorrect insert keys being the wrong way around and fixes itself', async () => {
const SQL = await sql({
locateFile: () => {
return 'playground/public/sql-wasm.wasm'
},
})
const db = new SQL.Database()
const { Insert } = await Sibyl<TableRow>(db, 'testing-DB')

const actual = Insert('test', [
{
id: 1,
name: 'Craig',
location: 'Brighton',
},
{
location: 'Cornwall',
id: 2,
name: 'Bob',
},
])

expect(actual).toStrictEqual('INSERT INTO test VALUES (1,"Brighton","Craig"); INSERT INTO test VALUES (2,"Cornwall","Bob");')
})
})
50 changes: 50 additions & 0 deletions src/tests/sortKeys.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, expect, it } from 'vitest'
import sql from 'sql.js'
import { Sibyl } from '../index'

interface TableRow {
id: number
name: string
location: string
}

describe('sortKeys tests', () => {
it('Formats a given set of array of objects alphabetically by their keys', async () => {
const DBName = 'testingDB'
const SQL = await sql({
locateFile: () => {
return 'playground/public/sql-wasm.wasm'
},
})
const db = new SQL.Database()
const { sortKeys } = await Sibyl<TableRow>(db, DBName)

const unsortedArray = [
{
name: 'Craig',
id: 1,
location: 'Brighton'
},
{
location: 'Cornwall',
name: 'Bob',
id: 2,
}
]
const actual = sortKeys(unsortedArray)

const expectation = [
{
id: 1,
location: 'Brighton',
name: 'Craig',
},
{
id: 2,
location: 'Cornwall',
name: 'Bob',
}
]
expect(actual).toStrictEqual(expectation)
})
})

0 comments on commit ff99c59

Please sign in to comment.