123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- '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;
|