Skip to content

Commit

Permalink
support isolation level (#24)
Browse files Browse the repository at this point in the history
* support isolation level

* update

* add test
  • Loading branch information
shiyuhang0 authored Oct 18, 2023
1 parent 7c3b2d6 commit df70faf
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 15 deletions.
12 changes: 12 additions & 0 deletions integration-test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,17 @@ describe('basic', () => {
const row = r[0] as Record<string, any>
expect(row.first_name).toEqual('base')
})

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

const tx = await con.begin({isolation:"READ COMMITTED"})
const result1 = await tx.execute(`select * from ${table}`) as Row[]
await con.execute(`insert into ${table} values (1, '\\"John\\"', 'Doe')`)
const result2 = await tx.execute(`select * from ${table}`) as Row[]
await tx.commit()
expect(result1.length+1).toEqual(result2.length)
})
})

4 changes: 4 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ export interface ExecuteOptions {
fullResult?: boolean
}

export interface TxOptions {
isolation?: 'READ COMMITTED' | 'REPEATABLE READ'
}

export type ExecuteArgs = object | any[] | null
24 changes: 17 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { format } from './format.js'
import { cast } from './decode.js'
import { DatabaseError } from './error.js'
import { Config, ExecuteOptions, ExecuteArgs } from './config.js'
import { Config, ExecuteOptions, ExecuteArgs, TxOptions } from './config.js'
import { postQuery } from './serverless.js'

export { Config, ExecuteOptions, ExecuteArgs, DatabaseError }
Expand Down Expand Up @@ -45,8 +45,13 @@ export class Tx {
this.conn = conn
}

async execute(query: string, args: ExecuteArgs = null, options: ExecuteOptions = defaultExecuteOptions): Promise<FullResult | Row[]> {
return this.conn.execute(query, args, options)
async execute(
query: string,
args: ExecuteArgs = null,
options: ExecuteOptions = defaultExecuteOptions,
txOptions: TxOptions = {}
): Promise<FullResult | Row[]> {
return this.conn.execute(query, args, options, txOptions)
}

async commit(): Promise<FullResult | Row[]> {
Expand Down Expand Up @@ -87,17 +92,22 @@ export class Connection {
}
}

async begin(): Promise<Tx> {
async begin(txOptions: TxOptions = {}): Promise<Tx> {
const conn = new Connection(this.config)
const tx = new Tx(conn)
await tx.execute('BEGIN')
await tx.execute('BEGIN', undefined, undefined, txOptions)
return tx
}

async execute(query: string, args: ExecuteArgs = null, options: ExecuteOptions = defaultExecuteOptions): Promise<FullResult | Row[]> {
async execute(
query: string,
args: ExecuteArgs = null,
options: ExecuteOptions = defaultExecuteOptions,
txOptions: TxOptions = {}
): Promise<FullResult | Row[]> {
const sql = args ? format(query, args) : query
const body = JSON.stringify({ query: sql })
const resp = await postQuery<QueryExecuteResponse>(this.config, body, this.session ?? '')
const resp = await postQuery<QueryExecuteResponse>(this.config, body, this.session ?? '', sql == 'BEGIN' ? txOptions.isolation : null)

this.session = resp?.session ?? null
if (this.session === null || this.session === '') {
Expand Down
20 changes: 12 additions & 8 deletions src/serverless.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Config } from './config.js'
import { DatabaseError } from './error.js'
import { Version } from './version.js'
export async function postQuery<T>(config: Config, body, session = ''): Promise<T> {
export async function postQuery<T>(config: Config, body, session = '', isolationLevel = null): Promise<T> {
let fetchCacheOption: Record<string, any> = { cache: 'no-store' }
// Cloudflare Workers does not support cache now https://github.com/cloudflare/workerd/issues/69
try {
Expand All @@ -14,16 +14,20 @@ export async function postQuery<T>(config: Config, body, session = ''): Promise<
const auth = btoa(`${config.username}:${config.password}`)
const { fetch } = config
const database = config.database ?? ''
const headers = {
'Content-Type': 'application/json',
'User-Agent': `serverless-js/${Version}`,
Authorization: `Basic ${auth}`,
'TiDB-Database': database,
'TiDB-Session': session
}
if (isolationLevel) {
headers['TiDB-Isolation-Level'] = isolationLevel
}
const response = await fetch(url.toString(), {
method: 'POST',
body: body,
headers: {
'Content-Type': 'application/json',
'User-Agent': `serverless-js/${Version}`,
Authorization: `Basic ${auth}`,
'TiDB-Database': database,
'TiDB-Session': session
},
headers,
...fetchCacheOption
})

Expand Down

0 comments on commit df70faf

Please sign in to comment.