mongo2crate
Version:
Sync MongoDB to CrateDB and Convert JSON schema to SQL DDL
80 lines (79 loc) • 3.32 kB
JavaScript
import _ from 'lodash/fp.js';
import { setDefaults } from '../util.js';
export const maybeShowColTypes = (endpoint, coltypes) => coltypes ? `${endpoint}?types` : endpoint;
export const getInsertColsAndPlaceholders = (fields) => {
const columns = fields.map((col) => `"${col}"`).join(',');
const placeholders = _.repeat(fields.length - 1, '?,') + '?';
return { columns, placeholders };
};
export const quoteColumn = (column) => {
const [first, ...rest] = column.split('.');
let quoted = `"${first}"`;
if (rest.length) {
for (const inner of rest) {
quoted += `['${inner}']`;
}
}
return quoted;
};
/**
* Given an update object return placeholder assignments and update values
*/
export const getAssignmentsAndUpdates = (record, update) => {
const placeholders = [];
const updates = [];
const columns = Object.keys(update);
for (const column of columns) {
// Numeric index so replace the entire value from the root of the nested path
if (/\.[0-9]+/.test(column)) {
const [first] = column.split('.');
placeholders.push(`${quoteColumn(first)} = ?`);
updates.push(record[first]);
}
else {
placeholders.push(`${quoteColumn(column)} = ?`);
updates.push(update[column]);
}
}
return { assignments: placeholders.join(','), updates };
};
export const getUniqueKeys = (records) => {
const keys = new Set();
// Get all the unique top-level keys
records.forEach((rec) => Object.keys(rec).forEach((key) => keys.add(key)));
// Sort keys so that the order is deterministic
return Array.from(keys).sort();
};
export const getInsertSqlAndArgs = (qualifiedName, record) => {
const keys = Object.keys(record);
const { columns, placeholders } = getInsertColsAndPlaceholders(keys);
const sql = `INSERT INTO ${qualifiedName} (${columns}) VALUES (${placeholders})`;
const args = Object.values(record);
return { sql, args };
};
export const getDeleteByIdSqlAndArgs = (qualifiedName, id) => {
const sql = `DELETE FROM ${qualifiedName} WHERE id = ?`;
const args = [id];
return { sql, args };
};
export const getBulkInsertSqlAndArgs = (qualifiedName, records) => {
// Get the set of unique keys across all the records
const keys = getUniqueKeys(records);
const defaults = setDefaults(keys, null);
const { columns, placeholders } = getInsertColsAndPlaceholders(keys);
const sql = `INSERT INTO ${qualifiedName} (${columns}) VALUES (${placeholders})`;
const args = records.map(_.flow(_.defaults(defaults), _.toPairs, _.sortBy(_.head), _.map(_.last)));
return { sql, args };
};
export const getUpsertSqlAndArgs = (qualifiedName, record, update) => {
const keys = Object.keys(record);
const { columns, placeholders } = getInsertColsAndPlaceholders(keys);
const { assignments, updates } = getAssignmentsAndUpdates(record, update);
const sql = `INSERT INTO ${qualifiedName} (${columns}) VALUES (${placeholders})
ON CONFLICT (id) DO UPDATE SET ${assignments}`;
const args = [...Object.values(record), ...updates];
return { sql, args };
};
export const getAuthHeader = (auth) => ({
Authorization: 'Basic ' + Buffer.from(auth, 'binary').toString('base64'),
});