db-migrate 1.0.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +487 -0
- package/LICENSE +22 -0
- package/README.md +100 -0
- package/api.js +463 -0
- package/bin/db-migrate +39 -0
- package/connect.js +198 -0
- package/get.js +67 -0
- package/index.js +85 -0
- package/lib/chain.js +157 -0
- package/lib/class.js +75 -0
- package/lib/commands/check.js +52 -0
- package/lib/commands/create-migration.js +252 -0
- package/lib/commands/db.js +63 -0
- package/lib/commands/down.js +45 -0
- package/lib/commands/dump.js +22 -0
- package/lib/commands/fn/plugin.js +45 -0
- package/lib/commands/generated.js +32 -0
- package/lib/commands/helper/assert.js +15 -0
- package/lib/commands/helper/load-config.js +26 -0
- package/lib/commands/helper/migration-hook.js +4 -0
- package/lib/commands/helper/register-events.js +19 -0
- package/lib/commands/index.js +9 -0
- package/lib/commands/on-complete.js +28 -0
- package/lib/commands/run.js +122 -0
- package/lib/commands/seed.js +48 -0
- package/lib/commands/set-default-argv.js +169 -0
- package/lib/commands/sync.js +52 -0
- package/lib/commands/undo-seed.js +54 -0
- package/lib/commands/up.js +52 -0
- package/lib/config.js +207 -0
- package/lib/driver/index.js +156 -0
- package/lib/driver/shadow.js +74 -0
- package/lib/executors/versioned/v1.js +48 -0
- package/lib/executors/versioned/v2.js +78 -0
- package/lib/file.js +190 -0
- package/lib/interface/migratorInterface.js +127 -0
- package/lib/interface/seederInterface.js +145 -0
- package/lib/learn.js +369 -0
- package/lib/methods/v2/conventions.js +47 -0
- package/lib/methods/v2/migrate.js +5 -0
- package/lib/methods/v2/statetravel.js +86 -0
- package/lib/methods/v2/translatestate.js +117 -0
- package/lib/relation.js +37 -0
- package/lib/state.js +154 -0
- package/lib/template.js +312 -0
- package/lib/templates/v2.js +12 -0
- package/lib/temputils.js +62 -0
- package/lib/walker.js +266 -0
- package/package.json +87 -0
- package/pnpm-lock.yaml +2574 -0
- package/te.js +70 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Promise = require('bluebird');
|
|
4
|
+
const State = require('../../state');
|
|
5
|
+
const log = require('db-migrate-shared').log;
|
|
6
|
+
const Learn = require('../../learn');
|
|
7
|
+
const Chain = require('../../chain');
|
|
8
|
+
const StateTravel = require('../../methods/v2/statetravel');
|
|
9
|
+
const Migrate = require('../../methods/v2/migrate');
|
|
10
|
+
const TranslateState = require('../../methods/v2/translatestate');
|
|
11
|
+
const AddConventions = require('../../methods/v2/conventions');
|
|
12
|
+
|
|
13
|
+
const execUnit = {
|
|
14
|
+
_extend: (context, type) => {
|
|
15
|
+
return {
|
|
16
|
+
atomic: function (actions) {
|
|
17
|
+
const action = actions[type];
|
|
18
|
+
const reverse = actions[type === 'up' ? 'up' : 'down'];
|
|
19
|
+
|
|
20
|
+
if (!action || !reverse) {
|
|
21
|
+
return Promise.reject(new Error('invalid operation'));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return action().catch(() => reverse());
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
up: async function (context, driver, file) {
|
|
30
|
+
const _file = file.get();
|
|
31
|
+
const chain = new Chain(context._driver, file, driver, context.internals);
|
|
32
|
+
if (!_file._meta.noDefaultColumn) {
|
|
33
|
+
chain.addChain(AddConventions);
|
|
34
|
+
}
|
|
35
|
+
chain.addChain(Learn);
|
|
36
|
+
chain.addChain(StateTravel);
|
|
37
|
+
chain.addChain(Migrate);
|
|
38
|
+
|
|
39
|
+
await State.startMigration(context._driver, file, context.internals);
|
|
40
|
+
// startMigration - needs secondary instance since we can not afford to
|
|
41
|
+
// loose state and the transaction start will include these for roll back
|
|
42
|
+
// we will disable them probably at all from DDL when the driver does not
|
|
43
|
+
// explicitly signal DDL transaction support (like crdb)
|
|
44
|
+
try {
|
|
45
|
+
await _file.migrate(chain, {
|
|
46
|
+
options: context.internals.safeOptions,
|
|
47
|
+
seedLink: context.seedLink,
|
|
48
|
+
dbm: context.internals.safeOptions.dbmigrate
|
|
49
|
+
});
|
|
50
|
+
} catch (err) {
|
|
51
|
+
context.internals.rollback = true;
|
|
52
|
+
|
|
53
|
+
// transfer last state
|
|
54
|
+
chain.transferInt();
|
|
55
|
+
|
|
56
|
+
log.error(
|
|
57
|
+
'An error occured. No alternative failure strategy defined. Rolling back!',
|
|
58
|
+
err
|
|
59
|
+
);
|
|
60
|
+
await execUnit.down(context, driver, file);
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
await Promise.promisify(context.writeMigrationRecord.bind(context))(file);
|
|
64
|
+
return State.endMigration(context._driver, file, context.internals);
|
|
65
|
+
// end migration, same as start migration
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
down: async function (context, driver, file) {
|
|
69
|
+
// start migration, see up comments
|
|
70
|
+
await State.startMigration(context._driver, file, context.internals);
|
|
71
|
+
await TranslateState(context._driver, file, driver, context.internals);
|
|
72
|
+
await State.endMigration(context._driver, file, context.internals);
|
|
73
|
+
return Promise.promisify(context.deleteMigrationRecord.bind(context))(file);
|
|
74
|
+
// end migration, see up comments
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
module.exports = execUnit;
|
package/lib/file.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const log = require('db-migrate-shared').log;
|
|
6
|
+
const inflection = require('inflection');
|
|
7
|
+
const Promise = require('bluebird');
|
|
8
|
+
const lpad = require('db-migrate-shared').util.lpad;
|
|
9
|
+
|
|
10
|
+
Promise.promisifyAll(fs);
|
|
11
|
+
|
|
12
|
+
const LOADER = {
|
|
13
|
+
seeder: 'allLoadedSeedsAsync',
|
|
14
|
+
migration: 'allLoadedMigrationsAsync'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function formatPath (dir, name) {
|
|
18
|
+
return path.join(dir, name);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function formatName (title, date) {
|
|
22
|
+
return formatDate(date) + '-' + formatTitle(title);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function formatDate (date) {
|
|
26
|
+
return [
|
|
27
|
+
date.getUTCFullYear(),
|
|
28
|
+
lpad(date.getUTCMonth() + 1, '0', 2),
|
|
29
|
+
lpad(date.getUTCDate(), '0', 2),
|
|
30
|
+
lpad(date.getUTCHours(), '0', 2),
|
|
31
|
+
lpad(date.getUTCMinutes(), '0', 2),
|
|
32
|
+
lpad(date.getUTCSeconds(), '0', 2)
|
|
33
|
+
].join('');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function formatTitle (title) {
|
|
37
|
+
return inflection.dasherize(title);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function parseDate (name) {
|
|
41
|
+
const date = new Date();
|
|
42
|
+
const match = name.match(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})-[^.]+/);
|
|
43
|
+
date.setUTCFullYear(match[1]);
|
|
44
|
+
date.setUTCDate(match[3]);
|
|
45
|
+
date.setUTCMonth(match[2] - 1);
|
|
46
|
+
date.setUTCHours(match[4]);
|
|
47
|
+
date.setUTCMinutes(match[5]);
|
|
48
|
+
date.setUTCSeconds(match[6]);
|
|
49
|
+
return date;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function parseTitle (name) {
|
|
53
|
+
const match = name.match(/\d{14}-([^.]+)/);
|
|
54
|
+
return inflection.humanize(match[1], true);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const filesRegEx = /\.js$/;
|
|
58
|
+
|
|
59
|
+
const File = function () {
|
|
60
|
+
if (arguments.length >= 3) {
|
|
61
|
+
this.title = arguments[0];
|
|
62
|
+
this.date = arguments[2];
|
|
63
|
+
this.name = this.formatName(this.title, this.date);
|
|
64
|
+
this.path = this.formatPath(arguments[1], this.name);
|
|
65
|
+
this.internals = arguments[4];
|
|
66
|
+
} else if (arguments.length === 2) {
|
|
67
|
+
this.path = arguments[0];
|
|
68
|
+
this.name = this.parseName(this.path);
|
|
69
|
+
this.date = this.parseDate(this.name);
|
|
70
|
+
this.title = this.parseTitle(this.name);
|
|
71
|
+
this.internals = arguments[1];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (this.internals) this.internals = this.internals.safeOptions;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
File.prototype = {
|
|
78
|
+
parseName: function (path) {
|
|
79
|
+
const match = path.match(/(\d{14}-[^.]+)(?:\.*?)?/);
|
|
80
|
+
return match[1];
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
get: function () {
|
|
84
|
+
return this._required || (this._required = require(this.path));
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
write: function (data) {
|
|
88
|
+
return fs.writeFileAsync(this.path, data);
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
parseTitle: parseTitle,
|
|
92
|
+
parseDate: parseDate,
|
|
93
|
+
formatTitle: formatTitle,
|
|
94
|
+
formatPath: formatPath,
|
|
95
|
+
formatName: formatName
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
File.registerHook = function (Plugin, internals) {
|
|
99
|
+
const plugin = [].concat(Plugin.hook('file:hook:require') || []).concat(
|
|
100
|
+
Plugin.hook('migrator:migration:hook:require') || [] // backwards compatible
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
internals.parser = internals.parser || {
|
|
104
|
+
filesRegEx: filesRegEx,
|
|
105
|
+
extensions: 'js'
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
if (!plugin) {
|
|
109
|
+
return Promise.resolve(null);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return Promise.resolve(plugin)
|
|
113
|
+
.map(function (plugin) {
|
|
114
|
+
// Backwards compatibility and notice for everyone so they
|
|
115
|
+
// can bug the plugin maintainer
|
|
116
|
+
if (plugin['migrator:migration:hook:require']) {
|
|
117
|
+
log.warn(
|
|
118
|
+
`The plugin '${plugin.name}' is outdated! The hook` +
|
|
119
|
+
`migrator:migration:hook:require was deprecated!`
|
|
120
|
+
);
|
|
121
|
+
log.warn(
|
|
122
|
+
`Report the maintainer of '${plugin.name}' to patch the ` +
|
|
123
|
+
`hook instead with file:hook:require.`
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
if (plugin.maintainer && plugin.maintainer.repository) {
|
|
127
|
+
log.verbose(
|
|
128
|
+
`The repo of the ${plugin.name} plugin is ${plugin.maintainer.repository}!`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return plugin['migrator:migration:hook:require']();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return plugin['file:hook:require']();
|
|
135
|
+
})
|
|
136
|
+
.each(function (parser) {
|
|
137
|
+
if (parser && parser.extensions) {
|
|
138
|
+
internals.parser.extensions =
|
|
139
|
+
internals.parser.extensions + '|' + parser.extensions;
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
.then(function () {
|
|
143
|
+
internals.parser.filesRegEx = new RegExp(
|
|
144
|
+
'\\.(' + internals.parser.extensions + ')$'
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
return internals.parser;
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
File.loadFromFileystem = function (dir, prefix, internals) {
|
|
152
|
+
log.verbose(`[${prefix}] loading from dir`, dir);
|
|
153
|
+
|
|
154
|
+
return fs
|
|
155
|
+
.readdirAsync(dir)
|
|
156
|
+
.filter(function (files) {
|
|
157
|
+
return internals.parser.filesRegEx.test(files);
|
|
158
|
+
})
|
|
159
|
+
.then(function (files) {
|
|
160
|
+
return files.sort();
|
|
161
|
+
})
|
|
162
|
+
.map(function (file) {
|
|
163
|
+
return new File(path.join(dir, file), internals);
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
File.loadFromDatabase = function (dir, prefix, driver, internals) {
|
|
168
|
+
log.verbose(`[${prefix}] loading from database`);
|
|
169
|
+
return driver[LOADER[prefix]]()
|
|
170
|
+
.catch(function (err) {
|
|
171
|
+
if (internals.dryRun) {
|
|
172
|
+
return [];
|
|
173
|
+
} else {
|
|
174
|
+
return Promise.reject(err);
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
.filter(function (result) {
|
|
178
|
+
return (
|
|
179
|
+
result.name.substr(0, result.name.lastIndexOf('/')) ===
|
|
180
|
+
internals.matching
|
|
181
|
+
);
|
|
182
|
+
})
|
|
183
|
+
.map(function (result) {
|
|
184
|
+
return new File(path.join(dir, result.name), internals);
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
Promise.promisifyAll(fs);
|
|
189
|
+
|
|
190
|
+
module.exports = File;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The migrator interface provides the ability to handle all abilities which
|
|
3
|
+
* are needed to successfully modify the DD of your tables.
|
|
4
|
+
* This includes all DDL methods provided by SQL naturally.
|
|
5
|
+
*
|
|
6
|
+
* Considering the zero downtime deployment we are handling migrations like
|
|
7
|
+
* the following:
|
|
8
|
+
*
|
|
9
|
+
* Zero Downtime notes
|
|
10
|
+
*
|
|
11
|
+
* *) The very first step is always a full dump, for the sake of security
|
|
12
|
+
*
|
|
13
|
+
* - all operations that are deleting a currently existing column, e.g. renaming a column:
|
|
14
|
+
* - 1. duplicate the column
|
|
15
|
+
* - if renamed:
|
|
16
|
+
* - 1. create a trigger to update both columns
|
|
17
|
+
* - 2. disable/delete trigger after successful deployment
|
|
18
|
+
* - if deleted:
|
|
19
|
+
* - 1. apply steps from the renaming process
|
|
20
|
+
* - 2. create a backup of this column (+PK)/table and delete it afterwards (after the successful deployment)
|
|
21
|
+
* - all operations that modify content
|
|
22
|
+
* - 1. Retrieve data to be applied
|
|
23
|
+
* - 2. Extract PKs of to be updated rows
|
|
24
|
+
* - 3. Create backup of to be updated rows
|
|
25
|
+
* - 4. Apply changes
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
function dummy () {
|
|
29
|
+
arguments[arguments.length - 1]('not implemented');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function MigratorInterface () {}
|
|
33
|
+
|
|
34
|
+
MigratorInterface.prototype = {
|
|
35
|
+
renameCollection: dummy,
|
|
36
|
+
|
|
37
|
+
dropCollection: dummy,
|
|
38
|
+
|
|
39
|
+
createCollection: dummy,
|
|
40
|
+
|
|
41
|
+
checkDBMS: dummy,
|
|
42
|
+
|
|
43
|
+
createDatabase: dummy,
|
|
44
|
+
|
|
45
|
+
switchDatabase: dummy,
|
|
46
|
+
|
|
47
|
+
dropDatabase: dummy,
|
|
48
|
+
|
|
49
|
+
bindForeignKey: dummy,
|
|
50
|
+
|
|
51
|
+
createTable: dummy,
|
|
52
|
+
|
|
53
|
+
dropTable: dummy,
|
|
54
|
+
|
|
55
|
+
renameTable: dummy,
|
|
56
|
+
|
|
57
|
+
addColumn: dummy,
|
|
58
|
+
|
|
59
|
+
removeColumn: dummy,
|
|
60
|
+
|
|
61
|
+
renameColumn: dummy,
|
|
62
|
+
|
|
63
|
+
changeColumn: dummy,
|
|
64
|
+
|
|
65
|
+
addIndex: dummy,
|
|
66
|
+
|
|
67
|
+
removeIndex: dummy,
|
|
68
|
+
|
|
69
|
+
addForeignKey: dummy,
|
|
70
|
+
|
|
71
|
+
removeForeignKey: dummy,
|
|
72
|
+
|
|
73
|
+
createMigrationsTable: dummy,
|
|
74
|
+
|
|
75
|
+
createSeedsTable: dummy,
|
|
76
|
+
|
|
77
|
+
normalizeColumnSpec: dummy,
|
|
78
|
+
|
|
79
|
+
runSql: dummy,
|
|
80
|
+
|
|
81
|
+
createColumnDef: dummy,
|
|
82
|
+
|
|
83
|
+
mapDataType: dummy,
|
|
84
|
+
|
|
85
|
+
createColumnConstraint: dummy,
|
|
86
|
+
|
|
87
|
+
recurseCallbackArray: dummy,
|
|
88
|
+
|
|
89
|
+
allLoadedMigrations: dummy,
|
|
90
|
+
|
|
91
|
+
allLoadedSeeds: dummy,
|
|
92
|
+
|
|
93
|
+
addSeedRecord: dummy,
|
|
94
|
+
|
|
95
|
+
startMigration: dummy,
|
|
96
|
+
|
|
97
|
+
endMigration: dummy,
|
|
98
|
+
|
|
99
|
+
addMigrationRecord: dummy,
|
|
100
|
+
|
|
101
|
+
deleteMigration: dummy,
|
|
102
|
+
|
|
103
|
+
deleteSeed: dummy,
|
|
104
|
+
|
|
105
|
+
quoteDDLArr: dummy,
|
|
106
|
+
|
|
107
|
+
quoteArr: dummy,
|
|
108
|
+
|
|
109
|
+
escapeString: dummy,
|
|
110
|
+
|
|
111
|
+
escape: dummy,
|
|
112
|
+
|
|
113
|
+
escapeDDL: dummy,
|
|
114
|
+
|
|
115
|
+
all: dummy,
|
|
116
|
+
|
|
117
|
+
close: dummy,
|
|
118
|
+
|
|
119
|
+
insert: dummy
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
module.exports = MigratorInterface;
|
|
123
|
+
module.exports.deprecated = {};
|
|
124
|
+
|
|
125
|
+
module.exports.extending = {};
|
|
126
|
+
|
|
127
|
+
module.exports.exclude = {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seeder interface provides the ability to handle all operations, that
|
|
3
|
+
* are not DDL specific and thus not a migration.
|
|
4
|
+
*
|
|
5
|
+
* These operations are currently, but not limited to:
|
|
6
|
+
*
|
|
7
|
+
* inserting data
|
|
8
|
+
* removing data
|
|
9
|
+
* searching data
|
|
10
|
+
* truncating whole tables
|
|
11
|
+
*
|
|
12
|
+
* This functionality is provided in two ways to the user. First there are
|
|
13
|
+
* traditional seeder. You can call them whenever you want, and how often
|
|
14
|
+
* you want. This might be handy when initializing a new development
|
|
15
|
+
* environment, but not if you want to use it for the production environment.
|
|
16
|
+
*
|
|
17
|
+
* The second seeder type, the version controlled seeders, short VC Seeds,
|
|
18
|
+
* is targeting the production environment and development environment.
|
|
19
|
+
* There is technically no big difference between them, except the following
|
|
20
|
+
* details:
|
|
21
|
+
*
|
|
22
|
+
* A VC Seed can be called from a migration, via seed.execute and seed.link. A
|
|
23
|
+
* normal seeder can not. Also A VC Seeder has a down and up function, like
|
|
24
|
+
* the way the migrations work, the static has a truncate function instead,
|
|
25
|
+
* which gets called before the seed function. This is because a seeder is
|
|
26
|
+
* mostly used to initialize something, a VC Seeder instead is used to
|
|
27
|
+
* populate changes made to the dataset and to have a clear separation of
|
|
28
|
+
* DDL and Data Maniupulations.
|
|
29
|
+
* And last but not least, a VC Seed can not be executed if it was already
|
|
30
|
+
* executed. You will need to roll back it first, it just acts pretty similar
|
|
31
|
+
* to migrations. A normal seed can be executed just as often as you want
|
|
32
|
+
* without the need to rollback your data.
|
|
33
|
+
*
|
|
34
|
+
* To note: If you rollback a migration, linked to a seeder, db-migrate will
|
|
35
|
+
* also rollback the seed. This is also a reason why you can't rollback a
|
|
36
|
+
* specific migration, you would going to break that much, you probably loose
|
|
37
|
+
* a bunch of valueable time.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
var Promise = require('bluebird');
|
|
41
|
+
|
|
42
|
+
function insert (table, options, callback) {
|
|
43
|
+
var foreignLinkage = this.foreignLinkage[table];
|
|
44
|
+
|
|
45
|
+
for (var o = 0; o < options.length; ++o) {
|
|
46
|
+
var option = Object.keys(options[o]);
|
|
47
|
+
|
|
48
|
+
for (var i = 0; i < option.length; ++i) {
|
|
49
|
+
if (typeof options[option[i]] === 'object') {
|
|
50
|
+
if (options[option[i]].type === 'lookup') {
|
|
51
|
+
if (!options[option[i]].table) {
|
|
52
|
+
if (foreignLinkage[option[i]]) {
|
|
53
|
+
options[option[i]].table = foreignLinkage[option[i]].table;
|
|
54
|
+
options[option[i]].field = foreignLinkage[option[i]].field;
|
|
55
|
+
} else {
|
|
56
|
+
return Promise.reject(
|
|
57
|
+
new Error('missing foreign key linkage!')
|
|
58
|
+
).nodeify(callback);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return lookup(options)
|
|
67
|
+
.then(function () {
|
|
68
|
+
return this.driver.insert(options);
|
|
69
|
+
})
|
|
70
|
+
.catch(function (e) {
|
|
71
|
+
throw e;
|
|
72
|
+
})
|
|
73
|
+
.nodeify(callback);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function lookup (options) {
|
|
77
|
+
var lookups = [];
|
|
78
|
+
var i = 0;
|
|
79
|
+
|
|
80
|
+
for (var o = 0; o < options.length; ++o) {
|
|
81
|
+
var option = Object.keys(options[o]);
|
|
82
|
+
|
|
83
|
+
for (; i < option.length; ++i) {
|
|
84
|
+
if (typeof options[option] === 'object') {
|
|
85
|
+
if (options[option].type === 'lookup') {
|
|
86
|
+
lookups.push(
|
|
87
|
+
this.driver.lookup(options[option]).catch(function (err) {
|
|
88
|
+
throw err;
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return Promise.settle(lookups);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function dummy () {
|
|
100
|
+
arguments[arguments.length - 1]('not implemented');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
var SeederInterface = {
|
|
104
|
+
lookup: dummy,
|
|
105
|
+
|
|
106
|
+
insert: dummy,
|
|
107
|
+
|
|
108
|
+
delete: dummy,
|
|
109
|
+
|
|
110
|
+
runSql: dummy,
|
|
111
|
+
|
|
112
|
+
buildWhereClause: dummy,
|
|
113
|
+
|
|
114
|
+
quoteDDLArr: dummy,
|
|
115
|
+
|
|
116
|
+
quoteArr: dummy,
|
|
117
|
+
|
|
118
|
+
escapeString: dummy,
|
|
119
|
+
|
|
120
|
+
escape: dummy,
|
|
121
|
+
|
|
122
|
+
escapeDDL: dummy,
|
|
123
|
+
|
|
124
|
+
checkDBMS: dummy,
|
|
125
|
+
|
|
126
|
+
update: dummy,
|
|
127
|
+
|
|
128
|
+
truncate: dummy,
|
|
129
|
+
|
|
130
|
+
switchDatabase: dummy,
|
|
131
|
+
|
|
132
|
+
remove: dummy,
|
|
133
|
+
|
|
134
|
+
close: dummy
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
module.exports = SeederInterface;
|
|
138
|
+
module.exports.deprecated = {};
|
|
139
|
+
module.exports.extending = {
|
|
140
|
+
_l: function (field) {
|
|
141
|
+
return { type: 'lookup', field: field };
|
|
142
|
+
},
|
|
143
|
+
__Test__insert: insert,
|
|
144
|
+
__Test__lookup: lookup
|
|
145
|
+
};
|