diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml
index bed0f39d76..1e0303a6f5 100644
--- a/.github/workflows/build_and_deploy.yml
+++ b/.github/workflows/build_and_deploy.yml
@@ -68,7 +68,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Environment to .env
env:
@@ -124,7 +124,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Frontend smoke test
run: echo "Not implemented"
@@ -140,7 +140,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Environment to .env
env:
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 2552910cdb..60e809a52d 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -18,7 +18,7 @@ jobs:
steps:
- name: Set cache key
id: set_cache_key
- run: echo "cache_key=docs-build-$(date --utc '+%V')" >> $GITHUB_OUTPUT
+ run: echo "cache_key=docs-build-$(date --utc +'%Y-%m-%d_%H:%M:%S')" >> $GITHUB_OUTPUT
build_doxygen:
uses: hotosm/gh-workflows/.github/workflows/doxygen_build.yml@main
@@ -32,7 +32,7 @@ jobs:
uses: hotosm/gh-workflows/.github/workflows/openapi_build.yml@main
needs: [get_cache_key]
with:
- image: ghcr.io/hotosm/fmtm/backend:ci-main
+ image: ghcr.io/hotosm/fmtm/backend:ci-${{ github.ref_name }}
example_env_file_path: ".env.example"
cache_paths: |
docs/openapi.json
@@ -45,6 +45,7 @@ jobs:
- build_doxygen
- build_openapi_json
with:
+ image: ghcr.io/hotosm/fmtm/backend:ci-${{ github.ref_name }}
cache_paths: |
docs/apidocs
docs/openapi.json
diff --git a/.github/workflows/r-extract_vars.yml b/.github/workflows/r-extract_vars.yml
index 3ce8fbcb83..8bb6073537 100644
--- a/.github/workflows/r-extract_vars.yml
+++ b/.github/workflows/r-extract_vars.yml
@@ -34,7 +34,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Extract api version
id: extract_api_version
diff --git a/.github/workflows/r-frontend_tests.yml b/.github/workflows/r-frontend_tests.yml
index 9e38287348..b871d81b66 100644
--- a/.github/workflows/r-frontend_tests.yml
+++ b/.github/workflows/r-frontend_tests.yml
@@ -10,7 +10,7 @@ jobs:
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v3
diff --git a/.github/workflows/r-pytest.yml b/.github/workflows/r-pytest.yml
index ade2ccb343..2b5a042d8a 100644
--- a/.github/workflows/r-pytest.yml
+++ b/.github/workflows/r-pytest.yml
@@ -34,7 +34,6 @@ jobs:
OSM_CLIENT_SECRET: ${{ env.OSM_CLIENT_SECRET }}
OSM_SECRET_KEY: ${{ env.OSM_SECRET_KEY }}
FRONTEND_MAIN_URL: ${{ vars.FRONTEND_MAIN_URL }}
- options: --user root
services:
# Start backend database
@@ -76,8 +75,8 @@ jobs:
image: "ghcr.io/hotosm/fmtm/odkcentral-proxy:latest"
steps:
- - uses: actions/checkout@v3
- - name: Run pytest as appuser
+ - uses: actions/checkout@v4
+ - name: Run pytest
run: |
cd src/backend
- gosu appuser pytest
+ pytest
diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml
index f15194d1e4..d52f0a2266 100644
--- a/.github/workflows/wiki.yml
+++ b/.github/workflows/wiki.yml
@@ -11,3 +11,5 @@ on:
jobs:
publish-docs-to-wiki:
uses: hotosm/gh-workflows/.github/workflows/wiki.yml@main
+ with:
+ homepage_path: "index.md"
diff --git a/README.md b/README.md
index c9b695f1dd..25d38711f6 100644
--- a/README.md
+++ b/README.md
@@ -264,20 +264,21 @@ Thanks goes to these wonderful people:
krtonga π» π π§ π€ |
Sam π» π π π€ π§ |
Petya π π π€ |
- Mohamed Bakari Mohamed π» |
- G. Willson π» |
+ Niraj Adhikari π» π€ π§ |
+ Deepak Pradhan (Varun) π» π€ π§ |
- Tayebwa Noah π |
- Mohammad Areeb π |
+ Mohamed Bakari Mohamed π» |
+ Sujan Adhikari π» |
AugustHottie π |
Ahmeed Etti-Balogun π |
Uju π |
Neelima Mohanty π |
- Deepak Pradhan (Varun) π» π€ π§ |
+ G. Willson π» |
- Niraj Adhikari π» π€ π§ |
+ Tayebwa Noah π |
+ Mohammad Areeb π |
diff --git a/docker-compose.deploy.yml b/docker-compose.deploy.yml
index b100eb6e2f..31aeedc9bd 100644
--- a/docker-compose.deploy.yml
+++ b/docker-compose.deploy.yml
@@ -40,7 +40,7 @@ services:
- 443:443
networks:
- fmtm-net
- restart: unless-stopped
+ restart: "unless-stopped"
command:
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
@@ -75,7 +75,7 @@ services:
- "5433:5432"
networks:
- fmtm-net
- restart: unless-stopped
+ restart: "unless-stopped"
api:
image: "ghcr.io/hotosm/fmtm/backend:${API_VERSION}-${GIT_BRANCH}"
@@ -96,7 +96,7 @@ services:
- .env
networks:
- fmtm-net
- restart: unless-stopped
+ restart: "unless-stopped"
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.tls=true"
@@ -105,6 +105,18 @@ services:
- "traefik.http.services.api-svc.loadbalancer.server.port=8000"
- "traefik.http.routers.api.service=api-svc"
+ migrations:
+ image: "ghcr.io/hotosm/fmtm/backend:${API_VERSION}-${GIT_BRANCH}"
+ container_name: fmtm_migrations
+ depends_on:
+ - api
+ env_file:
+ - .env
+ networks:
+ - fmtm-net
+ command: ["alembic", "upgrade", "head"]
+ restart: "no"
+
ui-main:
image: "ghcr.io/hotosm/fmtm/frontend:${FRONTEND_MAIN_VERSION}-${GIT_BRANCH}"
build:
@@ -124,7 +136,7 @@ services:
- BROTLI=true
- API_URL=${URL_SCHEME}://${API_URL}
- FRONTEND_MAIN_URL=${URL_SCHEME}://${FRONTEND_MAIN_URL}
- restart: unless-stopped
+ restart: "unless-stopped"
labels:
- "traefik.enable=true"
- "traefik.http.routers.ui-main.tls=true"
diff --git a/docker-compose.noodk.yml b/docker-compose.noodk.yml
index bfbf273396..19e6e3baf9 100644
--- a/docker-compose.noodk.yml
+++ b/docker-compose.noodk.yml
@@ -41,7 +41,7 @@ services:
- "5433:5432"
networks:
- fmtm-dev
- restart: unless-stopped
+ restart: "unless-stopped"
api:
image: "ghcr.io/hotosm/fmtm/backend:debug"
@@ -65,7 +65,19 @@ services:
- "5678:5678"
networks:
- fmtm-dev
- restart: unless-stopped
+ restart: "unless-stopped"
+
+ migrations:
+ image: "ghcr.io/hotosm/fmtm/backend:${API_VERSION}-${GIT_BRANCH}"
+ container_name: fmtm_migrations
+ depends_on:
+ - api
+ env_file:
+ - .env
+ networks:
+ - fmtm-net
+ command: ["alembic", "upgrade", "head"]
+ restart: "no"
ui-main:
image: "ghcr.io/hotosm/fmtm/frontend:debug"
@@ -89,4 +101,4 @@ services:
- "8081:8081"
networks:
- fmtm-dev
- restart: unless-stopped
+ restart: "unless-stopped"
diff --git a/docker-compose.yml b/docker-compose.yml
index 08af4cab4e..c1f7e7b8b2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -42,7 +42,7 @@ services:
- "5438:5432"
networks:
- fmtm-dev
- restart: unless-stopped
+ restart: "unless-stopped"
api:
image: "ghcr.io/hotosm/fmtm/backend:debug"
@@ -72,7 +72,19 @@ services:
- "5678:5678"
networks:
- fmtm-dev
- restart: unless-stopped
+ restart: "unless-stopped"
+
+ migrations:
+ image: "ghcr.io/hotosm/fmtm/backend:debug"
+ container_name: fmtm_migrations
+ depends_on:
+ - api
+ env_file:
+ - .env
+ networks:
+ - fmtm-dev
+ command: ["alembic", "upgrade", "head"]
+ restart: "no"
ui-main:
image: "ghcr.io/hotosm/fmtm/frontend:debug"
@@ -96,7 +108,7 @@ services:
- "8080:8080"
networks:
- fmtm-dev
- restart: unless-stopped
+ restart: "unless-stopped"
central-db:
image: "postgis/postgis:14-3.3-alpine"
@@ -111,7 +123,7 @@ services:
- "5434:5432"
networks:
- fmtm-dev
- restart: unless-stopped
+ restart: "unless-stopped"
central:
image: "ghcr.io/hotosm/fmtm/odkcentral:v2023.2.1"
@@ -122,7 +134,6 @@ services:
container_name: central_api
depends_on:
- central-db
- - pyxform
environment:
- DOMAIN=local
- SYSADMIN_EMAIL=${ODK_CENTRAL_USER}
@@ -154,7 +165,7 @@ services:
"--",
"./init-user-and-start.sh",
]
- restart: unless-stopped
+ restart: "unless-stopped"
central-proxy:
image: "ghcr.io/hotosm/fmtm/odkcentral-proxy:latest"
@@ -165,10 +176,4 @@ services:
- central
networks:
- fmtm-dev
- restart: unless-stopped
-
- pyxform:
- image: "ghcr.io/getodk/pyxform-http:v1.10.1.1"
- networks:
- - fmtm-dev
- restart: always
+ restart: "unless-stopped"
diff --git a/josm/docker-compose.yml b/josm/docker-compose.yml
index bd55504678..8c2fd2174c 100644
--- a/josm/docker-compose.yml
+++ b/josm/docker-compose.yml
@@ -35,7 +35,7 @@ services:
- x11
ports:
- 8111:80
- restart: unless-stopped
+ restart: "unless-stopped"
josm-novnc:
image: "ghcr.io/hotosm/fmtm/josm-novnc:latest"
@@ -51,4 +51,4 @@ services:
- "8112:8080"
networks:
- x11
- restart: unless-stopped
+ restart: "unless-stopped"
diff --git a/mkdocs.yml b/mkdocs.yml
index 8cbe2dad42..581bc51f6f 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -57,6 +57,7 @@ plugins:
merge_init_into_class: true
nav:
+ - Home: index.md
- Get Started:
- About: About.md
- Installation: INSTALL.md
diff --git a/src/backend/.dockerignore b/src/backend/.dockerignore
index 1b6ecc0069..3d82dd92e1 100644
--- a/src/backend/.dockerignore
+++ b/src/backend/.dockerignore
@@ -8,3 +8,5 @@
!container-entrypoint.sh
!pyproject.toml
!pdm.lock
+!migrations
+!alembic.ini
diff --git a/src/backend/Dockerfile b/src/backend/Dockerfile
index a97a291fd4..68cef1255c 100644
--- a/src/backend/Dockerfile
+++ b/src/backend/Dockerfile
@@ -90,7 +90,6 @@ RUN set -ex \
-y --no-install-recommends \
"nano" \
"curl" \
- "gosu" \
"libpcre3" \
"mime-support" \
"postgresql-client" \
@@ -108,8 +107,10 @@ COPY --from=build \
WORKDIR /opt
# Add app code
COPY app/ /opt/app/
+COPY migrations/ /opt/migrations/
+COPY alembic.ini /opt/
# Add non-root user, permissions
-RUN useradd -r -u 900 -m -c "hotosm account" -d /home/appuser -s /bin/false appuser \
+RUN useradd -r -u 1001 -m -c "hotosm account" -d /home/appuser -s /bin/false appuser \
&& mkdir -p /opt/logs /opt/tiles \
&& chown -R appuser:appuser /opt /home/appuser \
&& chmod +x /container-entrypoint.sh
@@ -123,7 +124,6 @@ USER appuser
FROM runtime as debug-no-odk
-USER appuser
COPY --from=extract-deps --chown=appuser \
/opt/python/requirements-debug.txt /opt/python/
RUN pip install --user --upgrade --no-warn-script-location \
@@ -147,14 +147,24 @@ USER appuser
-FROM debug-no-odk as ci
-COPY --from=extract-deps --chown=appuser \
+FROM runtime as ci
+# Run all ci as root
+USER root
+ENV PATH="/root/.local/bin:$PATH"
+RUN set -ex \
+ && apt-get update \
+ && DEBIAN_FRONTEND=noninteractive apt-get install \
+ -y --no-install-recommends \
+ "gosu" \
+ "git" \
+ && rm -rf /var/lib/apt/lists/*
+RUN mv /home/appuser/.local /root/.local
+COPY --from=extract-deps \
/opt/python/requirements-ci.txt /opt/python/
RUN pip install --user --upgrade --no-warn-script-location \
--no-cache-dir -r \
/opt/python/requirements-ci.txt \
&& rm -r /opt/python
-COPY --chown=appuser tests/ /opt/tests/
# Pre-compile packages to .pyc (init speed gains)
RUN python -c "import compileall; compileall.compile_path(maxlevels=10, quiet=1)"
# Override entrypoint, as not possible in Github action
diff --git a/src/backend/alembic.ini b/src/backend/alembic.ini
new file mode 100644
index 0000000000..b2c14b0b03
--- /dev/null
+++ b/src/backend/alembic.ini
@@ -0,0 +1,113 @@
+# A generic, single database configuration.
+
+[alembic]
+# path to migration scripts
+script_location = migrations
+
+# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
+# Uncomment the line below if you want the files to be prepended with date and time
+# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
+# for all available tokens
+# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
+
+# sys.path path, will be prepended to sys.path if present.
+# defaults to the current working directory.
+prepend_sys_path = .
+
+# timezone to use when rendering the date within the migration file
+# as well as the filename.
+# If specified, requires the python-dateutil library that can be
+# installed by adding `alembic[tz]` to the pip requirements
+# string value is passed to dateutil.tz.gettz()
+# leave blank for localtime
+# timezone =
+
+# max length of characters to apply to the
+# "slug" field
+# truncate_slug_length = 40
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+# set to 'true' to allow .pyc and .pyo files without
+# a source .py file to be detected as revisions in the
+# versions/ directory
+# sourceless = false
+
+# version location specification; This defaults
+# to migrations/versions. When using multiple version
+# directories, initial revisions must be specified with --version-path.
+# The path separator used here should be the separator specified by "version_path_separator" below.
+# version_locations = %(here)s/bar:%(here)s/bat:migrations/versions
+
+# version path separator; As mentioned above, this is the character used to split
+# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
+# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
+# Valid values for version_path_separator are:
+#
+# version_path_separator = :
+# version_path_separator = ;
+# version_path_separator = space
+version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
+
+# set to 'true' to search source files recursively
+# in each "version_locations" directory
+# new in Alembic version 1.10
+# recursive_version_locations = false
+
+# the output encoding used when revision files
+# are written from script.py.mako
+# output_encoding = utf-8
+
+sqlalchemy.url =
+
+[post_write_hooks]
+# post_write_hooks defines scripts or Python functions that are run
+# on newly generated revision scripts. See the documentation for further
+# detail and examples
+
+# format using "black" - use the console_scripts runner, against the "black" entrypoint
+# hooks = black
+# black.type = console_scripts
+# black.entrypoint = black
+# black.options = -l 79 REVISION_SCRIPT_FILENAME
+
+# Custom param that enables us to specify tables to ignore when determining migrations
+[alembic:exclude]
+tables = spatial_ref_sys
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = "%(asctime)s.%(msecs)03d [%(levelname)s] %(name)s | %(funcName)s:%(lineno)d | %(message)s"
+datefmt = "%y-%m-%d %H:%M:%S"
diff --git a/src/backend/app/central/central_crud.py b/src/backend/app/central/central_crud.py
index 6480e6e053..183c418df6 100644
--- a/src/backend/app/central/central_crud.py
+++ b/src/backend/app/central/central_crud.py
@@ -382,7 +382,32 @@ async def test_form_validity(xform_content: str, form_type: str):
f.write(xform_content)
xls2xform_convert(xlsform_path=xlsform_path, xform_path=outfile, validate=False)
- return {"message": "Your form is valid"}
+
+ namespaces = {
+ "h": "http://www.w3.org/1999/xhtml",
+ "odk": "http://www.opendatakit.org/xforms",
+ "xforms": "http://www.w3.org/2002/xforms",
+ }
+
+ import xml.etree.ElementTree as ET
+
+ with open(outfile, "r") as xml:
+ data = xml.read()
+
+ root = ET.fromstring(data)
+ instances = root.findall(".//xforms:instance[@src]", namespaces)
+
+ geojson_list = []
+ for inst in instances:
+ try:
+ if "src" in inst.attrib:
+ if (inst.attrib["src"].split("."))[1] == "geojson":
+ parts = (inst.attrib["src"].split("."))[0].split("/")
+ geojson_name = parts[-1]
+ geojson_list.append(geojson_name)
+ except Exception:
+ continue
+ return {"required media": geojson_list, "message": "Your form is valid"}
except Exception as e:
return JSONResponse(
content={"message": "Your form is invalid", "possible_reason": str(e)},
diff --git a/src/backend/app/db/database.py b/src/backend/app/db/database.py
index 7c24c42a76..2e0328221a 100644
--- a/src/backend/app/db/database.py
+++ b/src/backend/app/db/database.py
@@ -22,7 +22,7 @@
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
-from ..config import settings
+from app.config import settings
engine = create_engine(settings.FMTM_DB_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
diff --git a/src/backend/app/db/db_models.py b/src/backend/app/db/db_models.py
index 74ba6e682a..77483eefad 100644
--- a/src/backend/app/db/db_models.py
+++ b/src/backend/app/db/db_models.py
@@ -41,7 +41,7 @@
relationship,
)
-from ..models.enums import (
+from app.models.enums import (
BackgroundTaskStatus,
MappingLevel,
MappingPermission,
@@ -55,6 +55,7 @@
UserRole,
ValidationPermission,
)
+
from .database import Base, FmtmMetadata
from .postgis_utils import timestamp
diff --git a/src/backend/app/main.py b/src/backend/app/main.py
index 0373a8fef3..766eeffacb 100644
--- a/src/backend/app/main.py
+++ b/src/backend/app/main.py
@@ -33,7 +33,7 @@
from .auth import auth_routes
from .central import central_routes
from .config import settings
-from .db.database import Base, engine, get_db
+from .db.database import get_db
from .organization import organization_routes
from .projects import project_routes
from .projects.project_crud import read_xlsforms
@@ -172,10 +172,7 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE
async def startup_event():
"""Commands to run on server startup."""
log.debug("Starting up FastAPI server.")
- log.debug("Connecting to DB with SQLAlchemy")
- Base.metadata.create_all(bind=engine)
-
- # Read in XLSForms
+ log.debug("Reading XLSForms from DB.")
read_xlsforms(next(get_db()), xlsforms_path)
diff --git a/src/backend/migrations/alembic_helpers.py b/src/backend/migrations/alembic_helpers.py
new file mode 100644
index 0000000000..2ed288a5a3
--- /dev/null
+++ b/src/backend/migrations/alembic_helpers.py
@@ -0,0 +1,30 @@
+"""Helpers for alembic migrate and downgrade."""
+
+from alembic import op
+from sqlalchemy import engine_from_config
+from sqlalchemy.engine import reflection
+
+
+def table_does_not_exist(table, schema=None):
+ """Handle tables that do not exist."""
+ config = op.get_context().config
+ engine = engine_from_config(
+ config.get_section(config.config_ini_section), prefix="sqlalchemy."
+ )
+ insp = reflection.Inspector.from_engine(engine)
+ return insp.has_table(table, schema) is False
+
+
+def table_has_column(table, column):
+ """Handle tables when column already exists."""
+ config = op.get_context().config
+ engine = engine_from_config(
+ config.get_section(config.config_ini_section), prefix="sqlalchemy."
+ )
+ insp = reflection.Inspector.from_engine(engine)
+ has_column = False
+ for col in insp.get_columns(table):
+ if column not in col["name"]:
+ continue
+ has_column = True
+ return has_column
diff --git a/src/backend/migrations/env.py b/src/backend/migrations/env.py
new file mode 100644
index 0000000000..6bc495ecc1
--- /dev/null
+++ b/src/backend/migrations/env.py
@@ -0,0 +1,93 @@
+"""Main alembic migrations file."""
+
+from logging import getLogger
+from logging.config import fileConfig
+
+from alembic import context
+from geoalchemy2 import alembic_helpers
+from sqlalchemy import engine_from_config, pool
+
+from app.config import settings
+from app.db.db_models import Base
+
+config = context.config
+config.set_main_option("sqlalchemy.url", settings.FMTM_DB_URL)
+
+if config.config_file_name is not None:
+ fileConfig(config.config_file_name)
+
+target_metadata = Base.metadata
+exclude_tables = config.get_section("alembic:exclude").get("tables", "").split(",")
+log = getLogger(__name__)
+
+
+def include_object(object, name, type_, reflected, compare_to):
+ """Ignore our excluded tables in the autogen sweep."""
+ if type_ == "table" and name in exclude_tables:
+ return False
+ else:
+ return alembic_helpers.include_object(
+ object, name, type_, reflected, compare_to
+ )
+
+
+def run_migrations_offline() -> None:
+ """Run migrations in 'offline' mode.
+
+ This configures the context with just a URL
+ and not an Engine, though an Engine is acceptable
+ here as well. By skipping the Engine creation
+ we don't even need a DBAPI to be available.
+
+ Calls to context.execute() here emit the given string to the
+ script output.
+
+ """
+ log.info("Running offline migrations")
+
+ url = config.get_main_option("sqlalchemy.url")
+ context.configure(
+ url=url,
+ include_object=include_object,
+ target_metadata=target_metadata,
+ literal_binds=True,
+ dialect_opts={"paramstyle": "named"},
+ )
+
+ with context.begin_transaction():
+ context.run_migrations()
+ log.info("Complete offline migrations")
+
+
+def run_migrations_online() -> None:
+ """Run migrations in 'online' mode.
+
+ In this scenario we need to create an Engine
+ and associate a connection with the context.
+
+ """
+ log.info("Running online migrations")
+
+ connectable = engine_from_config(
+ config.get_section(config.config_ini_section),
+ prefix="sqlalchemy.",
+ poolclass=pool.NullPool,
+ )
+
+ with connectable.connect() as connection:
+ context.configure(
+ connection=connection,
+ include_object=include_object,
+ target_metadata=target_metadata,
+ )
+
+ with context.begin_transaction():
+ context.run_migrations()
+
+ log.info("Complete online migrations")
+
+
+if context.is_offline_mode():
+ run_migrations_offline()
+else:
+ run_migrations_online()
diff --git a/src/backend/migrations/script.py.mako b/src/backend/migrations/script.py.mako
new file mode 100644
index 0000000000..37d0cac313
--- /dev/null
+++ b/src/backend/migrations/script.py.mako
@@ -0,0 +1,24 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+
+"""
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
+
+
+def upgrade() -> None:
+ ${upgrades if upgrades else "pass"}
+
+
+def downgrade() -> None:
+ ${downgrades if downgrades else "pass"}
\ No newline at end of file
diff --git a/src/backend/migrations/versions/ec28a415c8d8_create_inital_tables.py b/src/backend/migrations/versions/ec28a415c8d8_create_inital_tables.py
new file mode 100644
index 0000000000..8aa8382f5a
--- /dev/null
+++ b/src/backend/migrations/versions/ec28a415c8d8_create_inital_tables.py
@@ -0,0 +1,2153 @@
+"""create inital tables.
+
+Revision ID: ec28a415c8d8
+Revises:
+Create Date: 2023-09-26 09:04:00.676103
+
+"""
+import imp
+import os
+
+import geoalchemy2
+import sqlalchemy as sa
+from alembic import op
+from sqlalchemy.dialects import postgresql
+
+alembic_helpers = imp.load_source(
+ "alembic_helpers",
+ (os.getcwd() + "/" + op.get_context().script.dir + "/alembic_helpers.py"),
+)
+
+# revision identifiers, used by Alembic.
+revision = "ec28a415c8d8"
+down_revision = None
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+ # ### commands auto generated by Alembic - please adjust! ###
+ if alembic_helpers.table_does_not_exist("loader_platform"):
+ op.create_table(
+ "loader_platform",
+ sa.Column("os", sa.VARCHAR(length=50), autoincrement=False, nullable=False),
+ sa.Column("declare_sect", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("pgbin", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("wget", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("unzip_command", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("psql", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("path_sep", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("loader", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "environ_set_command", sa.TEXT(), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "county_process_command", sa.TEXT(), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("os", name="loader_platform_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("dumpedpoints"):
+ op.create_table(
+ "dumpedpoints",
+ sa.Column("osm_id", sa.VARCHAR(), autoincrement=False, nullable=True),
+ sa.Column("polyid", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column("cid", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("clusteruid", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "geom",
+ geoalchemy2.types.Geometry(
+ geometry_type="POINT",
+ srid=4326,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ )
+ op.create_index(
+ "dumpedpoints_idx",
+ "dumpedpoints",
+ ["geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("pagc_lex"):
+ op.create_table(
+ "pagc_lex",
+ sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column("seq", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("word", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("stdword", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("token", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "is_custom",
+ sa.BOOLEAN(),
+ server_default=sa.text("true"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.PrimaryKeyConstraint("id", name="pagc_lex_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("zip_lookup_all"):
+ op.create_table(
+ "zip_lookup_all",
+ sa.Column("zip", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("st_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "state", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column("co_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "county", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column("cs_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "cousub", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column("pl_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "place", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column("cnt", sa.INTEGER(), autoincrement=False, nullable=True),
+ )
+
+ if alembic_helpers.table_does_not_exist("pagc_rules"):
+ op.create_table(
+ "pagc_rules",
+ sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column("rule", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "is_custom",
+ sa.BOOLEAN(),
+ server_default=sa.text("true"),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.PrimaryKeyConstraint("id", name="pagc_rules_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("addrfeat"):
+ op.create_table(
+ "addrfeat",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column("tlid", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "aridl", sa.VARCHAR(length=22), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aridr", sa.VARCHAR(length=22), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "linearid", sa.VARCHAR(length=22), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "fullname", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "lfromhn", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "ltohn", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "rfromhn", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "rtohn", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column("zipl", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column("zipr", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column(
+ "edge_mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "parityl", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "parityr", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "plus4l", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "plus4r", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "lfromtyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "ltotyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "rfromtyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "rtotyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "offsetl", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "offsetr", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'LINESTRING'::text OR the_geom IS NULL",
+ name="enforce_geotype_the_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_the_geom"),
+ sa.CheckConstraint(
+ "st_srid(the_geom) = 4269", name="enforce_srid_the_geom"
+ ),
+ sa.PrimaryKeyConstraint("gid", name="addrfeat_pkey"),
+ )
+ op.create_index("idx_addrfeat_zipr", "addrfeat", ["zipr"], unique=False)
+ op.create_index("idx_addrfeat_zipl", "addrfeat", ["zipl"], unique=False)
+ op.create_index("idx_addrfeat_tlid", "addrfeat", ["tlid"], unique=False)
+ op.create_index(
+ "idx_addrfeat_geom_gist",
+ "addrfeat",
+ ["the_geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("topology"):
+ op.create_table(
+ "topology",
+ sa.Column(
+ "id",
+ sa.INTEGER(),
+ server_default=sa.text("nextval('topology_id_seq'::regclass)"),
+ autoincrement=True,
+ nullable=False,
+ ),
+ sa.Column("name", sa.VARCHAR(), autoincrement=False, nullable=False),
+ sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "precision",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column(
+ "hasz",
+ sa.BOOLEAN(),
+ server_default=sa.text("false"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.PrimaryKeyConstraint("id", name="topology_pkey"),
+ sa.UniqueConstraint("name", name="topology_name_key"),
+ postgresql_ignore_search_path=False,
+ )
+
+ if alembic_helpers.table_does_not_exist("featnames"):
+ op.create_table(
+ "featnames",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column("tlid", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "fullname", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "name", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "predirabrv", sa.VARCHAR(length=15), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "pretypabrv", sa.VARCHAR(length=50), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "prequalabr", sa.VARCHAR(length=15), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sufdirabrv", sa.VARCHAR(length=15), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "suftypabrv", sa.VARCHAR(length=50), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sufqualabr", sa.VARCHAR(length=15), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "predir", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "pretyp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "prequal", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sufdir", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "suftyp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sufqual", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "linearid", sa.VARCHAR(length=22), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "paflag", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("gid", name="featnames_pkey"),
+ )
+ op.create_index(
+ "idx_tiger_featnames_tlid_statefp",
+ "featnames",
+ ["tlid", "statefp"],
+ unique=False,
+ )
+ op.create_index(
+ "idx_tiger_featnames_snd_name",
+ "featnames",
+ [sa.text("soundex(name::text)")],
+ unique=False,
+ )
+ op.create_index(
+ "idx_tiger_featnames_lname",
+ "featnames",
+ [sa.text("lower(name::text)")],
+ unique=False,
+ )
+
+ if alembic_helpers.table_does_not_exist("buildings"):
+ op.create_table(
+ "buildings",
+ sa.Column("id", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("project_id", sa.VARCHAR(), autoincrement=False, nullable=True),
+ sa.Column("osm_id", sa.VARCHAR(), autoincrement=False, nullable=True),
+ sa.Column(
+ "geom",
+ geoalchemy2.types.Geometry(
+ geometry_type="POLYGON",
+ srid=4326,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "tags",
+ postgresql.JSONB(astext_type=sa.Text()),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column("polyid", sa.BIGINT(), autoincrement=False, nullable=True),
+ )
+ op.create_index(
+ "buildings_idx",
+ "buildings",
+ ["geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("zcta5"):
+ op.create_table(
+ "zcta5",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "zcta5ce", sa.VARCHAR(length=5), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "classfp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aland",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "awater",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "partflg", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ spatial_index=False,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_the_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_the_geom"),
+ sa.CheckConstraint(
+ "st_srid(the_geom) = 4269", name="enforce_srid_the_geom"
+ ),
+ sa.PrimaryKeyConstraint(
+ "zcta5ce", "statefp", name="pk_tiger_zcta5_zcta5ce"
+ ),
+ sa.UniqueConstraint("gid", name="uidx_tiger_zcta5_gid"),
+ )
+
+ if alembic_helpers.table_does_not_exist("secondary_unit_lookup"):
+ op.create_table(
+ "secondary_unit_lookup",
+ sa.Column(
+ "name", sa.VARCHAR(length=20), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "abbrev", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("name", name="secondary_unit_lookup_pkey"),
+ )
+ op.create_index(
+ "secondary_unit_lookup_abbrev_idx",
+ "secondary_unit_lookup",
+ ["abbrev"],
+ unique=False,
+ )
+
+ if alembic_helpers.table_does_not_exist("pagc_gaz"):
+ op.create_table(
+ "pagc_gaz",
+ sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column("seq", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("word", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("stdword", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("token", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "is_custom",
+ sa.BOOLEAN(),
+ server_default=sa.text("true"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.PrimaryKeyConstraint("id", name="pagc_gaz_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("direction_lookup"):
+ op.create_table(
+ "direction_lookup",
+ sa.Column(
+ "name", sa.VARCHAR(length=20), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "abbrev", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("name", name="direction_lookup_pkey"),
+ )
+ op.create_index(
+ "direction_lookup_abbrev_idx", "direction_lookup", ["abbrev"], unique=False
+ )
+
+ if alembic_helpers.table_does_not_exist("state_lookup"):
+ op.create_table(
+ "state_lookup",
+ sa.Column("st_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "name", sa.VARCHAR(length=40), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "abbrev", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column("statefp", sa.CHAR(length=2), autoincrement=False, nullable=True),
+ sa.PrimaryKeyConstraint("st_code", name="state_lookup_pkey"),
+ sa.UniqueConstraint("abbrev", name="state_lookup_abbrev_key"),
+ sa.UniqueConstraint("name", name="state_lookup_name_key"),
+ sa.UniqueConstraint("statefp", name="state_lookup_statefp_key"),
+ )
+
+ if alembic_helpers.table_does_not_exist("tabblock20"):
+ op.create_table(
+ "tabblock20",
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tractce", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blockce", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "geoid", sa.VARCHAR(length=15), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "name", sa.VARCHAR(length=10), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column("ur", sa.VARCHAR(length=1), autoincrement=False, nullable=True),
+ sa.Column("uace", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column(
+ "uatype", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aland",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "awater",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ geometry_type="MULTIPOLYGON",
+ srid=4269,
+ spatial_index=False,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "housing",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "pop",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.PrimaryKeyConstraint("geoid", name="pk_tabblock20"),
+ )
+
+ if alembic_helpers.table_does_not_exist("splitpolygons"):
+ op.create_table(
+ "splitpolygons",
+ sa.Column("polyid", sa.BIGINT(), autoincrement=False, nullable=False),
+ sa.Column(
+ "geom",
+ geoalchemy2.types.Geometry(
+ geometry_type="POLYGON",
+ srid=4326,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "geog",
+ geoalchemy2.types.Geography(
+ from_text="ST_GeogFromText", name="geography"
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column("numfeatures", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "area",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.PrimaryKeyConstraint("polyid", name="splitpolygons_pkey"),
+ )
+ op.create_index(
+ "splitpolygons_idx",
+ "splitpolygons",
+ ["geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("cousub"):
+ op.create_table(
+ "cousub",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cousubfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cousubns", sa.VARCHAR(length=8), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cosbidfp", sa.VARCHAR(length=10), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "name", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "namelsad", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column("lsad", sa.VARCHAR(length=2), autoincrement=False, nullable=True),
+ sa.Column(
+ "classfp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cnectafp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "nectafp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "nctadvfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aland",
+ sa.NUMERIC(precision=14, scale=0),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "awater",
+ sa.NUMERIC(precision=14, scale=0),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_the_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_the_geom"),
+ sa.CheckConstraint(
+ "st_srid(the_geom) = 4269", name="enforce_srid_the_geom"
+ ),
+ sa.PrimaryKeyConstraint("cosbidfp", name="cousub_pkey"),
+ sa.UniqueConstraint("gid", name="uidx_cousub_gid"),
+ )
+ op.create_index(
+ "tige_cousub_the_geom_gist",
+ "cousub",
+ ["the_geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("zip_state"):
+ op.create_table(
+ "zip_state",
+ sa.Column("zip", sa.VARCHAR(length=5), autoincrement=False, nullable=False),
+ sa.Column(
+ "stusps", sa.VARCHAR(length=2), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("zip", "stusps", name="zip_state_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("place_lookup"):
+ op.create_table(
+ "place_lookup",
+ sa.Column("st_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "state", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column("pl_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "name", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("st_code", "pl_code", name="place_lookup_pkey"),
+ )
+ op.create_index(
+ "place_lookup_state_idx", "place_lookup", ["state"], unique=False
+ )
+ op.create_index(
+ "place_lookup_name_idx",
+ "place_lookup",
+ [sa.text("soundex(name::text)")],
+ unique=False,
+ )
+
+ if alembic_helpers.table_does_not_exist("lowfeaturecountpolygons"):
+ op.create_table(
+ "lowfeaturecountpolygons",
+ sa.Column("polyid", sa.BIGINT(), autoincrement=False, nullable=False),
+ sa.Column(
+ "geom",
+ geoalchemy2.types.Geometry(
+ geometry_type="POLYGON",
+ srid=4326,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "geog",
+ geoalchemy2.types.Geography(
+ from_text="ST_GeogFromText", name="geography"
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column("numfeatures", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "area",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column("n_polyid", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "n_area",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column("n_numfeatures", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "sharedbound",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.PrimaryKeyConstraint("polyid", name="lowfeaturecountpolygons_pkey"),
+ )
+ op.create_index(
+ "lowfeaturecountpolygons_idx",
+ "lowfeaturecountpolygons",
+ ["geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("place"):
+ op.create_table(
+ "place",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "placefp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "placens", sa.VARCHAR(length=8), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "plcidfp", sa.VARCHAR(length=7), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "name", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "namelsad", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column("lsad", sa.VARCHAR(length=2), autoincrement=False, nullable=True),
+ sa.Column(
+ "classfp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column("cpi", sa.VARCHAR(length=1), autoincrement=False, nullable=True),
+ sa.Column(
+ "pcicbsa", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "pcinecta", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column("aland", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column("awater", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_the_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_the_geom"),
+ sa.CheckConstraint(
+ "st_srid(the_geom) = 4269", name="enforce_srid_the_geom"
+ ),
+ sa.PrimaryKeyConstraint("plcidfp", name="place_pkey"),
+ sa.UniqueConstraint("gid", name="uidx_tiger_place_gid"),
+ )
+ op.create_index(
+ "tiger_place_the_geom_gist",
+ "place",
+ ["the_geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("zip_state_loc"):
+ op.create_table(
+ "zip_state_loc",
+ sa.Column("zip", sa.VARCHAR(length=5), autoincrement=False, nullable=False),
+ sa.Column(
+ "stusps", sa.VARCHAR(length=2), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "place", sa.VARCHAR(length=100), autoincrement=False, nullable=False
+ ),
+ sa.PrimaryKeyConstraint(
+ "zip", "stusps", "place", name="zip_state_loc_pkey"
+ ),
+ )
+
+ if alembic_helpers.table_does_not_exist("zip_lookup"):
+ op.create_table(
+ "zip_lookup",
+ sa.Column("zip", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column("st_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "state", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column("co_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "county", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column("cs_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "cousub", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column("pl_code", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "place", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column("cnt", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.PrimaryKeyConstraint("zip", name="zip_lookup_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("county_lookup"):
+ op.create_table(
+ "county_lookup",
+ sa.Column("st_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "state", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column("co_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "name", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("st_code", "co_code", name="county_lookup_pkey"),
+ )
+ op.create_index(
+ "county_lookup_state_idx", "county_lookup", ["state"], unique=False
+ )
+ op.create_index(
+ "county_lookup_name_idx",
+ "county_lookup",
+ [sa.text("soundex(name::text)")],
+ unique=False,
+ )
+
+ if alembic_helpers.table_does_not_exist("geocode_settings"):
+ op.create_table(
+ "geocode_settings",
+ sa.Column("name", sa.TEXT(), autoincrement=False, nullable=False),
+ sa.Column("setting", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("unit", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("category", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("short_desc", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.PrimaryKeyConstraint("name", name="geocode_settings_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("bg"):
+ op.create_table(
+ "bg",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tractce", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blkgrpce", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "bg_id", sa.VARCHAR(length=12), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "namelsad", sa.VARCHAR(length=13), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aland",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "awater",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ spatial_index=False,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_geom"),
+ sa.CheckConstraint("st_srid(the_geom) = 4269", name="enforce_srid_geom"),
+ sa.PrimaryKeyConstraint("bg_id", name="bg_pkey"),
+ comment="block groups",
+ )
+
+ if alembic_helpers.table_does_not_exist("geocode_settings_default"):
+ op.create_table(
+ "geocode_settings_default",
+ sa.Column("name", sa.TEXT(), autoincrement=False, nullable=False),
+ sa.Column("setting", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("unit", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("category", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("short_desc", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.PrimaryKeyConstraint("name", name="geocode_settings_default_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("edges"):
+ op.create_table(
+ "edges",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column("tlid", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "tfidl",
+ sa.NUMERIC(precision=10, scale=0),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "tfidr",
+ sa.NUMERIC(precision=10, scale=0),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "fullname", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "smid", sa.VARCHAR(length=22), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "lfromadd", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "ltoadd", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "rfromadd", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "rtoadd", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column("zipl", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column("zipr", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column(
+ "featcat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "hydroflg", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "railflg", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "roadflg", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "olfflg", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "passflg", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "divroad", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "exttyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column("ttyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True),
+ sa.Column(
+ "deckedroad", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "artpath", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "persist", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "gcseflg", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "offsetl", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "offsetr", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tnidf",
+ sa.NUMERIC(precision=10, scale=0),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "tnidt",
+ sa.NUMERIC(precision=10, scale=0),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTILINESTRING'::text OR the_geom IS NULL",
+ name="enforce_geotype_the_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_the_geom"),
+ sa.CheckConstraint(
+ "st_srid(the_geom) = 4269", name="enforce_srid_the_geom"
+ ),
+ sa.PrimaryKeyConstraint("gid", name="edges_pkey"),
+ )
+ op.create_index(
+ "idx_tiger_edges_the_geom_gist",
+ "edges",
+ ["the_geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+ op.create_index("idx_tiger_edges_countyfp", "edges", ["countyfp"], unique=False)
+ op.create_index("idx_edges_tlid", "edges", ["tlid"], unique=False)
+
+ if alembic_helpers.table_does_not_exist("faces"):
+ op.create_table(
+ "faces",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "tfid",
+ sa.NUMERIC(precision=10, scale=0),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "statefp00", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp00", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tractce00", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blkgrpce00", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blockce00", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cousubfp00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "submcdfp00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "conctyfp00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "placefp00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aiannhfp00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aiannhce00", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "comptyp00", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "trsubfp00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "trsubce00", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "anrcfp00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "elsdlea00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "scsdlea00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "unsdlea00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "uace00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cd108fp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sldust00", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sldlst00", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "vtdst00", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "zcta5ce00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tazce00", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "ugace00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "puma5ce00", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tractce", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blkgrpce", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blockce", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cousubfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "submcdfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "conctyfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "placefp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aiannhfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aiannhce", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "comptyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "trsubfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "trsubce", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "anrcfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "ttractce", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tblkgpce", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "elsdlea", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "scsdlea", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "unsdlea", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column("uace", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column(
+ "cd111fp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sldust", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "sldlst", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "vtdst", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "zcta5ce", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tazce", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "ugace", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "puma5ce", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "csafp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cbsafp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "metdivfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cnectafp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "nectafp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "nctadvfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "lwflag", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "offset", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "atotal",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "tractce20", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blkgrpce20", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blockce20", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp20", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "statefp20", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_the_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_the_geom"),
+ sa.CheckConstraint(
+ "st_srid(the_geom) = 4269", name="enforce_srid_the_geom"
+ ),
+ sa.PrimaryKeyConstraint("gid", name="faces_pkey"),
+ )
+ op.create_index(
+ "tiger_faces_the_geom_gist",
+ "faces",
+ ["the_geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+ op.create_index("idx_tiger_faces_tfid", "faces", ["tfid"], unique=False)
+ op.create_index("idx_tiger_faces_countyfp", "faces", ["countyfp"], unique=False)
+
+ if alembic_helpers.table_does_not_exist("loader_variables"):
+ op.create_table(
+ "loader_variables",
+ sa.Column(
+ "tiger_year", sa.VARCHAR(length=4), autoincrement=False, nullable=False
+ ),
+ sa.Column("website_root", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("staging_fold", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("data_schema", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column("staging_schema", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.PrimaryKeyConstraint("tiger_year", name="loader_variables_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("county"):
+ op.create_table(
+ "county",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyns", sa.VARCHAR(length=8), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cntyidfp", sa.VARCHAR(length=5), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "name", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "namelsad", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column("lsad", sa.VARCHAR(length=2), autoincrement=False, nullable=True),
+ sa.Column(
+ "classfp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "csafp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "cbsafp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "metdivfp", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column("aland", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "awater",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ spatial_index=False,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_geom"),
+ sa.CheckConstraint("st_srid(the_geom) = 4269", name="enforce_srid_geom"),
+ sa.PrimaryKeyConstraint("cntyidfp", name="pk_tiger_county"),
+ sa.UniqueConstraint("gid", name="uidx_county_gid"),
+ )
+ op.create_index("idx_tiger_county", "county", ["countyfp"], unique=False)
+
+ if alembic_helpers.table_does_not_exist("zip_lookup_base"):
+ op.create_table(
+ "zip_lookup_base",
+ sa.Column("zip", sa.VARCHAR(length=5), autoincrement=False, nullable=False),
+ sa.Column(
+ "state", sa.VARCHAR(length=40), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "county", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "city", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("zip", name="zip_lookup_base_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("tract"):
+ op.create_table(
+ "tract",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tractce", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tract_id", sa.VARCHAR(length=11), autoincrement=False, nullable=False
+ ),
+ sa.Column("name", sa.VARCHAR(length=7), autoincrement=False, nullable=True),
+ sa.Column(
+ "namelsad", sa.VARCHAR(length=20), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aland",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "awater",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ spatial_index=False,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_geom"),
+ sa.CheckConstraint("st_srid(the_geom) = 4269", name="enforce_srid_geom"),
+ sa.PrimaryKeyConstraint("tract_id", name="tract_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("layer"):
+ op.create_table(
+ "layer",
+ sa.Column("topology_id", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column("layer_id", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column("schema_name", sa.VARCHAR(), autoincrement=False, nullable=False),
+ sa.Column("table_name", sa.VARCHAR(), autoincrement=False, nullable=False),
+ sa.Column(
+ "feature_column", sa.VARCHAR(), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "feature_type", sa.INTEGER(), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "level",
+ sa.INTEGER(),
+ server_default=sa.text("0"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column("child_id", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.ForeignKeyConstraint(
+ ["topology_id"], ["topology.id"], name="layer_topology_id_fkey"
+ ),
+ sa.PrimaryKeyConstraint("topology_id", "layer_id", name="layer_pkey"),
+ sa.UniqueConstraint(
+ "schema_name",
+ "table_name",
+ "feature_column",
+ name="layer_schema_name_table_name_feature_column_key",
+ ),
+ )
+
+ if alembic_helpers.table_does_not_exist("street_type_lookup"):
+ op.create_table(
+ "street_type_lookup",
+ sa.Column(
+ "name", sa.VARCHAR(length=50), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "abbrev", sa.VARCHAR(length=50), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "is_hw",
+ sa.BOOLEAN(),
+ server_default=sa.text("false"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.PrimaryKeyConstraint("name", name="street_type_lookup_pkey"),
+ )
+ op.create_index(
+ "street_type_lookup_abbrev_idx",
+ "street_type_lookup",
+ ["abbrev"],
+ unique=False,
+ )
+
+ if alembic_helpers.table_does_not_exist("taskpolygons"):
+ op.create_table(
+ "taskpolygons",
+ sa.Column(
+ "geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column("clusteruid", sa.TEXT(), autoincrement=False, nullable=True),
+ )
+ op.create_index(
+ "taskpolygons_idx",
+ "taskpolygons",
+ ["geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("tabblock"):
+ op.create_table(
+ "tabblock",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "countyfp", sa.VARCHAR(length=3), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tractce", sa.VARCHAR(length=6), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "blockce", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tabblock_id",
+ sa.VARCHAR(length=16),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column(
+ "name", sa.VARCHAR(length=20), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column("ur", sa.VARCHAR(length=1), autoincrement=False, nullable=True),
+ sa.Column("uace", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "aland",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "awater",
+ sa.DOUBLE_PRECISION(precision=53),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ spatial_index=False,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_geom"),
+ sa.CheckConstraint("st_srid(the_geom) = 4269", name="enforce_srid_geom"),
+ sa.PrimaryKeyConstraint("tabblock_id", name="tabblock_pkey"),
+ )
+
+ if alembic_helpers.table_does_not_exist("countysub_lookup"):
+ op.create_table(
+ "countysub_lookup",
+ sa.Column("st_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "state", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column("co_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "county", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.Column("cs_code", sa.INTEGER(), autoincrement=False, nullable=False),
+ sa.Column(
+ "name", sa.VARCHAR(length=90), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint(
+ "st_code", "co_code", "cs_code", name="countysub_lookup_pkey"
+ ),
+ )
+ op.create_index(
+ "countysub_lookup_state_idx", "countysub_lookup", ["state"], unique=False
+ )
+ op.create_index(
+ "countysub_lookup_name_idx",
+ "countysub_lookup",
+ [sa.text("soundex(name::text)")],
+ unique=False,
+ )
+
+ if alembic_helpers.table_does_not_exist("addr"):
+ op.create_table(
+ "addr",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column("tlid", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "fromhn", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "tohn", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column("side", sa.VARCHAR(length=1), autoincrement=False, nullable=True),
+ sa.Column("zip", sa.VARCHAR(length=5), autoincrement=False, nullable=True),
+ sa.Column(
+ "plus4", sa.VARCHAR(length=4), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "fromtyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "totyp", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column("fromarmid", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("toarmid", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column(
+ "arid", sa.VARCHAR(length=22), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.PrimaryKeyConstraint("gid", name="addr_pkey"),
+ )
+ op.create_index("idx_tiger_addr_zip", "addr", ["zip"], unique=False)
+ op.create_index(
+ "idx_tiger_addr_tlid_statefp", "addr", ["tlid", "statefp"], unique=False
+ )
+
+ if alembic_helpers.table_does_not_exist("voronois"):
+ op.create_table(
+ "voronois",
+ sa.Column("clusteruid", sa.TEXT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ )
+ op.create_index(
+ "voronois_idx", "voronois", ["geom"], unique=False, postgresql_using="gist"
+ )
+
+ if alembic_helpers.table_does_not_exist("state"):
+ op.create_table(
+ "state",
+ sa.Column("gid", sa.INTEGER(), autoincrement=True, nullable=False),
+ sa.Column(
+ "region", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "division", sa.VARCHAR(length=2), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "statefp", sa.VARCHAR(length=2), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "statens", sa.VARCHAR(length=8), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "stusps", sa.VARCHAR(length=2), autoincrement=False, nullable=False
+ ),
+ sa.Column(
+ "name", sa.VARCHAR(length=100), autoincrement=False, nullable=True
+ ),
+ sa.Column("lsad", sa.VARCHAR(length=2), autoincrement=False, nullable=True),
+ sa.Column(
+ "mtfcc", sa.VARCHAR(length=5), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "funcstat", sa.VARCHAR(length=1), autoincrement=False, nullable=True
+ ),
+ sa.Column("aland", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column("awater", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column(
+ "intptlat", sa.VARCHAR(length=11), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "intptlon", sa.VARCHAR(length=12), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "the_geom",
+ geoalchemy2.types.Geometry(
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.CheckConstraint(
+ "geometrytype(the_geom) = 'MULTIPOLYGON'::text OR the_geom IS NULL",
+ name="enforce_geotype_the_geom",
+ ),
+ sa.CheckConstraint("st_ndims(the_geom) = 2", name="enforce_dims_the_geom"),
+ sa.CheckConstraint(
+ "st_srid(the_geom) = 4269", name="enforce_srid_the_geom"
+ ),
+ sa.PrimaryKeyConstraint("statefp", name="pk_tiger_state"),
+ sa.UniqueConstraint("gid", name="uidx_tiger_state_gid"),
+ sa.UniqueConstraint("stusps", name="uidx_tiger_state_stusps"),
+ )
+ op.create_index(
+ "idx_tiger_state_the_geom_gist",
+ "state",
+ ["the_geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("clusteredbuildings"):
+ op.create_table(
+ "clusteredbuildings",
+ sa.Column("id", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("project_id", sa.VARCHAR(), autoincrement=False, nullable=True),
+ sa.Column("osm_id", sa.VARCHAR(), autoincrement=False, nullable=True),
+ sa.Column(
+ "geom",
+ geoalchemy2.types.Geometry(
+ geometry_type="POLYGON",
+ srid=4326,
+ from_text="ST_GeomFromEWKT",
+ name="geometry",
+ _spatial_index_reflected=True,
+ ),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "tags",
+ postgresql.JSONB(astext_type=sa.Text()),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column("polyid", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column("numfeatures", sa.BIGINT(), autoincrement=False, nullable=True),
+ sa.Column("cid", sa.INTEGER(), autoincrement=False, nullable=True),
+ sa.Column("clusteruid", sa.TEXT(), autoincrement=False, nullable=True),
+ )
+ op.create_index(
+ "clusteredbuildings_idx",
+ "clusteredbuildings",
+ ["geom"],
+ unique=False,
+ postgresql_using="gist",
+ )
+
+ if alembic_helpers.table_does_not_exist("loader_lookuptables"):
+ op.create_table(
+ "loader_lookuptables",
+ sa.Column(
+ "process_order",
+ sa.INTEGER(),
+ server_default=sa.text("1000"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column(
+ "lookup_name",
+ sa.TEXT(),
+ autoincrement=False,
+ nullable=False,
+ comment="This is the table name to inherit from and suffix of resulting output table -- how the table will be named -- edges here would mean -- ma_edges , pa_edges etc. except in the case of national tables. national level tables have no prefix",
+ ),
+ sa.Column(
+ "table_name",
+ sa.TEXT(),
+ autoincrement=False,
+ nullable=True,
+ comment="suffix of the tables to load e.g. edges would load all tables like *edges.dbf(shp) -- so tl_2010_42129_edges.dbf . ",
+ ),
+ sa.Column(
+ "single_mode",
+ sa.BOOLEAN(),
+ server_default=sa.text("true"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column(
+ "load",
+ sa.BOOLEAN(),
+ server_default=sa.text("true"),
+ autoincrement=False,
+ nullable=False,
+ comment="Whether or not to load the table. For states and zcta5 (you may just want to download states10, zcta510 nationwide file manually) load your own into a single table that inherits from tiger.states, tiger.zcta5. You'll get improved performance for some geocoding cases.",
+ ),
+ sa.Column(
+ "level_county",
+ sa.BOOLEAN(),
+ server_default=sa.text("false"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column(
+ "level_state",
+ sa.BOOLEAN(),
+ server_default=sa.text("false"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column(
+ "level_nation",
+ sa.BOOLEAN(),
+ server_default=sa.text("false"),
+ autoincrement=False,
+ nullable=False,
+ comment="These are tables that contain all data for the whole US so there is just a single file",
+ ),
+ sa.Column(
+ "post_load_process", sa.TEXT(), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "single_geom_mode",
+ sa.BOOLEAN(),
+ server_default=sa.text("false"),
+ autoincrement=False,
+ nullable=True,
+ ),
+ sa.Column(
+ "insert_mode",
+ sa.CHAR(length=1),
+ server_default=sa.text("'c'::bpchar"),
+ autoincrement=False,
+ nullable=False,
+ ),
+ sa.Column(
+ "pre_load_process", sa.TEXT(), autoincrement=False, nullable=True
+ ),
+ sa.Column(
+ "columns_exclude",
+ postgresql.ARRAY(sa.TEXT()),
+ autoincrement=False,
+ nullable=True,
+ comment="List of columns to exclude as an array. This is excluded from both input table and output table and rest of columns remaining are assumed to be in same order in both tables. gid, geoid,cpi,suffix1ce are excluded if no columns are specified.",
+ ),
+ sa.Column(
+ "website_root_override",
+ sa.TEXT(),
+ autoincrement=False,
+ nullable=True,
+ comment="Path to use for wget instead of that specified in year table. Needed currently for zcta where they release that only for 2000 and 2010",
+ ),
+ sa.PrimaryKeyConstraint("lookup_name", name="loader_lookuptables_pkey"),
+ )
+
+ # ### end Alembic commands ###
+
+
+def downgrade() -> None:
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_table("loader_lookuptables")
+ op.drop_index(
+ "clusteredbuildings_idx",
+ table_name="clusteredbuildings",
+ postgresql_using="gist",
+ )
+ op.drop_table("clusteredbuildings")
+ op.drop_index(
+ "idx_tiger_state_the_geom_gist", table_name="state", postgresql_using="gist"
+ )
+ op.drop_table("state")
+ op.drop_index("voronois_idx", table_name="voronois", postgresql_using="gist")
+ op.drop_table("voronois")
+ op.drop_index("idx_tiger_addr_tlid_statefp", table_name="addr")
+ op.drop_index("idx_tiger_addr_zip", table_name="addr")
+ op.drop_table("addr")
+ op.drop_index("countysub_lookup_name_idx", table_name="countysub_lookup")
+ op.drop_index("countysub_lookup_state_idx", table_name="countysub_lookup")
+ op.drop_table("countysub_lookup")
+ op.drop_table("tabblock")
+ op.drop_index(
+ "taskpolygons_idx", table_name="taskpolygons", postgresql_using="gist"
+ )
+ op.drop_table("taskpolygons")
+ op.drop_index("street_type_lookup_abbrev_idx", table_name="street_type_lookup")
+ op.drop_table("street_type_lookup")
+ op.drop_table("layer")
+ op.drop_table("tract")
+ op.drop_table("zip_lookup_base")
+ op.drop_index("idx_tiger_county", table_name="county")
+ op.drop_table("county")
+ op.drop_table("loader_variables")
+ op.drop_index("idx_tiger_faces_countyfp", table_name="faces")
+ op.drop_index("idx_tiger_faces_tfid", table_name="faces")
+ op.drop_index(
+ "tiger_faces_the_geom_gist", table_name="faces", postgresql_using="gist"
+ )
+ op.drop_table("faces")
+ op.drop_index("idx_edges_tlid", table_name="edges")
+ op.drop_index("idx_tiger_edges_countyfp", table_name="edges")
+ op.drop_index(
+ "idx_tiger_edges_the_geom_gist", table_name="edges", postgresql_using="gist"
+ )
+ op.drop_table("edges")
+ op.drop_table("geocode_settings_default")
+ op.drop_table("bg")
+ op.drop_table("geocode_settings")
+ op.drop_index("county_lookup_name_idx", table_name="county_lookup")
+ op.drop_index("county_lookup_state_idx", table_name="county_lookup")
+ op.drop_table("county_lookup")
+ op.drop_table("zip_lookup")
+ op.drop_table("zip_state_loc")
+ op.drop_index(
+ "tiger_place_the_geom_gist", table_name="place", postgresql_using="gist"
+ )
+ op.drop_table("place")
+ op.drop_index(
+ "lowfeaturecountpolygons_idx",
+ table_name="lowfeaturecountpolygons",
+ postgresql_using="gist",
+ )
+ op.drop_table("lowfeaturecountpolygons")
+ op.drop_index("place_lookup_name_idx", table_name="place_lookup")
+ op.drop_index("place_lookup_state_idx", table_name="place_lookup")
+ op.drop_table("place_lookup")
+ op.drop_table("zip_state")
+ op.drop_index(
+ "tige_cousub_the_geom_gist", table_name="cousub", postgresql_using="gist"
+ )
+ op.drop_table("cousub")
+ op.drop_index(
+ "splitpolygons_idx", table_name="splitpolygons", postgresql_using="gist"
+ )
+ op.drop_table("splitpolygons")
+ op.drop_table("tabblock20")
+ op.drop_table("state_lookup")
+ op.drop_index("direction_lookup_abbrev_idx", table_name="direction_lookup")
+ op.drop_table("direction_lookup")
+ op.drop_table("pagc_gaz")
+ op.drop_index(
+ "secondary_unit_lookup_abbrev_idx", table_name="secondary_unit_lookup"
+ )
+ op.drop_table("secondary_unit_lookup")
+ op.drop_table("zcta5")
+ op.drop_index("buildings_idx", table_name="buildings", postgresql_using="gist")
+ op.drop_table("buildings")
+ op.drop_index("idx_tiger_featnames_lname", table_name="featnames")
+ op.drop_index("idx_tiger_featnames_snd_name", table_name="featnames")
+ op.drop_index("idx_tiger_featnames_tlid_statefp", table_name="featnames")
+ op.drop_table("featnames")
+ op.drop_table("topology")
+ op.drop_index(
+ "idx_addrfeat_geom_gist", table_name="addrfeat", postgresql_using="gist"
+ )
+ op.drop_index("idx_addrfeat_tlid", table_name="addrfeat")
+ op.drop_index("idx_addrfeat_zipl", table_name="addrfeat")
+ op.drop_index("idx_addrfeat_zipr", table_name="addrfeat")
+ op.drop_table("addrfeat")
+ op.drop_table("pagc_rules")
+ op.drop_table("zip_lookup_all")
+ op.drop_table("pagc_lex")
+ op.drop_index(
+ "dumpedpoints_idx", table_name="dumpedpoints", postgresql_using="gist"
+ )
+ op.drop_table("dumpedpoints")
+ op.drop_table("loader_platform")
+ # ### end Alembic commands ###
diff --git a/src/backend/pdm.lock b/src/backend/pdm.lock
index 47ede9e909..938fe14508 100644
--- a/src/backend/pdm.lock
+++ b/src/backend/pdm.lock
@@ -2,11 +2,26 @@
# It is not intended for manual editing.
[metadata]
-groups = ["default", "debug", "dev", "docs", "test"]
+groups = ["default", "test", "dev", "docs", "debug"]
cross_platform = true
static_urls = false
lock_version = "4.3"
-content_hash = "sha256:507fefabdf6bb662691e6652dd1beef9820d5921e89c24f7b04c1ff9e78a67df"
+content_hash = "sha256:f074e7e235d93874f1308bcdbdd80f830ce811de6b151534b4ca6e768c3cae41"
+
+[[package]]
+name = "alembic"
+version = "1.12.0"
+requires_python = ">=3.7"
+summary = "A database migration tool for SQLAlchemy."
+dependencies = [
+ "Mako",
+ "SQLAlchemy>=1.3.0",
+ "typing-extensions>=4",
+]
+files = [
+ {file = "alembic-1.12.0-py3-none-any.whl", hash = "sha256:03226222f1cf943deee6c85d9464261a6c710cd19b4fe867a3ad1f25afda610f"},
+ {file = "alembic-1.12.0.tar.gz", hash = "sha256:8e7645c32e4f200675e69f0745415335eb59a3663f5feb487abfa0b30c45888b"},
+]
[[package]]
name = "annotated-types"
@@ -693,6 +708,19 @@ files = [
{file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"},
]
+[[package]]
+name = "mako"
+version = "1.2.4"
+requires_python = ">=3.7"
+summary = "A super-fast templating language that borrows the best ideas from the existing templating languages."
+dependencies = [
+ "MarkupSafe>=0.9.2",
+]
+files = [
+ {file = "Mako-1.2.4-py3-none-any.whl", hash = "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818"},
+ {file = "Mako-1.2.4.tar.gz", hash = "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34"},
+]
+
[[package]]
name = "markdown"
version = "3.4.4"
@@ -992,7 +1020,7 @@ name = "osm-login-python"
version = "1.0.1"
requires_python = ">=3.9"
git = "https://github.com/hotosm/osm-login-python"
-revision = "9085757812f4e3cc4ec11b213574dcd8bb8e9b79"
+revision = "a396d081bfc31afc949108508e2184ef7763d954"
summary = "Use OSM Token exchange with OAuth2.0 for python projects."
dependencies = [
"itsdangerous~=2.1.2",
@@ -1482,7 +1510,7 @@ files = [
name = "questionary"
version = "2.0.1"
requires_python = ">=3.8"
-summary = "Python library to build pretty command line user prompts βοΈ"
+summary = "Python library to build pretty command line user prompts Γ’ΒοΏ½Γ―ΒΈοΏ½"
dependencies = [
"prompt-toolkit<=3.0.36,>=2.0",
]
@@ -1820,12 +1848,12 @@ files = [
[[package]]
name = "typing-extensions"
-version = "4.8.0"
-requires_python = ">=3.8"
-summary = "Backported and Experimental Type Hints for Python 3.8+"
+version = "4.7.1"
+requires_python = ">=3.7"
+summary = "Backported and Experimental Type Hints for Python 3.7+"
files = [
- {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
- {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
+ {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
+ {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
]
[[package]]
diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml
index ef92799b37..befb60dd8a 100644
--- a/src/backend/pyproject.toml
+++ b/src/backend/pyproject.toml
@@ -30,14 +30,16 @@ dependencies = [
"pydantic-settings>=2.0.3",
"geojson-pydantic==1.0.0",
"python-multipart>=0.0.6",
+ "sqlalchemy>=2.0.21",
+ "SQLAlchemy-Utils==0.41.1",
"psycopg2==2.9.7",
"geoalchemy2==0.14.1",
+ "alembic>=1.12.0",
"geojson==3.0.1",
"shapely==2.0.1",
"pyxform==1.12.1",
"qrcode==7.4.2",
"xmltodict==0.13.0",
- "SQLAlchemy-Utils==0.41.1",
"segno==1.5.2",
"osm-fieldwork==0.3.6rc1",
"sentry-sdk==1.30.0",