Skip to content

Commit fe88e82

Browse files
authoredJun 4, 2024
Add pg-native to monorepo (#3225)
I didn't do much to "modernize" the pg-native codebase other than running it through the standard eslint --fix that is applied to the rest of the code. There's some easy opportunities there to update it to es6 and so on...it still uses some pretty antiquated coding styles in places. This PR re-introduces the native tests on node v20, and updates test matrix to drop unsupported versions of node & add in node v22.
1 parent 4615695 commit fe88e82

37 files changed

+3076
-603
lines changed
 

‎.github/workflows/ci.yml

+8-11
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,22 @@ jobs:
3838
fail-fast: false
3939
matrix:
4040
node:
41-
- '10'
42-
- '12'
43-
- '14'
4441
- '16'
4542
- '18'
4643
- '20'
44+
- '22'
4745
os:
4846
- ubuntu-latest
4947
name: Node.js ${{ matrix.node }} (${{ matrix.os }})
5048
runs-on: ${{ matrix.os }}
5149
env:
52-
PGUSER: postgres
53-
PGPASSWORD: postgres
54-
PGHOST: localhost
55-
PGDATABASE: ci_db_test
56-
PGTESTNOSSL: 'true'
57-
SCRAM_TEST_PGUSER: scram_test
58-
SCRAM_TEST_PGPASSWORD: test4scram
59-
TEST_SKIP_NATIVE: ${{ matrix.node == 20 }}
50+
PGUSER: postgres
51+
PGPASSWORD: postgres
52+
PGHOST: localhost
53+
PGDATABASE: ci_db_test
54+
PGTESTNOSSL: 'true'
55+
SCRAM_TEST_PGUSER: scram_test
56+
SCRAM_TEST_PGPASSWORD: test4scram
6057
steps:
6158
- name: Show OS
6259
run: |

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"docs:start": "cd docs && yarn start",
1818
"pretest": "yarn build",
1919
"prepublish": "yarn build",
20-
"lint": "eslint --cache '*/**/*.{js,ts,tsx}'"
20+
"lint": "eslint --cache 'packages/**/*.{js,ts,tsx}'"
2121
},
2222
"devDependencies": {
2323
"@typescript-eslint/eslint-plugin": "^7.0.0",

‎packages/pg-native/README.md

+306
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
# node-pg-native
2+
3+
[![Build Status](https://travis-ci.org/brianc/node-pg-native.svg?branch=master)](https://travis-ci.org/brianc/node-pg-native)
4+
5+
High performance native bindings between node.js and PostgreSQL via [libpq](https://github.com/brianc/node-libpq) with a simple API.
6+
7+
## install
8+
9+
You need PostgreSQL client libraries & tools installed. An easy way to check is to type `pg_config`. If `pg_config` is in your path, you should be good to go. If it's not in your path you'll need to consult operating specific instructions on how to go about getting it there.
10+
11+
Some ways I've done it in the past:
12+
13+
- On macOS: `brew install libpq`
14+
- On Ubuntu/Debian: `apt-get install libpq-dev g++ make`
15+
- On RHEL/CentOS: `yum install postgresql-devel`
16+
- On Windows:
17+
1. Install Visual Studio C++ (successfully built with Express 2010). Express is free.
18+
2. Install PostgreSQL (`http://www.postgresql.org/download/windows/`)
19+
3. Add your Postgre Installation's `bin` folder to the system path (i.e. `C:\Program Files\PostgreSQL\9.3\bin`).
20+
4. Make sure that both `libpq.dll` and `pg_config.exe` are in that folder.
21+
22+
Afterwards `pg_config` should be in your path. Then...
23+
24+
```sh
25+
$ npm i pg-native
26+
```
27+
28+
## use
29+
30+
### async
31+
32+
```js
33+
var Client = require('pg-native')
34+
35+
var client = new Client();
36+
client.connect(function(err) {
37+
if(err) throw err
38+
39+
//text queries
40+
client.query('SELECT NOW() AS the_date', function(err, rows) {
41+
if(err) throw err
42+
43+
console.log(rows[0].the_date) //Tue Sep 16 2014 23:42:39 GMT-0400 (EDT)
44+
45+
//parameterized statements
46+
client.query('SELECT $1::text as twitter_handle', ['@briancarlson'], function(err, rows) {
47+
if(err) throw err
48+
49+
console.log(rows[0].twitter_handle) //@briancarlson
50+
})
51+
52+
//prepared statements
53+
client.prepare('get_twitter', 'SELECT $1::text as twitter_handle', 1, function(err) {
54+
if(err) throw err
55+
56+
//execute the prepared, named statement
57+
client.execute('get_twitter', ['@briancarlson'], function(err, rows) {
58+
if(err) throw err
59+
60+
console.log(rows[0].twitter_handle) //@briancarlson
61+
62+
//execute the prepared, named statement again
63+
client.execute('get_twitter', ['@realcarrotfacts'], function(err, rows) {
64+
if(err) throw err
65+
66+
console.log(rows[0].twitter_handle) //@realcarrotfacts
67+
68+
client.end(function() {
69+
console.log('ended')
70+
})
71+
})
72+
})
73+
})
74+
})
75+
})
76+
77+
```
78+
79+
### sync
80+
81+
Because `pg-native` is bound to [libpq](https://github.com/brianc/node-libpq) it is able to provide _sync_ operations for both connecting and queries. This is a bad idea in _non-blocking systems_ like web servers, but is exteremly convienent in scripts and bootstrapping applications - much the same way `fs.readFileSync` comes in handy.
82+
83+
```js
84+
var Client = require('pg-native')
85+
86+
var client = new Client()
87+
client.connectSync()
88+
89+
//text queries
90+
var rows = client.querySync('SELECT NOW() AS the_date')
91+
console.log(rows[0].the_date) //Tue Sep 16 2014 23:42:39 GMT-0400 (EDT)
92+
93+
//parameterized queries
94+
var rows = client.querySync('SELECT $1::text as twitter_handle', ['@briancarlson'])
95+
console.log(rows[0].twitter_handle) //@briancarlson
96+
97+
//prepared statements
98+
client.prepareSync('get_twitter', 'SELECT $1::text as twitter_handle', 1)
99+
100+
var rows = client.executeSync('get_twitter', ['@briancarlson'])
101+
console.log(rows[0].twitter_handle) //@briancarlson
102+
103+
var rows = client.executeSync('get_twitter', ['@realcarrotfacts'])
104+
console.log(rows[0].twitter_handle) //@realcarrotfacts
105+
```
106+
107+
## api
108+
109+
### constructor
110+
111+
- __`constructor Client()`__
112+
113+
Constructs and returns a new `Client` instance
114+
115+
### async functions
116+
117+
- __`client.connect(<params:string>, callback:function(err:Error))`__
118+
119+
Connect to a PostgreSQL backend server.
120+
121+
__params__ is _optional_ and is in any format accepted by [libpq](http://www.postgresql.org/docs/9.3/static/libpq-connect.html#LIBPQ-CONNSTRING). The connection string is passed _as is_ to libpq, so any format supported by libpq will be supported here. Likewise, any format _unsupported_ by libpq will not work. If no parameters are supplied libpq will use [environment variables](http://www.postgresql.org/docs/9.3/static/libpq-envars.html) to connect.
122+
123+
Returns an `Error` to the `callback` if the connection was unsuccessful. `callback` is _required_.
124+
125+
##### example
126+
127+
```js
128+
var client = new Client()
129+
client.connect(function(err) {
130+
if(err) throw err
131+
132+
console.log('connected!')
133+
})
134+
135+
var client2 = new Client()
136+
client2.connect('postgresql://user:password@host:5432/database?param=value', function(err) {
137+
if(err) throw err
138+
139+
console.log('connected with connection string!')
140+
})
141+
```
142+
143+
- __`client.query(queryText:string, <values:string[]>, callback:Function(err:Error, rows:Object[]))`__
144+
145+
Execute a query with the text of `queryText` and _optional_ parameters specified in the `values` array. All values are passed to the PostgreSQL backend server and executed as a parameterized statement. The callback is _required_ and is called with an `Error` object in the event of a query error, otherwise it is passed an array of result objects. Each element in this array is a dictionary of results with keys for column names and their values as the values for those columns.
146+
147+
##### example
148+
149+
```js
150+
var client = new Client()
151+
client.connect(function(err) {
152+
if (err) throw err
153+
154+
client.query('SELECT NOW()', function(err, rows) {
155+
if (err) throw err
156+
157+
console.log(rows) // [{ "now": "Tue Sep 16 2014 23:42:39 GMT-0400 (EDT)" }]
158+
159+
client.query('SELECT $1::text as name', ['Brian'], function(err, rows) {
160+
if (err) throw err
161+
162+
console.log(rows) // [{ "name": "Brian" }]
163+
164+
client.end()
165+
})
166+
})
167+
})
168+
```
169+
170+
171+
- __`client.prepare(statementName:string, queryText:string, nParams:int, callback:Function(err:Error))`__
172+
173+
Prepares a _named statement_ for later execution. You _must_ supply the name of the statement via `statementName`, the command to prepare via `queryText` and the number of parameters in `queryText` via `nParams`. Calls the callback with an `Error` if there was an error.
174+
175+
##### example
176+
177+
```js
178+
var client = new Client()
179+
client.connect(function(err) {
180+
if(err) throw err
181+
182+
client.prepare('prepared_statement', 'SELECT $1::text as name', 1, function(err) {
183+
if(err) throw err
184+
185+
console.log('statement prepared')
186+
client.end()
187+
})
188+
189+
})
190+
```
191+
192+
- __`client.execute(statementName:string, <values:string[]>, callback:Function(err:err, rows:Object[]))`__
193+
194+
Executes a previously prepared statement on this client with the name of `statementName`, passing it the optional array of query parameters as a `values` array. The `callback` is mandatory and is called with and `Error` if the execution failed, or with the same array of results as would be passed to the callback of a `client.query` result.
195+
196+
##### example
197+
198+
199+
```js
200+
var client = new Client()
201+
client.connect(function(err) {
202+
if(err) throw err
203+
204+
client.prepare('i_like_beans', 'SELECT $1::text as beans', 1, function(err) {
205+
if(err) throw err
206+
207+
client.execute('i_like_beans', ['Brak'], function(err, rows) {
208+
if(err) throw err
209+
210+
console.log(rows) // [{ "i_like_beans": "Brak" }]
211+
client.end()
212+
})
213+
})
214+
})
215+
```
216+
217+
- __`client.end(<callback:Function()>`__
218+
219+
Ends the connection. Calls the _optional_ callback when the connection is terminated.
220+
221+
##### example
222+
223+
```js
224+
var client = new Client()
225+
client.connect(function(err) {
226+
if(err) throw err
227+
client.end(function() {
228+
console.log('client ended') // client ended
229+
})
230+
})
231+
```
232+
233+
- __`client.cancel(callback:function(err))`__
234+
235+
Cancels the active query on the client. Callback receives an error if there was an error _sending_ the cancel request.
236+
237+
##### example
238+
```js
239+
var client = new Client()
240+
client.connectSync()
241+
//sleep for 100 seconds
242+
client.query('select pg_sleep(100)', function(err) {
243+
console.log(err) // [Error: ERROR: canceling statement due to user request]
244+
})
245+
client.cancel(function(err) {
246+
console.log('cancel dispatched')
247+
})
248+
249+
```
250+
251+
### sync functions
252+
253+
- __`client.connectSync(params:string)`__
254+
255+
Connect to a PostgreSQL backend server. Params is in any format accepted by [libpq](http://www.postgresql.org/docs/9.3/static/libpq-connect.html#LIBPQ-CONNSTRING). Throws an `Error` if the connection was unsuccessful.
256+
257+
- __`client.querySync(queryText:string, <values:string[]>) -> results:Object[]`__
258+
259+
Executes a query with a text of `queryText` and optional parameters as `values`. Uses a parameterized query if `values` are supplied. Throws an `Error` if the query fails, otherwise returns an array of results.
260+
261+
- __`client.prepareSync(statementName:string, queryText:string, nParams:int)`__
262+
263+
Prepares a name statement with name of `statementName` and a query text of `queryText`. You must specify the number of params in the query with the `nParams` argument. Throws an `Error` if the statement is un-preparable, otherwise returns an array of results.
264+
265+
- __`client.executeSync(statementName:string, <values:string[]>) -> results:Object[]`__
266+
267+
Executes a previously prepared statement on this client with the name of `statementName`, passing it the optional array of query paramters as a `values` array. Throws an `Error` if the execution fails, otherwas returns an array of results.
268+
269+
## testing
270+
271+
```sh
272+
$ npm test
273+
```
274+
275+
To run the tests you need a PostgreSQL backend reachable by typing `psql` with no connection parameters in your terminal. The tests use [environment variables](http://www.postgresql.org/docs/9.3/static/libpq-envars.html) to connect to the backend.
276+
277+
An example of supplying a specific host the tests:
278+
279+
```sh
280+
$ PGHOST=blabla.mydatabasehost.com npm test
281+
```
282+
283+
284+
## license
285+
286+
The MIT License (MIT)
287+
288+
Copyright (c) 2014 Brian M. Carlson
289+
290+
Permission is hereby granted, free of charge, to any person obtaining a copy
291+
of this software and associated documentation files (the "Software"), to deal
292+
in the Software without restriction, including without limitation the rights
293+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
294+
copies of the Software, and to permit persons to whom the Software is
295+
furnished to do so, subject to the following conditions:
296+
297+
The above copyright notice and this permission notice shall be included in
298+
all copies or substantial portions of the Software.
299+
300+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
301+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
302+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
303+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
304+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
305+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
306+
THE SOFTWARE.

0 commit comments

Comments
 (0)