123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- 'use strict';
- const Long = require('long');
- const hexArray = '0123456789ABCDEF'.split('');
- const Errors = require('../misc/errors');
- const CommonText = require('../cmd/common-text-cmd');
- const Iconv = require('iconv-lite');
- /**
- * Write bytes/hexadecimal value of a byte array to a string.
- * String output example :
- * 38 00 00 00 03 63 72 65 61 74 65 20 74 61 62 6C 8....create tabl
- * 65 20 42 6C 6F 62 54 65 73 74 63 6C 6F 62 74 65 e BlobTestclobte
- * 73 74 32 20 28 73 74 72 6D 20 74 65 78 74 29 20 st2 (strm text)
- * 43 48 41 52 53 45 54 20 75 74 66 38 CHARSET utf8
- */
- module.exports.log = function (opts, buf, off, end, header) {
- let out = [];
- if (!buf) return '';
- if (off === undefined || off === null) off = 0;
- if (end === undefined || end === null) end = buf.length;
- let asciiValue = new Array(16);
- asciiValue[8] = ' ';
- let useHeader = header !== undefined;
- let offset = off || 0;
- const maxLgh = Math.min(useHeader ? opts.debugLen - header.length : opts.debugLen, end - offset);
- const isLimited = end - offset > maxLgh;
- let byteValue;
- let posHexa = 0;
- let pos = 0;
- out.push(
- '+--------------------------------------------------+\n' +
- '| 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n' +
- '+--------------------------------------------------+------------------+\n'
- );
- if (useHeader) {
- while (pos < header.length) {
- if (posHexa === 0) out.push('| ');
- byteValue = header[pos++] & 0xff;
- out.push(hexArray[byteValue >>> 4], hexArray[byteValue & 0x0f], ' ');
- asciiValue[posHexa++] =
- byteValue > 31 && byteValue < 127 ? String.fromCharCode(byteValue) : '.';
- if (posHexa === 8) out.push(' ');
- }
- }
- pos = offset;
- while (pos < maxLgh + offset) {
- if (posHexa === 0) out.push('| ');
- byteValue = buf[pos] & 0xff;
- out.push(hexArray[byteValue >>> 4], hexArray[byteValue & 0x0f], ' ');
- asciiValue[posHexa++] =
- byteValue > 31 && byteValue < 127 ? String.fromCharCode(byteValue) : '.';
- if (posHexa === 8) out.push(' ');
- if (posHexa === 16) {
- out.push('| ', asciiValue.join(''), ' |\n');
- posHexa = 0;
- }
- pos++;
- }
- let remaining = posHexa;
- if (remaining > 0) {
- if (remaining < 8) {
- for (; remaining < 8; remaining++) {
- out.push(' ');
- asciiValue[posHexa++] = ' ';
- }
- out.push(' ');
- }
- for (; remaining < 16; remaining++) {
- out.push(' ');
- asciiValue[posHexa++] = ' ';
- }
- out.push('| ', asciiValue.join(''), isLimited ? ' |...\n' : ' |\n');
- } else if (isLimited) {
- out[out.length - 1] = ' |...\n';
- }
- out.push('+--------------------------------------------------+------------------+\n');
- return out.join('');
- };
- module.exports.escapeId = (opts, info, value) => {
- if (!value || value === '') {
- throw Errors.createError(
- 'Cannot escape empty ID value',
- false,
- info,
- '0A000',
- Errors.ER_NULL_ESCAPEID
- );
- }
- if (value.includes('\u0000')) {
- throw Errors.createError(
- 'Cannot escape ID with null character (u0000)',
- false,
- info,
- '0A000',
- Errors.ER_NULL_CHAR_ESCAPEID
- );
- }
- // always return escaped value, event when there is no special characters
- // to permit working with reserved words
- if (value.match(/^`.+`$/g)) {
- // already escaped
- return value;
- }
- return '`' + value.replace(/`/g, '``') + '`';
- };
- module.exports.escape = (opts, info, value) => {
- if (value === undefined || value === null) return 'NULL';
- switch (typeof value) {
- case 'boolean':
- return value ? 'true' : 'false';
- case 'bigint':
- case 'number':
- return '' + value;
- case 'object':
- if (Object.prototype.toString.call(value) === '[object Date]') {
- return opts.tz
- ? opts.tz === 'Etc/UTC'
- ? CommonText.getUtcDate(value, opts)
- : CommonText.getTimezoneDate(value, opts)
- : CommonText.getLocalDate(value, opts);
- } else if (Buffer.isBuffer(value)) {
- let stValue;
- if (Buffer.isEncoding(opts.collation.charset)) {
- stValue = value.toString(opts.collation.charset, 0, value.length);
- } else {
- stValue = Iconv.decode(value, opts.collation.charset);
- }
- return "_binary'" + escapeString(stValue) + "'";
- } else if (typeof value.toSqlString === 'function') {
- return "'" + escapeString(String(value.toSqlString())) + "'";
- } else if (Long.isLong(value)) {
- return value.toString();
- } else if (Array.isArray(value)) {
- let out = opts.arrayParenthesis ? '(' : '';
- for (let i = 0; i < value.length; i++) {
- if (i !== 0) out += ',';
- out += this.escape(opts, info, value[i]);
- }
- if (opts.arrayParenthesis) out += ')';
- return out;
- } else {
- if (
- value.type != null &&
- [
- 'Point',
- 'LineString',
- 'Polygon',
- 'MultiPoint',
- 'MultiLineString',
- 'MultiPolygon',
- 'GeometryCollection'
- ].includes(value.type)
- ) {
- //GeoJSON format.
- let prefix =
- info &&
- ((info.isMariaDB() && info.hasMinVersion(10, 1, 4)) ||
- (!info.isMariaDB() && info.hasMinVersion(5, 7, 6)))
- ? 'ST_'
- : '';
- switch (value.type) {
- case 'Point':
- return (
- prefix +
- "PointFromText('POINT(" +
- CommonText.geoPointToString(value.coordinates) +
- ")')"
- );
- case 'LineString':
- return (
- prefix +
- "LineFromText('LINESTRING(" +
- CommonText.geoArrayPointToString(value.coordinates) +
- ")')"
- );
- case 'Polygon':
- return (
- prefix +
- "PolygonFromText('POLYGON(" +
- CommonText.geoMultiArrayPointToString(value.coordinates) +
- ")')"
- );
- case 'MultiPoint':
- return (
- prefix +
- "MULTIPOINTFROMTEXT('MULTIPOINT(" +
- CommonText.geoArrayPointToString(value.coordinates) +
- ")')"
- );
- case 'MultiLineString':
- return (
- prefix +
- "MLineFromText('MULTILINESTRING(" +
- CommonText.geoMultiArrayPointToString(value.coordinates) +
- ")')"
- );
- case 'MultiPolygon':
- return (
- prefix +
- "MPolyFromText('MULTIPOLYGON(" +
- CommonText.geoMultiPolygonToString(value.coordinates) +
- ")')"
- );
- case 'GeometryCollection':
- return (
- prefix +
- "GeomCollFromText('GEOMETRYCOLLECTION(" +
- CommonText.geometricCollectionToString(value.geometries) +
- ")')"
- );
- }
- } else {
- if (opts.permitSetMultiParamEntries) {
- let out = '';
- let first = true;
- for (let key in value) {
- const val = value[key];
- if (typeof val === 'function') continue;
- if (first) {
- first = false;
- } else {
- out += ',';
- }
- out += '`' + key + '`=';
- out += this.escape(opts, info, val);
- }
- if (out === '') return "'" + escapeString(JSON.stringify(value)) + "'";
- return out;
- } else {
- return "'" + escapeString(JSON.stringify(value)) + "'";
- }
- }
- }
- default:
- return "'" + escapeString(value) + "'";
- }
- };
- // see https://mariadb.com/kb/en/library/string-literals/
- const LITTERAL_ESCAPE = {
- '\u0000': '\\0',
- "'": "\\'",
- '"': '\\"',
- '\b': '\\b',
- '\n': '\\n',
- '\r': '\\r',
- '\t': '\\t',
- '\u001A': '\\Z',
- '\\': '\\\\'
- };
- const escapeString = (val) => {
- const pattern = /[\u0000'"\b\n\r\t\u001A\\]/g;
- let offset = 0;
- let escaped = '';
- let match;
- while ((match = pattern.exec(val))) {
- escaped += val.substring(offset, match.index);
- escaped += LITTERAL_ESCAPE[match[0]];
- offset = pattern.lastIndex;
- }
- if (offset === 0) {
- return val;
- }
- if (offset < val.length) {
- escaped += val.substring(offset);
- }
- return escaped;
- };
|