Added supported function to geometryHelper, added geometrySupport to serverinfo (#9290)

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
Oreille
2021-11-01 22:31:34 +01:00
committed by GitHub
parent da16369b27
commit cb22ddfa7c
2 changed files with 38 additions and 37 deletions

View File

@@ -1,34 +1,36 @@
import { Field, RawField } from '@directus/shared/types';
import { Knex } from 'knex';
import { stringify as geojsonToWKT, GeoJSONGeometry } from 'wellknown';
import { getDatabaseClient } from '..';
import getDatabase from '..';
let geometryHelper: KnexSpatial | undefined;
export function getGeometryHelper(): KnexSpatial {
export function getGeometryHelper(database?: Knex): KnexSpatial {
if (!geometryHelper) {
const db = getDatabase();
const client = db.client.config.client as string;
database = database ?? getDatabase();
const client = getDatabaseClient(database);
const constructor = {
mysql: KnexSpatial_MySQL,
mariadb: KnexSpatial_MySQL,
sqlite3: KnexSpatial,
pg: KnexSpatial_PG,
sqlite: KnexSpatial_SQLite,
postgres: KnexSpatial_PG,
redshift: KnexSpatial_Redshift,
mssql: KnexSpatial_MSSQL,
oracledb: KnexSpatial_Oracle,
oracle: KnexSpatial_Oracle,
}[client];
if (!constructor) {
throw new Error(`Geometry helper not implemented on ${client}.`);
}
geometryHelper = new constructor(db);
geometryHelper = new constructor(database);
}
return geometryHelper;
return geometryHelper!;
}
class KnexSpatial {
constructor(protected knex: Knex) {}
supported(): boolean | Promise<boolean> {
return true;
}
isTrue(expression: Knex.Raw) {
return expression;
}
@@ -73,7 +75,17 @@ class KnexSpatial {
}
}
class KnexSpatial_SQLite extends KnexSpatial {
async supported() {
const res = await this.knex.select('name').from('pragma_function_list').where({ name: 'spatialite_version' });
return res.length > 0;
}
}
class KnexSpatial_PG extends KnexSpatial {
async supported() {
const res = await this.knex.select('oid').from('pg_proc').where({ proname: 'postgis_version' });
return res.length > 0;
}
createColumn(table: Knex.CreateTableBuilder, field: RawField | Field) {
const type = field.schema?.geometry_type ?? 'geometry';
return table.specificType(field.field, `geometry(${type})`);
@@ -145,7 +157,7 @@ class KnexSpatial_Oracle extends KnexSpatial {
return table.specificType(field.field, 'sdo_geometry');
}
asText(table: string, column: string): Knex.Raw {
return this.knex.raw('sdo_util.from_wktgeometry(??.??) as ??', [table, column, column]);
return this.knex.raw('sdo_util.to_wktgeometry(??.??) as ??', [table, column, column]);
}
fromText(text: string): Knex.Raw {
return this.knex.raw('sdo_geometry(?, 4326)', text);

View File

@@ -9,6 +9,7 @@ import fse from 'fs-extra';
import path from 'path';
import { merge } from 'lodash';
import { promisify } from 'util';
import { getGeometryHelper } from './helpers/geometry';
let database: Knex | null = null;
let inspector: ReturnType<typeof SchemaInspector> | null = null;
@@ -152,7 +153,7 @@ export async function validateDatabaseConnection(database?: Knex): Promise<void>
}
}
export function getDatabaseClient(database?: Knex): 'mysql' | 'postgres' | 'sqlite' | 'oracle' | 'mssql' {
export function getDatabaseClient(database?: Knex): 'mysql' | 'postgres' | 'sqlite' | 'oracle' | 'mssql' | 'redshift' {
database = database ?? getDatabase();
switch (database.client.constructor.name) {
@@ -167,6 +168,8 @@ export function getDatabaseClient(database?: Knex): 'mysql' | 'postgres' | 'sqli
return 'oracle';
case 'Client_MSSQL':
return 'mssql';
case 'Client_Redshift':
return 'redshift';
}
throw new Error(`Couldn't extract database client`);
@@ -219,32 +222,18 @@ export async function validateMigrations(): Promise<boolean> {
export async function validateDatabaseExtensions(): Promise<void> {
const database = getDatabase();
const databaseClient = getDatabaseClient(database);
if (databaseClient === 'postgres') {
let available = false;
let installed = false;
const exists = await database.raw(`SELECT name FROM pg_available_extensions WHERE name = 'postgis';`);
if (exists.rows.length > 0) {
available = true;
}
if (available) {
try {
await database.raw(`SELECT PostGIS_version();`);
installed = true;
} catch {
installed = false;
}
}
if (available === false) {
logger.warn(`PostGIS isn't installed. Geometry type support will be limited.`);
} else if (available === true && installed === false) {
logger.warn(
`PostGIS is installed, but hasn't been activated on this database. Geometry type support will be limited.`
);
const geometryHelper = getGeometryHelper(database);
const geometrySupport = await geometryHelper.supported();
if (!geometrySupport) {
switch (databaseClient) {
case 'postgres':
logger.warn(`PostGIS isn't installed. Geometry type support will be limited.`);
break;
case 'sqlite':
logger.warn(`Spatialite isn't installed. Geometry type support will be limited.`);
break;
default:
logger.warn(`Geometry type not supported on ${databaseClient}`);
}
}
}