diff --git a/docker-compose.yml b/docker-compose.yml index c1ba88f..7c589cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,9 +27,12 @@ services: restart: "always" env_file: - "env/test/.env" + ports: + - "5432" + dbtest: <<: *pipenv - command: ["bash", "-c", "pipenv install --dev --deploy --system && pytest -s"] + command: ["bash", "-c", "pipenv install --dev --deploy --system && pytest -s -vvv"] depends_on: - testdb diff --git a/docs/img/kagoshima_segments.png b/docs/img/kagoshima_segments.png new file mode 100644 index 0000000..c76cf51 Binary files /dev/null and b/docs/img/kagoshima_segments.png differ diff --git a/docs/practices.md b/docs/practices.md new file mode 100644 index 0000000..f9aba97 --- /dev/null +++ b/docs/practices.md @@ -0,0 +1,61 @@ +SQL practices +=== + +### ToC + +- [Practice 1](#practice-1) +- [Practice 2](#practice-2) +- [Practice 3](#practice-3) + +# Practice 1 + +- Count the number of subordinate 'ENTERPRISE\_CUSTOMER' organizations for each organization. + +# Practice 2 + +- Calculate the center of each `japan_segment`. + +# Practice 3 + +- Select `japan_segments` within the bounds represented as the following GeoJSON. + +```json +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 130.27313232421875, + 30.519681272749402 + ], + [ + 131.02020263671875, + 30.519681272749402 + ], + [ + 131.02020263671875, + 30.80909017893796 + ], + [ + 130.27313232421875, + 30.80909017893796 + ], + [ + 130.27313232421875, + 30.519681272749402 + ] + ] + ] + } + } + ] +} +``` + +![Kagoshima segments](./img/kagoshima_segments.png) diff --git a/sql/japan_segments.sql b/sql/japan_segments.sql new file mode 100644 index 0000000..7695819 --- /dev/null +++ b/sql/japan_segments.sql @@ -0,0 +1,49 @@ +begin; + +INSERT INTO japan_segments ( + id, + bounds +) VALUES + ( + 'KAGOSHIMA_1' + , ST_GeomFromEWKT('SRID=4326;POLYGON((130.616250541204 30.6818181818182,130.616250541204 30.7272727272727,130.668206090345 30.7272727272727,130.668206090345 30.6818181818182,130.616250541204 30.6818181818182))') + ) + ,( + 'KAGOSHIMA_2' + , ST_GeomFromEWKT('SRID=4326;POLYGON((130.668206090345 30.6818181818182,130.668206090345 30.7272727272727,130.720161639486 30.7272727272727,130.720161639486 30.6818181818182,130.668206090345 30.6818181818182))') + ) + ,( + 'KAGOSHIMA_3' + , ST_GeomFromEWKT('SRID=4326;POLYGON((130.720161639486 30.6818181818182,130.720161639486 30.7272727272727,130.772117188628 30.7272727272727,130.772117188628 30.6818181818182,130.720161639486 30.6818181818182))') + ) + ,( + 'KAGOSHIMA_4' + , ST_GeomFromEWKT('SRID=4326;POLYGON((129.68105065666 30.7272727272727,129.68105065666 30.7727272727273,129.733006205802 30.7727272727273,129.733006205802 30.7272727272727,129.68105065666 30.7272727272727))') + ) + ,( + 'KAGOSHIMA_5' + , ST_GeomFromEWKT('SRID=4326;POLYGON((129.733006205802 30.7272727272727,129.733006205802 30.7727272727273,129.784961754943 30.7727272727273,129.784961754943 30.7272727272727,129.733006205802 30.7272727272727))') + ) + ,( + 'KAGOSHIMA_6' + , ST_GeomFromEWKT('SRID=4326;POLYGON((129.784961754943 30.7272727272727,129.784961754943 30.7727272727273,129.836917304084 30.7727272727273,129.836917304084 30.7272727272727,129.784961754943 30.7272727272727))') + ) + ,( + 'KAGOSHIMA_7' + , ST_GeomFromEWKT('SRID=4326;POLYGON((129.836917304084 30.7272727272727,129.836917304084 30.7727272727273,129.888872853226 30.7727272727273,129.888872853226 30.7272727272727,129.836917304084 30.7272727272727))') + ) + ,( + 'KAGOSHIMA_8' + , ST_GeomFromEWKT('SRID=4326;POLYGON((129.888872853226 30.7272727272727,129.888872853226 30.7727272727273,129.940828402367 30.7727272727273,129.940828402367 30.7272727272727,129.888872853226 30.7272727272727))') + ) + ,( + 'KAGOSHIMA_9' + , ST_GeomFromEWKT('SRID=4326;POLYGON((129.940828402367 30.7272727272727,129.940828402367 30.7727272727273,129.992783951508 30.7727272727273,129.992783951508 30.7272727272727,129.940828402367 30.7272727272727))') + ) + ,( + 'KAGOSHIMA_10' + , ST_GeomFromEWKT('SRID=4326;POLYGON((129.992783951508 30.7272727272727,129.992783951508 30.7727272727273,130.044739500649 30.7727272727273,130.044739500649 30.7272727272727,129.992783951508 30.7272727272727))') + ) +; + +commit; diff --git a/sql/schema.sql b/sql/schema.sql index 1b1304f..254d102 100644 --- a/sql/schema.sql +++ b/sql/schema.sql @@ -32,3 +32,8 @@ CREATE TABLE enterprise_sales_enterprise_customers ( customer_organization_id ) ); + +CREATE TABLE japan_segments ( + "id" character varying(24) PRIMARY KEY NOT NULL, + "bounds" geometry(Polygon,4326) NOT NULL +); diff --git a/test/test_example.py b/test/test_example.py index 8e715b8..43720a2 100644 --- a/test/test_example.py +++ b/test/test_example.py @@ -4,7 +4,10 @@ from .dbtest import ( ) import os -from psycopg2.extras import RealDictCursor +from psycopg2.extras import ( + RealDictCursor, + RealDictRow +) PATH_TO_SQL_DIR = os.path.abspath( @@ -32,19 +35,140 @@ class TestExample(DbTest): assert len(organizations) == 7 - @dbconnect - def test_select_addresses(self, conn): + def test_count_the_number_of_subordinates(self, conn): self.load_fixtures( conn, os.path.join(PATH_TO_SQL_DIR, "organizations.sql") ) sql = """ - SELECT * FROM addresses; """ with conn.cursor(cursor_factory=RealDictCursor) as cur: cur.execute(sql) - addresses = cur.fetchall() - - assert len(addresses) == 7 + actual = cur.fetchall() + print(actual) + assert len(actual) == 7 + assert actual == [ + RealDictRow(**{ + "subordinates_count": 0, + "id": 1, + }) + , RealDictRow(**{ + "subordinates_count": 4, + "id": 2, + }) + , RealDictRow(**{ + "subordinates_count": 0, + "id": 3, + }) + , RealDictRow(**{ + "subordinates_count": 0, + "id": 4, + }) + , RealDictRow(**{ + "subordinates_count": 0, + "id": 5, + }) + , RealDictRow(**{ + "subordinates_count": 1, + "id": 6, + }) + , RealDictRow(**{ + "subordinates_count": 0, + "id": 7, + }) + ] + + @dbconnect + def test_calculate_center_of_each_segment(self, conn): + self.load_fixtures( + conn, + os.path.join(PATH_TO_SQL_DIR, "japan_segments.sql") + ) + + sql = """ + """ + with conn.cursor(cursor_factory=RealDictCursor) as cur: + cur.execute(sql) + actual = cur.fetchall() + print(actual) + assert len(actual) == 10 + assert actual == [ + RealDictRow(**{ + "id": "KAGOSHIMA_1", + "longitude": 130.642228315775, + "latitude": 30.7045454545455, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_2", + "longitude": 130.694183864916, + "latitude": 30.7045454545455, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_3", + "longitude": 130.746139414057, + "latitude": 30.7045454545455, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_4", + "longitude": 129.707028431231, + "latitude": 30.75, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_5", + "longitude": 129.758983980373, + "latitude": 30.75, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_6", + "longitude": 129.810939529514, + "latitude": 30.75, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_7", + "longitude": 129.862895078655, + "latitude": 30.75, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_8", + "longitude": 129.914850627797, + "latitude": 30.75, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_9", + "longitude": 129.966806176937, + "latitude": 30.75, + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_10", + "longitude": 130.018761726079, + "latitude": 30.75, + }) + ] + + @dbconnect + def test_segments_using_geojson_boundary(self, conn): + self.load_fixtures( + conn, + os.path.join(PATH_TO_SQL_DIR, "japan_segments.sql") + ) + + sql = """ + """ + with conn.cursor(cursor_factory=RealDictCursor) as cur: + cur.execute(sql) + actual = cur.fetchall() + print(actual) + assert len(actual) == 3 + assert actual == [ + RealDictRow(**{ + "id": "KAGOSHIMA_1", + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_2", + }) + , RealDictRow(**{ + "id": "KAGOSHIMA_3", + }) + ]