2018-10-23 23:45:42 +08:00
|
|
|
'use strict';
|
|
|
|
|
2016-02-04 17:26:31 +08:00
|
|
|
// Quote an PostgreSQL identifier if ncecessary
|
|
|
|
function quote_identifier_if_needed(txt) {
|
|
|
|
if ( txt && !txt.match(/^[a-z_][a-z_0-9]*$/)) {
|
|
|
|
return '"' + txt.replace(/\"/g, '""') + '"';
|
|
|
|
} else {
|
|
|
|
return txt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse PostgreSQL table name (possibly quoted and with optional schema).+
|
|
|
|
// Returns { schema: 'schema_name', table: 'table_name' }
|
|
|
|
function parse_table_name(table) {
|
|
|
|
|
|
|
|
function split_as_quoted_parts(table_name) {
|
|
|
|
// parse table into 'parts' that may be quoted, each part
|
|
|
|
// in the parts array being an object { part: 'text', quoted: false/true }
|
|
|
|
var parts = [];
|
|
|
|
var splitted = table_name.split(/\"/);
|
|
|
|
for (var i=0; i<splitted.length; i++ ) {
|
|
|
|
if ( splitted[i] === '' ) {
|
|
|
|
if ( parts.length > 0 && i < splitted.length-1 ) {
|
|
|
|
i++;
|
|
|
|
parts[parts.length - 1].part += '"' + splitted[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var is_quoted = (i > 0 && splitted[i-1] === '') ||
|
|
|
|
(i < splitted.length - 1 && splitted[i+1] === '');
|
|
|
|
parts.push({ part: splitted[i], quoted: is_quoted });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return parts;
|
|
|
|
}
|
|
|
|
|
|
|
|
var parts = split_as_quoted_parts(table);
|
|
|
|
|
|
|
|
function split_single_part(part) {
|
|
|
|
var schema_part = null;
|
|
|
|
var table_part = null;
|
|
|
|
if ( part.quoted ) {
|
|
|
|
table_part = part.part;
|
|
|
|
} else {
|
|
|
|
var parts = part.part.split('.');
|
|
|
|
if ( parts.length === 1 ) {
|
|
|
|
schema_part = null;
|
|
|
|
table_part = parts[0];
|
|
|
|
} else if ( parts.length === 2 ) {
|
|
|
|
schema_part = parts[0];
|
|
|
|
table_part = parts[1];
|
|
|
|
} // else invalid table name
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
schema: schema_part,
|
|
|
|
table: table_part
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function split_two_parts(part1, part2) {
|
|
|
|
var schema_part = null;
|
|
|
|
var table_part = null;
|
|
|
|
if ( part1.quoted && !part2.quoted ) {
|
|
|
|
if ( part2.part[0] === '.' ) {
|
|
|
|
schema_part = part1.part;
|
|
|
|
table_part = part2.part.slice(1);
|
|
|
|
} // else invalid table name (missing dot)
|
|
|
|
} else if ( !part1.quoted && part2.quoted ) {
|
|
|
|
if ( part1.part[part1.part.length - 1] === '.' ) {
|
|
|
|
schema_part = part1.part.slice(0, -1);
|
|
|
|
table_part = part2.part;
|
|
|
|
} // else invalid table name (missing dot)
|
|
|
|
} // else invalid table name (missing dot)
|
|
|
|
return {
|
|
|
|
schema: schema_part,
|
|
|
|
table: table_part
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( parts.length === 1 ) {
|
|
|
|
return split_single_part(parts[0]);
|
|
|
|
} else if ( parts.length === 2 ) {
|
|
|
|
return split_two_parts(parts[0], parts[1]);
|
|
|
|
} else if ( parts.length === 3 && parts[1].part === '.' ) {
|
|
|
|
return {
|
|
|
|
schema: parts[0].part,
|
|
|
|
table: parts[2].part
|
|
|
|
};
|
|
|
|
} // else invalid table name
|
|
|
|
}
|
|
|
|
|
|
|
|
function table_identifier(parsed_name) {
|
|
|
|
if ( parsed_name && parsed_name.table ) {
|
|
|
|
if ( parsed_name.schema ) {
|
|
|
|
return quote_identifier_if_needed(parsed_name.schema) + '.' + quote_identifier_if_needed(parsed_name.table);
|
|
|
|
} else {
|
|
|
|
return quote_identifier_if_needed(parsed_name.table);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
parse: parse_table_name,
|
|
|
|
quote: quote_identifier_if_needed,
|
|
|
|
table_identifier: table_identifier
|
|
|
|
};
|