knex-postgis
Version:
postgis extension for knex
951 lines (733 loc) • 24.1 kB
JavaScript
;
var chai = require('chai'),
tester = require('./tester'),
expect = chai.expect,
knex = tester.knex,
st = knex.postgis,
queryBuilder = tester.queryBuilder,
testSql = tester.testSql;
describe('asEWKT', function() {
it('can get geometry as EWKT from a geometry column', function() {
var query = queryBuilder().select('id', st.asEWKT('geom')).from('points');
var expected = {
sql: 'select "id", ST_asEWKT("geom") as "geom" from "points"',
bindings: []
};
testSql(query, expected);
});
});
describe('asGeoJSON', function() {
it('can get geometry as asGeoJSON from a geometry column', function() {
var query, expected;
query = queryBuilder().select('id', st.asGeoJSON('geom')).from('points');
expected = {
sql: 'select "id", ST_asGeoJSON("geom") as "geom" from "points"',
bindings: []
};
testSql(query, expected);
});
});
describe('asText', function() {
it('can get geometry as text from a geometry column', function() {
var query, expected;
query = queryBuilder()
.select('id', st.asText('geom'))
.from('points');
expected = {
sql: 'select "id", ST_asText("geom") as "geom" from "points"',
bindings: []
};
testSql(query, expected);
});
it('can get geometry as text from a geometry created with other postgis functions', function() {
var query, expected;
query = queryBuilder()
.select('id', st.asText(st.centroid('geom')).as('centroid'))
.from('points');
expected = {
sql: 'select "id", ST_asText(ST_centroid("geom")) as "centroid" from "points"',
bindings: []
};
testSql(query, expected);
});
it('alias the result if the input is a column', function() {
var query, expected;
query = queryBuilder()
.select('id', st.asText('geom'))
.from('points');
expected = {
sql: 'select "id", ST_asText("geom") as "geom" from "points"',
bindings: []
};
testSql(query, expected);
});
it('alias the result to a custom name', function() {
var query, expected;
query = queryBuilder()
.select('id', st.asText('geom').as('foo'))
.from('points');
expected = {
sql: 'select "id", ST_asText("geom") as "foo" from "points"',
bindings: []
};
testSql(query, expected);
});
});
describe('buffer', function() {
it('works with a column name and a number', function() {
var query, expected;
query = queryBuilder().select(st.buffer('geom', 1000));
expected = {
sql: 'select ST_Buffer("geom", ?)',
bindings: [1000]
};
testSql(query, expected);
});
it('works with a radius from a column name', function() {
var query, expected;
query = queryBuilder().select(st.buffer('geom', 'radius'));
expected = {
sql: 'select ST_Buffer("geom", "radius")',
bindings: []
};
testSql(query, expected);
});
});
describe('centroid', function() {
it('can get the centroid of a geometry column', function() {
var query, expected;
query = queryBuilder().select('id', st.centroid('geom')).from('points');
expected = {
sql: 'select "id", ST_centroid("geom") from "points"',
bindings: []
};
testSql(query, expected);
});
});
describe('DWithin', function() {
it('works correctly with geometry columns', function() {
var query, expected;
query = queryBuilder().select(st.dwithin('a', 'b', 12));
expected = {
sql: 'select ST_DWithin("a", "b", ?)',
bindings: [12]
};
testSql(query, expected);
});
it('works with a column name as the distance', function() {
var query, expected;
query = queryBuilder().select(st.dwithin('a', 'b', 'distanceColumn'));
expected = {
sql: 'select ST_DWithin("a", "b", "distanceColumn")',
bindings: []
};
testSql(query, expected);
});
it('works with a created geometry', function() {
var query, expected;
query = queryBuilder().select(st.dwithin('a', st.point(-48.23456, 20.12345), 12));
expected = {
sql: 'select ST_DWithin("a", ST_Point(?, ?), ?)',
bindings: [-48.23456, 20.12345, 12]
};
testSql(query, expected);
});
it('works as expected with spheroid argument', function() {
var query, expected;
query = queryBuilder().select(st.dwithin('a', 'b', 12, true));
expected = {
sql: 'select ST_DWithin("a", "b", ?, ?)',
bindings: [12, true]
};
testSql(query, expected);
});
it('throws an error with invalid boolean spheroid argument', function() {
expect(
function() {
return queryBuilder().select(st.dwithin('a', 'b', 12, []));
}
).to.throw('Invalid boolean provided');
});
});
describe('geomFromGeoJSON', function() {
it('can create a geometry from a json text', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geom': st.geomFromGeoJSON('{"type":"Point","coordinates":[-48.23456,20.12345]}')
})
.into('points');
expected = {
sql: 'insert into "points" ("geom", "id") values (ST_geomFromGeoJSON(?), ?)',
bindings: ['{"type":"Point","coordinates":[-48.23456,20.12345]}', 1]
};
testSql(query, expected);
});
it('can create a geometry collection from a json text', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geom': st.geomFromGeoJSON('{ "type": "GeometryCollection", "geometries": [ { "type": "Point", "coordinates": [100.0, 0.0] }, { "type": "LineString", "coordinates": [ [101.0, 0.0], [102.0, 1.0] ] } ] }')
})
.into('geometries');
expected = {
sql: 'insert into "geometries" ("geom", "id") values (ST_geomFromGeoJSON(?), ?)',
bindings: ['{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100,0]},{"type":"LineString","coordinates":[[101,0],[102,1]]}]}', 1]
};
testSql(query, expected);
});
it('can create a geometry from a json object', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geom': st.geomFromGeoJSON({type:'Point', coordinates:[-48.23456, 20.12345]})
})
.into('points');
expected = {
sql: 'insert into "points" ("geom", "id") values (ST_geomFromGeoJSON(?), ?)',
bindings: ['{"type":"Point","coordinates":[-48.23456,20.12345]}', 1]
};
testSql(query, expected);
});
it('can create a geometry from a column name', function() {
testSql(
queryBuilder()
.update({
'geom': st.geomFromGeoJSON('geoJsonColumn')
})
.table('points'),
{
sql: 'update "points" set "geom" = ST_geomFromGeoJSON("geoJsonColumn")',
bindings: []
});
});
it('prevents sql injection', function() {
expect(
function() {
return queryBuilder()
.insert({
id: 1,
geom: st.geomFromGeoJSON({type: 'Point', coordinates: 'DROP TABLE points;'})
})
.into('points');
}
).to.throw('Invalid GeoJSON');
});
});
describe('geomFromText', function() {
it('can create a geometry from a WKT text', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geom': st.geomFromText('Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326)
})
.into('points');
expected = {
sql: 'insert into "points" ("geom", "id") values (ST_geomFromText(?, ?), ?)',
bindings: ['Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326, 1]
};
testSql(query, expected);
});
it('allows srid from a column', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geom': st.geomFromText('Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 'srid')
})
.into('points');
expected = {
sql: 'insert into "points" ("geom", "id") values (ST_geomFromText(?, "srid"), ?)',
bindings: ['Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 1]
};
testSql(query, expected);
});
it('can create a geometry from a EWKT text', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geom': st.geomFromText('SRID=4326;Polygon((0 0, 0 1, 1 1, 1 0, 0 0))')
})
.into('points');
expected = {
sql: 'insert into "points" ("geom", "id") values (ST_geomFromText(?), ?)',
bindings: ['SRID=4326;Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 1]
};
testSql(query, expected);
});
it('allows spaces between WKT type and the first parenthesis', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geom': st.geomFromText('Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))', 4326)
})
.into('points');
expected = {
sql: 'insert into "points" ("geom", "id") values (ST_geomFromText(?, ?), ?)',
bindings: ['Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))', 4326, 1]
};
testSql(query, expected);
});
it('correctly identify as a column, an input that are equal to a WKT type', function() {
var query, expected;
query = queryBuilder()
.select('id', st.asText('point'))
.from('points')
.where(st.intersects('point', st.geomFromText('Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326)));
expected = {
sql: 'select "id", ST_asText("point") as "point" from "points" where ST_intersects("point", ST_geomFromText(?, ?))',
bindings: ['Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326]
};
testSql(query, expected);
});
it('prevents sql injection', function() {
var query, expected;
query = queryBuilder()
.insert({
id: 1,
geom: st.geomFromText("Point(')); DROP TABLE points; SELECT concat(concat(')", 4326)
})
.into('points');
expected = {
sql: 'insert into "points" ("geom", "id") values (ST_geomFromText("Point(\')); DROP TABLE points; SELECT concat(concat(\')", ?), ?)',
bindings: [4326, 1]
};
testSql(query, expected);
});
});
describe('intersects', function() {
it('can intersects two geometry columns', function() {
var query, expected;
query = queryBuilder()
.select('id', st.intersects('geom1', 'geom2'))
.from('points');
expected = {
sql: 'select "id", ST_intersects("geom1", "geom2") from "points"',
bindings: []
};
testSql(query, expected);
});
it('can intersects a geometry column with a geometry created with EWKT', function() {
var query, expected;
query = queryBuilder()
.select('id', st.asText('geom'))
.from('points')
.where(st.intersects('geom', 'SRID=4326;Polygon((0 0, 0 1, 1 1, 1 0, 0 0))'));
expected = {
sql: 'select "id", ST_asText("geom") as "geom" from "points" where ST_intersects("geom", ?)',
bindings: ['SRID=4326;Polygon((0 0, 0 1, 1 1, 1 0, 0 0))']
};
testSql(query, expected);
});
it('can intersects a geometry column with a geometry created with others postgis functions', function() {
var query, expected;
query = queryBuilder()
.select('id', st.asText('geom'))
.from('points')
.where(st.intersects('geom', st.geomFromText('Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326)));
expected = {
sql: 'select "id", ST_asText("geom") as "geom" from "points" where ST_intersects("geom", ST_geomFromText(?, ?))',
bindings: ['Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326]
};
testSql(query, expected);
});
});
describe('makeEnvelope', function() {
it('can make an envelope', function() {
var query, expected;
query = queryBuilder()
.select(st.makeEnvelope(-48.25456, 20.02345, -48.21456, 20.62345));
expected = {
sql: 'select ST_MakeEnvelope(?, ?, ?, ?)',
bindings: [-48.25456, 20.02345, -48.21456, 20.62345]
};
testSql(query, expected);
});
it('can make an envelope with a specified srid', function() {
var query, expected;
query = queryBuilder()
.select(st.makeEnvelope(-48.25456, 20.02345, -48.21456, 20.62345, 4326));
expected = {
sql: 'select ST_MakeEnvelope(?, ?, ?, ?, ?)',
bindings: [-48.25456, 20.02345, -48.21456, 20.62345, 4326]
};
testSql(query, expected);
});
it('throws an error if provided a non-number min-latitude', function() {
expect(
function() {
return queryBuilder()
.select(st.makeEnvelope(-48.25456, null, -48.21456, 20.62345));
}
).to.throw('Invalid number provided');
});
it('throws an error if provided a non-number max-longitude', function() {
expect(
function() {
return queryBuilder()
.select(st.makeEnvelope(-48.25456, 20.02345, {}, 20.62345));
}
).to.throw('Invalid number provided');
});
it('throws an error if provided a non-number srid', function() {
expect(
function() {
return queryBuilder()
.select(st.makeEnvelope(-48.25456, 20.02345, -48.21456, 20.62345, []));
}
).to.throw('Invalid number provided');
});
});
describe('makePoint', function() {
it('can make a point', function() {
var query, expected;
query = queryBuilder().select(st.makePoint(-48.23456, 20.12345));
expected = {
sql: 'select ST_MakePoint(?, ?)',
bindings: [-48.23456, 20.12345]
};
testSql(query, expected);
});
it('can make a point with a height', function() {
var query, expected;
query = queryBuilder().select(st.makePoint(-48.23456, 20.12345, 1.5));
expected = {
sql: 'select ST_MakePoint(?, ?, ?)',
bindings: [-48.23456, 20.12345, 1.5]
};
testSql(query, expected);
});
it('can make a point with a height and measure', function() {
var query, expected;
query = queryBuilder().select(st.makePoint(-48.23456, 20.12345, 1.5, 2.5));
expected = {
sql: 'select ST_MakePoint(?, ?, ?, ?)',
bindings: [-48.23456, 20.12345, 1.5, 2.5]
};
testSql(query, expected);
});
it('throws an error if provided a non-number longitude', function() {
expect(
function() {
return queryBuilder()
.select(st.makePoint(false, 20.12345));
}
).to.throw('Invalid number provided');
});
it('throws an error if provided a non-number latitude', function() {
expect(
function() {
return queryBuilder()
.select(st.makePoint(-48.23456, {test: true}));
}
).to.throw('Invalid number provided');
});
it('does not throw an error if provided a number-y string latitude', function() {
var query, expected;
query = queryBuilder().select(st.makePoint(-48.23456, '20.12345'));
expected = {
sql: 'select ST_MakePoint(?, ?)',
bindings: [-48.23456, '20.12345']
};
testSql(query, expected);
expect(
function() {
return queryBuilder()
.select(st.makePoint(-48.23456, '20.12345'));
}
).to.not.throw('Invalid number provided');
});
});
describe('makeValid', function() {
it('can convert a geometry column', function() {
testSql(queryBuilder().select('id', st.makeValid('geom')).from('points'), {
sql: 'select "id", ST_MakeValid("geom") from "points"',
bindings: []
});
});
});
describe('point', function() {
it('can make a point', function() {
var query, expected;
query = queryBuilder().select(st.point(-48.23456, 20.12345));
expected = {
sql: 'select ST_Point(?, ?)',
bindings: [-48.23456, 20.12345]
};
testSql(query, expected);
});
it('can make a point using column values', function() {
var query, expected;
query = queryBuilder().select(st.point('x', 'y'));
expected = {
sql: 'select ST_Point("x", "y")',
bindings: []
};
testSql(query, expected);
});
});
describe('transform', function() {
it('works with a column name and a number', function() {
var query, expected;
query = queryBuilder().select(st.transform('geom', 4326));
expected = {
sql: 'select ST_transform("geom", ?::int)',
bindings: [4326]
};
testSql(query, expected);
});
it('works with a srid from a column name', function() {
var query, expected;
query = queryBuilder().select(st.transform('geom', 'srid'));
expected = {
sql: 'select ST_transform("geom", "srid")',
bindings: []
};
testSql(query, expected);
});
});
describe('within', function() {
it('works as expected', function() {
var query, expected;
query = queryBuilder().select(st.within('a', 'b'));
expected = {
sql: 'select ST_Within("a", "b")',
bindings: []
};
testSql(query, expected);
});
it('works with a created geometry', function() {
var query, expected;
query = queryBuilder().select(st.within('a', st.point(-48.23456, 20.12345)));
expected = {
sql: 'select ST_Within("a", ST_Point(?, ?))',
bindings: [-48.23456, 20.12345]
};
testSql(query, expected);
});
});
describe('x', function() {
it('can get x coordinate from a geometry column', function() {
var query = queryBuilder().select(st.x('geom')).from('points');
var expected = {
sql: 'select ST_X("geom") from "points"',
bindings: []
};
testSql(query, expected);
});
it ('can get x coordinate from a wkt geometry', function() {
var query = queryBuilder().select(st.x('POINT(1 1)')).from('points');
var expected = {
sql: 'select ST_X(?) from "points"',
bindings: ['POINT(1 1)']
};
testSql(query, expected);
});
});
describe('y', function() {
it('can get y coordinate from a geometry column', function() {
var query = queryBuilder().select(st.y('geom')).from('points');
var expected = {
sql: 'select ST_Y("geom") from "points"',
bindings: []
};
testSql(query, expected);
});
it ('can get y coordinate from a wkt geometry', function() {
var query = queryBuilder().select(st.y('POINT(1 1)')).from('points');
var expected = {
sql: 'select ST_Y(?) from "points"',
bindings: ['POINT(1 1)']
};
testSql(query, expected);
});
});
describe('z', function() {
it('can get z coordinate from a geometry column', function() {
var query = queryBuilder().select(st.z('geom')).from('points');
var expected = {
sql: 'select ST_Z("geom") from "points"',
bindings: []
};
testSql(query, expected);
});
it ('can get z coordinate from a wkt geometry', function() {
var query = queryBuilder().select(st.z('POINT(1 2 3 4)')).from('points');
var expected = {
sql: 'select ST_Z(?) from "points"',
bindings: ['POINT(1 2 3 4)']
};
testSql(query, expected);
});
});
describe('m', function() {
it('can get m coordinate from a geometry column', function() {
var query = queryBuilder().select(st.m('geom')).from('points');
var expected = {
sql: 'select ST_M("geom") from "points"',
bindings: []
};
testSql(query, expected);
});
it ('can get m coordinate from a wkt geometry', function() {
var query = queryBuilder().select(st.m('POINT(1 2 3 4)')).from('points');
var expected = {
sql: 'select ST_M(?) from "points"',
bindings: ['POINT(1 2 3 4)']
};
testSql(query, expected);
});
});
describe('distance', function() {
it('works as expected', function() {
var query, expected;
query = queryBuilder().select(st.distance('a', 'b'));
expected = {
sql: 'select ST_Distance("a", "b")',
bindings: []
};
testSql(query, expected);
});
it('works with a created geometry', function() {
var query, expected;
query = queryBuilder().select(st.distance('a', st.point(-48.23456, 20.12345)));
expected = {
sql: 'select ST_Distance("a", ST_Point(?, ?))',
bindings: [-48.23456, 20.12345]
};
testSql(query, expected);
});
});
describe('distanceSphere', function() {
it('works as expected', function() {
var query, expected;
query = queryBuilder().select(st.distanceSphere('a', 'b'));
expected = {
sql: 'select ST_DistanceSphere("a", "b")',
bindings: []
};
testSql(query, expected);
});
it('works with a created geometry', function() {
var query, expected;
query = queryBuilder().select(st.distanceSphere('a', st.point(-48.23456, 20.12345)));
expected = {
sql: 'select ST_DistanceSphere("a", ST_Point(?, ?))',
bindings: [-48.23456, 20.12345]
};
testSql(query, expected);
});
});
describe('boundingBoxIntersects', function() {
it ('works with two columns', function() {
var query, expected;
query = queryBuilder().select(st.boundingBoxIntersects('a', 'b').as('intersects'));
expected = {
sql: 'select "a" && "b" as "intersects"',
bindings: []
};
testSql(query, expected);
});
it ('works with other functions', function() {
var query, expected;
query = queryBuilder().select(st.boundingBoxIntersects('a', st.buffer('b', 100)).as('intersects'));
expected = {
sql: 'select "a" && ST_Buffer("b", ?) as "intersects"',
bindings: [100]
};
testSql(query, expected);
});
});
describe('boundingBoxContained', function() {
it ('works with two columns', function() {
var query, expected;
query = queryBuilder().select(st.boundingBoxContained('a', 'b').as('contained'));
expected = {
sql: 'select "a" @ "b" as "contained"',
bindings: []
};
testSql(query, expected);
});
it ('works with other functions', function() {
var query, expected;
query = queryBuilder().select(st.boundingBoxContained('a', st.buffer('b', 100)).as('contained'));
expected = {
sql: 'select "a" @ ST_Buffer("b", ?) as "contained"',
bindings: [100]
};
testSql(query, expected);
});
});
describe('boundingBoxContains', function() {
it ('works with two columns', function() {
var query, expected;
query = queryBuilder().select(st.boundingBoxContains('a', 'b').as('contains'));
expected = {
sql: 'select "a" ~ "b" as "contains"',
bindings: []
};
testSql(query, expected);
});
it ('works with other functions', function() {
var query, expected;
query = queryBuilder().select(st.boundingBoxContains('a', st.buffer('b', 100)).as('contains'));
expected = {
sql: 'select "a" ~ ST_Buffer("b", ?) as "contains"',
bindings: [100]
};
testSql(query, expected);
});
});
describe('setSRID', function() {
it('works as expected', function() {
var query, expected;
query = queryBuilder().select(st.setSRID('a', 4326));
expected = {
sql: 'select ST_SetSRID("a", ?)',
bindings: [4326]
};
testSql(query, expected);
});
it('works with a created geometry', function() {
var query, expected;
query = queryBuilder().select(st.setSRID(st.point(-48.23456, 20.12345), 4326));
expected = {
sql: 'select ST_SetSRID(ST_Point(?, ?), ?)',
bindings: [-48.23456, 20.12345, 4326]
};
testSql(query, expected);
});
});
describe('geographyFromText', function() {
it('can create a geography from a WKT text', function() {
var query, expected;
query = queryBuilder()
.insert({
'id': 1,
'geog': st.geographyFromText('POINT(-118.4079 33.9434)')
})
.into('points');
expected = {
sql: 'insert into "points" ("geog", "id") values (ST_GeographyFromText(?), ?)',
bindings: ['POINT(-118.4079 33.9434)', 1]
};
testSql(query, expected);
});
});
describe('multi', function() {
it('works as expected', function() {
var query, expected;
query = queryBuilder().select(st.asText(st.multi(st.geomFromText('Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326))));
expected = {
sql: `select ST_asText(ST_Multi(ST_geomFromText(?, ?)))`,
bindings: ['Polygon((0 0, 0 1, 1 1, 1 0, 0 0))', 4326]
};
testSql(query, expected);
});
});