Skip to content

Commit c7d2ca7

Browse files
author
radicsge
committedMar 18, 2017
add postProcessingResult function
add missing configuration options (min, max)
1 parent 2fc9985 commit c7d2ca7

11 files changed

+90
-16
lines changed
 

‎docs/API/PgDb.md

+5
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ See the [mapping database types to js types](/mappingDatabaseTypes) section
142142

143143
See the [mapping database types to js types](/mappingDatabaseTypes) section
144144

145+
---
146+
## setPostProcessResult
147+
<span class="def"><span class="func">setPostProcessResult</span>(f:(res: <span class="type">any[]</span>, fields: <span class="type">ResultFieldType[]</span>, logger:<span class="type">PgDbLogger</span>)=&gt;<span class="type">void</span>): <span class="type">void</span></span>
148+
You can add a postprocessor function that will be executed for every result (even empty ones), if you want to do something extra.
149+
If you call it twice the second function will overwrite the first. So you can easily unset also if you call it will null;
145150

146151
---
147152
## transactionBegin

‎docs/connection.md

+14-4
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,19 @@ let pgdb = await PgDb.connect({
2424
With the following options:
2525
``` js
2626
export interface ConnectionOptions {
27+
//--- node-postgres specific ----------------------
2728
host?:string;
2829
user?:string; //can be specified through PGUSER env variable (defaults USER env var)
2930
database?:string; //can be specified through PGDATABASE env variable (defaults USER env var)
3031
password?:string; //can be specified through PGPASSWORD env variable
3132
port?:number; //can be specified through PGPORT env variable
32-
poolSize?:number;
33-
rows?:number;
33+
poolSize?:number; //number of connections to use in connection pool. 0 - disable pooling
34+
min?:number; //minimum number of resources to keep in pool at any given time.
35+
max?:number;
36+
rows?:number; //number of rows to return at a time from a prepared statement's portal. 0 will return all rows at once
3437
binary?:boolean;
35-
reapIntervalMillis?:number;
36-
poolLog?:boolean;
38+
reapIntervalMillis?:number; //frequency to check for idle clients within the client pool
39+
poolLog?:boolean; //pool log function / boolean
3740
client_encoding?:string;
3841
ssl?:boolean| any; // TlsOptions;
3942
application_name?:string;
@@ -43,10 +46,17 @@ export interface ConnectionOptions {
4346
idleTimeoutMillis?:number; // how long a client is allowed to remain idle before being closed
4447
poolIdleTimeout?:number;
4548

49+
//--- pogi specific ----------------------------
4650
logger?:PgDbLogger;
4751
skipUndefined?: 'all' | 'select' | 'none'; //if there is a undefined value in the query condition, what should pogi do. Default is 'none', meaning raise an error if a value is undefined.
4852
}
4953
```
54+
55+
About node-postgres specific, more explanation can be found at
56+
https://github.com/brianc/node-postgres/blob/f6c40b9331c90d794d5fcbb1d4ae2f28eabd4d42/lib/defaults.js
57+
and
58+
https://github.com/coopernurse/node-pool
59+
5060
##skipUndefined
5161
while most settings are self explanatory, this parameter is important. In the first version of pogi
5262
we ignored the condition if the value was undefined in order for ease the use e.g.:

‎lib/pgDb.d.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { QueryAble } from "./queryAble";
1+
import { QueryAble, ResultFieldType } from "./queryAble";
22
import { PgTable } from "./pgTable";
33
import { PgSchema } from "./pgSchema";
44
export declare enum FieldType {
@@ -25,6 +25,8 @@ export interface ConnectionOptions {
2525
port?: number;
2626
poolSize?: number;
2727
rows?: number;
28+
min?: number;
29+
max?: number;
2830
binary?: boolean;
2931
poolIdleTimeout?: number;
3032
reapIntervalMillis?: number;
@@ -49,12 +51,13 @@ export interface PgDbLogger {
4951
log: Function;
5052
error: Function;
5153
}
54+
export declare type PostProcessResultFunc = (res: any[], fields: ResultFieldType[], logger: PgDbLogger) => void;
5255
export declare class PgDb extends QueryAble {
5356
protected static instances: {
5457
[index: string]: Promise<PgDb>;
5558
};
5659
pool: any;
57-
connection: any;
60+
protected connection: any;
5861
config: ConnectionOptions;
5962
db: any;
6063
schemas: {
@@ -68,7 +71,9 @@ export declare class PgDb extends QueryAble {
6871
};
6972
[name: string]: any | PgSchema;
7073
pgdbTypeParsers: {};
74+
postProcessResult: PostProcessResultFunc;
7175
private constructor(pgdb?);
76+
setPostProcessResult(f: (res: any[], fields: ResultFieldType[], logger: PgDbLogger) => void): void;
7277
/** If planned to used as a static singleton */
7378
static getInstance(config: ConnectionOptions): Promise<PgDb>;
7479
close(): Promise<void>;

‎lib/pgDb.js

+3-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎lib/pgDb.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎lib/queryAble.js

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎lib/queryAble.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/pgDb.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {QueryAble} from "./queryAble";
1+
import {QueryAble, ResultFieldType} from "./queryAble";
22
var pg = require('pg');
33
var util = require('util');
44
var readline = require('readline');
@@ -74,14 +74,20 @@ export interface ConnectionOptions {
7474
password?: string; // can be specified through PGPASSWORD env variable
7575
port?: number; // can be specified through PGPORT env variable
7676
poolSize?: number;
77+
78+
//number of rows to return at a time from a prepared statement's portal. 0 will return all rows at once
7779
rows?: number;
80+
81+
min?: number; //set min pool size
82+
max?: number; //set pool max size
83+
7884
binary?: boolean;
7985
poolIdleTimeout?: number;
8086
reapIntervalMillis?: number;
8187
poolLog?: boolean;
8288
client_encoding?: string;
8389
ssl?: boolean| any; //| TlsOptions;
84-
application_name?: string;
90+
application_name?: string; //default:process.env.PGAPPNAME - name displayed in the pg_stat_activity view and included in CSV log entries
8591
fallback_application_name?: string;
8692
parseInputDatesAsUTC?: boolean;
8793
connectionString?: string;
@@ -102,23 +108,28 @@ export interface PgDbLogger {
102108
error: Function;
103109
}
104110

111+
export type PostProcessResultFunc = (res: any[], fields: ResultFieldType[], logger:PgDbLogger)=>void;
112+
113+
105114
export class PgDb extends QueryAble {
106115
protected static instances: {[index: string]: Promise<PgDb>};
107-
pool;
108-
connection;
109-
config: ConnectionOptions;
116+
/*protected*/ pool;
117+
protected connection;
118+
/*protected*/ config: ConnectionOptions;
110119
db;
111120
schemas: {[name: string]: PgSchema};
112121
tables: {[name: string]: PgTable<any>} = {};
113122
fn: {[name: string]: (...any)=>any} = {};
114123
[name: string]: any|PgSchema;
115-
pgdbTypeParsers = {};
124+
/*protected*/ pgdbTypeParsers = {};
125+
/*protected*/ postProcessResult: PostProcessResultFunc;
116126

117-
private constructor(pgdb: {config?,schemas?,pool?,pgdbTypeParsers?,getLogger?:()=>any} = {}) {
127+
private constructor(pgdb: {config?,schemas?,pool?,pgdbTypeParsers?,getLogger?:()=>any, postProcessResult?:PostProcessResultFunc } = {}) {
118128
super();
119129
this.schemas = {};
120130
this.config = pgdb.config;
121131
this.pool = pgdb.pool;
132+
this.postProcessResult = pgdb.postProcessResult;
122133
this.pgdbTypeParsers = pgdb.pgdbTypeParsers || {};
123134
this.db = this;
124135
if (pgdb.getLogger) {
@@ -139,6 +150,8 @@ export class PgDb extends QueryAble {
139150
}
140151
}
141152

153+
setPostProcessResult(f:(res: any[], fields: ResultFieldType[], logger:PgDbLogger)=>void) {this.postProcessResult = f;}
154+
142155
/** If planned to used as a static singleton */
143156
static async getInstance(config: ConnectionOptions): Promise<PgDb> {
144157
if (config.connectionString) {

‎src/queryAble.ts

+10
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ export class QueryAble {
8888
logger.log('reused connection', sql, util.inspect(params, false, null), connection.processID);
8989
let res = await connection.query(sql, params);
9090
pgUtils.postProcessResult(res.rows, res.fields, this.db.pgdbTypeParsers);
91+
if (this.db.postProcessResult) this.db.postProcessResult(res.rows, res.fields, logger);
92+
9193
return res.rows;
9294
} else {
9395
connection = await this.db.pool.connect();
@@ -98,6 +100,8 @@ export class QueryAble {
98100
connection.release();
99101
connection = null;
100102
pgUtils.postProcessResult(res.rows, res.fields, this.db.pgdbTypeParsers);
103+
if (this.db.postProcessResult) this.db.postProcessResult(res.rows, res.fields, logger);
104+
101105
return res.rows;
102106
} catch(e){
103107
logger.error(sql, util.inspect(params, false, null), connection ? connection.processID : null, e);
@@ -139,6 +143,8 @@ export class QueryAble {
139143
stream.on('data', (res) => {
140144
try {
141145
pgUtils.postProcessResult([res], stream._result.fields, this.db.pgdbTypeParsers);
146+
if (this.db.postProcessResult) this.db.postProcessResult([res], stream._result.fields, this.getLogger(false));
147+
142148
if (callback(res)) {
143149
stream.emit('close');
144150
}
@@ -160,6 +166,8 @@ export class QueryAble {
160166
stream.on('data', (res) => {
161167
try {
162168
pgUtils.postProcessResult([res], stream._result.fields, this.db.pgdbTypeParsers);
169+
if (this.db.postProcessResult) this.db.postProcessResult([res], stream._result.fields, this.getLogger(false));
170+
163171
if (callback(res)) {
164172
stream.emit('close');
165173
}
@@ -195,6 +203,8 @@ export class QueryAble {
195203
let convertTypeFilter = through(function(data) {
196204
try {
197205
pgUtils.postProcessResult([data], pgStream._result.fields, pgdb.pgdbTypeParsers);
206+
if (pgdb.postProcessResult) pgdb.postProcessResult([data], pgStream._result.fields, logger);
207+
198208
this.emit('data', data);
199209
} catch (err) {
200210
this.emit('error', err);

‎src/test/pgDbSpec.ts

+15
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ describe("pgdb", () => {
123123
}));
124124

125125

126+
127+
126128
it("After adding parser should be able to parse complex type", w(async() => {
127129
await pgdb.setTypeParser('permissionForResourceType', (val) => parseComplexType(val));
128130
await pgdb.setTypeParser('_permissionForResourceType', (val) => val=="{}" ? [] : parseComplexTypeArray(val));
@@ -692,4 +694,17 @@ describe("pgdb", () => {
692694

693695
}));
694696

697+
698+
it("Testing postprocess function", w(async() => {
699+
await table.insert({name: 'A'});
700+
701+
pgdb.setPostProcessResult((res, fields, logger)=> {
702+
res[0].name='B';
703+
});
704+
let res = await pgdb.query(`select * from ${table}`);
705+
expect(res[0].name=='B').toBeTruthy();
706+
res = await table.findAll();
707+
expect(res[0].name=='B').toBeTruthy();
708+
pgdb.setPostProcessResult(null);
709+
}));
695710
});

‎utils_sql/lower.sql

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATE OR REPLACE FUNCTION LOWER(text[]) RETURNS text[] LANGUAGE SQL IMMUTABLE AS
2+
$$
3+
SELECT array_agg(LOWER(value)) FROM unnest($1) value;
4+
$$;

0 commit comments

Comments
 (0)
Please sign in to comment.