Skip to content
Merged
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
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
language: node_js
node_js:
- '0.6'
- '0.8'
- '0.10'
85 changes: 45 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,58 @@ npm install sql-ddl-sync

## About

This module is used by [ORM](http://dresende.github.com/node-orm2) to synchronize model tables in the different supported
dialects. Sorry there is no API documentation for now but there are a couple of tests you can read and find out how to use
it if you want.
This module is part of [ORM](http://dresende.github.com/node-orm2). It's used synchronize model tables in supported dialects.
Sorry there is no API documentation for now but there are a couple of tests you can read and find out how to use it if you want.

## Example

Install module and install `mysql`, create a file with the contents below and change line 2 to match valid credentials.
Install `orm` & the required driver (eg: `mysql`).
Create a file with the contents below and change insert your database credentials.
Run once and you'll see table `ddl_sync_test` appear in your database. Then make some changes to it (add/drop/change columns)
and run the code again. Your table should always return to the same structure.

```js
var mysql = require("mysql");
var db = mysql.createConnection("mysql://username:password@localhost/database");

var Sync = require("sql-ddl-sync").Sync;
var sync = new Sync({
dialect : "mysql",
db : db,
debug : function (text) {
console.log("> %s", text);
}
});

sync.defineCollection("ddl_sync_test", {
id : { type : "number", primary: true, serial: true },
name : { type : "text", required: true },
age : { type : "number", rational: true },
male : { type : "boolean" },
born : { type : "date", time: true },
born2 : { type : "date" },
int2 : { type : "number", size: 2 },
int4 : { type : "number", size: 4 },
int8 : { type : "number", size: 8 },
float4 : { type : "number", rational: true, size: 4 },
float8 : { type : "number", rational: true, size: 8 },
type : { type : "enum", values: [ 'dog', 'cat'], defaultValue: 'dog', required: true },
photo : { type : "binary" }
});

sync.sync(function (err) {
if (err) {
console.log("> Sync Error");
console.log(err);
} else {
console.log("> Sync Done");
}
process.exit(0);
var orm = require("orm");
var mysql = require("mysql");
var Sync = require("sql-ddl-sync").Sync;

orm.connect("mysql://username:password@localhost/database", function (err, db) {
if (err) throw err;
var driver = db.driver;

var sync = new Sync({
dialect : "mysql",
driver : driver,
debug : function (text) {
console.log("> %s", text);
}
});

sync.defineCollection("ddl_sync_test", {
id : { type : "number", primary: true, serial: true },
name : { type : "text", required: true },
age : { type : "number", rational: true },
male : { type : "boolean" },
born : { type : "date", time: true },
born2 : { type : "date" },
int2 : { type : "number", size: 2 },
int4 : { type : "number", size: 4 },
int8 : { type : "number", size: 8 },
float4 : { type : "number", rational: true, size: 4 },
float8 : { type : "number", rational: true, size: 8 },
type : { type : "enum", values: [ 'dog', 'cat'], defaultValue: 'dog', required: true },
photo : { type : "binary" }
});

sync.sync(function (err) {
if (err) {
console.log("> Sync Error");
console.log(err);
} else {
console.log("> Sync Done");
}
process.exit(0);
});
});

```
Expand Down
135 changes: 30 additions & 105 deletions lib/Dialects/mysql.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ var columnSizes = {
floating: { 4: 'FLOAT', 8: 'DOUBLE' }
};

exports.hasCollection = function (db, name, cb) {
db.query("SHOW TABLES LIKE ?", [ name ], function (err, rows) {
exports.hasCollection = function (driver, name, cb) {
driver.execQuery("SHOW TABLES LIKE ?", [ name ], function (err, rows) {
if (err) return cb(err);

return cb(null, rows.length > 0);
});
};

exports.getCollectionProperties = function (db, name, cb) {
db.query("SHOW COLUMNS FROM ??", [ name ], function (err, cols) {
exports.getCollectionProperties = function (driver, name, cb) {
driver.execQuery("SHOW COLUMNS FROM ??", [ name ], function (err, cols) {
if (err) return cb(err);

var columns = {}, m;
Expand Down Expand Up @@ -121,73 +121,73 @@ exports.getCollectionProperties = function (db, name, cb) {
});
};

exports.createCollection = function (db, name, columns, keys, cb) {
return db.query(SQL.CREATE_TABLE({
exports.createCollection = function (driver, name, columns, keys, cb) {
return driver.execQuery(SQL.CREATE_TABLE({
name : name,
columns : columns,
keys : keys
}, exports), cb);
}, driver), cb);
};

exports.dropCollection = function (db, name, cb) {
return db.query(SQL.DROP_TABLE({
exports.dropCollection = function (driver, name, cb) {
return driver.execQuery(SQL.DROP_TABLE({
name : name
}, exports), cb);
}, driver), cb);
};

exports.addCollectionColumn = function (db, name, column, after_column, cb) {
return db.query(SQL.ALTER_TABLE_ADD_COLUMN({
exports.addCollectionColumn = function (driver, name, column, after_column, cb) {
return driver.execQuery(SQL.ALTER_TABLE_ADD_COLUMN({
name : name,
column : column,
after : after_column,
first : !after_column
}, exports), cb);
}, driver), cb);
};

exports.modifyCollectionColumn = function (db, name, column, cb) {
return db.query(SQL.ALTER_TABLE_MODIFY_COLUMN({
exports.modifyCollectionColumn = function (driver, name, column, cb) {
return driver.execQuery(SQL.ALTER_TABLE_MODIFY_COLUMN({
name : name,
column : column
}, exports), cb);
}, driver), cb);
};

exports.dropCollectionColumn = function (db, name, column, cb) {
return db.query(SQL.ALTER_TABLE_DROP_COLUMN({
exports.dropCollectionColumn = function (driver, name, column, cb) {
return driver.execQuery(SQL.ALTER_TABLE_DROP_COLUMN({
name : name,
column : column
}, exports), cb);
}, driver), cb);
};

exports.getCollectionIndexes = function (db, name, cb) {
exports.getCollectionIndexes = function (driver, name, cb) {
var q = "";
q += "SELECT index_name, column_name, non_unique ";
q += "FROM information_schema.statistics ";
q += "WHERE table_name = ?";

db.query(q, [name], function (err, rows) {
driver.execQuery(q, [name], function (err, rows) {
if (err) return cb(err);

return cb(null, convertIndexRows(rows));
});
};

exports.addIndex = function (db, name, unique, collection, columns, cb) {
return db.query(SQL.CREATE_INDEX({
exports.addIndex = function (driver, name, unique, collection, columns, cb) {
return driver.execQuery(SQL.CREATE_INDEX({
name : name,
unique : unique,
collection : collection,
columns : columns
}, exports), cb);
}, driver), cb);
};

exports.removeIndex = function (db, name, collection, cb) {
return db.query(SQL.DROP_INDEX({
exports.removeIndex = function (driver, name, collection, cb) {
return driver.execQuery(SQL.DROP_INDEX({
name : name,
collection : collection
}, exports), cb);
}, driver), cb);
};

exports.getType = function (collection, name, property) {
exports.getType = function (collection, name, property, driver) {
var type = false;

switch (property.type) {
Expand Down Expand Up @@ -230,7 +230,7 @@ exports.getType = function (collection, name, property) {
}
break;
case "enum":
type = "ENUM (" + property.values.map(exports.escapeVal) + ")";
type = "ENUM (" + property.values.map(driver.query.escapeVal) + ")";
break;
case "point":
type = "POINT";
Expand All @@ -250,7 +250,7 @@ exports.getType = function (collection, name, property) {
type += " AUTO_INCREMENT";
}
if (property.hasOwnProperty("defaultValue")) {
type += " DEFAULT " + exports.escapeVal(property.defaultValue);
type += " DEFAULT " + driver.query.escapeVal(property.defaultValue);
}

return {
Expand All @@ -259,59 +259,6 @@ exports.getType = function (collection, name, property) {
};
};

exports.escapeId = function () {
return Array.prototype.slice.apply(arguments).map(function (el) {
return "`" + el.replace(/`/g, '``') + "`";
}).join(".");
};

exports.escapeVal = function (val, timeZone) {
if (val === undefined || val === null) {
return 'NULL';
}

if (Buffer.isBuffer(val)) {
return bufferToString(val);
}

if (Array.isArray(val)) {
return arrayToList(val, timeZone || "local");
}

if (util.isDate(val)) {
val = dateToString(val, timeZone || "local");
} else {
switch (typeof val) {
case 'boolean':
return (val) ? 'true' : 'false';
case 'number':
if (!isFinite(val)) {
val = val.toString();
break;
}
return val + '';
case "object":
return objectToValues(val, timeZone || "local");
case "function":
return val(exports);
}
}

val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
switch(s) {
case "\0": return "\\0";
case "\n": return "\\n";
case "\r": return "\\r";
case "\b": return "\\b";
case "\t": return "\\t";
case "\x1a": return "\\Z";
default: return "\\" + s;
}
});

return "'" + val + "'";
};

function convertIndexRows(rows) {
var indexes = {};

Expand All @@ -332,28 +279,6 @@ function convertIndexRows(rows) {
return indexes;
}

function objectToValues(object, timeZone) {
var values = [];
for (var key in object) {
var value = object[key];

if(typeof value === 'function') {
continue;
}

values.push(exports.escapeId(key) + ' = ' + exports.escapeVal(value, timeZone));
}

return values.join(', ');
}

function arrayToList(array, timeZone) {
return "(" + array.map(function(v) {
if (Array.isArray(v)) return arrayToList(v);
return exports.escapeVal(v, timeZone);
}).join(', ') + ")";
}

function bufferToString(buffer) {
var hex = '';

Expand Down
Loading