Skip to content

Commit

Permalink
Add test and optimize readme (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
shiyuhang0 authored Aug 11, 2023
1 parent dcaf1f8 commit 04533c4
Show file tree
Hide file tree
Showing 12 changed files with 541 additions and 68 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Integration Test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: |
npm ci
export DATABASE_URL=${{ secrets.DATABASE_URL }}
npm run integrationTest
28 changes: 28 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Lint

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
- run: |
npm run lint -- --fix
if [ "$(git diff | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes. See status below:"
git diff
exit 1
fi
43 changes: 0 additions & 43 deletions .github/workflows/test.yml

This file was deleted.

23 changes: 23 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Unit Test

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: |
npm ci
npm test
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

This driver is for serverless and edge compute platforms that require HTTP external connections, such as Vercel Edge Functions or Cloudflare Workers.


## Installation

```
Expand Down Expand Up @@ -126,3 +127,55 @@ const config = {
const conn = connect(config)
const results = await conn.execute('select 1 from test',null,{arrayMode:true,fullResult:true})
```

## Features

### Supported SQL

The following SQL statements are supported: `Select`, `Show`, `Explain`, `Use`, `Insert`, `Update`, `Delete`, `Begin`, `Commit`, `Rollback`.

And most of the DDL are supported.

### Data Type Mapping

The type mapping between TiDB and Javascript is as follows:

| TiDB Type | Javascript Type |
|-------------------|-----------------|
| TINYINT | number |
| UNSIGNED TINYINT | number |
| BOOL | number |
| SMALLINT | number |
| UNSIGNED SMALLINT | number |
| MEDIUMINT | number |
| INT | number |
| UNSIGNED INT | number |
| YEAR | number |
| FLOAT | number |
| DOUBLE | number |
| BIGINT | string |
| UNSIGNED BIGINT | string |
| DECIMAL | string |
| CHAR | string |
| VARCHAR | string |
| BINARY | string |
| VARBINARY | string |
| TINYTEXT | string |
| TEXT | string |
| MEDIUMTEXT | string |
| LONGTEXT | string |
| TINYBLOB | string |
| BLOB | string |
| MEDIUMBLOB | string |
| LONGBLOB | string |
| DATE | string |
| TIME | string |
| DATETIME | string |
| TIMESTAMP | string |
| ENUM | string |
| SET | string |
| BIT | string |
| JSON | any |
| Others | string |

> The following types can not be distinguished between empty string and null if it is nullable: `CHAR`, `VARCHAR`, `BINARY`, `VARBINARY`, `TINYTEXT`, `TEXT`, `MEDIUMTEXT`, `LONGTEXT`, `TINYBLOB`, `BLOB`, `MEDIUMBLOB`, `LONGBLOB`, `ENUM`, `SET`, `BIT`.
1 change: 1 addition & 0 deletions __tests__/decode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ describe('decode', () => {
describe('cast', () => {

})

})
130 changes: 130 additions & 0 deletions integration-test/basic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { connect,Row,FullResult } from '../dist/index'
import { fetch } from 'undici'
import * as dotenv from 'dotenv';

let databaseURL
const database = 'test_serverless_basic'
const table = 'employee'

const EmployeeTable = `CREATE TABLE ${database}.${table} (emp_no INT,first_name VARCHAR(255),last_name VARCHAR(255))`

beforeAll(async () => {
dotenv.config();
databaseURL = process.env.DATABASE_URL
const con = connect({url: databaseURL, fetch})
await con.execute(`DROP DATABASE IF EXISTS ${database}`)
await con.execute(`CREATE DATABASE ${database}`)
await con.execute(EmployeeTable)
await con.execute(`insert into ${database}.${table} values (0, 'base', 'base')`)
});

describe('basic', () => {
test('ddl', async () => {
const con = connect({url: databaseURL, database: database, fetch})
const results = await con.execute(`SHOW TABLES`)
expect(JSON.stringify(results)).toContain(`${table}`)
})

test('dml', async () => {
const con = connect({url: databaseURL, database: database, fetch})
await con.execute(`delete from ${table} where emp_no = 1`)

await con.execute(`insert into ${table} values (1, 'John', 'Doe')`)
const result1 = await con.execute(`select * from ${table} where emp_no = 1`)
expect(JSON.stringify(result1)).toContain('John')
await con.execute(`update ${table} set first_name = 'Jane' where emp_no = 1`)
const result2 = await con.execute(`select * from ${table} where emp_no = 1`)
expect(JSON.stringify(result2)).toContain('Jane')
await con.execute(`delete from ${table} where emp_no = 1`)
const result3 = await con.execute(`select * from ${table} where emp_no = 1`) as Row[]
expect(result3.length).toEqual(0)
})

test('option', async () => {
const con = connect({url: databaseURL, database: database, fetch})
const result1 = await con.execute(`select * from ${table} where emp_no=0`,null, {arrayMode: true})
expect(result1 instanceof Array).toEqual(true)

const result2 = await con.execute(`select * from ${table} where emp_no=0`,null, {fullResult: true})
expect(result2 instanceof Array).toEqual(false)
const except: FullResult = {
statement: `select * from ${table} where emp_no=0`,
types:{
emp_no: 'INT',
first_name: 'VARCHAR',
last_name: 'VARCHAR'
},
rows: [{
emp_no: 0,
first_name: 'base',
last_name: 'base'
}],
rowsAffected: 0,
lastInsertId: null,
rowCount: 1
}
expect(JSON.stringify(result2)).toEqual(JSON.stringify(except))
})

test('query with escape', async () => {
const con = connect({url: databaseURL, database: database, fetch})
await con.execute(`delete from ${table} where emp_no = 1 or emp_no = 2`)
await con.execute(`insert into ${table} values (1, '\\'John\\'', 'Doe')`)
await con.execute(`insert into ${table} values (2, '\\"John\\"', 'Doe')`)

// "select * from employee where first_name = '\\'John\\''"
const r1 = await con.execute('select * from employee where first_name = ?',["'John'"]) as Row[]
// 'select * from employee where first_name = \'\\"John\\"\''
const r2 = await con.execute('select * from employee where first_name =:name',{name: '"John"'}) as Row[]
expect(r1.length).toEqual(1)
expect(r2.length).toEqual(1)
const row1 = r1[0] as Record<string, any>
const row2 = r2[0] as Record<string, any>
expect(row1.emp_no).toEqual(1)
expect(row2.emp_no).toEqual(2)
})

test('transaction isolation', async () => {
const con = connect({url: databaseURL, database: database, fetch})
await con.execute(`delete from ${table} where emp_no = 1`)
let tx
try{
tx = await con.begin()
await tx.execute(`insert into ${table} values (1, 'John', 'Doe')`)
const r1 = await tx.execute(`select * from ${table} where emp_no = 1`) as Row[]
const r2 = await con.execute(`select * from ${table} where emp_no = 1`) as Row[]
expect(r1.length).toEqual(1)
expect(r2.length).toEqual(0)
await tx.commit()
} catch (e) {
if (tx){
tx.rollback()
}
throw e
}
})

test('transaction rollback', async () => {
const con = connect({url: databaseURL, database: database, fetch})
await con.execute(`delete from ${table} where emp_no = 1`)

let tx
try {
const tx = await con.begin()
await tx.execute(`insert into ${table} values (1, 'John', 'Doe')`)
await tx.execute(`update ${table} set first_name = 'Jane' where emp_no = 0`)
await tx.rollback()
} catch (e) {
if (tx){
tx.rollback()
}
throw e
}

const r = await con.execute(`select * from ${table} where emp_no = 0 or emp_no = 1`) as Row[]
expect(r.length).toEqual(1)
const row = r[0] as Record<string, any>
expect(row.first_name).toEqual('base')
})
})

Loading

0 comments on commit 04533c4

Please sign in to comment.