clickhouse-migrations 1.3.1 → 1.3.2
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/lib/cli.js +1 -1
- package/lib/migrate.js +181 -332
- package/lib/sql-parse.js +9 -9
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +18 -12
package/lib/cli.js
CHANGED
package/lib/migrate.js
CHANGED
|
@@ -1,74 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
39
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
40
|
-
if (ar || !(i in from)) {
|
|
41
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
42
|
-
ar[i] = from[i];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
46
|
-
};
|
|
47
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
48
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
49
4
|
};
|
|
50
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
6
|
exports.migration = exports.migrate = void 0;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (type === void 0) { type = 'info'; }
|
|
7
|
+
const client_1 = require("@clickhouse/client");
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
+
const sql_parse_1 = require("./sql-parse");
|
|
12
|
+
const version_1 = require("./version");
|
|
13
|
+
const log = (type = 'info', message, error) => {
|
|
60
14
|
if (type === 'info') {
|
|
61
|
-
console.log('\x1b[36m',
|
|
15
|
+
console.log('\x1b[36m', `clickhouse-migrations :`, '\x1b[0m', message);
|
|
62
16
|
}
|
|
63
17
|
else {
|
|
64
|
-
console.error('\x1b[36m',
|
|
18
|
+
console.error('\x1b[36m', `clickhouse-migrations :`, '\x1b[31m', `Error: ${message}`, error ? `\n\n ${error}` : '');
|
|
65
19
|
}
|
|
66
20
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
url
|
|
70
|
-
username
|
|
71
|
-
password
|
|
21
|
+
const connect = (url, username, password, db_name, timeout, ca_cert, cert, key) => {
|
|
22
|
+
const db_params = {
|
|
23
|
+
url,
|
|
24
|
+
username,
|
|
25
|
+
password,
|
|
72
26
|
application: 'clickhouse-migrations',
|
|
73
27
|
};
|
|
74
28
|
if (db_name) {
|
|
@@ -99,301 +53,203 @@ var connect = function (url, username, password, db_name, timeout, ca_cert, cert
|
|
|
99
53
|
}
|
|
100
54
|
return (0, client_1.createClient)(db_params);
|
|
101
55
|
};
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
_a.label = 5;
|
|
124
|
-
case 5:
|
|
125
|
-
_a.trys.push([5, 8, , 10]);
|
|
126
|
-
return [4 /*yield*/, client.query({
|
|
127
|
-
query: "SELECT 1 AS ok FROM system.databases WHERE name = {db_name:String}",
|
|
128
|
-
query_params: { db_name: db_name },
|
|
129
|
-
format: 'JSONEachRow',
|
|
130
|
-
})];
|
|
131
|
-
case 6:
|
|
132
|
-
resultSet = _a.sent();
|
|
133
|
-
return [4 /*yield*/, resultSet.json()];
|
|
134
|
-
case 7:
|
|
135
|
-
rows = (_a.sent());
|
|
136
|
-
exists = rows.length > 0;
|
|
137
|
-
return [3 /*break*/, 10];
|
|
138
|
-
case 8:
|
|
139
|
-
e_2 = _a.sent();
|
|
140
|
-
log('error', "can't verify that the database ".concat(db_name, " exists."), e_2.message);
|
|
141
|
-
return [4 /*yield*/, client.close()];
|
|
142
|
-
case 9:
|
|
143
|
-
_a.sent();
|
|
144
|
-
process.exit(1);
|
|
145
|
-
return [3 /*break*/, 10];
|
|
146
|
-
case 10:
|
|
147
|
-
if (!!exists) return [3 /*break*/, 12];
|
|
148
|
-
log('error', "the database ".concat(db_name, " doesn't exist and --skip-db-creation is set. Please create the database manually or remove --skip-db-creation."));
|
|
149
|
-
return [4 /*yield*/, client.close()];
|
|
150
|
-
case 11:
|
|
151
|
-
_a.sent();
|
|
152
|
-
process.exit(1);
|
|
153
|
-
_a.label = 12;
|
|
154
|
-
case 12: return [4 /*yield*/, client.close()];
|
|
155
|
-
case 13:
|
|
156
|
-
_a.sent();
|
|
157
|
-
return [2 /*return*/];
|
|
158
|
-
case 14:
|
|
159
|
-
q = db_engine
|
|
160
|
-
? "CREATE DATABASE IF NOT EXISTS \"".concat(db_name, "\" ").concat(db_engine)
|
|
161
|
-
: "CREATE DATABASE IF NOT EXISTS \"".concat(db_name, "\"");
|
|
162
|
-
_a.label = 15;
|
|
163
|
-
case 15:
|
|
164
|
-
_a.trys.push([15, 17, , 18]);
|
|
165
|
-
return [4 /*yield*/, client.command({
|
|
166
|
-
query: q,
|
|
167
|
-
clickhouse_settings: {
|
|
168
|
-
wait_end_of_query: 1,
|
|
169
|
-
},
|
|
170
|
-
})];
|
|
171
|
-
case 16:
|
|
172
|
-
_a.sent();
|
|
173
|
-
return [3 /*break*/, 18];
|
|
174
|
-
case 17:
|
|
175
|
-
e_3 = _a.sent();
|
|
176
|
-
log('error', "can't create the database ".concat(db_name, "."), e_3.message);
|
|
177
|
-
process.exit(1);
|
|
178
|
-
return [3 /*break*/, 18];
|
|
179
|
-
case 18: return [4 /*yield*/, client.close()];
|
|
180
|
-
case 19:
|
|
181
|
-
_a.sent();
|
|
182
|
-
return [2 /*return*/];
|
|
56
|
+
const create_db = async (host, username, password, db_name, db_engine, timeout, ca_cert, cert, key, skip_db_creation) => {
|
|
57
|
+
// Don't specify database name when creating it - connect to default database
|
|
58
|
+
const client = connect(host, username, password, undefined, timeout, ca_cert, cert, key);
|
|
59
|
+
try {
|
|
60
|
+
await client.ping();
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
log('error', `Failed to connect to ClickHouse`, e.message);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
if (skip_db_creation) {
|
|
67
|
+
// Database creation is disabled - verify the database already exists.
|
|
68
|
+
let exists = false;
|
|
69
|
+
try {
|
|
70
|
+
const resultSet = await client.query({
|
|
71
|
+
query: `SELECT 1 AS ok FROM system.databases WHERE name = {db_name:String}`,
|
|
72
|
+
query_params: { db_name },
|
|
73
|
+
format: 'JSONEachRow',
|
|
74
|
+
});
|
|
75
|
+
const rows = (await resultSet.json());
|
|
76
|
+
exists = rows.length > 0;
|
|
183
77
|
}
|
|
184
|
-
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
78
|
+
catch (e) {
|
|
79
|
+
log('error', `can't verify that the database ${db_name} exists.`, e.message);
|
|
80
|
+
await client.close();
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
if (!exists) {
|
|
84
|
+
log('error', `the database ${db_name} doesn't exist and --skip-db-creation is set. Please create the database manually or remove --skip-db-creation.`);
|
|
85
|
+
await client.close();
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
await client.close();
|
|
89
|
+
return;
|
|
190
90
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return [4 /*yield*/, client.command({
|
|
202
|
-
query: q,
|
|
203
|
-
clickhouse_settings: {
|
|
204
|
-
wait_end_of_query: 1,
|
|
205
|
-
},
|
|
206
|
-
})];
|
|
207
|
-
case 2:
|
|
208
|
-
_a.sent();
|
|
209
|
-
return [3 /*break*/, 4];
|
|
210
|
-
case 3:
|
|
211
|
-
e_4 = _a.sent();
|
|
212
|
-
log('error', "can't create the _migrations table.", e_4.message);
|
|
213
|
-
process.exit(1);
|
|
214
|
-
return [3 /*break*/, 4];
|
|
215
|
-
case 4: return [2 /*return*/];
|
|
216
|
-
}
|
|
91
|
+
// In open source ClickHouse - default DB engine is "Atomic", for Cloud - "Shared". If not set, appropriate default is used.
|
|
92
|
+
const q = db_engine
|
|
93
|
+
? `CREATE DATABASE IF NOT EXISTS "${db_name}" ${db_engine}`
|
|
94
|
+
: `CREATE DATABASE IF NOT EXISTS "${db_name}"`;
|
|
95
|
+
try {
|
|
96
|
+
await client.command({
|
|
97
|
+
query: q,
|
|
98
|
+
clickhouse_settings: {
|
|
99
|
+
wait_end_of_query: 1,
|
|
100
|
+
},
|
|
217
101
|
});
|
|
218
|
-
}
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
log('error', `can't create the database ${db_name}.`, e.message);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
await client.close();
|
|
219
108
|
};
|
|
220
|
-
|
|
221
|
-
|
|
109
|
+
const init_migration_table = async (client, table_engine = 'MergeTree') => {
|
|
110
|
+
const q = `CREATE TABLE IF NOT EXISTS _migrations (
|
|
111
|
+
uid UUID DEFAULT generateUUIDv4(),
|
|
112
|
+
version UInt32,
|
|
113
|
+
checksum String,
|
|
114
|
+
migration_name String,
|
|
115
|
+
applied_at DateTime DEFAULT now()
|
|
116
|
+
)
|
|
117
|
+
ENGINE = ${table_engine}
|
|
118
|
+
ORDER BY tuple(applied_at)`;
|
|
119
|
+
try {
|
|
120
|
+
await client.command({
|
|
121
|
+
query: q,
|
|
122
|
+
clickhouse_settings: {
|
|
123
|
+
wait_end_of_query: 1,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
log('error', `can't create the _migrations table.`, e.message);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const get_migrations = (migrations_home) => {
|
|
133
|
+
let files;
|
|
222
134
|
try {
|
|
223
135
|
files = fs_1.default.readdirSync(migrations_home);
|
|
224
136
|
}
|
|
225
137
|
catch (e) {
|
|
226
|
-
log('error',
|
|
138
|
+
log('error', `no migration directory ${migrations_home}. Please create it.`);
|
|
227
139
|
process.exit(1);
|
|
228
140
|
}
|
|
229
|
-
|
|
230
|
-
files.forEach(
|
|
141
|
+
const migrations = [];
|
|
142
|
+
files.forEach((file) => {
|
|
231
143
|
// Manage only .sql files.
|
|
232
144
|
if (!file.endsWith('.sql')) {
|
|
233
145
|
return;
|
|
234
146
|
}
|
|
235
|
-
|
|
147
|
+
const version = Number(file.split('_')[0]);
|
|
236
148
|
if (!version) {
|
|
237
|
-
log('error',
|
|
149
|
+
log('error', `a migration name should start from number, example: 1_init.sql. Please check, if the migration ${file} is named correctly`);
|
|
238
150
|
process.exit(1);
|
|
239
151
|
}
|
|
240
152
|
migrations.push({
|
|
241
|
-
version
|
|
242
|
-
file
|
|
153
|
+
version,
|
|
154
|
+
file,
|
|
243
155
|
});
|
|
244
156
|
});
|
|
245
157
|
if (!migrations) {
|
|
246
|
-
log('error',
|
|
158
|
+
log('error', `no migrations in the ${migrations_home} migrations directory`);
|
|
247
159
|
}
|
|
248
160
|
// Order by version.
|
|
249
|
-
migrations.sort(
|
|
161
|
+
migrations.sort((m1, m2) => m1.version - m2.version);
|
|
250
162
|
return migrations;
|
|
251
163
|
};
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
164
|
+
const apply_migrations = async (client, migrations, migrations_home) => {
|
|
165
|
+
let migration_query_result = [];
|
|
166
|
+
try {
|
|
167
|
+
const resultSet = await client.query({
|
|
168
|
+
query: `SELECT version, checksum, migration_name FROM _migrations ORDER BY version`,
|
|
169
|
+
format: 'JSONEachRow',
|
|
170
|
+
});
|
|
171
|
+
migration_query_result = await resultSet.json();
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
log('error', `can't select data from the _migrations table.`, e.message);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
const migrations_applied = [];
|
|
178
|
+
migration_query_result.forEach((row) => {
|
|
179
|
+
migrations_applied[row.version] = {
|
|
180
|
+
version: row.version,
|
|
181
|
+
checksum: row.checksum,
|
|
182
|
+
migration_name: row.migration_name,
|
|
183
|
+
};
|
|
184
|
+
// Check if migration file was not removed after apply.
|
|
185
|
+
const migration_exist = migrations.find(({ version }) => version === row.version);
|
|
186
|
+
if (!migration_exist) {
|
|
187
|
+
log('error', `a migration file shouldn't be removed after apply. Please, restore the migration ${row.migration_name}.`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
let applied_migrations = '';
|
|
192
|
+
for (const migration of migrations) {
|
|
193
|
+
const content = fs_1.default.readFileSync(migrations_home + '/' + migration.file).toString();
|
|
194
|
+
const checksum = crypto_1.default.createHash('md5').update(content).digest('hex');
|
|
195
|
+
if (migrations_applied[migration.version]) {
|
|
196
|
+
// Check if migration file was not changed after apply.
|
|
197
|
+
if (migrations_applied[migration.version].checksum !== checksum) {
|
|
198
|
+
log('error', `a migration file should't be changed after apply. Please, restore content of the ${migrations_applied[migration.version].migration_name} migrations.`);
|
|
274
199
|
process.exit(1);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return version === row.version;
|
|
288
|
-
});
|
|
289
|
-
if (!migration_exist) {
|
|
290
|
-
log('error', "a migration file shouldn't be removed after apply. Please, restore the migration ".concat(row.migration_name, "."));
|
|
291
|
-
process.exit(1);
|
|
292
|
-
}
|
|
200
|
+
}
|
|
201
|
+
// Skip if a migration is already applied.
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
// Extract sql from the migration.
|
|
205
|
+
const queries = (0, sql_parse_1.sql_queries)(content);
|
|
206
|
+
const sets = (0, sql_parse_1.sql_sets)(content);
|
|
207
|
+
for (const query of queries) {
|
|
208
|
+
try {
|
|
209
|
+
await client.command({
|
|
210
|
+
query: query,
|
|
211
|
+
clickhouse_settings: sets,
|
|
293
212
|
});
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
_b.label = 6;
|
|
297
|
-
case 6:
|
|
298
|
-
if (!(_i < migrations_1.length)) return [3 /*break*/, 17];
|
|
299
|
-
migration_1 = migrations_1[_i];
|
|
300
|
-
content = fs_1.default.readFileSync(migrations_home + '/' + migration_1.file).toString();
|
|
301
|
-
checksum = crypto_1.default.createHash('md5').update(content).digest('hex');
|
|
302
|
-
if (migrations_applied[migration_1.version]) {
|
|
303
|
-
// Check if migration file was not changed after apply.
|
|
304
|
-
if (migrations_applied[migration_1.version].checksum !== checksum) {
|
|
305
|
-
log('error', "a migration file should't be changed after apply. Please, restore content of the ".concat(migrations_applied[migration_1.version].migration_name, " migrations."));
|
|
306
|
-
process.exit(1);
|
|
307
|
-
}
|
|
308
|
-
// Skip if a migration is already applied.
|
|
309
|
-
return [3 /*break*/, 16];
|
|
310
|
-
}
|
|
311
|
-
queries = (0, sql_parse_1.sql_queries)(content);
|
|
312
|
-
sets = (0, sql_parse_1.sql_sets)(content);
|
|
313
|
-
_a = 0, queries_1 = queries;
|
|
314
|
-
_b.label = 7;
|
|
315
|
-
case 7:
|
|
316
|
-
if (!(_a < queries_1.length)) return [3 /*break*/, 12];
|
|
317
|
-
query = queries_1[_a];
|
|
318
|
-
_b.label = 8;
|
|
319
|
-
case 8:
|
|
320
|
-
_b.trys.push([8, 10, , 11]);
|
|
321
|
-
return [4 /*yield*/, client.command({
|
|
322
|
-
query: query,
|
|
323
|
-
clickhouse_settings: sets,
|
|
324
|
-
})];
|
|
325
|
-
case 9:
|
|
326
|
-
_b.sent();
|
|
327
|
-
return [3 /*break*/, 11];
|
|
328
|
-
case 10:
|
|
329
|
-
e_6 = _b.sent();
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
330
215
|
if (applied_migrations) {
|
|
331
|
-
log('info',
|
|
216
|
+
log('info', `The migration(s) ${applied_migrations} was successfully applied!`);
|
|
332
217
|
}
|
|
333
|
-
log('error',
|
|
334
|
-
process.exit(1);
|
|
335
|
-
return [3 /*break*/, 11];
|
|
336
|
-
case 11:
|
|
337
|
-
_a++;
|
|
338
|
-
return [3 /*break*/, 7];
|
|
339
|
-
case 12:
|
|
340
|
-
_b.trys.push([12, 14, , 15]);
|
|
341
|
-
return [4 /*yield*/, client.insert({
|
|
342
|
-
table: '_migrations',
|
|
343
|
-
values: [{ version: migration_1.version, checksum: checksum, migration_name: migration_1.file }],
|
|
344
|
-
format: 'JSONEachRow',
|
|
345
|
-
})];
|
|
346
|
-
case 13:
|
|
347
|
-
_b.sent();
|
|
348
|
-
return [3 /*break*/, 15];
|
|
349
|
-
case 14:
|
|
350
|
-
e_7 = _b.sent();
|
|
351
|
-
log('error', "can't insert a data into the table _migrations.", e_7.message);
|
|
218
|
+
log('error', `the migrations ${migration.file} has an error. Please, fix it (be sure that already executed parts of the migration would not be run second time) and re-run migration script.`, e.message);
|
|
352
219
|
process.exit(1);
|
|
353
|
-
|
|
354
|
-
case 15:
|
|
355
|
-
applied_migrations = applied_migrations ? applied_migrations + ', ' + migration_1.file : migration_1.file;
|
|
356
|
-
_b.label = 16;
|
|
357
|
-
case 16:
|
|
358
|
-
_i++;
|
|
359
|
-
return [3 /*break*/, 6];
|
|
360
|
-
case 17:
|
|
361
|
-
if (applied_migrations) {
|
|
362
|
-
log('info', "The migration(s) ".concat(applied_migrations, " was successfully applied!"));
|
|
363
|
-
}
|
|
364
|
-
else {
|
|
365
|
-
log('info', "No migrations to apply.");
|
|
366
|
-
}
|
|
367
|
-
return [2 /*return*/];
|
|
220
|
+
}
|
|
368
221
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
case 0:
|
|
376
|
-
migrations = get_migrations(migrations_home);
|
|
377
|
-
return [4 /*yield*/, create_db(host, username, password, db_name, db_engine, timeout, ca_cert, cert, key, skip_db_creation)];
|
|
378
|
-
case 1:
|
|
379
|
-
_a.sent();
|
|
380
|
-
client = connect(host, username, password, db_name, timeout, ca_cert, cert, key);
|
|
381
|
-
return [4 /*yield*/, init_migration_table(client, table_engine)];
|
|
382
|
-
case 2:
|
|
383
|
-
_a.sent();
|
|
384
|
-
return [4 /*yield*/, apply_migrations(client, migrations, migrations_home)];
|
|
385
|
-
case 3:
|
|
386
|
-
_a.sent();
|
|
387
|
-
return [4 /*yield*/, client.close()];
|
|
388
|
-
case 4:
|
|
389
|
-
_a.sent();
|
|
390
|
-
return [2 /*return*/];
|
|
222
|
+
try {
|
|
223
|
+
await client.insert({
|
|
224
|
+
table: '_migrations',
|
|
225
|
+
values: [{ version: migration.version, checksum: checksum, migration_name: migration.file }],
|
|
226
|
+
format: 'JSONEachRow',
|
|
227
|
+
});
|
|
391
228
|
}
|
|
392
|
-
|
|
393
|
-
|
|
229
|
+
catch (e) {
|
|
230
|
+
log('error', `can't insert a data into the table _migrations.`, e.message);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
applied_migrations = applied_migrations ? applied_migrations + ', ' + migration.file : migration.file;
|
|
234
|
+
}
|
|
235
|
+
if (applied_migrations) {
|
|
236
|
+
log('info', `The migration(s) ${applied_migrations} was successfully applied!`);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
log('info', `No migrations to apply.`);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
const migration = async (migrations_home, host, username, password, db_name, db_engine, table_engine, timeout, ca_cert, cert, key, skip_db_creation) => {
|
|
243
|
+
const migrations = get_migrations(migrations_home);
|
|
244
|
+
await create_db(host, username, password, db_name, db_engine, timeout, ca_cert, cert, key, skip_db_creation);
|
|
245
|
+
const client = connect(host, username, password, db_name, timeout, ca_cert, cert, key);
|
|
246
|
+
await init_migration_table(client, table_engine);
|
|
247
|
+
await apply_migrations(client, migrations, migrations_home);
|
|
248
|
+
await client.close();
|
|
249
|
+
};
|
|
394
250
|
exports.migration = migration;
|
|
395
|
-
|
|
396
|
-
|
|
251
|
+
const migrate = () => {
|
|
252
|
+
const program = new commander_1.Command();
|
|
397
253
|
program.name('clickhouse-migrations').description('ClickHouse migrations.').version(version_1.VERSION);
|
|
398
254
|
program
|
|
399
255
|
.command('migrate')
|
|
@@ -410,16 +266,9 @@ var migrate = function () {
|
|
|
410
266
|
.option('--cert <path>', 'Client certificate file path', process.env.CH_MIGRATIONS_CERT)
|
|
411
267
|
.option('--key <path>', 'Client key file path', process.env.CH_MIGRATIONS_KEY)
|
|
412
268
|
.option('--skip-db-creation', 'Skip database creation', process.env.CH_MIGRATIONS_SKIP_DB_CREATION === 'true')
|
|
413
|
-
.action(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
case 0: return [4 /*yield*/, migration(options.migrationsHome, options.host, options.user, options.password, options.db, options.dbEngine, options.tableEngine, options.timeout, options.caCert, options.cert, options.key, options.skipDbCreation)];
|
|
417
|
-
case 1:
|
|
418
|
-
_a.sent();
|
|
419
|
-
return [2 /*return*/];
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
}); });
|
|
269
|
+
.action(async (options) => {
|
|
270
|
+
await migration(options.migrationsHome, options.host, options.user, options.password, options.db, options.dbEngine, options.tableEngine, options.timeout, options.caCert, options.cert, options.key, options.skipDbCreation);
|
|
271
|
+
});
|
|
423
272
|
program.parse();
|
|
424
273
|
};
|
|
425
274
|
exports.migrate = migrate;
|
package/lib/sql-parse.js
CHANGED
|
@@ -2,30 +2,30 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sql_sets = exports.sql_queries = void 0;
|
|
4
4
|
// Extract sql queries from migrations.
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const sql_queries = (content) => {
|
|
6
|
+
const queries = content
|
|
7
7
|
.replace(/(--|#!|#\s).*(\n|\r\n|\r|$)/gm, '\n')
|
|
8
8
|
.replace(/^\s*(SET\s).*(\n|\r\n|\r|$)/gm, '')
|
|
9
9
|
.replace(/(\n|\r\n|\r)/gm, ' ')
|
|
10
10
|
.replace(/\s+/g, ' ')
|
|
11
11
|
.split(';')
|
|
12
|
-
.map(
|
|
13
|
-
.filter(
|
|
12
|
+
.map((el) => el.trim())
|
|
13
|
+
.filter((el) => el.length != 0);
|
|
14
14
|
return queries;
|
|
15
15
|
};
|
|
16
16
|
exports.sql_queries = sql_queries;
|
|
17
17
|
// Extract query settings from migrations.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const sql_sets = (content) => {
|
|
19
|
+
const sets = {};
|
|
20
|
+
const sets_arr = content
|
|
21
21
|
.replace(/(--|#!|#\s).*(\n|\r\n|\r|$)/gm, '\n')
|
|
22
22
|
.replace(/^\s*(?!SET\s).*(\n|\r\n|\r|$)/gm, '')
|
|
23
23
|
.replace(/^\s*(SET\s)/gm, '')
|
|
24
24
|
.replace(/(\n|\r\n|\r)/gm, ' ')
|
|
25
25
|
.replace(/\s+/g, '')
|
|
26
26
|
.split(';');
|
|
27
|
-
sets_arr.forEach(
|
|
28
|
-
|
|
27
|
+
sets_arr.forEach((set_full) => {
|
|
28
|
+
const set = set_full.split('=');
|
|
29
29
|
if (set[0]) {
|
|
30
30
|
sets[set[0]] = set[1];
|
|
31
31
|
}
|
package/lib/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.3.
|
|
1
|
+
export declare const VERSION = "1.3.2";
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clickhouse-migrations",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "ClickHouse Migrations",
|
|
5
5
|
"bin": {
|
|
6
6
|
"clickhouse-migrations": "lib/cli.js"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"author": "VVVi",
|
|
16
16
|
"repository": "VVVi/clickhouse-migrations",
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "rm lib/*; tsc",
|
|
18
|
+
"build": "rm -rf lib/*; tsc",
|
|
19
19
|
"test": "jest --config jestconfig.json",
|
|
20
20
|
"test:unit": "jest --config jestconfig.json --testPathPatterns=\"\\.(unit|integration)\\.test\\.ts$\"",
|
|
21
21
|
"test:e2e": "jest --config jestconfig.json --testPathPatterns=\"\\.e2e\\.test\\.ts$\"",
|
|
@@ -34,17 +34,23 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@eslint/js": "^10.0.1",
|
|
36
36
|
"@types/jest": "^30.0.0",
|
|
37
|
-
"@types/node": "^20.19.
|
|
38
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
39
|
-
"@typescript-eslint/parser": "^8.
|
|
40
|
-
"eslint": "^10.
|
|
37
|
+
"@types/node": "^20.19.43",
|
|
38
|
+
"@typescript-eslint/eslint-plugin": "^8.61.1",
|
|
39
|
+
"@typescript-eslint/parser": "^8.61.1",
|
|
40
|
+
"eslint": "^10.5.0",
|
|
41
41
|
"eslint-config-prettier": "^10.1.8",
|
|
42
|
-
"eslint-plugin-prettier": "^5.5.
|
|
43
|
-
"jest": "^30.
|
|
44
|
-
"prettier": "^3.8.
|
|
45
|
-
"ts-jest": "^29.4.
|
|
46
|
-
"typescript": "^
|
|
47
|
-
"typescript-eslint": "^8.
|
|
42
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
43
|
+
"jest": "^30.4.2",
|
|
44
|
+
"prettier": "^3.8.4",
|
|
45
|
+
"ts-jest": "^29.4.11",
|
|
46
|
+
"typescript": "^6.0.3",
|
|
47
|
+
"typescript-eslint": "^8.61.1"
|
|
48
|
+
},
|
|
49
|
+
"overrides": {
|
|
50
|
+
"js-yaml": "^4.2.0",
|
|
51
|
+
"@babel/core": "^7.29.7",
|
|
52
|
+
"test-exclude": "^8.0.0",
|
|
53
|
+
"glob": "^13.0.6"
|
|
48
54
|
},
|
|
49
55
|
"files": [
|
|
50
56
|
"lib/**/*"
|