Comparing version 0.4.0 to 0.5.0
{ | ||
"name": "zol", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Type safe composable SQL abstraction layer", | ||
@@ -40,3 +40,4 @@ "keywords": [ | ||
"devDependencies": { | ||
"pg": ">=7.0.2 <8", | ||
"@types/node": "12.7.11", | ||
"pg": ">=8 <9", | ||
"rimraf": "2.6.2", | ||
@@ -50,8 +51,8 @@ "rollup": "0.51.7", | ||
"dependencies": { | ||
"@types/pg": ">=7.1.0 <=7.4.11", | ||
"@types/pg": ">=8 <9", | ||
"pg-cursor": ">=2.0.0 <3" | ||
}, | ||
"peerDependencies": { | ||
"pg": ">=7.0.2 <8" | ||
"pg": ">=8 <9" | ||
} | ||
} |
import * as pgLib from "pg"; | ||
import { QueryResult } from "pg"; | ||
import { StreamingRows } from "./StreamingRows"; | ||
@@ -30,6 +31,19 @@ | ||
/** | ||
* Don't do any parsing of Postgres values, just leave them as a string | ||
*/ | ||
function identityTypeParser(val: string) { | ||
return val; | ||
} | ||
export function runCustomQuery(conn: pgLib.Client, propNames: string[], propParsers: ((val: string) => any)[], text: string, values: any): Promise<any[]> { | ||
return new Promise<any[]>((resolve, reject) => { | ||
const customQuery = new CustomQuery(propNames, propParsers, text, values, (err: any) => { | ||
conn.query({ | ||
text: text, | ||
values: values, | ||
rowMode: "array", | ||
types: { | ||
getTypeParser: () => identityTypeParser | ||
} | ||
}, (err: any, result: QueryResult) => { | ||
if (<boolean>err) { | ||
@@ -41,114 +55,90 @@ err.query = text; | ||
if (customQuery.parseError !== null) { | ||
reject(new ColumnParseError( | ||
customQuery.parseError.message, | ||
text, | ||
customQuery.parseErrorValue, | ||
customQuery.parseErrorParseFunction, | ||
customQuery.parseError)); | ||
return; | ||
const resultRows = result.rows; | ||
const resultRowsLength = resultRows.length; | ||
const numFields = propNames.length; | ||
const rows = []; | ||
for (let i = 0; i < resultRowsLength; ++i) { | ||
const row = resultRows[i]; | ||
const newRow: any = {}; | ||
for (let j = 0; j < numFields; ++j) { | ||
const colValue = row[j]; | ||
// This try block is more broad than necessary.. we only expect | ||
// an error to happen inside the call to: | ||
// | ||
// this.propParsers[i](..) | ||
// | ||
// But it is left as it is for efficiency. The other fragments | ||
// of code cannot possibly throw an Error (famous last words) | ||
try { | ||
newRow[propNames[j]] = | ||
colValue !== null | ||
? propParsers[j](colValue) | ||
: null; | ||
} catch (e) { | ||
reject(new ColumnParseError( | ||
e.message, | ||
text, | ||
row[j], | ||
propParsers[j].name, | ||
e)); | ||
return; | ||
} | ||
} | ||
rows.push(newRow); | ||
} | ||
resolve(customQuery.rows); | ||
resolve(rows); | ||
}); | ||
conn.query(customQuery); | ||
}); | ||
} | ||
const CustomQuery: any = function(this: any, propNames: any, propParsers: any, text: any, values: any, callback: any) { | ||
pgLib.Query.call(this, text, values, callback); | ||
export function runCustomQueryStreaming(conn: pgLib.Client, propNames: string[], propParsers: ((val: string) => any)[], text: string, values: any, rowChunkSize: number): Promise<StreamingRows<any>> { | ||
function parseRows(resultRows: any[]): any[] { | ||
const resultRowsLength = resultRows.length; | ||
const numFields = propNames.length; | ||
this.parseError = null; | ||
this.propNames = propNames; | ||
this.propParsers = propParsers; | ||
this.numFields = this.propNames.length; | ||
this.rows = []; | ||
}; | ||
CustomQuery.prototype = Object.create(pgLib.Query.prototype); | ||
CustomQuery.prototype.constructor = CustomQuery; | ||
const rows = []; | ||
CustomQuery.prototype.handleRowDescription = function(this: any) { | ||
// Ignore | ||
}; | ||
for (let i = 0; i < resultRowsLength; ++i) { | ||
const row = resultRows[i]; | ||
const newRow: any = {}; | ||
for (let j = 0; j < numFields; ++j) { | ||
const colValue = row[j]; | ||
// This try block is more broad than necessary.. we only expect | ||
// an error to happen inside the call to: | ||
// | ||
// this.propParsers[i](..) | ||
// | ||
// But it is left as it is for efficiency. The other fragments | ||
// of code cannot possibly throw an Error (famous last words) | ||
try { | ||
newRow[propNames[j]] = | ||
colValue !== null | ||
? propParsers[j](colValue) | ||
: null; | ||
} catch (e) { | ||
throw new ColumnParseError( | ||
e.message, | ||
text, | ||
row[j], | ||
propParsers[j].name, | ||
e); | ||
} | ||
} | ||
rows.push(newRow); | ||
} | ||
CustomQuery.prototype.handleDataRow = function(this: any, msg: any) { | ||
if (this.parseError !== null) { | ||
return; | ||
return rows; | ||
} | ||
const newRow: any = {}; | ||
for (let i = 0; i < this.numFields; ++i) { | ||
// This try block is more broad than necessary.. we only expect | ||
// an error to happen inside the call to: | ||
// | ||
// this.propParsers[i](..) | ||
// | ||
// But it is left as it is for efficiency. The other fragments | ||
// of code cannot possibly throw an Error (famous last words) | ||
try { | ||
newRow[this.propNames[i]] = | ||
msg.fields[i] !== null | ||
? this.propParsers[i](msg.fields[i]) | ||
: null; | ||
} catch (e) { | ||
this.parseError = e; | ||
this.parseErrorValue = msg.fields[i]; | ||
this.parseErrorParseFunction = this.propParsers[i].name; | ||
return; | ||
} | ||
} | ||
this.rows.push(newRow); | ||
}; | ||
const CustomCursor: any = function(this: any, propNames: any, propParsers: any, text: any, values: any) { | ||
Cursor.call(this, text, values); | ||
this.parseError = null; | ||
this.propNames = propNames; | ||
this.propParsers = propParsers; | ||
this.numFields = this.propNames.length; | ||
}; | ||
CustomCursor.prototype = Object.create(Cursor.prototype); | ||
CustomCursor.prototype.constructor = Cursor; | ||
CustomCursor.prototype.handleRowDescription = function(this: any) { | ||
// Code was taken straight from the original Cursor source code: | ||
this.state = "idle"; | ||
this._shiftQueue(); | ||
}; | ||
CustomCursor.prototype.handleDataRow = function(this: any, msg: any) { | ||
const row: any = {}; | ||
if (this.parseError === null) { | ||
for (let i = 0; i < this.numFields; ++i) { | ||
// This try block is more broad than necessary.. we only expect | ||
// an error to happen inside the call to: | ||
// | ||
// this.propParsers[i](..) | ||
// | ||
// But it is left as it is for efficiency. The other fragments | ||
// of code cannot possibly throw an Error (famous last words) | ||
try { | ||
row[this.propNames[i]] = | ||
msg.fields[i] !== null | ||
? this.propParsers[i](msg.fields[i]) | ||
: null; | ||
} catch (e) { | ||
this.parseError = e; | ||
this.parseErrorValue = msg.fields[i]; | ||
this.parseErrorParseFunction = this.propParsers[i].name; | ||
return new Promise<StreamingRows<any>>((resolve, reject) => { | ||
const cursor = new Cursor(text, values, { | ||
rowMode: "array", | ||
types: { | ||
getTypeParser: () => identityTypeParser | ||
} | ||
} | ||
} | ||
}); | ||
// Code was taken straight from the original Cursor source code: | ||
this.emit("row", row, this._result); | ||
this._rows.push(row); | ||
}; | ||
export function runCustomQueryStreaming(conn: pgLib.Client, propNames: string[], propParsers: ((val: string) => any)[], text: string, values: any, rowChunkSize: number): Promise<StreamingRows<any>> { | ||
return new Promise<StreamingRows<any>>((resolve, reject) => { | ||
const cursor = new CustomCursor(propNames, propParsers, text, values); | ||
conn.query(cursor); | ||
@@ -160,3 +150,3 @@ | ||
cursor.read(rowChunkSize, (err: any, rows: any) => { | ||
cursor.read(rowChunkSize, (err: any, rows: any[]) => { | ||
if (<boolean>err) { | ||
@@ -166,2 +156,3 @@ reject(err); | ||
} | ||
if (rows.length === 0) { | ||
@@ -177,4 +168,2 @@ resolve({ | ||
return new Promise<void>((resolve, reject) => { | ||
let userError: null | any = null; | ||
const next = (err: any, rows: any[]) => { | ||
@@ -186,37 +175,41 @@ if (<boolean>err) { | ||
if (rows.length === 0) { | ||
if (cursor.parseError !== null) { | ||
reject(new ColumnParseError( | ||
cursor.parseError.message, | ||
text, | ||
cursor.parseErrorValue, | ||
cursor.parseErrorParseFunction, | ||
cursor.parseError)); | ||
} else if (userError !== null) { | ||
reject(userError); | ||
} else { | ||
resolve(); | ||
} | ||
resolve(); | ||
} else { | ||
if (cursor.parseError === null && userError === null) { | ||
action(rows).then(() => { | ||
cursor.read(rowChunkSize, next); | ||
}, (err) => { | ||
userError = err; | ||
cursor.read(rowChunkSize, next); | ||
let parsedRows; | ||
try { | ||
parsedRows = parseRows(rows); | ||
} catch (err) { | ||
cursor.close(() => { | ||
reject(err); | ||
}); | ||
} else { | ||
return; | ||
} | ||
action(parsedRows).then(() => { | ||
cursor.read(rowChunkSize, next); | ||
} | ||
}, (err) => { | ||
cursor.close(() => { | ||
reject(err); | ||
}); | ||
}); | ||
} | ||
}; | ||
if (cursor.parseError === null) { | ||
action(rows).then(() => { | ||
cursor.read(rowChunkSize, next); | ||
}, (err) => { | ||
userError = err; | ||
cursor.read(rowChunkSize, next); | ||
let parsedRows; | ||
try { | ||
parsedRows = parseRows(rows); | ||
} catch (err) { | ||
cursor.close(() => { | ||
reject(err); | ||
}); | ||
} else { | ||
return; | ||
} | ||
action(parsedRows).then(() => { | ||
cursor.read(rowChunkSize, next); | ||
} | ||
}, (err) => { | ||
cursor.close(() => { | ||
reject(err); | ||
}); | ||
}); | ||
}); | ||
@@ -223,0 +216,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
7152597
8
12499
+ Added@types/pg@8.11.10(transitive)
- Removed@types/pg@7.4.11(transitive)
- Removed@types/pg-types@2.2.0(transitive)
- Removedbuffer-writer@2.0.0(transitive)
- Removedpacket-reader@1.0.0(transitive)
- Removedpg@7.18.2(transitive)
- Removedpg-connection-string@0.1.3(transitive)
- Removedpg-packet-stream@1.1.0(transitive)
- Removedpg-pool@2.0.10(transitive)
- Removedsemver@4.3.2(transitive)
Updated@types/pg@>=8 <9