Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added SQLite 3 Support With developmentseed/node-sqlite3 #9

Merged
merged 2 commits into from

2 participants

Curtis Schlak Ryan Sandor Richards
Curtis Schlak

Extended migrate.js to contain the encoder for SQLite 3. Changed the READMEs to mention SQLite 3 support.

Ryan Sandor Richards rsandor merged commit 8cdbfaf into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 273 additions and 25 deletions.
  1. +10 −5 README
  2. +10 −5 README.markdown
  3. +34 −0 config.sqlite3.js
  4. +219 −15 migrate.js
15 README
View
@@ -3,6 +3,8 @@ Migrate - A database agnostic migration system for Node.js
By Ryan Sandor Richards
+SQLite 3 Contribution by Curtis Schlak
+
Introduction
--------------------------------------------------------------------------------
Migrate is a tool that allows you to define database schema migrations with
@@ -14,9 +16,10 @@ Requirements
--------------------------------------------------------------------------------
1. Node.js - http://github.com/ry/node
2. node-mysql - https://github.com/felixge/node-mysql
+3. node-sqlite3 - https://github.com/developmentseed/node-sqlite3
-Please note that at the current time we only support MySQL but other DBMS' are
-on their way (next up: Postgres).
+Please note that at the current time we only support MySQL and SQLite 3 but
+other DBMS' are on their way (next up: Postgres).
Installation
--------------------------------------------------------------------------------
@@ -31,12 +34,14 @@ the directory where the migrate.js file resides.
The configuration file has the following keys:
* `dbms` - The database management system to use (currently we only support a
- a value of `'mysql'`).
+ a value of either `'mysql'` or `'sqlite3'`).
* `migration_path` - Relative path to the directory in which migrations are
stored.
* `mysql` - Just a simple client configuration for mysql. Fill out your username,
password, and any other information needed to connect to the database via
node-mysql's `Client` class.
+* `sqlite3` - Just a simple client configuration for SQLite 3. Fill out the
+ filename for the database to which you would like to connect.
How do I use migrate?
--------------------------------------------------------------------------------
@@ -258,8 +263,8 @@ Producing SQL:
Outtro
--------------------------------------------------------------------------------
So that about sums it up. Simple and easy ;). It's a very early alpha version so
-please don't hate on only having MySQL support! If you have a feature request
-feel free to send me a message and I'll try to get it in ASAP.
+please don't hate on only having MySQL and SQLite 3 support! If you have a
+feature request feel free to send me a message and I'll try to get it in ASAP.
Thanks!
15 README.markdown
View
@@ -3,6 +3,8 @@ Migrate - A database agnostic migration system for Node.js
By Ryan Sandor Richards
+SQLite 3 Contribution by Curtis Schlak
+
Introduction
--------------------------------------------------------------------------------
Migrate is a tool that allows you to define database schema migrations with
@@ -14,9 +16,10 @@ Requirements
--------------------------------------------------------------------------------
1. Node.js - http://github.com/ry/node
2. node-mysql - https://github.com/felixge/node-mysql
+3. node-sqlite3 - https://github.com/developmentseed/node-sqlite3
-Please note that at the current time we only support MySQL but other DBMS' are
-on their way (next up: Postgres).
+Please note that at the current time we only support MySQL and SQLite 3 but
+other DBMS' are on their way (next up: Postgres).
Installation
--------------------------------------------------------------------------------
@@ -31,12 +34,14 @@ the directory where the migrate.js file resides.
The configuration file has the following keys:
* `dbms` - The database management system to use (currently we only support a
- a value of `'mysql'`).
+ a value of either `'mysql'` or `'sqlite3'`).
* `migration_path` - Relative path to the directory in which migrations are
stored.
* `mysql` - Just a simple client configuration for mysql. Fill out your username,
password, and any other information needed to connect to the database via
node-mysql's `Client` class.
+* `sqlite3` - Just a simple client configuration for SQLite 3. Fill out the
+ filename for the database to which you would like to connect.
How do I use migrate?
--------------------------------------------------------------------------------
@@ -258,8 +263,8 @@ Producing SQL:
Outtro
--------------------------------------------------------------------------------
So that about sums it up. Simple and easy ;). It's a very early alpha version so
-please don't hate on only having MySQL support! If you have a feature request
-feel free to send me a message and I'll try to get it in ASAP.
+please don't hate on only having MySQL and SQLite 3 support! If you have a
+feature request feel free to send me a message and I'll try to get it in ASAP.
Thanks!
34 config.sqlite3.js
View
@@ -0,0 +1,34 @@
+/*
+ * config.sqlite3.js - A database agnostic migration system for Node.js.
+ * Copyright (c) 2012 Curtis Schlak (https://github.com/realistschuckle)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// Path to the migrations directory (relative to migrate)
+exports.migration_path = './migrations/';
+
+// Which DBMS to use for executing migrations
+exports.dbms = 'sqlite3';
+
+// Configuration for SQLite3 (filename, verbose)
+exports.sqlite3 = {
+ filename: './another.something.sqlite3',
+ verbose: true
+};
234 migrate.js
View
@@ -77,18 +77,20 @@ function CreateTable(name) {
default_value: null
};
- if (arguments.length < 1)
+ if (arguments.length == 0) {
return;
+ }
if (typeof arguments[0] == "string") {
- if (arguments.length < 2)
- return;
-
column.name = arguments[0];
- column.type = arguments[1];
-
- if (arguments[2] && typeof(arguments[2]) == "object")
- column = merge(column, arguments[2]);
+
+ if (arguments.length > 1) {
+ column.type = arguments[1];
+
+ if (arguments[2] && typeof(arguments[2]) == "object") {
+ column = merge(column, arguments[2]);
+ }
+ }
}
else if (typeof arguments[0] == 'object') {
column = merge(column, arguments[0]);
@@ -100,8 +102,8 @@ function CreateTable(name) {
}
if (!valid_type(column.type))
- return;
-
+ return column;
+
this.columns.push(column);
};
@@ -165,7 +167,7 @@ function RenameTable(old_name, new_name) {
*/
function ChangeTable(name) {
CreateTable.call(this, name);
-
+
this.remove_columns = [];
this.change_columns = [];
this.remove_indices = [];
@@ -176,8 +178,7 @@ function ChangeTable(name) {
* Alters a column and renames it.
*/
this.rename = function(old_name, new_column) {
- this.column(new_column);
- this.rename_columns[old_name] = this.columns.pop();
+ this.rename_columns[old_name] = this.column(new_column);
};
/**
@@ -286,7 +287,10 @@ function Migration(opts) {
// Encodes an object and appends it to the migrations SQL representation.
function encode(o) {
- sql += encoder.encode(o);
+ var encoding = encoder.encode(o);
+ if(encoding) {
+ sql += encoding;
+ }
}
function reset() {
@@ -563,8 +567,183 @@ Encoders['mysql'] = function() {
};
}();
+/**
+ * Translates migrations into valid SQLite 3.
+ */
+Encoders['sqlite3'] = function() {
+ // Mapping of abstract migrate types to concrete SQLite 3 types
+ var types = {
+ 'integer': 'INT',
+ 'string': 'VARCHAR',
+ 'text': 'TEXT',
+ 'float': 'FLOAT',
+ 'decimal': 'DECIMAL',
+ 'datetime': 'DATETIME',
+ 'timestamp': 'TIMESTAMP',
+ 'time': 'TIME',
+ 'date': 'DATE',
+ 'binary': 'VARBINARY',
+ 'boolean': 'TINYINT'
+ };
+
+ // Intensely helpful function for creating a SQLite type from a column object.
+ function parse_type(column) {
+ // type, limit, precision, scale
+ var type = null;
+
+ if (column.type == 'integer') {
+ if (column.limit == 1)
+ type = "TINYINT";
+ else if (column.limit == 2)
+ type = "SMALLINT";
+ else if (column.limit == 3)
+ type = "MEDIUMINT";
+ else if (column.limit == 8)
+ type = "BIGINT";
+ else
+ type = "INT";
+ }
+ else if (column.type == 'string' || column.type == 'binary') {
+ type = types[column.type];
+ if (column.limit)
+ type += "(" + column.limit + ")";
+ else
+ type += '(255)';
+ }
+ else if (column.type == 'decimal') {
+ type = types[column.type];
+ if (column.precision && column.scale) {
+ type += "(" + column.precision + "," + column.scale + ")";
+ }
+ else if (column.precision) {
+ type += "(" + column.precision + ")";
+ }
+ }
+ else
+ type = types[column.type];
+
+ if (column.not_null)
+ type += ' NOT NULL';
+
+ if (column.default_value) {
+ type += ' DEFAULT ';
+ if (column.type == 'string' || column.type == 'text')
+ type += "'" + column.default_value + "'";
+ else
+ type += column.default_value;
+ }
+
+ return type;
+ }
+
+ /*
+ * The following functions do the the actual work of generating the SQL for the encode function.
+ */
+ function create_table(table) {
+ var sql = "CREATE TABLE " + table.name, defs = [], i;
+
+ for (i = 0; i < table.columns.length; i++)
+ defs.push("\t" + table.columns[i].name + " " + parse_type(table.columns[i]));
+
+ if (table.primary_key_name)
+ defs.push("\tPRIMARY KEY (" + table.primary_key_name + ")");
+
+ if (defs.length)
+ sql += " (\n" + defs.join(",\n") + "\n)";
+
+ sql += ";\n";
+
+ for (i = 0; i < table.indices.length; i++)
+ sql += "\tCREATE INDEX IF NOT EXISTS ix_" + table.name + "_" + table.indices[i] + " ON " + table.name + "(" + table.indices[i] + ");";
+
+ return sql;
+ }
+
+ function drop_table(table) {
+ return "DROP TABLE " + table.name + ";\n";
+ }
+
+ function rename_table(table) {
+ return "ALTER TABLE " + table.old_name + " RENAME TO " + table.new_name + ";\n";
+ }
+
+ function change_table(table) {
+ if(table.primary_key_name || table.remove_columns.length || table.remove_key || table.change_columns.length || table.rename_columns.length) {
+ return exit('You can only add columns to tables in a change_table migration.');
+ }
+
+ var sql = "ALTER TABLE " + table.name, defs = [], i;
+
+ for (i = 0; i < table.columns.length; i++)
+ defs.push("\tADD COLUMN " + table.columns[i].name + " " + parse_type(table.columns[i]));
+
+ if (defs.length)
+ sql += "\n" + defs.join(",\n") + ";";
+
+ for (i = 0; i < table.indices.length; i++)
+ sql += "\nCREATE INDEX IF NOT EXISTS ix_" + table.name + "_" + table.indices[i] + " ON " + table.name + "(" + table.indices[i] + ");";
+
+ for (i = 0; i < table.remove_indices.length; i++)
+ sql += "\nDROP INDEX IF EXISTS ix_" + table.name + "_" + table.remove_indices[i] + " ON " + table.name + "(" + table.remove_indices[i] + ");";
+
+ return sql;
+ }
+
+ function add_column(column) {
+ return "ALTER TABLE " + column.table_name + " ADD COLUMN " +
+ column.name + " " + parse_type(column) + ";\n";
+ }
+
+ function rename_column(column) {
+ return exit('You can only add columns to tables in a change_table migration.');
+ }
+
+ function change_column(column) {
+ return exit('You can only add columns to tables in a change_table migration.');
+ }
+
+ function remove_column(column) {
+ return exit('You can only add columns to tables in a change_table migration.');
+ }
+
+ function add_index(index) {
+ return "CREATE INDEX IF NOT EXISTS ix_" + index.table_name + "_" + index.name + " ON " + index.table_name + "(" + index.name + ");";
+ }
+
+ function remove_index(index) {
+ return "DROP INDEX IF EXISTS ix_" + index.table_name + "_" + index.name + " ON " + index.table_name + "(" + index.name + ");";
+ }
+
+ return {
+ encode: function(o) {
+ if (o instanceof ChangeTable)
+ return change_table(o);
+ else if (o instanceof CreateTable)
+ return create_table(o);
+ else if (o instanceof DropTable)
+ return drop_table(o);
+ else if (o instanceof RenameTable)
+ return rename_table(o);
+ else if (o instanceof AddColumn)
+ return add_column(o);
+ else if (o instanceof RenameColumn)
+ return rename_column(o);
+ else if (o instanceof ChangeColumn)
+ return change_column(o);
+ else if (o instanceof RemoveColumn)
+ return remove_column(o);
+ else if (o instanceof AddIndex)
+ return add_index(o);
+ else if (o instanceof RemoveIndex)
+ return remove_index(o);
+ else
+ throw "Error: SQLite 3 Encoder Encountered Unknown Rule Type.";
+ }
+ };
+}();
+
// The real "beef" is here, this section handles the command-line usage of the module.
-var sys = require('sys'),
+var sys = require('util'),
exec = require('child_process').exec,
fs = require('fs'),
config = require('./config');
@@ -827,6 +1006,31 @@ var Connect = {
client.query("create table schema_migrations (version BIGINT);");
return main();
});
+ },
+ sqlite3: function() {
+ var sqlite3 = require("sqlite3");
+ if(config.sqlite3.verbose) {
+ sqlite3.verbose();
+ }
+ client = new sqlite3.Database(config.sqlite3.filename, function(err) {
+ if(err) {
+ return exit(err);
+ }
+ client.get("select name from sqlite_master where type=? and name=?;", "table", "schema_migrations", function(err, row) {
+ if(row) {
+ return main();
+ }
+ sys.puts("Creating migration table.");
+ client.run("create table schema_migrations(version BIGINT);", function(err) {
+ if(err) {
+ return exit(err);
+ }
+ return main();
+ });
+ });
+ });
+ client.end = function() {client = null;};
+ client.query = client.all;
}
};
Something went wrong with that request. Please try again.