DiscofyAPI/node_modules/mariadb/lib/cmd/common-binary-cmd.js

328 lines
11 KiB
JavaScript

'use strict';
const ResultSet = require('./resultset');
class CommonBinary extends ResultSet {
constructor(resolve, reject, cmdOpts, connOpts, sql, values) {
super(resolve, reject);
this.configAssign(connOpts, cmdOpts);
this.sql = sql;
this.initialValues = values;
}
/**
* Write (and escape) current parameter value to output writer
*
* @param out output writer
* @param value current parameter
* @param opts connection options
* @param info connection information
*/
writeParam(out, value, opts, info) {
let flushed = false;
switch (typeof value) {
case 'boolean':
flushed = out.writeInt8(0x00);
flushed = out.writeInt8(value ? 0x01 : 0x00) || flushed;
break;
case 'bigint':
case 'number':
flushed = out.writeInt8(0x00);
flushed = out.writeLengthStringAscii('' + value) || flushed;
break;
case 'object':
if (Object.prototype.toString.call(value) === '[object Date]') {
flushed = out.writeInt8(0x00);
flushed = out.writeBinaryDate(value, opts) || flushed;
} else if (Buffer.isBuffer(value)) {
flushed = out.writeInt8(0x00);
flushed = out.writeLengthEncodedBuffer(value) || flushed;
} else if (typeof value.toSqlString === 'function') {
flushed = out.writeInt8(0x00);
flushed = out.writeLengthEncodedString(String(value.toSqlString())) || flushed;
} else {
if (
value.type != null &&
[
'Point',
'LineString',
'Polygon',
'MultiPoint',
'MultiLineString',
'MultiPolygon',
'GeometryCollection'
].includes(value.type)
) {
const geoBuff = this.getBufferFromGeometryValue(value);
if (geoBuff) {
flushed = out.writeInt8(0x00); //Value follow
flushed =
out.writeLengthEncodedBuffer(Buffer.concat([Buffer.from([0, 0, 0, 0]), geoBuff])) ||
flushed;
} else {
flushed = out.writeInt8(0x01); //NULL
}
} else {
//TODO check if permitSetMultiParamEntries is needed !?
flushed = out.writeInt8(0x00);
flushed = out.writeLengthEncodedString(JSON.stringify(value)) || flushed;
}
}
break;
default:
flushed = out.writeInt8(0x00);
flushed = out.writeLengthEncodedString(value) || flushed;
}
return flushed;
}
getBufferFromGeometryValue(value, headerType) {
let geoBuff;
let pos;
let type;
if (!headerType) {
switch (value.type) {
case 'Point':
geoBuff = Buffer.allocUnsafe(21);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(1, 1); //wkbPoint
if (
value.coordinates &&
Array.isArray(value.coordinates) &&
value.coordinates.length >= 2 &&
!isNaN(value.coordinates[0]) &&
!isNaN(value.coordinates[1])
) {
geoBuff.writeDoubleLE(value.coordinates[0], 5); //X
geoBuff.writeDoubleLE(value.coordinates[1], 13); //Y
return geoBuff;
} else {
return null;
}
case 'LineString':
if (value.coordinates && Array.isArray(value.coordinates)) {
const pointNumber = value.coordinates.length;
geoBuff = Buffer.allocUnsafe(9 + 16 * pointNumber);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(2, 1); //wkbLineString
geoBuff.writeInt32LE(pointNumber, 5);
for (let i = 0; i < pointNumber; i++) {
if (
value.coordinates[i] &&
Array.isArray(value.coordinates[i]) &&
value.coordinates[i].length >= 2 &&
!isNaN(value.coordinates[i][0]) &&
!isNaN(value.coordinates[i][1])
) {
geoBuff.writeDoubleLE(value.coordinates[i][0], 9 + 16 * i); //X
geoBuff.writeDoubleLE(value.coordinates[i][1], 17 + 16 * i); //Y
} else {
return null;
}
}
return geoBuff;
} else {
return null;
}
case 'Polygon':
if (value.coordinates && Array.isArray(value.coordinates)) {
const numRings = value.coordinates.length;
let size = 0;
for (let i = 0; i < numRings; i++) {
size += 4 + 16 * value.coordinates[i].length;
}
geoBuff = Buffer.allocUnsafe(9 + size);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(3, 1); //wkbPolygon
geoBuff.writeInt32LE(numRings, 5);
pos = 9;
for (let i = 0; i < numRings; i++) {
const lineString = value.coordinates[i];
if (lineString && Array.isArray(lineString)) {
geoBuff.writeInt32LE(lineString.length, pos);
pos += 4;
for (let j = 0; j < lineString.length; j++) {
if (
lineString[j] &&
Array.isArray(lineString[j]) &&
lineString[j].length >= 2 &&
!isNaN(lineString[j][0]) &&
!isNaN(lineString[j][1])
) {
geoBuff.writeDoubleLE(lineString[j][0], pos); //X
geoBuff.writeDoubleLE(lineString[j][1], pos + 8); //Y
pos += 16;
} else {
return null;
}
}
}
}
return geoBuff;
} else {
return null;
}
case 'MultiPoint':
type = 'MultiPoint';
geoBuff = Buffer.allocUnsafe(9);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(4, 1); //wkbMultiPoint
break;
case 'MultiLineString':
type = 'MultiLineString';
geoBuff = Buffer.allocUnsafe(9);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(5, 1); //wkbMultiLineString
break;
case 'MultiPolygon':
type = 'MultiPolygon';
geoBuff = Buffer.allocUnsafe(9);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(6, 1); //wkbMultiPolygon
break;
case 'GeometryCollection':
geoBuff = Buffer.allocUnsafe(9);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(7, 1); //wkbGeometryCollection
if (value.geometries && Array.isArray(value.geometries)) {
const coordinateLength = value.geometries.length;
const subArrays = [geoBuff];
for (let i = 0; i < coordinateLength; i++) {
const tmpBuf = this.getBufferFromGeometryValue(value.geometries[i]);
if (tmpBuf == null) break;
subArrays.push(tmpBuf);
}
geoBuff.writeInt32LE(subArrays.length - 1, 5);
return Buffer.concat(subArrays);
} else {
geoBuff.writeInt32LE(0, 5);
return geoBuff;
}
default:
return null;
}
if (value.coordinates && Array.isArray(value.coordinates)) {
const coordinateLength = value.coordinates.length;
const subArrays = [geoBuff];
for (let i = 0; i < coordinateLength; i++) {
const tmpBuf = this.getBufferFromGeometryValue(value.coordinates[i], type);
if (tmpBuf == null) break;
subArrays.push(tmpBuf);
}
geoBuff.writeInt32LE(subArrays.length - 1, 5);
return Buffer.concat(subArrays);
} else {
geoBuff.writeInt32LE(0, 5);
return geoBuff;
}
} else {
switch (headerType) {
case 'MultiPoint':
if (
value &&
Array.isArray(value) &&
value.length >= 2 &&
!isNaN(value[0]) &&
!isNaN(value[1])
) {
geoBuff = Buffer.allocUnsafe(21);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(1, 1); //wkbPoint
geoBuff.writeDoubleLE(value[0], 5); //X
geoBuff.writeDoubleLE(value[1], 13); //Y
return geoBuff;
}
return null;
case 'MultiLineString':
if (value && Array.isArray(value)) {
const pointNumber = value.length;
geoBuff = Buffer.allocUnsafe(9 + 16 * pointNumber);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(2, 1); //wkbLineString
geoBuff.writeInt32LE(pointNumber, 5);
for (let i = 0; i < pointNumber; i++) {
if (
value[i] &&
Array.isArray(value[i]) &&
value[i].length >= 2 &&
!isNaN(value[i][0]) &&
!isNaN(value[i][1])
) {
geoBuff.writeDoubleLE(value[i][0], 9 + 16 * i); //X
geoBuff.writeDoubleLE(value[i][1], 17 + 16 * i); //Y
} else {
return null;
}
}
return geoBuff;
}
return null;
case 'MultiPolygon':
if (value && Array.isArray(value)) {
const numRings = value.length;
let size = 0;
for (let i = 0; i < numRings; i++) {
size += 4 + 16 * value[i].length;
}
geoBuff = Buffer.allocUnsafe(9 + size);
geoBuff.writeInt8(0x01, 0); //LITTLE ENDIAN
geoBuff.writeInt32LE(3, 1); //wkbPolygon
geoBuff.writeInt32LE(numRings, 5);
pos = 9;
for (let i = 0; i < numRings; i++) {
const lineString = value[i];
if (lineString && Array.isArray(lineString)) {
geoBuff.writeInt32LE(lineString.length, pos);
pos += 4;
for (let j = 0; j < lineString.length; j++) {
if (
lineString[j] &&
Array.isArray(lineString[j]) &&
lineString[j].length >= 2 &&
!isNaN(lineString[j][0]) &&
!isNaN(lineString[j][1])
) {
geoBuff.writeDoubleLE(lineString[j][0], pos); //X
geoBuff.writeDoubleLE(lineString[j][1], pos + 8); //Y
pos += 16;
} else {
return null;
}
}
}
}
return geoBuff;
}
return null;
}
return null;
}
}
/**
* Read text result-set row
*
* see: https://mariadb.com/kb/en/library/resultset-row/#text-resultset-row
* data are created according to their type.
*
* @param columns columns metadata
* @param packet current row packet
* @param connOpts connection options
* @returns {*} row data
*/
parseRow(columns, packet, connOpts) {
throw new Error('not implemented');
}
}
module.exports = CommonBinary;