Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postgres Adapter [WIP] #4

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .env

This file was deleted.

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dist
coverage
migrations
/migrations
.env
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ modules
.gitignore
circle.yml
coverage
migrations
/migrations
.env
File renamed without changes.
2 changes: 1 addition & 1 deletion modules/orm/adapters/mysql/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import connection from './connection'
import Builder from './builder'
import Builder from '../builder'
import { getTableName } from '../../../global/get-name'


Expand Down
16 changes: 16 additions & 0 deletions modules/orm/adapters/postgres/connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pg from 'pg'

const config = {
user: process.env.DB_USERNAME, //env var: PGUSER
database: process.env.DB_NAME, //env var: PGDATABASE
password: process.env.DB_PASSWORD, //env var: PGPASSWORD
host: process.env.DB_HOST, // Server hosting the postgres database
port: 5432, //env var: PGPORT
max: 10, // max number of clients in the pool
idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
};


const connection = new pg.Pool(config)

export default connection
132 changes: 132 additions & 0 deletions modules/orm/adapters/postgres/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import connection from './connection'
import Builder from '../builder'
import { getTableName } from '../../../global/get-name'


class PostgresAdapter {

/*
Generic Adapter Methods (these should be in every adapter)
select, create, queryBuilder, getJoins, makeRelatable
/*


Builds the mysql query, used query builder and root model class
*/
select({ model, select, where, limit, joins = [] }) {
return new Promise((resolve, reject) => {
connection.connect((err, client, done) => {
if(err) return reject(err)

console.log(`SELECT ${select ? select : '*'} FROM ${model.tableName()}${where ? ` WHERE ${where}` : ''}${this.getJoins(joins)}${limit ? ` LIMIT ${limit}` : ''}`)
client.query(`SELECT ${select ? select : '*'} FROM ${model.tableName()}${where ? ` WHERE ${where}` : ''}${this.getJoins(joins)}${limit ? ` LIMIT ${limit}` : ''}`, (error, result) => {
if(error) return reject(error)

if(joins.length > 0) results = this.mergeInJoins(results)
resolve(this.makeRelatable(limit === 1 ? results[0] : results, model))
})
})
})
}

/*
create a row in the database
*/
create({ model, data }) {
return new Promise((resolve, reject) => {
connection.connect((err, client, done) => {
if(err) return reject(err)

client.query(`INSERT INTO ${model.tableName()} SET ?`, data, (error, result) => {
if(error) return reject(error)
resolve(this.makeRelatable({
id: result.insertId,
...data
}, model))

})
})
})
}

/*
returns a new query builder instance
*/
queryBuilder(options) {
return new Builder(options)
}

/*
creates join query from any model realtionships
used on eager loads
*/
getJoins(joins) {
return joins.map(join => ` INNER JOIN \`${join.includeTable}\` ON ${join.localField} = ${join.remoteField}`)
}


/*
Proxy object that returns item from resulting query
or will check for a relationship on the model
and return a promise.

ex
result.id -> returns `id` on the result Object

result.users
-> returns users if extists on the object.
otherwise, checks for `users` function on the
model and returns the related query promise
*/

makeRelatable(result, model) {
return new Proxy(result, {
get(target, name) {
if(name in target) return target[name]
if(getTableName(name) in target) return target[getTableName(name)]

let instance = new model(result)
if(name in instance) return instance[name]().result()
}
})
}

/*
POSTGRES SPECIFIC METHODS
*/


/*
Joins nested tables for when eager loading a relationship

converts
{
users: { name: 'Bob'},
chats: {...},
}
to
{
name: 'Bob',
chats: {...}
}
*/
mergeInJoins(results) {
return results.map(result => {
let newResult = {}
Object.keys(result).forEach((item, index) => {
if(index === 0) newResult = result[item]
else newResult[item] = result[item]
})
return newResult
})
}

/*
parse out {id: 1, messages: 'hi'} into postgres where clause
*/
getWhereClause() {

}
}

export default new PostgresAdapter()
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@
},
"main": "dist/index.js",
"scripts": {
"local-test": "mocha --require babel-register --require tests/setup/local-setup tests/unit --recursive",
"build": "babel modules --out-dir dist --no-comments",
"local-cover": "istanbul cover ./node_modules/.bin/_mocha -- --require babel-register --require tests/setup/local-setup tests/unit --recursive",
"test": "istanbul cover --include-all-sources ./node_modules/.bin/_mocha -- --require babel-register --require tests/setup/setup tests/unit --recursive && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage"
"local-test": "node ./tests/setup/local/test",
"local-cover": "istanbul cover ./node_modules/.bin/_mocha -- --require babel-register --require tests/setup/local/cover tests/unit --recursive",
"test": "node ./tests/setup/ci/test && istanbul cover --include-all-sources ./node_modules/.bin/_mocha -- --require babel-register --require tests/setup/ci/cover tests/unit --recursive && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage"
},
"author": "",
"license": "ISC",
"dependencies": {
"pluralize": "^3.0.0"
},
"peerDependencies": {
"mysql": "^2.11.1"
"mysql": "^2.11.1",
"pg": "^6.1.0"
},
"devDependencies": {
"babel-plugin-transform-async-functions": "^6.8.0",
Expand All @@ -31,9 +32,11 @@
"chai": "^3.5.0",
"coveralls": "^2.11.14",
"dotenv": "^2.0.0",
"glob": "^7.1.1",
"istanbul": "^1.1.0-alpha.1",
"mocha": "^3.1.2",
"mysql": "^2.11.1",
"pg": "^6.1.0",
"sinon": "^1.17.6"
}
}
8 changes: 8 additions & 0 deletions tests/setup/ci/cover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require('babel-register')
require('babel-polyfill')

var expect = require('chai').expect
var sinon = require('sinon')

global.expect = expect
global.sinon = sinon
10 changes: 10 additions & 0 deletions tests/setup/ci/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require('babel-register')
require('babel-polyfill')

var expect = require('chai').expect
var sinon = require('sinon')

global.expect = expect
global.sinon = sinon

require('../run-drivers')
6 changes: 4 additions & 2 deletions tests/setup/local-setup.js → tests/setup/local/cover.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require('babel-register')
require('dotenv').config()
require('babel-polyfill')
import { expect } from 'chai'
import sinon from 'sinon'

var expect = require('chai').expect
var sinon = require('sinon')

global.expect = expect
global.sinon = sinon
11 changes: 11 additions & 0 deletions tests/setup/local/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require('babel-register')
require('dotenv').config()
require('babel-polyfill')

var expect = require('chai').expect
var sinon = require('sinon')

global.expect = expect
global.sinon = sinon

require('../run-drivers')
29 changes: 29 additions & 0 deletions tests/setup/run-drivers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
var Mocha = require('mocha'),
path = require('path'),
glob = require('glob');

var drivers = [
'mysql',
'postgres'
]

let files = glob.sync(process.cwd()+'/tests/unit/**/*.js')
let index = 0

function run(index) {
process.env.DB_DRIVER = drivers[index]

var mocha = new Mocha()
files.forEach(file => mocha.addFile(file))

mocha.run(failures => {
if(failures) process.exit(failures)
})
.on('end', () => {
index++
if(drivers[index]) return run(index)
process.exit()
})
}

run(index)
6 changes: 0 additions & 6 deletions tests/setup/setup.js

This file was deleted.

74 changes: 74 additions & 0 deletions tests/setup/setup.psql
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
-- ************************************************************
-- Sequel Pro SQL dump
-- Version 4541
--
-- http://www.sequelpro.com/
-- https://github.com/sequelpro/sequelpro
--
-- Host: 192.168.10.10 (MySQL 5.7.12-0ubuntu1.1)
-- Database: chat
-- Generation Time: 2016-11-07 16:42:08 +0000
-- ************************************************************


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;


-- Dump of table chats
-- ------------------------------------------------------------

DROP TABLE IF EXISTS chats;

CREATE SEQUENCE chats_seq;

CREATE TABLE chats (
id int check (id > 0) NOT NULL DEFAULT NEXTVAL ('chats_seq'),
user_id int DEFAULT NULL,
ip varchar(200) DEFAULT NULL,
user_agent varchar(200),
email varchar(200) DEFAULT NULL,
messages varchar(200),
PRIMARY KEY (id)
) ;


INSERT INTO chats (id, user_id, ip, user_agent, email, messages)
VALUES
(1,1,NULL,NULL,NULL,'blah'),
(2,23,NULL,NULL,NULL,NULL),
(3,NULL,NULL,NULL,NULL,'blah'),
(4,23,NULL,NULL,NULL,NULL),
(5,NULL,NULL,NULL,NULL,'blah'),
(6,23,NULL,NULL,NULL,NULL),
(7,NULL,NULL,NULL,NULL,'blah'),
(8,23,NULL,NULL,NULL,NULL),
(9,NULL,NULL,NULL,NULL,'blah'),
(10,23,NULL,NULL,NULL,NULL),
(11,NULL,NULL,NULL,NULL,'blah'),
(12,23,NULL,NULL,NULL,NULL);



-- Dump of table users
-- ------------------------------------------------------------

DROP TABLE IF EXISTS users;

CREATE SEQUENCE users_seq;

CREATE TABLE users (
id int check (id > 0) NOT NULL DEFAULT NEXTVAL ('users_seq'),
name varchar(11) DEFAULT NULL,
PRIMARY KEY (id)
) ;


INSERT INTO users (id, name)
VALUES
(1,'Bob');
2 changes: 1 addition & 1 deletion tests/setup/setup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ UNLOCK TABLES;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;