Skip to content
Permalink
Browse files
[CONJS-39] support geometric GeoJSON structure format
  • Loading branch information
rusher committed Sep 10, 2018
1 parent a4ac4c9 commit 1c65cc7
Show file tree
Hide file tree
Showing 3 changed files with 950 additions and 252 deletions.
@@ -233,30 +233,169 @@ class Query extends ResultSet {
out.writeInt8(QUOTE);
} else if (typeof value.toSqlString === "function") {
out.writeStringEscapeQuote(String(value.toSqlString()));
} else if (opts.permitSetMultiParamEntries) {
let first = true;
for (let key in value) {
const val = value[key];
if (typeof val === "function") continue;
if (first) {
first = false;
} else {
if (
value.type != null &&
[
"Point",
"LineString",
"Polygon",
"MultiPoint",
"MultiLineString",
"MultiPolygon",
"GeometryCollection"
].includes(value.type)
) {
//GeoJSON format.
switch (value.type) {
case "Point":
out.writeStringAscii(
"ST_PointFromText('POINT(" + this.geoPointToString(value.coordinates) + ")')"
);
break;

case "LineString":
out.writeStringAscii(
"ST_LineFromText('LINESTRING(" +
this.geoArrayPointToString(value.coordinates) +
")')"
);
break;

case "Polygon":
out.writeStringAscii(
"ST_PolygonFromText('POLYGON(" +
this.geoMultiArrayPointToString(value.coordinates) +
")')"
);
break;

case "MultiPoint":
out.writeStringAscii(
"ST_MPointFromText('MULTIPOINT(" +
this.geoArrayPointToString(value.coordinates) +
")')"
);
break;

case "MultiLineString":
out.writeStringAscii(
"ST_MLineFromText('MULTILINESTRING(" +
this.geoMultiArrayPointToString(value.coordinates) +
")')"
);
break;

case "MultiPolygon":
out.writeStringAscii(
"ST_MPolyFromText('MULTIPOLYGON(" +
this.geoMultiPolygonToString(value.coordinates) +
")')"
);
break;

case "GeometryCollection":
out.writeStringAscii(
"ST_GeomCollFromText('GEOMETRYCOLLECTION(" +
this.geometricCollectionToString(value.geometries) +
")')"
);
break;
}
} else {
if (opts.permitSetMultiParamEntries) {
let first = true;
for (let key in value) {
const val = value[key];
if (typeof val === "function") continue;
if (first) {
first = false;
} else {
out.writeStringAscii(",");
}
out.writeString("`" + key + "`");
out.writeStringAscii("=");
this.writeParam(out, val, opts);
}
if (first) out.writeStringEscapeQuote(JSON.stringify(value));
} else {
out.writeStringAscii(",");
out.writeStringEscapeQuote(JSON.stringify(value));
}
out.writeString("`" + key + "`");
out.writeStringAscii("=");
this.writeParam(out, val, opts);
}
if (first) out.writeStringEscapeQuote(JSON.stringify(value));
} else {
out.writeStringEscapeQuote(JSON.stringify(value));
}
break;
default:
out.writeStringEscapeQuote(value);
}
}

geometricCollectionToString(geo) {
if (!geo) return "";
let st = "";
for (let i = 0; i < geo.length; i++) {
//GeoJSON format.
st += i != 0 ? "," : "";
switch (geo[i].type) {
case "Point":
st += "POINT(" + this.geoPointToString(geo[i].coordinates) + ")";
break;

case "LineString":
st += "LINESTRING(" + this.geoArrayPointToString(geo[i].coordinates) + ")";
break;

case "Polygon":
st += "POLYGON(" + this.geoMultiArrayPointToString(geo[i].coordinates) + ")";
break;

case "MultiPoint":
st += "MULTIPOINT(" + this.geoArrayPointToString(geo[i].coordinates) + ")";
break;

case "MultiLineString":
st += "MULTILINESTRING(" + this.geoMultiArrayPointToString(geo[i].coordinates) + ")";
break;

case "MultiPolygon":
st += "MULTIPOLYGON(" + this.geoMultiPolygonToString(geo[i].coordinates) + ")";
break;
}
}
return st;
}

geoMultiPolygonToString(coords) {
if (!coords) return "";
let st = "";
for (let i = 0; i < coords.length; i++) {
st += (i != 0 ? ",(" : "(") + this.geoMultiArrayPointToString(coords[i]) + ")";
}
return st;
}

geoMultiArrayPointToString(coords) {
if (!coords) return "";
let st = "";
for (let i = 0; i < coords.length; i++) {
st += (i != 0 ? ",(" : "(") + this.geoArrayPointToString(coords[i]) + ")";
}
return st;
}

geoArrayPointToString(coords) {
if (!coords) return "";
let st = "";
for (let i = 0; i < coords.length; i++) {
st += (i != 0 ? "," : "") + this.geoPointToString(coords[i]);
}
return st;
}

geoPointToString(coords) {
if (!coords) return "";
return (isNaN(coords[0]) ? "" : coords[0]) + " " + (isNaN(coords[1]) ? "" : coords[1]);
}

/**
* Read text result-set row
*
@@ -18,85 +18,102 @@ class Packet {
skip(n) {
this.pos += n;
}

readGeometry() {
const geoBuf = this.readBufferLengthEncoded();
if (geoBuf === null) {
return null;
}
let geoPos = 4;
return readGeometryObject();
return readGeometryObject(false);

function parseCoordinates(byteOrder) {
geoPos += 16;
const x = byteOrder ? geoBuf.readDoubleLE(geoPos - 16) : geoBuf.readDoubleBE(geoPos - 16);
const y = byteOrder ? geoBuf.readDoubleLE(geoPos - 8) : geoBuf.readDoubleBE(geoPos - 8);
return [x, y];
}

function readGeometryObject() {
function readGeometryObject(inner) {
const byteOrder = geoBuf[geoPos++];
const wkbType = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
geoPos += 4;
switch (wkbType) {
case 1: //wkbPoint
geoPos += 16;
if (byteOrder) {
return { x: geoBuf.readDoubleLE(geoPos - 16), y: geoBuf.readDoubleLE(geoPos - 8) };
} else {
return { x: geoBuf.readDoubleBE(geoPos - 16), y: geoBuf.readDoubleBE(geoPos - 8) };
}
const coords = parseCoordinates(byteOrder);

if (inner) return coords;
return {
type: "Point",
coordinates: coords
};

case 2: //wkbLineString
const pointNumber = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
geoPos += 4;
let points = [];
let coordinates = [];
for (let i = 0; i < pointNumber; i++) {
geoPos += 16;
if (byteOrder) {
points.push({
x: geoBuf.readDoubleLE(geoPos - 16),
y: geoBuf.readDoubleLE(geoPos - 8)
});
} else {
points.push({
x: geoBuf.readDoubleBE(geoPos - 16),
y: geoBuf.readDoubleBE(geoPos - 8)
});
}
coordinates.push(parseCoordinates(byteOrder));
}
return points;
if (inner) return coordinates;
return {
type: "LineString",
coordinates: coordinates
};

case 3: //wkbPolygon
let polygon = [];
let polygonCoordinates = [];
const numRings = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
geoPos += 4;
for (let ring = 0; ring < numRings; ring++) {
const pointNumber = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
geoPos += 4;
let arr = [];
let linesCoordinates = [];
for (let i = 0; i < pointNumber; i++) {
geoPos += 16;
if (byteOrder) {
arr.push({
x: geoBuf.readDoubleLE(geoPos - 16),
y: geoBuf.readDoubleLE(geoPos - 8)
});
} else {
arr.push({
x: geoBuf.readDoubleBE(geoPos - 16),
y: geoBuf.readDoubleBE(geoPos - 8)
});
}
linesCoordinates.push(parseCoordinates(byteOrder));
}
polygon.push(arr);
polygonCoordinates.push(linesCoordinates);
}
return polygon;

if (inner) return polygonCoordinates;
return {
type: "Polygon",
coordinates: polygonCoordinates
};

case 4: //wkbMultiPoint
return {
type: "MultiPoint",
coordinates: parseGeomArray(byteOrder, true)
};

case 5: //wkbMultiLineString
return {
type: "MultiLineString",
coordinates: parseGeomArray(byteOrder, true)
};
case 6: //wkbMultiPolygon
return {
type: "MultiPolygon",
coordinates: parseGeomArray(byteOrder, true)
};
case 7: //wkbGeometryCollection
let arr = [];
const number = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
geoPos += 4;
for (let i = 0; i < number; i++) {
arr.push(readGeometryObject());
}
return arr;
return {
type: "GeometryCollection",
geometries: parseGeomArray(byteOrder, false)
};
}
return null;
}

function parseGeomArray(byteOrder, inner) {
let coordinates = [];
const number = byteOrder ? geoBuf.readInt32LE(geoPos) : geoBuf.readInt32BE(geoPos);
geoPos += 4;
for (let i = 0; i < number; i++) {
coordinates.push(readGeometryObject(inner));
}
return coordinates;
}
}

peek() {

0 comments on commit 1c65cc7

Please sign in to comment.