128 Commits
0.0.4 ... 1.0.2

Author SHA1 Message Date
Mario de Frutos
4c434ffb8d Release 1.0.2 artifact 2016-07-15 15:52:38 +02:00
Mario de Frutos
b041821fc0 Merge pull request #150 from CartoDB/develop
Release 1.0.2 wit mocks for augment functions
2016-07-15 15:49:03 +02:00
Mario de Frutos
876515f9aa Merge pull request #127 from CartoDB/table_level_functions
Add table level functions and mocks
2016-07-15 15:47:02 +02:00
Mario de Frutos
25570e5b11 Merge pull request #147 from CartoDB/develop
Release 1.0.2
2016-07-15 15:28:52 +02:00
Carla
d93752efa3 move addr_host as a parameter 2016-07-15 11:34:42 +02:00
Mario de Frutos
588cda3262 Merge pull request #146 from CartoDB/release-v-1.0.2
Release v 1.0.2
2016-07-14 17:12:33 +02:00
john krauss
e43d0ca4cf Merge pull request #144 from CartoDB/getmeasure-using-obsmeta
Getmeasure using obsmeta
2016-07-14 09:24:51 -04:00
john krauss
987c4c5b76 Merge pull request #145 from CartoDB/obsmeta-end-to-end
use obs_meta for tests
2016-07-14 09:22:57 -04:00
John Krauss
51ce13f8b9 update NEWS with additional improvements 2016-07-14 09:21:16 -04:00
John Krauss
25f4dbc416 use obs_meta for tests 2016-07-14 09:11:02 -04:00
John Krauss
c09e0b6e83 can eliminate getrelatedcolumn 2016-07-13 18:42:25 -04:00
John Krauss
748428ace1 Merge branch 'release-v-1.0.2' into getmeasure-using-obsmeta 2016-07-13 18:41:04 -04:00
john krauss
10a0dc9b26 Merge pull request #141 from CartoDB/fix-hardcoded-getcategory-geom
Fix hardcoded getcategory geom
2016-07-13 18:39:31 -04:00
john krauss
9245de84b0 Merge pull request #142 from CartoDB/comment-notices
comment out notices
2016-07-13 18:38:59 -04:00
john krauss
514e1e4c5b Merge pull request #138 from CartoDB/mx-tests
test location for MX
2016-07-13 18:38:46 -04:00
John Krauss
7bb1bbd804 handle predenomination of points properly 2016-07-13 18:37:17 -04:00
John Krauss
1d008ccbe9 should not try to use area normalization for zhvi 2016-07-13 18:33:53 -04:00
John Krauss
f581278b8a default is now NULL 2016-07-13 18:24:45 -04:00
John Krauss
cbf1c5e67d fix default normalizations 2016-07-13 18:16:53 -04:00
John Krauss
adc663b563 default to area normalization for point, no normalization for polygon getmeasures 2016-07-13 18:14:09 -04:00
John Krauss
3a37b98b72 we still needt hese for getdemographicsnapshot 2016-07-13 17:54:19 -04:00
John Krauss
a4a20e9c1d prevent internal join for denominated getmeasure by polygon 2016-07-13 17:41:05 -04:00
John Krauss
f485426085 fix syntax error 2016-07-13 17:38:54 -04:00
John Krauss
75e765f256 explicit type casts for = ANY 2016-07-13 17:38:05 -04:00
John Krauss
b690478aff use IN ANY to avoid joins elsewhere, and filter by nonzero overlap for all getmeasure polygon queries 2016-07-13 17:36:27 -04:00
John Krauss
6fa9d5c96a add missing array_agg 2016-07-13 17:27:03 -04:00
John Krauss
fc6317161f avoid joins 2016-07-13 17:26:01 -04:00
John Krauss
c07d9f6833 add missing params 2016-07-13 17:13:45 -04:00
John Krauss
ff173a0152 filter so theres some overlap 2016-07-13 17:12:16 -04:00
John Krauss
a7de1f2228 intersects, not overlaps 2016-07-13 16:57:27 -04:00
John Krauss
86529ada5a use st_overlaps instead of && 2016-07-13 16:53:50 -04:00
John Krauss
80cdc5e8ca fix predicate 2016-07-13 16:48:06 -04:00
John Krauss
7c8c5cca0a fix params 2016-07-13 16:42:02 -04:00
John Krauss
a946ab9d03 fix params in denominated polygon getmeasure 2016-07-13 16:28:50 -04:00
John Krauss
da127baa3c implementation for polygon/multipolygon weighted getmeasure 2016-07-13 16:24:33 -04:00
John Krauss
e89a88aa83 use subselects as joins are horrifically slow over FDW 2016-07-13 15:59:27 -04:00
John Krauss
af2259bb0a fix wrong number of variables INTO 2016-07-13 13:39:33 -04:00
John Krauss
fb083f4b9e fix typo 2016-07-13 13:30:05 -04:00
John Krauss
976e119abb fix typo 2016-07-13 12:21:53 -04:00
John Krauss
bbc6f9ef36 getmeasure bypassing several older functions, areas not yet implemented 2016-07-13 12:20:01 -04:00
John Krauss
5229279ee9 Merge branch 'comment-notices' into release-v-1.0.2-preview 2016-07-13 11:14:00 -04:00
John Krauss
0090e537fc add comment-notices branch merge to NEWS.md 2016-07-13 11:07:06 -04:00
John Krauss
e4052ed565 better feedback in autotest 2016-07-13 10:59:25 -04:00
John Krauss
2107796f07 updates to NEWS.md and observatory.control 2016-07-12 17:49:34 -04:00
john krauss
2463623658 Merge pull request #136 from CartoDB/obs-meta-internal
Use obs_meta for OBS_GetMeasureByID, support obs_meta
2016-07-12 17:33:43 -04:00
John Krauss
91797918c1 Merge branch 'fix-hardcoded-getcategory-geom' into release-v-1.0.2-preview 2016-07-12 16:10:19 -04:00
John Krauss
6a39bedee7 fix ambiguous colname for categories in points too 2016-07-12 16:10:00 -04:00
John Krauss
6ce0e5a8d9 Merge branch 'fix-hardcoded-getcategory-geom' into release-v-1.0.2-preview 2016-07-12 16:08:05 -04:00
John Krauss
81176d1df2 fix possible ambiguity in category colname 2016-07-12 16:06:19 -04:00
John Krauss
f22854b4e9 Merge branch 'fix-hardcoded-getcategory-geom' into release-v-1.0.2-preview 2016-07-12 15:58:02 -04:00
John Krauss
54701d595a Merge branch 'obs-meta-internal' into release-v-1.0.2-preview 2016-07-12 15:57:44 -04:00
John Krauss
4b26eeda65 fix to correct segment for testarea area 2016-07-12 15:33:26 -04:00
John Krauss
4fc02f99e2 choose largest segment in the polygon 2016-07-12 14:37:43 -04:00
John Krauss
5bb4285528 fix typo 2016-07-12 14:16:28 -04:00
John Krauss
1e9c3fb860 fix typo 2016-07-12 14:15:00 -04:00
John Krauss
62a2c259a7 fix typo 2016-07-12 14:13:09 -04:00
John Krauss
61854a070d fix wrong quoting 2016-07-12 14:11:02 -04:00
John Krauss
8654c22c87 handle area categories properly 2016-07-12 14:06:43 -04:00
John Krauss
62c08864af remove bad "target_table" notice 2016-07-12 12:37:30 -04:00
John Krauss
af39a37b43 fix missing comma 2016-07-12 12:34:32 -04:00
John Krauss
26b61a6ddb minor formatting 2016-07-12 12:26:10 -04:00
John Krauss
965fb94704 fix bugs in obs_getcategory implementation 2016-07-12 12:22:06 -04:00
John Krauss
84dec8bdf4 simplify obs_getcategory and use obs_meta 2016-07-12 12:09:42 -04:00
John Krauss
568996930b test location for MX 2016-07-12 12:02:49 -04:00
John Krauss
ebc27dbbb7 faster obs_meta generation, use better formatting and handle NULL boundary_id 2016-07-12 11:52:56 -04:00
John Krauss
56fa19118b adjust expectations 2016-07-12 11:25:50 -04:00
John Krauss
4f3baac10a adjust expectations and make sure echo is none 2016-07-12 11:21:42 -04:00
John Krauss
b512985b46 drop/create less, better indexes 2016-07-12 11:15:08 -04:00
John Krauss
329b4dbca3 do not imitate foreign keys 2016-07-12 10:46:53 -04:00
John Krauss
897cf38d42 faster generation of obs-meta via indexes 2016-07-12 10:42:00 -04:00
John Krauss
fe6343c73f should use coaelesce, not nullif 2016-07-12 10:16:19 -04:00
John Krauss
26ee8aedb1 solve null identifier issue 2016-07-12 10:16:13 -04:00
John Krauss
66e2c6be54 create obs_meta out of dump band 2016-07-12 10:16:02 -04:00
John Krauss
6b41994a87 add missing formatstring args 2016-07-12 10:15:53 -04:00
John Krauss
d3d5cbdbbd use obs_meta in obs_getmeasurebyid 2016-07-12 10:15:44 -04:00
John Krauss
4d51ecc12e comment out notices 2016-07-12 10:14:59 -04:00
Carlos Matallín
c0030acb0c Merge pull request #131 from CartoDB/docs-781
rebranding
2016-07-07 18:57:47 +02:00
Carlos Matallín
e938ee0c7b Merge branch 'develop' into docs-781 2016-07-07 18:57:26 +02:00
Rafa de la Torre
8fa2d642bf Update release dir with make release 2016-07-01 19:02:53 +02:00
Rafa de la Torre
926435a908 Update NEWS and control file for v1.0.1 2016-07-01 18:57:21 +02:00
Rafa de la Torre
80073aa213 Merge remote-tracking branch 'origin/develop' 2016-07-01 18:53:11 +02:00
Rafa de la Torre
3f78797e14 Merge pull request #130 from CartoDB/preemptive-setsrid
preemptively set_srid for obs_getavailableboundaries
2016-07-01 18:49:57 +02:00
John Krauss
11dbb860ab preemptively set_srid for obs_getavailableboundaries 2016-07-01 18:43:05 +02:00
Carla
9ade6588e2 Add augment functions, add mocks for data retrieval, create own fdw functions to avoid cartodb dependency 2016-07-01 12:31:39 +02:00
Andy Eschbacher
5ef1427bc3 Merge pull request #126 from CartoDB/develop
documentation updates
2016-06-28 13:11:00 -04:00
csobier
3f63f6f138 Merge pull request #125 from CartoDB/docs-879-update-license
modified license content as per Operations request
2016-06-28 12:22:47 -04:00
Rafa de la Torre
3d59adc452 Remove paragraph from RELEASE.md doc
Remove paragraph about generating upgrade and downgrade paths, as we're
not applying it to the release process.
2016-06-28 17:27:35 +02:00
Rafa de la Torre
50c5f01f3f New release v1.0.0. 2016-06-28 17:27:16 +02:00
Rafa de la Torre
0dad5427c4 Merge pull request #124 from CartoDB/release-v-1.0.0
Release v 1.0.0
2016-06-28 17:19:32 +02:00
csobier
71c098c1c3 updated API file to show where all live, public docs are coming from. Updated link to PDF catalog 2016-06-28 10:48:46 -04:00
csobier
4057f76fc1 modified license content as per Operations request 2016-06-28 07:52:21 -04:00
John Krauss
17aeb5187b update to NEWS and control file in prep for release 2016-06-27 12:51:39 -04:00
John Krauss
cf7c115a76 Merge branch 'release-v-0.0.6' into fix-geom_geoid_colname 2016-06-27 12:39:09 -04:00
John Krauss
4e8341daab Merge branch 'release-v-0.0.6' into obs-dump-version 2016-06-27 12:37:15 -04:00
John Krauss
ca4327d3cd use data_geoid_colname with data table, reenable area-based measure tests that can catch this bug 2016-06-27 11:55:03 -04:00
John Krauss
bac48d7bea add missing RETURN 2016-06-22 14:35:40 -04:00
John Krauss
91383fe933 correct obs_getdumpversion to obs_dumpversion 2016-06-22 14:33:53 -04:00
John Krauss
446bdec30d obs_dumpversion and associated tests 2016-06-22 14:29:58 -04:00
John Krauss
f362e97f88 remove geometrycollection from obs_table fixture 2016-06-22 14:20:03 -04:00
John Krauss
975137641d fix ambiguous reference o the_geom 2016-06-22 13:38:29 -04:00
John Krauss
9379224629 use intersection against geom instead of && against bounds, update fixtures 2016-06-22 12:20:52 -04:00
John Krauss
7733529ff5 Merge remote-tracking branch 'origin/develop' into more-automated-tests 2016-06-22 12:13:03 -04:00
John Krauss
5a68f77b64 use Madrid for all spanish tests, add point for england/wales wales specifically 2016-06-20 13:16:12 -04:00
John Krauss
63448d6214 many more (commented out) tests for complete geom coverage, plus getuscensusmeasure tests 2016-06-01 18:16:50 -04:00
csobier
a18b07fa84 rebranded name must appear in ALL CAPS 2016-05-31 12:33:15 -04:00
csobier
11b05877f4 reverted rebranded code, as instruted. Legacy cartodb code instead 2016-05-31 12:05:34 -04:00
Mario de Frutos
62b23be2e0 Merge branch 'master' into develop 2016-05-30 18:31:22 +02:00
Mario de Frutos
eefdae8a58 Version 0.0.5 SQL file 2016-05-30 18:30:21 +02:00
Mario de Frutos
563c31a77f Version 0.0.5 SQL file 2016-05-30 18:26:02 +02:00
Mario de Frutos
3334e60ab8 Merge pull request #103 from CartoDB/develop
Version 0.0.5
2016-05-30 18:22:59 +02:00
csobier
da6aac4a18 Merge pull request #102 from CartoDB/docs-101-license-phrasing
updated license INE description
2016-05-30 12:01:18 -04:00
csobier
5e99b60329 updated license INE description 2016-05-30 11:05:50 -04:00
Mario de Frutos
67d735af03 Merge pull request #99 from CartoDB/bump-control-0.0.5
updating version to 0.0.5
2016-05-30 16:20:00 +02:00
Andy Eschbacher
e960f3e097 backfilling news 2016-05-26 14:13:12 -04:00
Andy Eschbacher
8fbb9ebbcc updating version to 0.0.5 2016-05-26 13:48:37 -04:00
Andy Eschbacher
389823d4fd Merge pull request #96 from CartoDB/add-getmeasurebyid
Adds OBS_GetMeasureById
2016-05-26 13:37:50 -04:00
Andy Eschbacher
076e285ed7 adds notes on test calls 2016-05-26 13:37:02 -04:00
Andy Eschbacher
43dc37f62b Merge branch 'develop' into add-getmeasurebyid 2016-05-26 13:31:55 -04:00
Andy Eschbacher
49d584822c adds another test on different types of inputs 2016-05-26 13:28:56 -04:00
csobier
02ca484719 applied docs 781 to data observatory docs 2016-05-26 12:31:01 -04:00
Andy Eschbacher
3502282835 adds more description for timespan 2016-05-24 13:30:22 -04:00
Andy Eschbacher
f9ecf1595c adds docs for obs_getmeasurebyid 2016-05-24 13:28:21 -04:00
Andy Eschbacher
b5267c14bf removes unneeded todo 2016-05-24 13:15:19 -04:00
Andy Eschbacher
afb548c75d adds tests 2016-05-24 12:02:32 -04:00
Andy Eschbacher
94756a2377 minor formatting changes 2016-05-24 11:27:41 -04:00
Andy Eschbacher
2e312464aa fixes geom_ref in where condition 2016-05-24 11:22:39 -04:00
Andy Eschbacher
3f77a384c7 adds missing comma 2016-05-24 11:06:53 -04:00
Andy Eschbacher
1ba7299fe4 adds obs_getmeasurebyid 2016-05-24 11:02:35 -04:00
32 changed files with 22208 additions and 8959 deletions

90
NEWS.md
View File

@@ -1,3 +1,89 @@
0.0.1 (open date)
1.0.2 (2016-07-12)
---
__Bugfixes__
* Fix for `OBS_GetCategory` outside the US ([#135](https://github.com/CartoDB/observatory-extension/pull/137))
* `OBS_GetMeasure` now respects the `normalize` parameter even when passed
a multi/polygon. Previously, no normalization was erroneously assumed.
__Improvements__
* Automated tests cover Mexico data
* `obs_meta` is now provisioned during unit tests
* `obs_meta` is now used during end-to-end tests
* `OBS_GetMeasureByID` uses `obs_meta` internally, which should help
performance
* `OBS_GetCategory` uses `obs_meta` internally, which should help perfromance
* `OBS_GetCategory` will pick the correct category for an arbitrary polygon
(the category covering the highest % of that polygon)
* `OBS_GetMeasure` has been updated to use `obs_meta` internally, which should
help performance
* `OBS_GetMeasure` now can be passed "none" and skip normalization by area or
denominator for points
* Fixtures are only loaded at the start of the unit test suite, and dropped at the end,
instead of at the start/end of each individual test file
* Comment noisy NOTICEs ([#73](https://github.com/CartoDB/observatory-extension/issues/73))
1.0.1 (2016-07-01)
---
__Bugfixes__
* Fix for ERROR: Operation on mixed SRID geometries #130
1.0.0 (6/27/2016)
-----
* Incremented to 1.0.0 to be in compliance with [SemVer](http://semver.org/),
which disallows use of 0.x.x versions. This also reflects that we are
already in production.
__API Changes__
* Added `OBS_DumpVersion` to look up version data ([#118](https://github.com/CartoDB/observatory-extension/pull/118))
__Improvements__
* Whether data exists for a geom now determined by polygon intersection instead of
BBOX overlap ([#119](https://github.com/CartoDB/observatory-extension/pull/119))
* Automated tests cover Spanish and UK data
([#115](https://github.com/CartoDB/observatory-extension/pull/115))
* Automated tests cover `OBS_GetUSCensusMeasure`
([#105](https://github.com/CartoDB/observatory-extension/pull/105))
__Bugfixes__
* Geom table can have different `geomref_colname` than the data table
([#123](https://github.com/CartoDB/observatory-extension/pull/123))
0.0.5 (5/27/2016)
-----
* Adds new function `OBS_GetMeasureById` ([#96](https://github.com/CartoDB/observatory-extension/pull/96))
0.0.4 (5/25/2016)
-----
* Updates queries involving US Census measure tags to be more generic ([#95](https://github.com/CartoDB/observatory-extension/pull/95))
* Fixes tests which relied on an erroneous subset of block groups ([#95](https://github.com/CartoDB/observatory-extension/pull/95))
0.0.3 (5/24/2016)
-----
* Generalizes internal queries to properly pull from multiple named geometry references
* Adds tests for Who's on First boundaries
* Improves automatic fixtures testing script
0.0.2 (5/19/2016)
-----
* Adds Data Observatory exploration functions
* Adds Data Observatory boundary functions
* Adds Data Observatory measure functions
* Adds script to generate fixtures for tests
* Adds script for the automatic testing of metadata
* Adds full documentation for all included functions
* removes `cartodb` extension dependency
0.0.1 (5/19/2016)
------------------
* First iteration of `OBS_GetDemographicSnapshot(location Geometry(Point,4326))`;
* First iteration of `OBS_GetDemographicSnapshot(location Geometry(Point,4326))`

View File

@@ -20,12 +20,6 @@ script for the new release, `release/observatory--X.Y.Z.sql`:
make release
```
Then, the release manager shall produce upgrade and downgrade scripts
to migrate to/from the previous release. In the case of minor/patch
releases this simply consist in extracting the functions that have changed
and placing them in the proper `release/observatory--X.Y.Z--A.B.C.sql`
file.
The new release can be deployed for staging/smoke tests with this command:
```

View File

@@ -4,6 +4,8 @@ This file is for reference purposes only. It is intended for tracking the Data O
## Documentation
* Overview (local file in the Docs repo)
* Accessing the Data Observatory (local file in the Docs repo)
* [Measures Functions](measures_functions.md)
* [Boundary Functions](boundary_functions.md)
* [Discovery Functions](discovery_functions.md)

View File

@@ -1,8 +1,8 @@
# Boundary Functions
Use the following functions to retrieve [Boundary](/cartodb-platform/data/overview/#boundary-data) data. Data ranges from small areas (e.g. US Census Block Groups) to large areas (e.g. Countries). You can access boundaries by point location lookup, bounding box lookup, direct ID access and several other methods described below.
Use the following functions to retrieve [Boundary](/carto-engine/data/overview/#boundary-data) data. Data ranges from small areas (e.g. US Census Block Groups) to large areas (e.g. Countries). You can access boundaries by point location lookup, bounding box lookup, direct ID access and several other methods described below.
You can [access](/cartodb-platform/data/accessing/#accessing-the-data-observatory) boundaries through the CartoDB Editor. The same methods will work if you are using the CartoDB Platform to develop your application. We [encourage you](/cartodb-platform/data/accessing/#best-practices) to use table modifying methods (UPDATE and INSERT) over dynamic methods (SELECT).
You can [access](/carto-engine/data/accessing/#accessing-the-data-observatory) boundaries through the CARTO Editor. The same methods will work if you are using the CARTO Engine to develop your application. We [encourage you](/carto-engine/data/accessing/#best-practices) to use table modifying methods (UPDATE and INSERT) over dynamic methods (SELECT).
## OBS_GetBoundariesByGeometry(polygon geometry, geometry_id text)

View File

@@ -1,6 +1,6 @@
# Discovery Functions
If you are using the [discovery methods](/cartodb-platform/data/overview/#discovery-methods) from the Data Observatory, use the following functions to retrieve [boundary](/cartodb-platform/data/overview/#boundary-data) and [measures](/cartodb-platform/data/overview/#measures-data) data.
If you are using the [discovery methods](/carto-engine/data/overview/#discovery-methods) from the Data Observatory, use the following functions to retrieve [boundary](/carto-engine/data/overview/#boundary-data) and [measures](/carto-engine/data/overview/#measures-data) data.
## OBS_Search(search_term)
@@ -47,7 +47,7 @@ A TABLE containing the following properties
Key | Description
--- | ---
boundary_id | a boundary identifier from the [boundary ID glossary](/cartodb-platform/data/glossary/#boundary-ids)
boundary_id | a boundary identifier from the [boundary ID glossary](/carto-engine/data/glossary/#boundary-ids)
description | a brief description of the boundary dataset
time_span | the timespan attached the boundary. this does not mean that the boundary is invalid outside of the timespan, but is the explicit timespan published with the geometry.

View File

@@ -29,7 +29,7 @@ Disputed Areas | whosonfirst.wof_disputed_geom | none
## OBS_GetUSCensusMeasure Names Table
This list contains human readable names accepted in the ```OBS_GetUSCensusMeasure``` function. For the more comprehensive list of columns available to the ```OBS_GetMeasure``` function, see the [Data Observatory Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf).
This list contains human readable names accepted in the ```OBS_GetUSCensusMeasure``` function. For the more comprehensive list of columns available to the ```OBS_GetMeasure``` function, see the [Data Observatory Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf).
Measure name | Measure description
------------------------ | --------------------

View File

@@ -1,6 +1,8 @@
# License
The Data Observatory is a collection of various sources of data with varying licenses. We have worked hard to find you data that will work for the broadest set of use-cases. For competency, please still review the terms for any dataset you use and respect the rights of the owners for each dataset. The following third-party data sources are used in the Data Observatory, and we have included the links to the terms governing their use.
The Data Observatory is a collection of data sources with varying licenses and terms of use. We have endeavored to find you data that will work for the broadest set of use-cases. The following third-party data sources are used in the Data Observatory, and we have included the links to the terms governing their use.
_**Legal Note**: The Data Observatory makes use of a variety of third party data and databases (collectively, the “Data”). You acknowledge that the included Data, and the licenses and terms of use, may be amended from time to time. Whenever you use the Data, you agree to the current relevant terms or license. Some Data will require that you provide attribution to the data source. Other Data may be protected by US or international copyright laws, treaties, or conventions. The Data and associated metadata are provided 'as-is', without express or implied warranty of any kind, including, but not limited to, infringement, merchantability and fitness for a particular purpose. CartoDB is not responsible for the accuracy, completeness, timeliness or quality of the Data._
Name | Terms link
-------|---------
@@ -14,5 +16,5 @@ Natural Earth | [http://www.naturalearthdata.com/about/terms-of-use/](http://w
Quattroshapes | [https://github.com/foursquare/quattroshapes/blob/master/LICENSE.md](https://github.com/foursquare/quattroshapes/blob/master/LICENSE.md)
Zetashapes | [http://zetashapes.com/license](http://zetashapes.com/license)
Spielman & Singleton | [https://www.openicpsr.org/repoEntity/show/41329](https://www.openicpsr.org/repoEntity/show/41329)
Instituto Nacional de Estadistica | [http://www.ine.es/ss/Satellite?L=0&c=Page&cid=1254735849170&p=1254735849170&pagename=Ayuda%2FINELayout](http://www.ine.es/ss/Satellite?L=0&c=Page&cid=1254735849170&p=1254735849170&pagename=Ayuda%2FINELayout)
El Instituto Nacional de Estadística (INE) | The National Statistics Institute (INE) of Spain includes data from multiple sources. If you are re-using their data, they explicitly require that you reference them accordingly<br /><br />[http://www.ine.es/ss/Satellite?L=0&c=Page&cid=1254735849170&p=1254735849170&pagename=Ayuda%2FINELayout](http://www.ine.es/ss/Satellite?L=0&c=Page&cid=1254735849170&p=1254735849170&pagename=Ayuda%2FINELayout)

View File

@@ -1,10 +1,10 @@
# Measures Functions
[Data Observatory Measures](/cartodb-platform/data/overview/#measures-methods) are the numerical location data you can access. The measure functions allow you to access individual measures to augment your own data or integrate in your analysis workflows. Measures are used by sending an identifier or a geometry (point or polygon) and receiving back a measure (an absolute value) for that location.
[Data Observatory Measures](/carto-engine/data/overview/#measures-methods) are the numerical location data you can access. The measure functions allow you to access individual measures to augment your own data or integrate in your analysis workflows. Measures are used by sending an identifier or a geometry (point or polygon) and receiving back a measure (an absolute value) for that location.
There are hundreds of measures and the list is growing with each release. You can currently discover and learn about measures contained in the Data Observatory by downloading our [Data Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf).
There are hundreds of measures and the list is growing with each release. You can currently discover and learn about measures contained in the Data Observatory by downloading our [Data Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf).
You can [access](/cartodb-platform/data/accessing/#accessing-the-data-observatory) measures through the CartoDB Editor. The same methods will work if you are using the CartoDB Platform to develop your application. We [encourage you](/cartodb-platform/data/accessing/#best-practices) to use table modifying methods (UPDATE and INSERT) over dynamic methods (SELECT).
You can [access](/carto-engine/data/accessing/#accessing-the-data-observatory) measures through the CARTO Editor. The same methods will work if you are using the CARTO Engine to develop your application. We [encourage you](/carto-engine/data/accessing/#best-practices) to use table modifying methods (UPDATE and INSERT) over dynamic methods (SELECT).
## OBS_GetUSCensusMeasure(point geometry, measure_name text)
@@ -16,7 +16,7 @@ Name |Description
--- | ---
point | a WGS84 point geometry (the_geom)
measure_name | a human readable name of a US Census variable. The list of measure_names is [available in the glossary](/cartodb-platform/data/glossary/#obsgetuscensusmeasure-names-table).
normalize | for measures that are are **sums** (e.g. population) the default normalization is 'area' and response comes back as a rate per square kilometer. Other options are 'denominator', which will use the denominator specified in the [Data Catalog](http://cartodb.github.io/bigmetadata/index.html) (optional)
normalize | for measures that are are **sums** (e.g. population) the default normalization is 'area' and response comes back as a rate per square kilometer. Other options are 'denominator', which will use the denominator specified in the [Data Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf) (optional)
boundary_id | source of geometries to pull measure from (e.g., 'us.census.tiger.census_tract')
time_span | time span of interest (e.g., 2010 - 2014)
@@ -47,7 +47,7 @@ Name |Description
--- | ---
polygon | a WGS84 polygon geometry (the_geom)
measure_name | a human readable string name of a US Census variable. The list of measure_names is [available in the glossary](/cartodb-platform/data/glossary/#obsgetuscensusmeasure-names-table).
normalize | for measures that are **sums** (e.g. population) the default normalization is 'none' and response comes back as a raw value. Other options are 'denominator', which will use the denominator specified in the [Data Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf) (optional)
normalize | for measures that are **sums** (e.g. population) the default normalization is 'none' and response comes back as a raw value. Other options are 'denominator', which will use the denominator specified in the [Data Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf) (optional)
boundary_id | source of geometries to pull measure from (e.g., 'us.census.tiger.census_tract')
time_span | time span of interest (e.g., 2010 - 2014)
@@ -70,7 +70,7 @@ SET local_male_population = OBS_GetUSCensusMeasure(the_geom, 'Male Population')
## OBS_GetMeasure(point geometry, measure_id text)
The ```OBS_GetMeasure(point, measure_id)``` function returns any Data Observatory measure at a point location. You can browse all available Measures in the [Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf)).
The ```OBS_GetMeasure(point, measure_id)``` function returns any Data Observatory measure at a point location. You can browse all available Measures in the [Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf).
#### Arguments
@@ -78,7 +78,7 @@ Name |Description
--- | ---
point | a WGS84 point geometry (the_geom)
measure_id | a measure identifier from the Data Observatory ([see available measures](https://cartodb.github.io/bigmetadata/observatory.pdf)). It is important to note that these are different than 'measure_name' used in the Census based functions above.
normalize | for measures that are are **sums** (e.g. population) the default normalization is 'area' and response comes back as a rate per square kilometer. The other option is 'denominator', which will use the denominator specified in the [Data Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf). (optional)
normalize | for measures that are are **sums** (e.g. population) the default normalization is 'area' and response comes back as a rate per square kilometer. The other option is 'denominator', which will use the denominator specified in the [Data Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf). (optional)
boundary_id | source of geometries to pull measure from (e.g., 'us.census.tiger.census_tract')
time_span | time span of interest (e.g., 2010 - 2014)
@@ -109,7 +109,7 @@ Name |Description
--- | ---
polygon_geometry | a WGS84 polygon geometry (the_geom)
measure_id | a measure identifier from the Data Observatory ([see available measures](https://cartodb.github.io/bigmetadata/observatory.pdf))
normalize | for measures that are are **sums** (e.g. population) the default normalization is 'none' and response comes back as a raw value. Other options are 'denominator', which will use the denominator specified in the [Data Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf) (optional)
normalize | for measures that are are **sums** (e.g. population) the default normalization is 'none' and response comes back as a raw value. Other options are 'denominator', which will use the denominator specified in the [Data Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf) (optional)
boundary_id | source of geometries to pull measure from (e.g., 'us.census.tiger.census_tract')
time_span | time span of interest (e.g., 2010 - 2014)
@@ -134,9 +134,43 @@ SET household_count = OBS_GetMeasure(the_geom, 'us.census.acs.B11001001')
* If an unrecognized normalization type is input, raise an error: `'Only valid inputs for "normalize" are "area" (default) and "denominator".`
## OBS_GetMeasureById(geom_ref text, measure_id text, boundary_id text)
The ```OBS_GetMeasureById(geom_ref, measure_id, boundary_id)``` function returns any Data Observatory measure that corresponds to the boundary in ```boundary_id``` that has a geometry reference of ```geom_ref```.
#### Arguments
Name |Description
--- | ---
geom_ref | a geometry reference (e.g., a US Census geoid)
measure_id | a measure identifier from the Data Observatory ([see available measures](https://cartodb.github.io/bigmetadata/observatory.pdf))
boundary_id | source of geometries to pull measure from (e.g., 'us.census.tiger.census_tract')
time_span (optional) | time span of interest (e.g., 2010 - 2014). If `NULL` is passed, the measure from the most recent data will be used.
#### Returns
A NUMERIC value
Key | Description
--- | ---
value | the raw measure associated with `geom_ref`
#### Example
Add a measure to an empty column based on county geoids in your table
```SQL
UPDATE tablename
SET household_count = OBS_GetMeasureById(geoid_column, 'us.census.acs.B11001001', 'us.census.tiger.county')
```
#### Errors
* Returns `NULL` if there is a mismatch between the geometry reference and the boundary id such as using the geoid of a county with the boundary of block groups
## OBS_GetCategory(point geometry, category_id text)
The ```OBS_GetCategory(point, category_id)``` function returns any Data Observatory Category value at a point location. The Categories available are currently limited to Segmentation categories. See the Segmentation section of the [Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf) for more detail.
The ```OBS_GetCategory(point, category_id)``` function returns any Data Observatory Category value at a point location. The Categories available are currently limited to Segmentation categories. See the Segmentation section of the [Catalog](http://data-observatory.s3.amazonaws.com/observatory.pdf) for more detail.
#### Arguments

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
comment = 'CartoDB Observatory backend extension'
default_version = '0.0.4'
default_version = '1.0.2'
requires = 'postgis'
superuser = true
schema = cdb_observatory

View File

@@ -24,16 +24,18 @@ def query(q, is_meta=False, **options):
params['api_key'] = META_API_KEY if is_meta else API_KEY
return requests.get(url, params=params)
MEASURE_COLUMNS = [(r['id'], ) for r in query('''
SELECT id FROM obs_column
WHERE type ILIKE 'numeric'
AND weight > 0
MEASURE_COLUMNS = [(r['numer_id'], r['point_only'], ) for r in query('''
SELECT distinct numer_id, numer_aggregate NOT ILIKE 'sum' as point_only
FROM obs_meta
WHERE numer_type ILIKE 'numeric'
AND numer_weight > 0
''', is_meta=True).json()['rows']]
CATEGORY_COLUMNS = [(r['id'], ) for r in query('''
SELECT id FROM obs_column
WHERE type ILIKE 'text'
AND weight > 0
CATEGORY_COLUMNS = [(r['numer_id'], ) for r in query('''
SELECT distinct numer_id
FROM obs_meta
WHERE numer_type ILIKE 'text'
AND numer_weight > 0
''', is_meta=True).json()['rows']]
BOUNDARY_COLUMNS = [(r['id'], ) for r in query('''
@@ -42,7 +44,16 @@ WHERE type ILIKE 'geometry'
AND weight > 0
''', is_meta=True).json()['rows']]
def default_point(column_id):
US_CENSUS_MEASURE_COLUMNS = [(r['numer_name'], ) for r in query('''
SELECT distinct numer_name
FROM obs_meta
WHERE numer_type ILIKE 'numeric'
AND 'us.census.acs.acs' = ANY (subsection_tags)
AND numer_weight > 0
''', is_meta=True).json()['rows']]
def default_geometry_id(column_id):
'''
Returns default test point for the column_id.
'''
@@ -63,8 +74,76 @@ def default_point(column_id):
return 'CDB_LatLng(40.7, -73.9)'
def default_point(column_id):
'''
Returns default test point for the column_id.
'''
if column_id == 'whosonfirst.wof_disputed_geom':
return 'CDB_LatLng(33.78, 76.57)'
elif column_id == 'whosonfirst.wof_marinearea_geom':
return 'CDB_LatLng(43.33, -68.47)'
elif column_id in ('us.census.tiger.school_district_elementary',
'us.census.tiger.school_district_secondary',
'us.census.tiger.school_district_elementary_clipped',
'us.census.tiger.school_district_secondary_clipped'):
return 'CDB_LatLng(40.7025, -73.7067)'
elif column_id.startswith('uk'):
if 'WA' in column_id:
return 'CDB_LatLng(51.46844551219723, -3.184833526611328)'
else:
return 'CDB_LatLng(51.51461834694225, -0.08883476257324219)'
elif column_id.startswith('es'):
return 'CDB_LatLng(42.8226119029222, -2.51141249535454)'
elif column_id.startswith('us.zillow'):
return 'CDB_LatLng(28.3305906291771, -81.3544048197256)'
elif column_id.startswith('mx.'):
return 'CDB_LatLng(19.41347699386547, -99.17019367218018)'
else:
return 'CDB_LatLng(40.7, -73.9)'
def default_area(column_id):
'''
Returns default test area for the column_id
'''
point = default_point(column_id)
area = 'ST_Transform(ST_Buffer(ST_Transform({point}, 3857), 1000), 4326)'.format(
point=point)
return area
@parameterized(US_CENSUS_MEASURE_COLUMNS)
def test_get_us_census_measure_points(name):
print 'test_get_us_census_measure_points, ', name
resp = query('''
SELECT * FROM {schema}OBS_GetUSCensusMeasure({point}, '{name}')
'''.format(name=name.replace("'", "''"),
schema='cdb_observatory.' if USE_SCHEMA else '',
point=default_point('')))
assert_equal(resp.status_code, 200)
rows = resp.json()['rows']
assert_equal(1, len(rows))
assert_is_not_none(rows[0].values()[0])
@parameterized(MEASURE_COLUMNS)
def test_measure_points(column_id):
def test_get_measure_areas(column_id, point_only):
print 'test_get_measure_areas, ', column_id, point_only
if point_only:
return
resp = query('''
SELECT * FROM {schema}OBS_GetMeasure({area}, '{column_id}')
'''.format(column_id=column_id,
schema='cdb_observatory.' if USE_SCHEMA else '',
area=default_area(column_id)))
assert_equal(resp.status_code, 200)
rows = resp.json()['rows']
assert_equal(1, len(rows))
assert_is_not_none(rows[0].values()[0])
@parameterized(MEASURE_COLUMNS)
def test_get_measure_points(column_id, point_only):
print 'test_get_measure_points, ', column_id, point_only
resp = query('''
SELECT * FROM {schema}OBS_GetMeasure({point}, '{column_id}')
'''.format(column_id=column_id,
@@ -75,8 +154,21 @@ SELECT * FROM {schema}OBS_GetMeasure({point}, '{column_id}')
assert_equal(1, len(rows))
assert_is_not_none(rows[0].values()[0])
#@parameterized(CATEGORY_COLUMNS)
#def test_get_category_areas(column_id):
# resp = query('''
#SELECT * FROM {schema}OBS_GetCategory({area}, '{column_id}')
# '''.format(column_id=column_id,
# schema='cdb_observatory.' if USE_SCHEMA else '',
# area=default_area(column_id)))
# assert_equal(resp.status_code, 200)
# rows = resp.json()['rows']
# assert_equal(1, len(rows))
# assert_is_not_none(rows[0].values()[0])
@parameterized(CATEGORY_COLUMNS)
def test_category_points(column_id):
def test_get_category_points(column_id):
print 'test_get_category_points, ', column_id
resp = query('''
SELECT * FROM {schema}OBS_GetCategory({point}, '{column_id}')
'''.format(column_id=column_id,
@@ -87,14 +179,62 @@ SELECT * FROM {schema}OBS_GetCategory({point}, '{column_id}')
assert_equal(1, len(rows))
assert_is_not_none(rows[0].values()[0])
@parameterized(BOUNDARY_COLUMNS)
def test_boundary_points(column_id):
resp = query('''
SELECT * FROM {schema}OBS_GetBoundary({point}, '{column_id}')
'''.format(column_id=column_id,
schema='cdb_observatory.' if USE_SCHEMA else '',
point=default_point(column_id)))
assert_equal(resp.status_code, 200)
rows = resp.json()['rows']
assert_equal(1, len(rows))
assert_is_not_none(rows[0].values()[0])
#@parameterized(BOUNDARY_COLUMNS)
#def test_get_boundaries_by_geometry(column_id):
# resp = query('''
#SELECT * FROM {schema}OBS_GetBoundariesByGeometry({area}, '{column_id}')
# '''.format(column_id=column_id,
# schema='cdb_observatory.' if USE_SCHEMA else '',
# area=default_area(column_id)))
# assert_equal(resp.status_code, 200)
# rows = resp.json()['rows']
# assert_equal(1, len(rows))
# assert_is_not_none(rows[0].values()[0])
#@parameterized(BOUNDARY_COLUMNS)
#def test_get_points_by_geometry(column_id):
# resp = query('''
#SELECT * FROM {schema}OBS_GetPointsByGeometry({area}, '{column_id}')
# '''.format(column_id=column_id,
# schema='cdb_observatory.' if USE_SCHEMA else '',
# area=default_area(column_id)))
# assert_equal(resp.status_code, 200)
# rows = resp.json()['rows']
# assert_equal(1, len(rows))
# assert_is_not_none(rows[0].values()[0])
#@parameterized(BOUNDARY_COLUMNS)
#def test_get_boundary_points(column_id):
# resp = query('''
#SELECT * FROM {schema}OBS_GetBoundary({point}, '{column_id}')
# '''.format(column_id=column_id,
# schema='cdb_observatory.' if USE_SCHEMA else '',
# point=default_point(column_id)))
# assert_equal(resp.status_code, 200)
# rows = resp.json()['rows']
# assert_equal(1, len(rows))
# assert_is_not_none(rows[0].values()[0])
#@parameterized(BOUNDARY_COLUMNS)
#def test_get_boundary_id(column_id):
# resp = query('''
#SELECT * FROM {schema}OBS_GetBoundaryId({point}, '{column_id}')
# '''.format(column_id=column_id,
# schema='cdb_observatory.' if USE_SCHEMA else '',
# point=default_point(column_id)))
# assert_equal(resp.status_code, 200)
# rows = resp.json()['rows']
# assert_equal(1, len(rows))
# assert_is_not_none(rows[0].values()[0])
#@parameterized(BOUNDARY_COLUMNS)
#def test_get_boundary_by_id(column_id):
# resp = query('''
#SELECT * FROM {schema}OBS_GetBoundaryById({geometry_id}, '{column_id}')
# '''.format(column_id=column_id,
# schema='cdb_observatory.' if USE_SCHEMA else '',
# geometry_id=default_geometry_id(column_id)))
# assert_equal(resp.status_code, 200)
# rows = resp.json()['rows']
# assert_equal(1, len(rows))
# assert_is_not_none(rows[0].values()[0])

View File

@@ -33,7 +33,8 @@ def select_star(tablename):
cdb = Dumpr('observatory.cartodb.com','')
metadata = ['obs_table', 'obs_column_table', 'obs_column', 'obs_column_tag', 'obs_tag', 'obs_column_to_column']
metadata = ['obs_table', 'obs_column_table', 'obs_column', 'obs_column_tag',
'obs_tag', 'obs_column_to_column', 'obs_dump_version', ]
fixtures = [
('us.census.tiger.census_tract', 'us.census.tiger.census_tract', '2014'),
@@ -89,3 +90,124 @@ with open('src/pg/test/fixtures/load_fixtures.sql', 'w') as outfile:
cdb.dump(' '.join([select_star(tablename), "WHERE {}::text {} {}".format(colname, compare, where)]),
tablename, outfile, schema='observatory')
dropfiles.write('DROP TABLE IF EXISTS observatory.{};\n'.format(tablename))
outfile.write('''
ALTER TABLE observatory.obs_table
ADD PRIMARY KEY (id);
ALTER TABLE observatory.obs_column_table
ADD PRIMARY KEY (column_id, table_id);
CREATE UNIQUE INDEX ON observatory.obs_column_table (table_id, column_id);
CREATE UNIQUE INDEX ON observatory.obs_column_table (table_id, colname);
ALTER TABLE observatory.obs_column
ADD PRIMARY KEY (id);
ALTER TABLE observatory.obs_column_to_column
ADD PRIMARY KEY (source_id, target_id, reltype);
CREATE UNIQUE INDEX ON observatory.obs_column_to_column (target_id, source_id, reltype);
CREATE INDEX ON observatory.obs_column_to_column (reltype);
ALTER TABLE observatory.obs_column_tag
ADD PRIMARY KEY (column_id, tag_id);
CREATE UNIQUE INDEX ON observatory.obs_column_tag (tag_id, column_id);
ALTER TABLE observatory.obs_tag
ADD PRIMARY KEY (id);
CREATE INDEX ON observatory.obs_tag (type);
VACUUM ANALYZE observatory.obs_table;
VACUUM ANALYZE observatory.obs_column_table;
VACUUM ANALYZE observatory.obs_column;
VACUUM ANALYZE observatory.obs_column_to_column;
VACUUM ANALYZE observatory.obs_column_tag;
VACUUM ANALYZE observatory.obs_tag;
CREATE TABLE observatory.obs_meta AS
SELECT numer_c.id numer_id,
denom_c.id denom_id,
geom_c.id geom_id,
MAX(numer_c.name) numer_name,
MAX(denom_c.name) denom_name,
MAX(geom_c.name) geom_name,
MAX(numer_c.description) numer_description,
MAX(denom_c.description) denom_description,
MAX(geom_c.description) geom_description,
MAX(numer_c.aggregate) numer_aggregate,
MAX(denom_c.aggregate) denom_aggregate,
MAX(geom_c.aggregate) geom_aggregate,
MAX(numer_c.type) numer_type,
MAX(denom_c.type) denom_type,
MAX(geom_c.type) geom_type,
MAX(numer_data_ct.colname) numer_colname,
MAX(denom_data_ct.colname) denom_colname,
MAX(geom_geom_ct.colname) geom_colname,
MAX(numer_geomref_ct.colname) numer_geomref_colname,
MAX(denom_geomref_ct.colname) denom_geomref_colname,
MAX(geom_geomref_ct.colname) geom_geomref_colname,
MAX(numer_t.tablename) numer_tablename,
MAX(denom_t.tablename) denom_tablename,
MAX(geom_t.tablename) geom_tablename,
MAX(numer_t.timespan) numer_timespan,
MAX(denom_t.timespan) denom_timespan,
MAX(numer_c.weight) numer_weight,
MAX(denom_c.weight) denom_weight,
MAX(geom_c.weight) geom_weight,
MAX(geom_t.timespan) geom_timespan,
MAX(geom_t.the_geom_webmercator)::geometry AS the_geom_webmercator,
ARRAY_AGG(DISTINCT s_tag.id) section_tags,
ARRAY_AGG(DISTINCT ss_tag.id) subsection_tags,
ARRAY_AGG(DISTINCT unit_tag.id) unit_tags
FROM observatory.obs_column_table numer_data_ct,
observatory.obs_table numer_t,
observatory.obs_column_table numer_geomref_ct,
observatory.obs_column geomref_c,
observatory.obs_column_to_column geomref_c2c,
observatory.obs_column geom_c,
observatory.obs_column_table geom_geom_ct,
observatory.obs_column_table geom_geomref_ct,
observatory.obs_table geom_t,
observatory.obs_column_tag ss_ctag,
observatory.obs_tag ss_tag,
observatory.obs_column_tag s_ctag,
observatory.obs_tag s_tag,
observatory.obs_column_tag unit_ctag,
observatory.obs_tag unit_tag,
observatory.obs_column numer_c
LEFT JOIN (
observatory.obs_column_to_column denom_c2c
JOIN observatory.obs_column denom_c ON denom_c2c.target_id = denom_c.id
JOIN observatory.obs_column_table denom_data_ct ON denom_data_ct.column_id = denom_c.id
JOIN observatory.obs_table denom_t ON denom_data_ct.table_id = denom_t.id
JOIN observatory.obs_column_table denom_geomref_ct ON denom_geomref_ct.table_id = denom_t.id
) ON denom_c2c.source_id = numer_c.id
WHERE numer_c.id = numer_data_ct.column_id
AND numer_data_ct.table_id = numer_t.id
AND numer_t.id = numer_geomref_ct.table_id
AND numer_geomref_ct.column_id = geomref_c.id
AND geomref_c2c.reltype = 'geom_ref'
AND geomref_c.id = geomref_c2c.source_id
AND geom_c.id = geomref_c2c.target_id
AND geom_geomref_ct.column_id = geomref_c.id
AND geom_geomref_ct.table_id = geom_t.id
AND geom_geom_ct.column_id = geom_c.id
AND geom_geom_ct.table_id = geom_t.id
AND geom_c.type ILIKE 'geometry'
AND numer_c.type NOT ILIKE 'geometry'
AND numer_t.id != geom_t.id
AND numer_c.id != geomref_c.id
AND unit_tag.type = 'unit'
AND ss_tag.type = 'subsection'
AND s_tag.type = 'section'
AND unit_ctag.column_id = numer_c.id
AND unit_ctag.tag_id = unit_tag.id
AND ss_ctag.column_id = numer_c.id
AND ss_ctag.tag_id = ss_tag.id
AND s_ctag.column_id = numer_c.id
AND s_ctag.tag_id = s_tag.id
AND (denom_c2c.reltype = 'denominator' OR denom_c2c.reltype IS NULL)
AND (denom_geomref_ct.column_id = geomref_c.id OR denom_geomref_ct.column_id IS NULL)
AND (denom_t.timespan = numer_t.timespan OR denom_t.timespan IS NULL)
GROUP BY numer_c.id, denom_c.id, geom_c.id,
numer_t.id, denom_t.id, geom_t.id;
''')
dropfiles.write('''
DROP TABLE IF EXISTS observatory.obs_meta;
''')

View File

@@ -1,5 +1,5 @@
comment = 'CartoDB Observatory backend extension'
default_version = '0.0.4'
default_version = '1.0.2'
requires = 'postgis'
superuser = true
schema = cdb_observatory

View File

@@ -0,0 +1,67 @@
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_ConnectRemoteTable(fdw_name text, schema_name text, user_dbname text, user_hostname text, username text, user_tablename text, user_schema text)
RETURNS void
AS $$
DECLARE
row record;
option record;
connection_str json;
BEGIN
-- Build connection string
connection_str := '{"server":{"extensions":"postgis", "dbname":"'
|| user_dbname ||'", "host":"' || user_hostname ||'", "port":"5432"}, "users":{"public"'
|| ':{"user":"' || username ||'", "password":""} } }';
-- This function tries to be as idempotent as possible, by not creating anything more than once
-- (not even using IF NOT EXIST to avoid throwing warnings)
IF NOT EXISTS ( SELECT * FROM pg_extension WHERE extname = 'postgres_fdw') THEN
CREATE EXTENSION postgres_fdw;
END IF;
-- Create FDW first if it does not exist
IF NOT EXISTS ( SELECT * FROM pg_foreign_server WHERE srvname = fdw_name)
THEN
EXECUTE FORMAT('CREATE SERVER %I FOREIGN DATA WRAPPER postgres_fdw', fdw_name);
END IF;
-- Set FDW settings
FOR row IN SELECT p.key, p.value from lateral json_each_text(connection_str->'server') p
LOOP
IF NOT EXISTS (WITH a AS (select split_part(unnest(srvoptions), '=', 1) as options from pg_foreign_server where srvname=fdw_name) SELECT * from a where options = row.key)
THEN
EXECUTE FORMAT('ALTER SERVER %I OPTIONS (ADD %I %L)', fdw_name, row.key, row.value);
ELSE
EXECUTE FORMAT('ALTER SERVER %I OPTIONS (SET %I %L)', fdw_name, row.key, row.value);
END IF;
END LOOP;
-- Create user mappings
FOR row IN SELECT p.key, p.value from lateral json_each(connection_str->'users') p LOOP
-- Check if entry on pg_user_mappings exists
IF NOT EXISTS ( SELECT * FROM pg_user_mappings WHERE srvname = fdw_name AND usename = row.key ) THEN
EXECUTE FORMAT ('CREATE USER MAPPING FOR %I SERVER %I', row.key, fdw_name);
END IF;
-- Update user mapping settings
FOR option IN SELECT o.key, o.value from lateral json_each_text(row.value) o LOOP
IF NOT EXISTS (WITH a AS (select split_part(unnest(umoptions), '=', 1) as options from pg_user_mappings WHERE srvname = fdw_name AND usename = row.key) SELECT * from a where options = option.key) THEN
EXECUTE FORMAT('ALTER USER MAPPING FOR %I SERVER %I OPTIONS (ADD %I %L)', row.key, fdw_name, option.key, option.value);
ELSE
EXECUTE FORMAT('ALTER USER MAPPING FOR %I SERVER %I OPTIONS (SET %I %L)', row.key, fdw_name, option.key, option.value);
END IF;
END LOOP;
END LOOP;
-- Create schema if it does not exist.
IF NOT EXISTS ( SELECT * from pg_namespace WHERE nspname=fdw_name) THEN
EXECUTE FORMAT ('CREATE SCHEMA %I', fdw_name);
END IF;
-- Bring the remote cdb_tablemetadata
IF NOT EXISTS ( SELECT * FROM PG_CLASS WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname=fdw_name) and relname='cdb_tablemetadata') THEN
EXECUTE FORMAT ('CREATE FOREIGN TABLE %I.cdb_tablemetadata (tabname text, updated_at timestamp with time zone) SERVER %I OPTIONS (table_name ''cdb_tablemetadata_text'', schema_name ''public'', updatable ''false'')', fdw_name, fdw_name);
END IF;
-- Import target table
EXECUTE FORMAT ('IMPORT FOREIGN SCHEMA %I LIMIT TO (%I) from SERVER %I INTO %I', user_schema, user_tablename, fdw_name, schema_name);
END;
$$ LANGUAGE PLPGSQL;

View File

@@ -158,28 +158,6 @@ BEGIN
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_GetRelatedColumn(columns_ids text[], reltype text )
RETURNS TEXT[]
AS $$
DECLARE
result TEXT[];
BEGIN
EXECUTE '
With ids as (
select row_number() over() as no, id from (select unnest($1) as id) t
)
select array_agg(target_id order by no)
FROM ids
LEFT JOIN observatory.obs_column_to_column
on source_id = id
where reltype = $2 or reltype is null
'
INTO result
using columns_ids, reltype;
return result;
END;
$$ LANGUAGE plpgsql;
-- Function that replaces all non digits or letters with _ trims and lowercases the
-- passed measure name
@@ -199,3 +177,20 @@ BEGIN
RETURN result;
END;
$$ LANGUAGE plpgsql;
-- Function that returns the currently deployed obs_dump_version from the
-- remote table of the same name.
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_DumpVersion(
)
RETURNS TEXT
AS $$
DECLARE
result text;
BEGIN
EXECUTE '
SELECT MAX(dump_id) FROM observatory.obs_dump_version
' INTO result;
RETURN result;
END;
$$ LANGUAGE plpgsql;

View File

@@ -169,19 +169,19 @@ BEGIN
IF geom_table_name IS NULL
THEN
RAISE NOTICE 'Point % is outside of the data region', ST_AsText(geom);
--raise notice 'Point % is outside of the data region', ST_AsText(geom);
-- TODO this should return JSON
RETURN QUERY SELECT '{}'::json;
RETURN;
END IF;
IF data_table_info IS NULL THEN
RAISE NOTICE 'Cannot find data table for boundary ID %, column_ids %, and time_span %', geometry_level, column_ids, time_span;
--raise notice 'Cannot find data table for boundary ID %, column_ids %, and time_span %', geometry_level, column_ids, time_span;
END IF;
IF ST_GeometryType(geom) = 'ST_Point'
THEN
RAISE NOTICE 'geom_table_name %, data_table_info %', geom_table_name, data_table_info::json[];
--raise notice 'geom_table_name %, data_table_info %', geom_table_name, data_table_info::json[];
results := cdb_observatory._OBS_GetPoints(geom,
geom_table_name,
data_table_info);
@@ -260,7 +260,7 @@ BEGIN
USING geom
INTO geoid;
RAISE NOTICE 'geoid is %, geometry table is % ', geoid, geom_table_name;
--raise notice 'geoid is %, geometry table is % ', geoid, geom_table_name;
EXECUTE
format('SELECT ST_Area(the_geom::geography) / (1000 * 1000)
@@ -273,7 +273,7 @@ BEGIN
IF area IS NULL
THEN
RAISE NOTICE 'No geometry at %', ST_AsText(geom);
--raise notice 'No geometry at %', ST_AsText(geom);
END IF;
query := 'SELECT Array[';
@@ -338,48 +338,221 @@ $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetMeasure(
geom geometry(Geometry, 4326),
measure_id TEXT,
normalize TEXT DEFAULT 'area', -- TODO none/null
normalize TEXT DEFAULT NULL,
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL
)
RETURNS NUMERIC
AS $$
DECLARE
geom_type TEXT;
map_type TEXT;
numer_aggregate TEXT;
numer_colname TEXT;
numer_geomref_colname TEXT;
numer_tablename TEXT;
denom_colname TEXT;
denom_geomref_colname TEXT;
denom_tablename TEXT;
geom_colname TEXT;
geom_geomref_colname TEXT;
geom_tablename TEXT;
result NUMERIC;
measure_ids TEXT[];
denominator_id TEXT;
vals NUMERIC[];
sql TEXT;
numer_name TEXT;
BEGIN
IF normalize ILIKE 'area' THEN
measure_ids := ARRAY[measure_id];
EXECUTE
$query$
SELECT numer_aggregate, numer_colname, numer_geomref_colname, numer_tablename,
denom_colname, denom_geomref_colname, denom_tablename,
geom_colname, geom_geomref_colname, geom_tablename, numer_name
FROM observatory.obs_meta
WHERE (geom_id = $1 OR ($1 = ''))
AND numer_id = $2
AND (numer_timespan = $3 OR ($3 = ''))
ORDER BY geom_weight DESC, numer_timespan DESC
LIMIT 1
$query$
INTO numer_aggregate, numer_colname, numer_geomref_colname, numer_tablename,
denom_colname, denom_geomref_colname, denom_tablename,
geom_colname, geom_geomref_colname, geom_tablename, numer_name
USING COALESCE(boundary_id, ''), measure_id, COALESCE(time_span, '');
IF ST_GeometryType(geom) = 'ST_Point' THEN
geom_type := 'point';
ELSIF ST_GeometryType(geom) IN ('ST_Polygon', 'ST_MultiPolygon') THEN
geom_type := 'polygon';
ELSE
RAISE EXCEPTION 'Invalid geometry type (%), can only handle ''ST_Point'', ''ST_Polygon'', and ''ST_MultiPolygon''',
ST_GeometryType(geom);
END IF;
IF normalize ILIKE 'area' AND numer_aggregate ILIKE 'sum' THEN
map_type := 'areaNormalized';
ELSIF normalize ILIKE 'denominator' THEN
EXECUTE 'SELECT (cdb_observatory._OBS_GetRelatedColumn(ARRAY[$1], ''denominator''))[1]
' INTO denominator_id
USING measure_id;
measure_ids := ARRAY[measure_id, denominator_id];
ELSIF normalize ILIKE 'none' THEN
-- TODO we need a switch on obs_get to disable area normalization
RAISE EXCEPTION 'No normalization not yet supported.';
map_type := 'denominated';
ELSE
RAISE EXCEPTION 'Only valid inputs for "normalize" are "area" (default) and "denominator".';
-- defaults: area normalization for point if it's possible and none for
-- polygon or non-summable point
IF geom_type = 'point' AND numer_aggregate ILIKE 'sum' THEN
map_type := 'areaNormalized';
ELSE
map_type := 'predenominated';
END IF;
END IF;
EXECUTE '
SELECT ARRAY_AGG(val) FROM (SELECT (cdb_observatory._OBS_Get($1, $2, $3, $4)->>''value'')::NUMERIC val) b
'
INTO vals
USING geom, measure_ids, time_span, boundary_id;
IF normalize ILIKE 'denominator' THEN
RETURN (vals)[1]/(vals)[2];
ELSE
RETURN (vals)[1];
IF geom_type = 'point' THEN
IF map_type = 'areaNormalized' THEN
sql = format('WITH _geom AS (SELECT ST_Area(geom.%I::Geography) / 1000000 area, geom.%I geom_ref
FROM observatory.%I geom
WHERE ST_Within(%L, geom.%I)
LIMIT 1)
SELECT numer.%I / (SELECT area FROM _geom)
FROM observatory.%I numer
WHERE numer.%I = (SELECT geom_ref FROM _geom)',
geom_colname, geom_geomref_colname, geom_tablename,
geom, geom_colname, numer_colname, numer_tablename,
numer_geomref_colname);
ELSIF map_type = 'denominated' THEN
sql = format('SELECT numer.%I / NULLIF((SELECT denom.%I FROM observatory.%I denom WHERE denom.%I = numer.%I LIMIT 1), 0)
FROM observatory.%I numer
WHERE numer.%I = (SELECT geom.%I FROM observatory.%I geom WHERE ST_Within(%L, geom.%I) LIMIT 1)',
numer_colname, denom_colname, denom_tablename,
denom_geomref_colname, numer_geomref_colname,
numer_tablename,
numer_geomref_colname, geom_geomref_colname,
geom_tablename, geom, geom_colname);
ELSIF map_type = 'predenominated' THEN
sql = format('SELECT numer.%I
FROM observatory.%I numer
WHERE numer.%I = (SELECT geom.%I FROM observatory.%I geom WHERE ST_Within(%L, geom.%I) LIMIT 1)',
numer_colname, numer_tablename,
numer_geomref_colname, geom_geomref_colname, geom_tablename,
geom, geom_colname);
END IF;
ELSIF geom_type = 'polygon' THEN
IF map_type = 'areaNormalized' THEN
sql = format('WITH _geom AS (SELECT ST_Area(ST_Intersection(%L, geom.%I))
/ ST_Area(geom.%I) overlap, geom.%I geom_ref
FROM observatory.%I geom
WHERE ST_Intersects(%L, geom.%I)
AND ST_Area(ST_Intersection(%L, geom.%I)) / ST_Area(geom.%I) > 0)
SELECT SUM(numer.%I * (SELECT _geom.overlap FROM _geom WHERE _geom.geom_ref = numer.%I)) /
ST_Area(%L::Geography)
FROM observatory.%I numer
WHERE numer.%I = ANY ((SELECT ARRAY_AGG(geom_ref) FROM _geom)::TEXT[])',
geom, geom_colname, geom_colname,
geom_geomref_colname, geom_tablename,
geom, geom_colname,
geom, geom_colname, geom_colname,
numer_colname, numer_geomref_colname,
geom, numer_tablename,
numer_geomref_colname);
ELSIF map_type = 'denominated' THEN
sql = format('WITH _geom AS (SELECT ST_Area(ST_Intersection(%L, geom.%I))
/ ST_Area(geom.%I) overlap, geom.%I geom_ref
FROM observatory.%I geom
WHERE ST_Intersects(%L, geom.%I)
AND ST_Area(ST_Intersection(%L, geom.%I)) / ST_Area(geom.%I) > 0),
_denom AS (SELECT denom.%I, denom.%I geom_ref
FROM observatory.%I denom
WHERE denom.%I = ANY ((SELECT ARRAY_AGG(geom_ref) FROM _geom)::TEXT[]))
SELECT SUM(numer.%I * (SELECT _geom.overlap FROM _geom WHERE _geom.geom_ref = numer.%I)) /
SUM((SELECT _denom.%I * (SELECT _geom.overlap
FROM _geom
WHERE _geom.geom_ref = _denom.geom_ref)
FROM _denom WHERE _denom.geom_ref = numer.%I))
FROM observatory.%I numer
WHERE numer.%I = ANY ((SELECT ARRAY_AGG(geom_ref) FROM _geom)::TEXT[])',
geom, geom_colname,
geom_colname, geom_geomref_colname,
geom_tablename,
geom, geom_colname,
geom, geom_colname, geom_colname,
denom_colname, denom_geomref_colname,
denom_tablename,
denom_geomref_colname,
numer_colname, numer_geomref_colname,
denom_colname,
numer_geomref_colname,
numer_tablename,
numer_geomref_colname);
ELSIF map_type = 'predenominated' THEN
IF numer_aggregate NOT ILIKE 'sum' THEN
RAISE EXCEPTION 'Cannot calculate "%" (%) for custom area as it cannot be summed, use ST_PointOnSurface instead',
numer_name, numer_id;
ELSE
sql = format('WITH _geom AS (SELECT ST_Area(ST_Intersection(%L, geom.%I))
/ ST_Area(geom.%I) overlap, geom.%I geom_ref
FROM observatory.%I geom
WHERE ST_Intersects(%L, geom.%I)
AND ST_Area(ST_Intersection(%L, geom.%I)) / ST_Area(geom.%I) > 0)
SELECT SUM(numer.%I * (SELECT _geom.overlap FROM _geom WHERE _geom.geom_ref = numer.%I))
FROM observatory.%I numer
WHERE numer.%I = ANY ((SELECT ARRAY_AGG(geom_ref) FROM _geom)::TEXT[])',
geom, geom_colname, geom_colname,
geom_geomref_colname, geom_tablename,
geom, geom_colname,
geom, geom_colname, geom_colname,
numer_colname, numer_geomref_colname,
numer_tablename,
numer_geomref_colname);
END IF;
END IF;
END IF;
EXECUTE sql INTO result;
RETURN result;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetMeasureById(
geom_ref TEXT,
measure_id TEXT,
boundary_id TEXT,
time_span TEXT DEFAULT NULL
)
RETURNS NUMERIC
AS $$
DECLARE
target_table TEXT;
colname TEXT;
measure_val NUMERIC;
data_geoid_colname TEXT;
BEGIN
EXECUTE
$query$
SELECT numer_colname, numer_geomref_colname, numer_tablename
FROM observatory.obs_meta
WHERE (geom_id = $1 OR ($1 = ''))
AND numer_id = $2
AND (numer_timespan = $3 OR ($3 = ''))
ORDER BY geom_weight DESC, numer_timespan DESC
LIMIT 1
$query$
INTO colname, data_geoid_colname, target_table
USING COALESCE(boundary_id, ''), measure_id, COALESCE(time_span, '');
--RAISE DEBUG 'target_table %, colname %', target_table, colname;
EXECUTE format(
'SELECT %I
FROM observatory.%I data
WHERE data.%I = %L',
colname,
target_table,
data_geoid_colname, geom_ref)
INTO measure_val;
RETURN measure_val;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetCategory(
geom geometry(Geometry, 4326),
category_id TEXT,
@@ -389,27 +562,61 @@ CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetCategory(
RETURNS TEXT
AS $$
DECLARE
denominator_id TEXT;
categories TEXT[];
data_table TEXT;
geom_table TEXT;
colname TEXT;
data_geomref_colname TEXT;
geom_geomref_colname TEXT;
geom_colname TEXT;
category_val TEXT;
category_share NUMERIC;
BEGIN
IF boundary_id IS NULL THEN
-- TODO we should determine best boundary for this geom
boundary_id := 'us.census.tiger.census_tract';
EXECUTE
$query$
SELECT numer_colname, numer_geomref_colname, numer_tablename,
geom_geomref_colname, geom_colname, geom_tablename
FROM observatory.obs_meta
WHERE (geom_id = $1 OR ($1 = ''))
AND numer_id = $2
AND (numer_timespan = $3 OR ($3 = ''))
ORDER BY geom_weight DESC, numer_timespan DESC
LIMIT 1
$query$
INTO colname, data_geomref_colname, data_table,
geom_geomref_colname, geom_colname, geom_table
USING COALESCE(boundary_id, ''), category_id, COALESCE(time_span, '');
IF ST_GeometryType(geom) = 'ST_Point' THEN
EXECUTE format(
'SELECT data.%I
FROM observatory.%I data, observatory.%I geom
WHERE data.%I = geom.%I
AND ST_WITHIN(%L, geom.%I) ',
colname, data_table, geom_table, data_geomref_colname,
geom_geomref_colname, geom, geom_colname)
INTO category_val;
ELSE
-- favor the category with the most area
EXECUTE format(
'SELECT data.%I category, SUM(overlap_fraction) category_share
FROM observatory.%I data, (
SELECT ST_Area(
ST_Intersection(%L, a.%I)
) / ST_Area(%L) AS overlap_fraction, a.%I geomref
FROM observatory.%I as a
WHERE %L && a.%I) _overlaps
WHERE data.%I = _overlaps.geomref
GROUP BY category
ORDER BY SUM(overlap_fraction) DESC
LIMIT 1',
colname, data_table,
geom, geom_colname, geom, geom_geomref_colname,
geom_table, geom, geom_colname, data_geomref_colname)
INTO category_val, category_share;
END IF;
IF time_span IS NULL THEN
-- TODO we should determine latest timespan for this measure
time_span := '2010 - 2014';
END IF;
EXECUTE '
SELECT ARRAY_AGG(val) FROM (SELECT (cdb_observatory._OBS_GetCategories($1, $2, $3, $4))->>''category'' val LIMIT 1) b
'
INTO categories
USING geom, ARRAY[category_id], boundary_id, time_span;
RETURN (categories)[1];
RETURN category_val;
END;
$$ LANGUAGE plpgsql;
@@ -417,7 +624,7 @@ $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetUSCensusMeasure(
geom geometry(Geometry, 4326),
name TEXT,
normalize TEXT DEFAULT 'area',
normalize TEXT DEFAULT NULL,
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL
)
@@ -483,7 +690,7 @@ $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetPopulation(
geom geometry(Geometry, 4326),
normalize TEXT DEFAULT 'area',
normalize TEXT DEFAULT NULL,
boundary_id TEXT DEFAULT NULL,
time_span TEXT DEFAULT NULL
)
@@ -586,7 +793,7 @@ BEGIN
q := q || q_select || format('FROM observatory.%I ', ((data_table_info)[1]->>'tablename'));
q := format(q || ' ) ' || q_sum || ' ]::numeric[] FROM _overlaps, values
WHERE values.%I = _overlaps.%I', geom_geoid_colname, geom_geoid_colname);
WHERE values.%I = _overlaps.%I', data_geoid_colname, geom_geoid_colname);
EXECUTE
q
@@ -749,7 +956,7 @@ BEGIN
IF geom_table_name IS NULL
THEN
RAISE NOTICE 'Point % is outside of the data region', ST_AsText(geom);
--raise notice 'Point % is outside of the data region', ST_AsText(geom);
RETURN QUERY SELECT '{}'::text[], '{}'::text[];
RETURN;
END IF;
@@ -763,7 +970,7 @@ BEGIN
IF data_table_info IS NULL
THEN
RAISE NOTICE 'No data table found for this location';
--raise notice 'No data table found for this location';
RETURN QUERY SELECT NULL::json;
RETURN;
END IF;
@@ -778,7 +985,7 @@ BEGIN
IF geoid IS NULL
THEN
RAISE NOTICE 'No geometry id for this location';
--raise notice 'No geometry id for this location';
RETURN QUERY SELECT NULL::json;
RETURN;
END IF;

View File

@@ -114,7 +114,7 @@ BEGIN
AND
observatory.OBS_column.type = 'Geometry'
AND
$1 && bounds::box2d
ST_Intersects($1, st_setsrid(observatory.obs_table.the_geom, 4326))
$string$ || timespan_query
USING geom;
RETURN;

View File

@@ -64,11 +64,11 @@ BEGIN
-- if no tables are found, raise notice and return null
IF target_table IS NULL
THEN
RAISE NOTICE 'No boundaries found for ''%'' in ''%''', ST_AsText(geom), boundary_id;
--RAISE NOTICE 'No boundaries found for ''%'' in ''%''', ST_AsText(geom), boundary_id;
RETURN NULL::geometry;
END IF;
RAISE NOTICE 'target_table: %', target_table;
--RAISE NOTICE 'target_table: %', target_table;
-- return the first boundary in intersections
EXECUTE format(
@@ -143,7 +143,7 @@ BEGIN
-- if no tables are found, raise notice and return null
IF target_table IS NULL
THEN
RAISE NOTICE 'Warning: No boundaries found for ''%''', boundary_id;
--RAISE NOTICE 'Warning: No boundaries found for ''%''', boundary_id;
RETURN NULL::text;
END IF;
@@ -159,7 +159,7 @@ BEGIN
, target_table)
INTO geoid_colname;
RAISE NOTICE 'target_table: %, geoid_colname: %', target_table, geoid_colname;
--RAISE NOTICE 'target_table: %, geoid_colname: %', target_table, geoid_colname;
-- return geometry id column value
EXECUTE format(
@@ -212,11 +212,11 @@ BEGIN
SELECT * INTO geoid_colname, target_table, geom_colname
FROM cdb_observatory._OBS_GetGeometryMetadata(boundary_id);
RAISE NOTICE '%', target_table;
--RAISE NOTICE '%', target_table;
IF target_table IS NULL
THEN
RAISE NOTICE 'No geometries found';
--RAISE NOTICE 'No geometries found';
RETURN NULL::geometry;
END IF;
@@ -272,12 +272,12 @@ BEGIN
-- if no tables are found, raise notice and return null
IF target_table IS NULL
THEN
RAISE NOTICE 'No boundaries found for bounding box ''%'' in ''%''', ST_AsText(geom), boundary_id;
--RAISE NOTICE 'No boundaries found for bounding box ''%'' in ''%''', ST_AsText(geom), boundary_id;
RETURN QUERY SELECT NULL::geometry, NULL::text;
RETURN;
END IF;
RAISE NOTICE 'target_table: %', target_table;
--RAISE NOTICE 'target_table: %', target_table;
-- return first boundary in intersections
RETURN QUERY
@@ -418,12 +418,12 @@ BEGIN
-- if no tables are found, raise notice and return null
IF target_table IS NULL
THEN
RAISE NOTICE 'No boundaries found for bounding box ''%'' in ''%''', ST_AsText(geom), boundary_id;
--RAISE NOTICE 'No boundaries found for bounding box ''%'' in ''%''', ST_AsText(geom), boundary_id;
RETURN QUERY SELECT NULL::geometry, NULL::text;
RETURN;
END IF;
RAISE NOTICE 'target_table: %', target_table;
--RAISE NOTICE 'target_table: %', target_table;
-- return first boundary in intersections
RETURN QUERY

View File

@@ -0,0 +1,119 @@
CREATE TYPE cdb_observatory.ds_fdw_metadata as (schemaname text, tabname text, servername text);
CREATE TYPE cdb_observatory.ds_return_metadata as (colnames text[], coltypes text[]);
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_ConnectUserTable(username text, orgname text, user_db_role text, input_schema text, dbname text, host_addr text, table_name text)
RETURNS cdb_observatory.ds_fdw_metadata
AS $$
DECLARE
fdw_server text;
fdw_import_schema text;
connection_str json;
import_foreign_schema_q text;
epoch_timestamp text;
BEGIN
SELECT extract(epoch from now() at time zone 'utc')::int INTO epoch_timestamp;
fdw_server := 'fdw_server_' || username || '_' || epoch_timestamp;
fdw_import_schema:= fdw_server;
-- Import foreign table
EXECUTE FORMAT ('SELECT cdb_observatory._OBS_ConnectRemoteTable(%L, %L, %L, %L, %L, %L, %L)', fdw_server, fdw_import_schema, dbname, host_addr, user_db_role, table_name, input_schema);
RETURN (fdw_import_schema::text, table_name::text, fdw_server::text);
EXCEPTION
WHEN others THEN
-- Disconnect user imported table. Delete schema and FDW server.
EXECUTE 'DROP FOREIGN TABLE IF EXISTS ' || fdw_import_schema || '.' || table_name;
EXECUTE 'DROP SCHEMA IF EXISTS ' || fdw_import_schema || ' CASCADE';
EXECUTE 'DROP SERVER IF EXISTS ' || fdw_server || ' CASCADE;';
RETURN (null, null, null);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_GetReturnMetadata(username text, orgname text, function_name text, params json)
RETURNS cdb_observatory.ds_return_metadata
AS $$
DECLARE
colnames text[];
coltypes text[];
requested_measures text[];
measure text;
BEGIN
-- Simple mock, there should be real logic in here.
IF $3 NOT ILIKE 'GetMeasure' OR $3 IS NULL THEN
RAISE 'This function is not supported yet: %', $3;
END IF;
SELECT translate($4::json->>'tag_name','[]', '{}')::text[] INTO requested_measures;
FOREACH measure IN ARRAY requested_measures
LOOP
IF NOT measure ILIKE ANY (Array['total_pop', 'pop_16_over']::text[]) THEN
RAISE 'This measure is not supported yet: %', measure;
END IF;
SELECT array_append(colnames, measure) INTO colnames;
SELECT array_append(coltypes, 'double precision'::text) INTO coltypes;
END LOOP;
RETURN (colnames::text[], coltypes::text[]);
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_FetchJoinFdwTableData(username text, orgname text, table_schema text, table_name text, function_name text, params json)
RETURNS SETOF record
AS $$
DECLARE
data_query text;
tag_name text[];
tag text;
tags_list text;
tags_query text;
rec RECORD;
BEGIN
SELECT translate($6::json->>'tag_name','[]', '{}')::text[] INTO tag_name;
SELECT array_to_string(tag_name, ',') INTO tags_list;
tags_query := '';
FOREACH tag IN ARRAY tag_name
LOOP
SELECT tags_query || ' sum(' || tag || '/fraction)::double precision as ' || tag || ', ' INTO tags_query;
END LOOP;
-- Simple mock, there should be real logic in here.
data_query := '(WITH _areas AS(SELECT ST_Area(a.the_geom::geography)'
|| '/ (1000 * 1000) as fraction, a.geoid, b.cartodb_id FROM '
|| 'observatory.obs_c6fb99c47d61289fbb8e561ff7773799d3fcc308 as a, '
|| table_schema || '.' || table_name || ' AS b '
|| 'WHERE b.the_geom && a.the_geom ), values AS (SELECT geoid, '
|| tags_list
|| ' FROM observatory.obs_1a098da56badf5f32e336002b0a81708c40d29cd ) '
|| 'SELECT '
|| tags_query
|| ' cartodb_id::int FROM _areas, values '
|| 'WHERE values.geoid = _areas.geoid GROUP BY cartodb_id);';
FOR rec IN EXECUTE data_query
LOOP
RETURN NEXT rec;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE OR REPLACE FUNCTION cdb_observatory._OBS_DisconnectUserTable(username text, orgname text, table_schema text, table_name text, servername text)
RETURNS boolean
AS $$
BEGIN
EXECUTE 'DROP FOREIGN TABLE IF EXISTS "' || table_schema || '".' || table_name;
EXECUTE 'DROP SCHEMA IF EXISTS ' || table_schema || ' CASCADE';
EXECUTE 'DROP SERVER IF EXISTS ' || servername || ' CASCADE;';
RETURN true;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

View File

@@ -9,21 +9,15 @@ t
_obs_geomtable_with_null_response
t
(1 row)
test_get_obs_column_with_geoid_and_census_1|test_get_obs_column_with_geoid_and_census_2
t|t
(1 row)
obs_getcolumndata_missing_measure
t
(1 row)
_obs_buildsnapshotquery_test_1
t
(1 row)
_obs_buildsnapshotquery_test_2
t
(1 row)
_obs_getrelatedcolumn_test
t
(1 row)
_obs_standardizemeasurename_test
t
(1 row)
obs_dumpversion_notnull
t
(1 row)

View File

@@ -1,5 +1,4 @@
\i test/fixtures/load_fixtures.sql
SET client_min_messages TO WARNING;
\pset format unaligned
\set ECHO none
obs_getdemographicsnapshot_test_no_returns
t
@@ -76,3 +75,15 @@ t
obs_getuscensuscategory_polygon
t
(1 row)
obs_getmeasurebyid_cartodb_census_tract
t
(1 row)
obs_getmeasurebyid_null_boundary_null_timespan
t
(1 row)
obs_getmeasurebyid_cartodb_block_group
t
(1 row)
obs_getmeasurebyid_nulls
t
(1 row)

View File

@@ -1,5 +1,4 @@
\i test/fixtures/load_fixtures.sql
SET client_min_messages TO WARNING;
\pset format unaligned
\set ECHO none
_obs_searchtables_tables_match|_obs_searchtables_timespan_matches
t|t

View File

@@ -1,7 +1,4 @@
\pset format unaligned
\set ECHO all
\i test/fixtures/load_fixtures.sql
SET client_min_messages TO WARNING;
\set ECHO none
obs_getboundary_cartodb_census_tract
t

View File

@@ -6,6 +6,7 @@ DROP TABLE IF EXISTS observatory.obs_column;
DROP TABLE IF EXISTS observatory.obs_column_tag;
DROP TABLE IF EXISTS observatory.obs_tag;
DROP TABLE IF EXISTS observatory.obs_column_to_column;
DROP TABLE IF EXISTS observatory.obs_dump_version;
DROP TABLE IF EXISTS observatory.obs_65f29658e096ca1485bf683f65fdbc9f05ec3c5d;
DROP TABLE IF EXISTS observatory.obs_1746e37b7cd28cb131971ea4187d42d71f09c5f3;
DROP TABLE IF EXISTS observatory.obs_1a098da56badf5f32e336002b0a81708c40d29cd;
@@ -19,3 +20,5 @@ DROP TABLE IF EXISTS observatory.obs_6c1309a64d8f3e6986061f4d1ca7b57743e75e74;
DROP TABLE IF EXISTS observatory.obs_d39f7fe5959891c8296490d83c22ded31c54af13;
DROP TABLE IF EXISTS observatory.obs_144e8b4f906885b2e057ac4842644a553ae49c6e;
DROP TABLE IF EXISTS observatory.obs_c6fb99c47d61289fbb8e561ff7773799d3fcc308;
DROP TABLE IF EXISTS observatory.obs_meta;

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,8 @@
\pset format unaligned
\set ECHO all
\i test/fixtures/load_fixtures.sql
SET client_min_messages TO WARNING;
\set ECHO none
-- OBS_GeomTable
-- get table with known geometry_id
@@ -27,29 +29,6 @@ SELECT
-- 'us.census.tiger.census_tract'
-- );
WITH result as (
SELECT
array_agg(a) expected from cdb_observatory._OBS_GetColumnData(
'us.census.tiger.census_tract',
Array['us.census.spielman_singleton_segments.X55', 'us.census.acs.B01003001'],
'2010 - 2014') a
)
select
(expected)[1]::text = '{"colname":"x55","tablename":"obs_65f29658e096ca1485bf683f65fdbc9f05ec3c5d","aggregate":null,"name":"Spielman-Singleton Segments: 55 Clusters","type":"Text","description":"Sociodemographic classes from Spielman and Singleton 2015, 55 clusters","boundary_id":"us.census.tiger.census_tract"}' as test_get_obs_column_with_geoid_and_census_1,
(expected)[2]::text = '{"colname":"total_pop","tablename":"obs_b393b5b88c6adda634b2071a8005b03c551b609a","aggregate":"sum","name":"Total Population","type":"Numeric","description":"The total number of all people living in a given geographic area. This is a very useful catch-all denominator when calculating rates.","boundary_id":"us.census.tiger.census_tract"}' as test_get_obs_column_with_geoid_and_census_2
from result;
-- should be null-valued
WITH result as (
SELECT
array_agg(a) expected from cdb_observatory._OBS_GetColumnData(
'us.census.tiger.census_tract',
Array['us.census.tiger.baloney'],
'2010 - 2014') a
)
select expected is null as OBS_GetColumnData_missing_measure
from result;
-- OBS_BuildSnapshotQuery
-- Should give back: SELECT vals[1] As total_pop, vals[2] As male_pop, vals[3] As female_pop, vals[4] As median_age
SELECT
@@ -63,16 +42,8 @@ SELECT
Array['mandarin_orange']
) = 'SELECT vals[1] As mandarin_orange' As _OBS_BuildSnapshotQuery_test_2;
SELECT cdb_observatory._OBS_GetRelatedColumn(
Array[
'es.ine.t3_1',
'us.census.acs.B01003001',
'us.census.acs.B01001002'
],
'denominator'
) = '{es.ine.t1_1,NULL,us.census.acs.B01003001}' As _OBS_GetRelatedColumn_test;
-- should give back a standardized measure name
SELECT cdb_observatory._OBS_StandardizeMeasureName('test 343 %% 2 qqq }}{{}}') = 'test_343_2_qqq' As _OBS_StandardizeMeasureName_test;
\i test/fixtures/drop_fixtures.sql
SELECT cdb_observatory.OBS_DumpVersion()
IS NOT NULL AS OBS_DumpVersion_notnull;

View File

@@ -1,6 +1,6 @@
\i test/fixtures/load_fixtures.sql
\pset format unaligned
\set ECHO none
SET client_min_messages TO WARNING;
--
WITH result as(
@@ -131,7 +131,7 @@ WITH result as (
-- Point-based OBS_GetMeasure with zillow
SELECT abs(OBS_GetMeasure_zhvi_point - 583600) / 583600 < 0.001 AS OBS_GetMeasure_zhvi_point_test FROM cdb_observatory.OBS_GetMeasure(
ST_SetSRID(ST_Point(-73.94602417945862, 40.6768220087458), 4326),
'us.zillow.AllHomes_Zhvi', 'area', 'us.census.tiger.zcta5', '2014-01'
'us.zillow.AllHomes_Zhvi', null, 'us.census.tiger.zcta5', '2014-01'
) As t(OBS_GetMeasure_zhvi_point);
-- Point-based OBS_GetMeasure with zillow default to latest
@@ -172,7 +172,7 @@ SELECT cdb_observatory.OBS_GetCategory(
-- Poly-based OBS_GetCategory
SELECT cdb_observatory.OBS_GetCategory(
cdb_observatory._TestArea(), 'us.census.spielman_singleton_segments.X10') = 'Low income, mix of minorities' As obs_getcategory_polygon;
cdb_observatory._TestArea(), 'us.census.spielman_singleton_segments.X10') = 'Wealthy, urban without Kids' As obs_getcategory_polygon;
-- Point-based OBS_GetPopulation, default normalization (area)
SELECT (abs(OBS_GetPopulation - 10923.093200390833950) / 10923.093200390833950) < 0.001 As OBS_GetPopulation FROM
@@ -201,7 +201,38 @@ SELECT cdb_observatory.OBS_GetUSCensusCategory(
-- Area-based OBS_GetUSCensusCategory
SELECT cdb_observatory.OBS_GetUSCensusCategory(
cdb_observatory._testarea(), 'Spielman-Singleton Segments: 10 Clusters') = 'Low income, mix of minorities' As OBS_GetUSCensusCategory_polygon;
cdb_observatory._testarea(), 'Spielman-Singleton Segments: 10 Clusters') = 'Wealthy, urban without Kids' As OBS_GetUSCensusCategory_polygon;
\i test/fixtures/drop_fixtures.sql
-- OBS_GetMeasureById tests
-- typical query
SELECT (cdb_observatory.OBS_GetMeasureById(
'36047048500',
'us.census.acs.B01003001',
'us.census.tiger.census_tract',
'2010 - 2014'
) - 3241) / 3241 < 0.0001 As OBS_GetMeasureById_cartodb_census_tract;
-- no boundary_id should give null
SELECT cdb_observatory.OBS_GetMeasureById(
'36047048500',
'us.census.acs.B01003001',
NULL,
NULL
) IS NULL As OBS_GetMeasureById_null_boundary_null_timespan;
-- query at block_group level
SELECT (cdb_observatory.OBS_GetMeasureById(
'360470485002',
'us.census.acs.B01003001',
'us.census.tiger.block_group',
'2010 - 2014'
) - 1900) / 1900 < 0.0001 As OBS_GetMeasureById_cartodb_block_group;
-- geom ref / boundary mismatch
SELECT cdb_observatory.OBS_GetMeasureById(
'36047048500',
'us.census.acs.B01003001',
'us.census.tiger.block_group',
'2010 - 2014'
) IS NULL As OBS_GetMeasureById_nulls;

View File

@@ -1,5 +1,6 @@
\i test/fixtures/load_fixtures.sql
\pset format unaligned
\set ECHO none
SET client_min_messages TO WARNING;
-- set up variables for use in testing
@@ -32,5 +33,3 @@ SELECT COUNT(*) > 0 AS _OBS_GetAvailableBoundariesExist
FROM cdb_observatory.OBS_GetAvailableBoundaries(
cdb_observatory._TestPoint()
) AS t(boundary_id, description, time_span, tablename);
\i test/fixtures/drop_fixtures.sql

View File

@@ -1,6 +1,6 @@
\pset format unaligned
\set ECHO all
\i test/fixtures/load_fixtures.sql
\set ECHO none
SET client_min_messages TO WARNING;
-- set up variables for use in testing