-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
118 lines (107 loc) · 4.88 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { v4 as uuidv4 } from 'uuid';
import getUuid from 'uuid-by-string';
let options = {
idempotent: false
};
const now = new Date();
export const createTable = (tableName, documents, _options, callback, schema = {}, columns, idx = 0) => {
options = { ...options, ..._options };
if (!schema[tableName]) {
schema[tableName] = { columns: {}, length: 0, queries: {}, rows: [] };
// console.log(`CREATE TABLE '${tableName}' ('yosql_id' INTEGER PRIMARY KEY UNIQUE);`);
schema[tableName]['columns']['yosql_id'] = { type: 'UUID PRIMARY KEY UNIQUE', order: 0 };
schema[tableName]['columns']['yosql_created_at'] = { type: 'TEXT', order: 1 };
schema[tableName].queries.create = `CREATE TABLE ${'`' + tableName + '`'} (yosql_id UUID PRIMARY KEY UNIQUE, yosql_created_at TEXT);`;
return createTable(tableName, documents, options, callback, schema, columns, idx);
} else if (columns && idx < columns.length) {
return addColumn(tableName, columns[idx], () => {
return createTable(tableName, documents, options, callback, schema, columns, ++idx);
}, schema);
} else if (!columns && documents.length) {
columns = Object.keys(documents[0]).filter(key => {
return parseValue(typeof documents[0][key]) !== 'object';
});
return addColumn(tableName, columns[idx], () => {
return createTable(tableName, documents, options, callback, schema, columns, ++idx);
}, schema);
}
columns = columns || [];
return insertRows(tableName, columns, documents, callback, schema);
}
const parseValue = value => {
if (typeof value === 'object') {
if (value instanceof Date) return value.toISOString();
else if (Array.isArray(value)) return value;
else if (value === null) return 'NULL';
else return [value];
} else if (value === undefined) return 'NULL';
else if (value === '') return 'NULL';
else if (typeof value === 'string') return value.replace(/\'/g,"''")
return value;
}
const insertRows = (tableName, columns, documents, callback, schema) => {
documents.forEach(document => {
document.yosql_id = document.yosql_id || (options.idempotent ? getUuid(document[options.idempotent]) : uuidv4());
document.yosql_created_at = document.yosql_created_at || now.toISOString();
return insertRow(tableName, columns, document, schema);
});
const columnNames = [];
Object.keys(schema[tableName].columns).forEach(column => {
columnNames[schema[tableName].columns[column].order] = column;
});
const inserts = schema[tableName].rows.map(row => {
const filledRow = [];
columnNames.forEach((column, idx) => {
filledRow[idx] = row.hasOwnProperty(column) ? row[column] : 'NULL';
});
return `'${filledRow.join("', '")}'`;
}).join('), (');
schema[tableName].queries.insert = `INSERT INTO \`${tableName}\` (\`${columnNames.join('`, `')}\`) VALUES (${inserts});`.split("'NULL'").join('NULL');
return callback(null, schema);
}
const insertRow = (tableName, columns, document, schema) => {
const newColumn = Object.keys(document).find(key => {
return !columns.includes(key);
});
if (newColumn) {
document[newColumn] = parseValue(document[newColumn]);
if (Array.isArray(document[newColumn])) {
if (document[newColumn].length) {
if (typeof parseValue(document[newColumn][0]) === 'string') {
document[newColumn] = document[newColumn].map(item => {
const obj = {};
obj[newColumn] = parseValue(item);
return obj;
});
}
document[newColumn].map((obj) => {
return obj || {};
}).forEach(obj => {
return obj[`${tableName}_yosql_id`] = document['yosql_id'];
});
// console.log(`${tableName}_${newColumn}`);
return createTable(`${tableName}_${newColumn}`, document[newColumn], options, () => {
delete document[newColumn];
return insertRow(tableName, columns, document, schema);
}, schema);
} else {
delete document[newColumn];
return insertRow(tableName, columns, document, schema);
}
}
columns.push(newColumn);
return addColumn(tableName, newColumn, () => {
return insertRow(tableName, columns, document, schema);
}, schema);
}
const row = {};
columns.forEach(column => row[column] = parseValue(document[column]));
return schema[tableName].rows.push(row);
}
const addColumn = (tableName, column, callback, schema) => {
if (schema[tableName]['columns'][column]) return callback();
schema[tableName]['columns'][column] = { type: 'TEXT', order: Object.keys(schema[tableName].columns).length };
// console.log(`ALTER TABLE '${tableName}' ADD COLUMN '${column}' TEXT;`);
schema[tableName].queries.create = schema[tableName].queries.create.replace(');', `, ${'`' + column + '`'} ${schema[tableName]['columns'][column].type} ${column.includes('_yosql_id') ? `, INDEX ${column}_index(${column}(36))`:''});`);
return callback(null, schema);
}