不要怂,就是干,撸起袖子干!

Commit 644f6eff by Martin Aspeli

Support for foreign keys in creating tables

1 parent 750817c5
...@@ -45,6 +45,7 @@ module.exports = (function() { ...@@ -45,6 +45,7 @@ module.exports = (function() {
var query = "CREATE TABLE IF NOT EXISTS <%= table %> (<%= attributes%>) ENGINE=<%= engine %> <%= charset %>" var query = "CREATE TABLE IF NOT EXISTS <%= table %> (<%= attributes%>) ENGINE=<%= engine %> <%= charset %>"
, primaryKeys = [] , primaryKeys = []
, foreignKeys = {}
, attrStr = [] , attrStr = []
for (var attr in attributes) { for (var attr in attributes) {
...@@ -54,6 +55,11 @@ module.exports = (function() { ...@@ -54,6 +55,11 @@ module.exports = (function() {
if (Utils._.includes(dataType, 'PRIMARY KEY')) { if (Utils._.includes(dataType, 'PRIMARY KEY')) {
primaryKeys.push(attr) primaryKeys.push(attr)
attrStr.push(QueryGenerator.addQuotes(attr) + " " + dataType.replace(/PRIMARY KEY/, '')) attrStr.push(QueryGenerator.addQuotes(attr) + " " + dataType.replace(/PRIMARY KEY/, ''))
} else if (Utils._.includes(dataType, 'REFERENCES')) {
// MySQL doesn't support inline REFERENCES declarations: move to the end
var m = dataType.match(/^(.+) (REFERENCES.*)$/)
attrStr.push(QueryGenerator.addQuotes(attr) + " " + m[1])
foreignKeys[attr] = m[2]
} else { } else {
attrStr.push(QueryGenerator.addQuotes(attr) + " " + dataType) attrStr.push(QueryGenerator.addQuotes(attr) + " " + dataType)
} }
...@@ -72,6 +78,12 @@ module.exports = (function() { ...@@ -72,6 +78,12 @@ module.exports = (function() {
values.attributes += ", PRIMARY KEY (" + pkString + ")" values.attributes += ", PRIMARY KEY (" + pkString + ")"
} }
for (var fkey in foreignKeys) {
if(foreignKeys.hasOwnProperty(fkey)) {
values.attributes += ", FOREIGN KEY (" + QueryGenerator.addQuotes(fkey) + ") " + foreignKeys[fkey]
}
}
return Utils._.template(query)(values).trim() + ";" return Utils._.template(query)(values).trim() + ";"
}, },
...@@ -438,6 +450,27 @@ module.exports = (function() { ...@@ -438,6 +450,27 @@ module.exports = (function() {
template += " PRIMARY KEY" template += " PRIMARY KEY"
} }
if(dataType.references) {
template += " REFERENCES " + Utils.escape(dataType.references)
if(dataType.referencesKeys) {
// TODO: This isn't really right - for composite primary keys we need a different approach
template += "(" + dataType.referencesKeys.map(Utils.escape).join(', ') + ")"
} else {
template += "(" + Utils.escape('id') + ")"
}
if(dataType.onDelete) {
template += " ON DELETE " + dataType.onDeleteAction.toUpperCase()
}
if(dataType.onUpdate) {
template += " ON UPDATE " + dataType.onUpdateAction.toUpperCase()
}
}
result[name] = template result[name] = template
} else { } else {
result[name] = dataType result[name] = dataType
......
...@@ -62,7 +62,7 @@ module.exports = (function() { ...@@ -62,7 +62,7 @@ module.exports = (function() {
var values = { var values = {
table: QueryGenerator.addQuotes(tableName), table: QueryGenerator.addQuotes(tableName),
attributes: attrStr.join(", "), attributes: attrStr.join(", ")
} }
var pks = primaryKeys[tableName].map(function(pk){ var pks = primaryKeys[tableName].map(function(pk){
...@@ -556,6 +556,29 @@ module.exports = (function() { ...@@ -556,6 +556,29 @@ module.exports = (function() {
template += " PRIMARY KEY" template += " PRIMARY KEY"
} }
if(dataType.references) {
template += " REFERENCES <%= referencesTable %> (<%= referencesKeys %>)"
replacements.referencesTable = dataType.references
if(dataType.referencesKeys) {
// TODO: This isn't really right - for composite primary keys we need a different approach
replacements.referencesKeys = dataType.referencesKeys.map(Utils.escape).join(', ')
} else {
replacements.referencesKeys = Utils.escape('id')
}
if(dataType.onDelete) {
template += " ON DELETE <%= onDeleteAction %>"
replacements.onDeleteAction = dataType.onDeleteAction.toUpperCase()
}
if(dataType.onUpdate) {
template += " ON UPDATE <%= onUpdateAction %>"
replacements.onUpdateAction = dataType.onUpdateAction.toUpperCase()
}
}
result[name] = Utils._.template(template)(replacements) result[name] = Utils._.template(template)(replacements)
} else { } else {
result[name] = dataType result[name] = dataType
......
...@@ -217,6 +217,29 @@ module.exports = (function() { ...@@ -217,6 +217,29 @@ module.exports = (function() {
} }
} }
if(dataType.references) {
template += " REFERENCES <%= referencesTable %> (<%= referencesKeys %>)"
replacements.referencesTable = dataType.references
if(dataType.referencesKeys) {
// TODO: This isn't really right - for composite primary keys we need a different approach
replacements.referencesKeys = dataType.referencesKeys.map(Utils.escape).join(', ')
} else {
replacements.referencesKeys = Utils.escape('id')
}
if(dataType.onDelete) {
template += " ON DELETE <%= onDeleteAction %>"
replacements.onDeleteAction = dataType.onDeleteAction.toUpperCase()
}
if(dataType.onUpdate) {
template += " ON UPDATE <%= onUpdateAction %>"
replacements.onUpdateAction = dataType.onUpdateAction.toUpperCase()
}
}
result[name] = Utils._.template(template)(replacements) result[name] = Utils._.template(template)(replacements)
} else { } else {
result[name] = dataType result[name] = dataType
......
...@@ -10,6 +10,9 @@ describe('QueryGenerator', function() { ...@@ -10,6 +10,9 @@ describe('QueryGenerator', function() {
afterEach(function() { Helpers.drop() }) afterEach(function() { Helpers.drop() })
var suites = { var suites = {
// TODO: Test attributesToSQL
createTableQuery: [ createTableQuery: [
{ {
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}], arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
...@@ -26,6 +29,14 @@ describe('QueryGenerator', function() { ...@@ -26,6 +29,14 @@ describe('QueryGenerator', function() {
{ {
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}, {charset: 'latin1'}], arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}, {charset: 'latin1'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` ENUM(\"A\", \"B\", \"C\"), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=latin1;" expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` ENUM(\"A\", \"B\", \"C\"), `name` VARCHAR(255)) ENGINE=InnoDB DEFAULT CHARSET=latin1;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `id` INTEGER , PRIMARY KEY (`id`)) ENGINE=InnoDB;"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `otherId` INTEGER, FOREIGN KEY (`otherId`) REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB;"
} }
], ],
......
...@@ -14,6 +14,9 @@ describe('QueryGenerator', function() { ...@@ -14,6 +14,9 @@ describe('QueryGenerator', function() {
afterEach(function() { Helpers.drop() }) afterEach(function() { Helpers.drop() })
var suites = { var suites = {
// TODO: Test attributesToSQL
createTableQuery: [ createTableQuery: [
{ {
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}], arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
...@@ -26,6 +29,14 @@ describe('QueryGenerator', function() { ...@@ -26,6 +29,14 @@ describe('QueryGenerator', function() {
{ {
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}], arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "DROP TYPE IF EXISTS \"enum_myTable_title\"; CREATE TYPE \"enum_myTable_title\" AS ENUM(\"A\", \"B\", \"C\"); CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" \"enum_myTable_title\", \"name\" VARCHAR(255));" expectation: "DROP TYPE IF EXISTS \"enum_myTable_title\"; CREATE TYPE \"enum_myTable_title\" AS ENUM(\"A\", \"B\", \"C\"); CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" \"enum_myTable_title\", \"name\" VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255), \"id\" INTEGER , PRIMARY KEY (\"id\"));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES "otherTable" ("id") ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS \"myTable\" (\"title\" VARCHAR(255), \"name\" VARCHAR(255), \"otherId\" INTEGER REFERENCES \"otherTable\" (\"id\") ON DELETE CASCADE ON UPDATE NO ACTION);"
} }
], ],
......
...@@ -9,6 +9,36 @@ describe('QueryGenerator', function() { ...@@ -9,6 +9,36 @@ describe('QueryGenerator', function() {
afterEach(function() { Helpers.drop() }) afterEach(function() { Helpers.drop() })
var suites = { var suites = {
// TODO: Test attributesToSQL
createTableQuery: [
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'ENUM("A", "B", "C")', name: 'VARCHAR(255)'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` ENUM(\"A\", \"B\", \"C\"), `name` VARCHAR(255));"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', id: 'INTEGER PRIMARY KEY'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `id` INTEGER PRIMARY KEY);"
},
{
arguments: ['myTable', {title: 'VARCHAR(255)', name: 'VARCHAR(255)', otherId: 'INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION'}],
expectation: "CREATE TABLE IF NOT EXISTS `myTable` (`title` VARCHAR(255), `name` VARCHAR(255), `otherId` INTEGER REFERENCES `otherTable` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION);"
}
],
insertQuery: [ insertQuery: [
{ {
arguments: ['myTable', { name: 'foo' }], arguments: ['myTable', { name: 'foo' }],
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!