All Projects → svenvc → P3

svenvc / P3

Licence: mit
A lean and mean PostgreSQL client for Pharo

Programming Languages

smalltalk
420 projects

Projects that are alternatives of or similar to P3

Niklick
Rails Versioned API solution template for hipsters! (Ruby, Ruby on Rails, REST API, GraphQL, Docker, RSpec, Devise, Postgress DB)
Stars: ✭ 39 (-17.02%)
Mutual labels:  postgresql
Pgtools
Gui application to monitor postgres database events in real time
Stars: ✭ 42 (-10.64%)
Mutual labels:  postgresql
Pg party
Automatic partitioning on date-timestamp columns for PostgreSQL v9.1+
Stars: ✭ 44 (-6.38%)
Mutual labels:  postgresql
Ansible Role Patroni
🐘 Ansible Role for Patroni
Stars: ✭ 40 (-14.89%)
Mutual labels:  postgresql
Pg cron
Run periodic jobs in PostgreSQL
Stars: ✭ 1,002 (+2031.91%)
Mutual labels:  postgresql
Tinder Clone
Fullstack Tinder app clone made with React/Ts/Nest
Stars: ✭ 43 (-8.51%)
Mutual labels:  postgresql
Gympoint Api
Rest API of a gym management application - built with Express, Postgres, Redis, and Nodemailer.
Stars: ✭ 39 (-17.02%)
Mutual labels:  postgresql
Sales Cashregister
Cash Register Version 2.0 with barcode logon and to 8 buttongroups with each 23 programmable product buttons and equipped with inventory management system
Stars: ✭ 45 (-4.26%)
Mutual labels:  postgresql
Ar Uuid
Override migration methods to support UUID columns without having to be explicit about it.
Stars: ✭ 41 (-12.77%)
Mutual labels:  postgresql
K2
Koa2 API template with passport, GraphQL, flowtype, knex and more.
Stars: ✭ 44 (-6.38%)
Mutual labels:  postgresql
Marten.fsharp
A set of FSharp wrappers around Marten
Stars: ✭ 40 (-14.89%)
Mutual labels:  postgresql
Ether sql
A python library to push ethereum blockchain data into an sql database.
Stars: ✭ 41 (-12.77%)
Mutual labels:  postgresql
Phalcon Vm
Vagrant configuration for PHP7, Phalcon 3.x and Zephir development.
Stars: ✭ 43 (-8.51%)
Mutual labels:  postgresql
Toro
Multithreaded message processing on Postgres
Stars: ✭ 39 (-17.02%)
Mutual labels:  postgresql
Pg variables
Session wide variables for PostgreSQL
Stars: ✭ 44 (-6.38%)
Mutual labels:  postgresql
Ansible Elixir Playbooks
Ansible playbooks for Elixir build server and Phoenix Website. Sample app here: https://github.com/LunarLogic/phoenix_website
Stars: ✭ 39 (-17.02%)
Mutual labels:  postgresql
Postgraphile Nest
GraphQL (PostGraphile) module for Nest framework (node.js)
Stars: ✭ 43 (-8.51%)
Mutual labels:  postgresql
Pghoard
PostgreSQL backup and restore service
Stars: ✭ 1,027 (+2085.11%)
Mutual labels:  postgresql
Ensembl Hive
EnsEMBL Hive - a system for creating and running pipelines on a distributed compute resource
Stars: ✭ 44 (-6.38%)
Mutual labels:  postgresql
Dagbot
The official Repository for dagbot, the self proclaimmed n1 meme bot.
Stars: ✭ 40 (-14.89%)
Mutual labels:  postgresql

P3

P3 is a modern, lean and mean PostgreSQL client for Pharo.

Build Status

P3Client uses frontend/backend protocol 3.0 (PostgreSQL version 7.4 [2003] and later), implementing the simple and extended query cycles. It supports plaintext and md5 password authentication. When SQL queries return row data, it efficiently converts incoming data to objects. P3Client supports most common PostgreSQL types.

P3Client can be configured manually or through a URL.

P3Client new url: 'psql://username:[email protected]:5432/databasename'.

Not all properties need to be specified, the minimum is the following URL.

P3Client new url: 'psql://[email protected]'.

P3Client has a minimal public protocol, basically #query: (#execute: is an alias).

Opening a connection to the server (#open) and running the authentication and startup protocols (#connect) are done automatically when needed from #query.

P3Client also supports SSL connections. Use #connectSSL to initiate such a connection.

Through the #prepare: message, you can ask P3Client to prepare/parse an SQL statement or query with parameters. This will give you a P3PreparedStatement instance than you can then execute with specific parameters. Polymorphic to this there is also P3FormattedStatement which you create using the #format: message. These work at the textual, client side level.

Basic Usage

Here is the simplest test that does an actual query, it should return true.

(P3Client new url: 'psql://[email protected]') in: [ :client |
   [ client isWorking ] ensure: [ client close ] ].

This is how to create a simple table with some rows in it.

(P3Client new url: 'psql://[email protected]') in: [ :client |
   client execute: 'DROP TABLE IF EXISTS table1'.
   client execute: 'CREATE TABLE table1 (id INTEGER, name TEXT, enabled BOOLEAN)'.
   client execute: 'INSERT INTO table1 (id, name, enabled) VALUES (1, ''foo'', true)'.
   client execute: 'INSERT INTO table1 (id, name, enabled) VALUES (2, ''bar'', false)'.
   client close ].

Now we can query the contents of the simple table we just created.

(P3Client new url: 'psql://[email protected]') in: [ :client |
   [ client query: 'SELECT * FROM table1' ] ensure: [ client close ] ].

The result is an instance of P3Result

   a P3Result('SELECT 2' 2 records 3 colums)

P3Result contains 3 elements, results, descriptions & data:

  • Results is a string (collection of strings for multiple embedded queries) indicating successful execution.
  • Descriptions is a collection of row field description objects.
  • Data is a collection of rows with fully converted field values as objects.

The data itself is an array with 2 sub arrays, one for each record.

#( #(1 'foo' true) #(2 'bar' false) )

Finally we can clean up.

(P3Client new url: 'psql://[email protected]') in: [ :client |
   [ client execute: 'DROP TABLE table1' ] ensure: [ client close ] ].

References

Using Prepared and Formatted Statements

Although you are free to create your SQL statements in any way you see fit, feeding them to #execute: and #query:, inserting arguments in SQL statements can be hard (because you have to know the correct syntax), error prone (because you might violate syntax rules) and dangerous (due to SQL injection attacks).

P3 can help here with two mechanisms: prepared and formatted statements. They are mostly polymorphic and use the same template notation. They allow you to create a statement once, specifying placeholders with $n, and execute it once or multiple times with concrete arguments, with the necessary conversions happening automatically.

The difference between the two is that formatted statements are implemented using simple textual substitution on the client side, while prepared statements are evaluated on the server side with full syntax checking, and are executed with more type checks. Prepared statements are more efficient since the server can do part of its optimalization in the prepare phase, saving time on each execution.

Here is a transcript of how to use them. First we set up a client and create a test table.

client := P3Client new url: 'psql://[email protected]'.

client execute: 'DROP TABLE IF EXISTS table1'.
client execute: 'CREATE TABLE table1 (id INTEGER, name TEXT, weight REAL, enabled BOOLEAN)'.

Next we insert some data and then query it using prepared statements.

statement := client prepare: 'INSERT INTO table1 (id, name, weight, enabled) VALUES ($1, $2, $3, $4)'.

statement execute: { 1. 'foo'. 75.5. true }.
statement executeBatch: { { 2. 'bar'. 80.25. true }. { 3. 'foobar'. 10.75. false } }.

statement close.

statement := client prepare: 'SELECT id, name, weight FROM table1 WHERE id = $1 AND enabled = $2'.
statement query: { 1. true }.

statement close.

Note that prepared statements are server side resources that need to be closed when no longer needed. Prepared statements exist in the scope of a single session/connection.

Next we start over and do the same insert and query using formatted statements.

client execute: 'TRUNCATE TABLE table1'.

statement := client format: 'INSERT INTO table1 (id, name, weight, enabled) VALUES ($1, $2, $3, $4)'.

statement execute: { 1. 'foo'. 75.5. true }.
statement executeBatch: { { 2. 'bar'. 80.25. true }. { 3. 'foobar'. 10.75. false } }.

statement := client format: 'SELECT id, name, weight FROM table1 WHERE id = $1 AND enabled = $2'.
statement query: { 1. true }.

And finally we clean up.

client execute: 'DROP TABLE table1'.
client close.

Supported Data Types

P3 supports most common PostgreSQL types. Here are some tables with the details. As of PostgreSQL 9.6, there are 41 general purpose data types of which 32 are currently implemented.

These are the 32 general purpose data type currently implemented, with the Pharo class they map to.

Name Alias Description Oid Class
bigint int8 signed eight-byte integer 20 Integer
bigserial serial8 autoincrementing eight-byte integer 20 Integer
bit [n] fixed-length bit string 1560 P3FixedBitString
bit varying varbit variable-length bit string 1562 P3BitString
boolean bool logical boolean (true/false) 16 Boolean
box rectangular box on a plane (upperright, lowerleft) 603 P3Box
bytea binary data (byte array) 17 ByteArray
character [n] char fixed-length character string 1042 String
character varying varchar variable-length character string 1043 String
circle circle on a plane (center, radius) 718 P3Circle
date calendar date (year,month,day) 1082 Date
double precision float8 double precision floating point number (8 bytes) 701 Float
integer int, int4 signed four-byte integer 23 Integer
interval time span 114 P3Interval
json textual JSON data 114 NeoJSONObject
jsonb binary JSON data, decomposed 3802 NeoJSONObject
line infinite line on a plane (ax+by+c=0) 628 P3Line
lseg line segment on a plane (start,stop) 601 P3LineSegment
numeric decimal exact number of selectable precision 1700 ScaledDecimal
path geometric path on a plane (points) 602 P3Path
point geometric point on a plane (x, y) 600 P3Point
polygon closed geometric path on a plane (points) 604 P3Polygon
real float4 single-precision floating point number (4-bytes) 700 Float
smallint int2 signed two-byte integer 21 Integer
smallserial serial2 autoincrementing two-byte integer 21 Integer
serial serial4 autoincrementing four-byte integer 23 Integer
text variable-length character string 25 String
time [ without time zone ] time of day (no time zone) 1083 Time
time with time zone timetz time of day including time zone 1266 Time
timestamp [ without time zone ] date and time (no time zone) 1114 DateAndTime
timestamp with time zone timestamptz date and time includig time zone 1184 DateAndTime
uuid universal unique identifier 2950 UUID

Here are the 9 general purpose data types that are not yet implemented.

Name Description Oid
cidr IPv4 or IPv6 network address 650
inet IPv4 or IPv6 host address 869
macaddr MAC (Media Access Control) address 829
money currency amount 790
pg_lsn PostgreSQL Log Sequence Number 3220
tsquery text search query 3615
tsvector text search document 3614
txid_snapshot user-level transaction ID snapshot 2970
xml XML data 142

Additionally, the following 9 common types are also implemented, with the Pharo class they map to.

Name Description Oid Class
oid object identifier 26 Integer
name name 19 String
bpchar text 1042 String
void void 2278 UndefinedObject
_bool boolean array 1000 Array
_int4 integer array 1007 Array
_text string array 1009 Array
_varchar string array 1015 Array
_float8 float array 1022 Array

P3 also supports enums. Each enum definition creates a new type. You can send #loadEnums to P3Client to create mappings for all visible enums.

When you do a query that results in data of an unknown type you will get an error, P3 cannot convert typeOid XXX, where XXX is the oid in the pg_type table.

Glorp

Included is P3DatabaseDriver, an interface between Glorp, an advanced object-relational mapper, and P3Client.

To install this driver (after loading Glorp itself), do

PharoDatabaseAccessor DefaultDriver: P3DatabaseDriver.

Configure your session using a Glorp Login object

Login new
   database: PostgreSQLPlatform new;
   username: 'username';
   password: 'password';
   connectString: 'host:5432_databasename';
   encodingStrategy: #utf8;
   yourself.

Code loading

The default group loads P3Client and its basic dependencies NeoJSON and ZTimestamp

Metacello new
   baseline: 'P3';
   repository: 'github://svenvc/P3';
   load.

The glorp group loads P3DatabaseDriver and the whole of Glorp (warning: large download)

Metacello new
   baseline: 'P3';
   repository: 'github://svenvc/P3';
   load: 'glorp'.

Unit tests

P3ClientTest holds unit tests for the P3 PSQL client.

Configure it by setting its class side's connection URL.

P3ClientTest url: 'psql://sven:[email protected]:5432/database'.

The minimal being the following:

P3ClientTest url: 'psql://[email protected]'.

Development, Goals, Contributing

The main goal of P3 is to be a modern, lean and mean PostgreSQL client for Pharo. Right now, P3 is functional and usable.

The quality of open source software is determined by it being alive, supported and maintained.

The first way to help is to simply use P3 in your projects and tells us about your successes and the issues that you encounter. You can ask questions on the Pharo mailing lists.

Development happens on GitHub, where you can create issues.

Contributions should be done with pull requests solving specific issues.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].