map - show geometry in MySQL

This commit is contained in:
Jan Prochazka 2022-06-11 09:45:23 +02:00
parent 0a0ce6ad98
commit 343cf84a58
9 changed files with 248 additions and 14 deletions

View File

@ -483,6 +483,22 @@ export abstract class GridDisplay {
processReferences(select: Select, displayedColumnInfo: DisplayedColumnInfo, options) {}
createColumnExpression(col, source, alias?) {
let expr = null;
if (this.dialect.createColumnViewExpression) {
expr = this.dialect.createColumnViewExpression(col.columnName, col.dataType, source, alias);
if (expr) {
return expr;
}
}
return {
exprType: 'column',
alias: alias || col.columnName,
source,
...col,
};
}
createSelectBase(name: NamedObjectInfo, columns: ColumnInfo[], options) {
if (!columns) return null;
const orderColumnName = columns[0].columnName;
@ -492,12 +508,7 @@ export abstract class GridDisplay {
name: _.pick(name, ['schemaName', 'pureName']),
alias: 'basetbl',
},
columns: columns.map(col => ({
exprType: 'column',
alias: col.columnName,
source: { alias: 'basetbl' },
...col,
})),
columns: columns.map(col => this.createColumnExpression(col, { alias: 'basetbl' })),
orderBy: [
{
exprType: 'column',

View File

@ -267,12 +267,9 @@ export class TableGridDisplay extends GridDisplay {
) {
for (const column of columns) {
if (this.addAllExpandedColumnsToSelected || this.config.addedColumns.includes(column.uniqueName)) {
select.columns.push({
exprType: 'column',
columnName: column.columnName,
alias: column.uniqueName,
source: { name: column, alias: parentAlias },
});
select.columns.push(
this.createColumnExpression(column, { name: column, alias: parentAlias }, column.uniqueName)
);
displayedColumnInfo[column.uniqueName] = {
...column,
sourceAlias: parentAlias,

View File

@ -84,3 +84,18 @@ export function getIconForRedisType(type) {
return null;
}
}
export function isWktGeometry(s) {
if (!_isString(s)) return false;
return (
s.startsWith('POINT(') ||
s.startsWith('LINESTRING(') ||
s.startsWith('POLYGON(') ||
s.startsWith('MULTIPOINT(') ||
s.startsWith('MULTILINESTRING(') ||
s.startsWith('MULTIPOLYGON(') ||
s.startsWith('GEOMCOLLECTION(') ||
s.startsWith('GEOMETRYCOLLECTION(')
);
}

View File

@ -34,4 +34,7 @@ export interface SqlDialect {
disableExplicitTransaction?: boolean;
predefinedDataTypes: string[];
// create sql-tree expression
createColumnViewExpression(columnName: string, dataType: string, source: { alias: string }, alias?: string): any;
}

View File

@ -57,6 +57,8 @@
"dependencies": {
"chartjs-plugin-zoom": "^1.2.0",
"date-fns": "^2.28.0",
"interval-operations": "^1.0.7"
"interval-operations": "^1.0.7",
"leaflet": "^1.8.0",
"wellknown": "^0.5.0"
}
}

View File

@ -0,0 +1,111 @@
<script lang="ts">
import _ from 'lodash';
import { onMount } from 'svelte';
import 'leaflet/dist/leaflet.css';
import leaflet from 'leaflet';
import wellknown from 'wellknown';
import { isWktGeometry } from 'dbgate-tools';
// import Map from 'ol/Map';
// import View from 'ol/View';
// import TileLayer from 'ol/layer/Tile';
// import XYZ from 'ol/source/XYZ';
export let selection;
export let wrap;
let refContainer;
let map;
let selectionLayers = [];
function addSelectionToMap() {
if (!map) return;
if (!selection) return;
for (const selectionLayer of selectionLayers) {
selectionLayer.remove();
}
selectionLayers = [];
const geoValues = selection.map(x => x.value).filter(isWktGeometry);
if (geoValues.length > 0) {
// parse WKT to geoJSON array
const geometries = geoValues.map(wellknown);
const geoJson = {
type: 'GeometryCollection',
geometries,
};
const geoJsonObj = leaflet
.geoJSON(geoJson, {
style: function () {
return {
weight: 2,
fillColor: '#ff7800',
color: '#ff7800',
opacity: 0.8,
fillOpacity: 0.4,
};
},
pointToLayer: function (feature, latlng) {
return leaflet.circleMarker(latlng, {
radius: 7,
weight: 2,
fillColor: '#ff7800',
color: '#ff7800',
opacity: 0.8,
fillOpacity: 0.4,
});
},
})
.addTo(map);
map.fitBounds(geoJsonObj.getBounds());
selectionLayers.push(geoJsonObj);
}
}
onMount(() => {
// new Map({
// target: refContainer,
// layers: [
// new TileLayer({
// source: new XYZ({
// url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
// }),
// }),
// ],
// view: new View({
// center: [0, 0],
// zoom: 2,
// }),
// });
map = leaflet.map(refContainer); // .setView([51.505, -0.09], 13);
leaflet
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap',
})
.addTo(map);
addSelectionToMap();
// map.fitBounds([
// [50, 15],
// [50.1, 15],
// [50, 15.1],
// ]);
// const marker = leaflet.marker([50, 15]).addTo(map);
// <div bind:this={refContainer} class="flex1 map-container" />
});
$: {
selection;
addSelectionToMap();
}
</script>
<div bind:this={refContainer} class="flex1" />

View File

@ -1,4 +1,6 @@
<script lang="ts" context="module">
import { isWktGeometry } from 'dbgate-tools';
const formats = [
{
type: 'textWrap',
@ -36,12 +38,31 @@
component: HtmlCellView,
single: false,
},
{
type: 'map',
title: 'Map',
component: MapCellView,
single: false,
},
];
function autodetect(selection) {
if (selection[0]?.engine?.databaseEngineTypes?.includes('document')) {
return 'jsonRow';
}
if (selection.length > 0 && _.every(selection, x => isWktGeometry(x.value))) {
return 'map';
}
if (
selection.find(x => x.column.toLowerCase().includes('lat')) &&
(selection.find(x => x.column.toLowerCase().includes('lon')) ||
selection.find(x => x.column.toLowerCase().includes('lng')))
) {
return 'map';
}
const value = selection.length == 1 ? selection[0].value : null;
if (_.isString(value)) {
if (value.startsWith('[') || value.startsWith('{')) return 'json';
@ -62,6 +83,7 @@
import HtmlCellView from '../celldata/HtmlCellView.svelte';
import JsonCellView from '../celldata/JsonCellView.svelte';
import JsonRowView from '../celldata/JsonRowView.svelte';
import MapCellView from '../celldata/MapCellView.svelte';
import PictureCellView from '../celldata/PictureCellView.svelte';
import TextCellViewNoWrap from '../celldata/TextCellViewNoWrap.svelte';
import TextCellViewWrap from '../celldata/TextCellViewWrap.svelte';

View File

@ -2,6 +2,18 @@ const { driverBase } = global.DBGATE_TOOLS;
const { mysqlSplitterOptions } = require('dbgate-query-splitter/lib/options');
const Dumper = require('./Dumper');
const spatialTypes = [
'POINT',
'LINESTRING',
'POLYGON',
'GEOMETRY',
'MULTIPOINT',
'MULTILINESTRING',
'MULTIPOLYGON',
'GEOMCOLLECTION',
'GEOMETRYCOLLECTION',
];
/** @type {import('dbgate-types').SqlDialect} */
const dialect = {
rangeSelect: true,
@ -68,6 +80,23 @@ const dialect = {
'time',
'year',
],
createColumnViewExpression(columnName, dataType, source, alias) {
if (dataType && spatialTypes.includes(dataType.toUpperCase())) {
return {
exprType: 'call',
func: 'ST_AsText',
alias: alias || columnName,
args: [
{
exprType: 'column',
columnName,
source,
},
],
};
}
},
};
const mysqlDriverBase = {

View File

@ -2956,6 +2956,15 @@ concat-stream@^1.5.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
concat-stream@~1.5.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266"
integrity sha512-H6xsIBfQ94aESBG8jGHXQ7i5AEpy5ZeVaLDOisDICiTCKpqEfr34/KmTrspKQNoLKNu9gTkovlpQcUi630AKiQ==
dependencies:
inherits "~2.0.1"
readable-stream "~2.0.0"
typedarray "~0.0.5"
concurrently@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-5.1.0.tgz#05523986ba7aaf4b58a49ddd658fab88fa783132"
@ -6993,6 +7002,11 @@ lcid@^2.0.0:
dependencies:
invert-kv "^2.0.0"
leaflet@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.8.0.tgz#4615db4a22a304e8e692cae9270b983b38a2055e"
integrity sha512-gwhMjFCQiYs3x/Sf+d49f10ERXaEFCPr+nVTryhAW8DWbMGqJqt9G4XuIaHmFW08zYvhgdzqXGr8AlW8v8dQkA==
left-pad@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
@ -7520,6 +7534,11 @@ minimist@^1.2.3, minimist@^1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
minimist@~1.2.0:
version "1.2.6"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
minipass-collect@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
@ -8841,6 +8860,11 @@ printj@~1.1.0, printj@~1.1.2:
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
integrity sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@ -9156,6 +9180,18 @@ readable-stream@~1.1.9:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@~2.0.0:
version "2.0.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
integrity sha512-TXcFfb63BQe1+ySzsHZI/5v1aJPCShfqvWJ64ayNImXMsN1Cd0YGk/wm8KB7/OeessgPc9QvS9Zou8QTkFzsLw==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
readdirp@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
@ -10960,7 +10996,7 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
typedarray@^0.0.6:
typedarray@^0.0.6, typedarray@~0.0.5:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
@ -11332,6 +11368,14 @@ webpack@^4.42.0:
watchpack "^1.6.0"
webpack-sources "^1.4.1"
wellknown@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/wellknown/-/wellknown-0.5.0.tgz#09ae9871fa826cf0a6ec1537ef00c379d78d7101"
integrity sha1-Ca6YcfqCbPCm7BU37wDDedeNcQE=
dependencies:
concat-stream "~1.5.0"
minimist "~1.2.0"
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"