{"id":49609506,"url":"https://github.com/exasol-labs/exasol-json-tables","last_synced_at":"2026-05-04T16:07:15.348Z","repository":{"id":352379406,"uuid":"1212686673","full_name":"exasol-labs/exasol-json-tables","owner":"exasol-labs","description":"Exasol JSON Tables: ingest, query, and reshape JSON-shaped data in Exasol.","archived":false,"fork":false,"pushed_at":"2026-04-19T08:45:50.000Z","size":521,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-19T10:29:00.682Z","etag":null,"topics":["exasol","json"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exasol-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-16T16:18:51.000Z","updated_at":"2026-04-19T08:45:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/exasol-labs/exasol-json-tables","commit_stats":null,"previous_names":["exasol-labs/exasol-json-tables"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/exasol-labs/exasol-json-tables","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exasol-labs%2Fexasol-json-tables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exasol-labs%2Fexasol-json-tables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exasol-labs%2Fexasol-json-tables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exasol-labs%2Fexasol-json-tables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exasol-labs","download_url":"https://codeload.github.com/exasol-labs/exasol-json-tables/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exasol-labs%2Fexasol-json-tables/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32614428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["exasol","json"],"created_at":"2026-05-04T16:07:09.320Z","updated_at":"2026-05-04T16:07:13.092Z","avatar_url":"https://github.com/exasol-labs.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Exasol JSON Tables\n\nExasol JSON Tables makes JSON feel natural inside Exasol.\n\nIt gives you one workflow for:\n\n- ingesting raw JSON or NDJSON into Exasol\n- querying that data with JSON-friendly SQL instead of raw helper tables\n- reshaping SQL results back into the nested contract and emitting final JSON with `TO_JSON(...)` when you need it\n\nThe usual Exasol pattern for JSON is to store the document as a string and then use built-in JSON functions whenever you need to extract a field, filter on a nested value, or reshape part of the payload. That works, but it gets heavy once the data is deeply nested, reused across many queries, or needs array-aware analytics. Exasol JSON Tables is an alternative workflow: ingest JSON into a stable relational contract once, then query and reshape it through a JSON-friendly SQL surface instead of repeatedly pulling values back out of strings.\n\n## Why Use It\n\nExasol JSON Tables gives you a clean JSON native interface:\n\n- query nested fields with path syntax like `\"meta.info.note\"`\n- index and expand arrays with syntax like `\"tags[LAST]\"` and `JOIN item IN s.\"items\"`\n- inspect variants with `JSON_TYPEOF(...)` and `JSON_AS_*`\n- keep missing vs explicit `null` semantics intact\n- materialize structured results back into a reusable nested contract\n- finish with `TO_JSON(*)` or `TO_JSON(\"field1\", \"field2\")` when you want final JSON output\n- JSON document size is no longer bound by string size limits\n\nIt is especially useful if you want to:\n\n- analyze semi-structured event or API data directly in Exasol\n- build bronze/silver/gold pipelines on top of JSON-shaped source data\n- migrate analytics workloads from MongoDB into SQL\n- return nested, document-style output from ordinary relational tables through structured results plus `TO_JSON(...)`\n\n## What You Get\n\nExasol JSON Tables has three main capabilities:\n\n### Ingest\n\nTake JSON or NDJSON and load it into Exasol using a stable table-family contract that preserves:\n\n- nested objects\n- arrays\n- explicit JSON `null`\n- mixed/variant fields\n\n### Query\n\nInstall a wrapper surface on top of those source tables so users query documents instead of low-level storage details.\n\nThat surface supports:\n\n- dotted paths\n- bracket access\n- rowset expansion for arrays\n- explicit-null helpers\n- JSON-aware variant helpers\n\n### Reshape\n\nTake query results and materialize them back into the same nested contract, so they can:\n\n- be queried again through the wrapper surface\n- be used as a durable intermediate result\n- be emitted as final JSON through `TO_JSON(*)` or `TO_JSON(...)`\n\n## Quick Example\n\nAfter installation and wrapper setup, a query can look like this:\n\n```sql\nSELECT\n  \"id\",\n  CASE\n    WHEN JSON_IS_EXPLICIT_NULL(\"note\") THEN 'explicit-null'\n    WHEN \"note\" IS NULL THEN 'missing'\n    ELSE 'value'\n  END AS note_state,\n  JSON_TYPEOF(\"value\") AS value_type,\n  JSON_AS_VARCHAR(\"value\") AS value_text,\n  \"meta.info.note\" AS deep_note,\n  \"tags[LAST]\" AS last_tag\nFROM JSON_VIEW.SAMPLE\nORDER BY \"id\";\n```\n\nAnd when arrays should behave like rows:\n\n```sql\nSELECT\n  s.\"id\",\n  item._index,\n  item.value,\n  item.label\nFROM JSON_VIEW.SAMPLE s\nJOIN item IN s.\"items\"\nORDER BY s.\"id\", item._index;\n```\n\nAnd when you want the final document back out of a wrapped family:\n\n```sql\nSELECT TO_JSON(*) AS doc_json\nFROM JSON_VIEW.SAMPLE\nORDER BY \"_id\";\n```\n\n## Install\n\nThe supported product entrypoint is:\n\n- `exasol-json-tables`\n\nInstall the Python package:\n\n```bash\npython3 -m pip install -e .\n```\n\nBuild the Rust ingest engine:\n\n```bash\ncargo build --manifest-path crates/json_tables_ingest/Cargo.toml\n```\n\nThen verify the CLI:\n\n```bash\nexasol-json-tables --help\n```\n\nFor repo-local development, `python3 -m pip install -r requirements-dev.txt` installs the same package in editable mode.\n\n## Quickstart\n\nThe simplest end-to-end path is a single command:\n\n```bash\nexasol-json-tables ingest-and-wrap \\\n  --input ./data.json \\\n  --name customer_events \\\n  --artifact-dir ./dist/exasol-json-tables \\\n  --exasol-temp-dir /tmp/exasol-json-tables\n```\n\nThat will:\n\n1. ingest the JSON into Exasol\n2. emit a source manifest\n3. generate the wrapper package\n4. install it\n5. validate it\n\nAfter that, activate the wrapper syntax in your SQL session:\n\n```sql\nALTER SESSION SET SQL_PREPROCESSOR_SCRIPT = JVS_WRAP_PP.JSON_WRAPPER_PREPROCESSOR;\n```\n\nAt that point, the primary final-output surface is available too:\n\n```sql\nSELECT TO_JSON(*) AS doc_json\nFROM JSON_VIEW.CUSTOMER_EVENTS;\n```\n\n## Access Modes\n\nThere are three supported ways to work with the wrapper surface:\n\n### 1. Manual Session Activation\n\nThis is the lowest-level authoring mode:\n\n```sql\nALTER SESSION SET SQL_PREPROCESSOR_SCRIPT = JVS_WRAP_PP.JSON_WRAPPER_PREPROCESSOR;\n```\n\nUse it when you are exploring interactively in a SQL client and want full wrapper syntax on that session.\n\n### 2. Connection Bootstrap\n\nFor applications, CI, and managed SQL clients, the normal pattern is to run the same activation SQL immediately after opening a connection or when checking one out from a pool.\n\nThat keeps wrapper syntax available without asking each user or request handler to remember the activation step manually.\n\n### 3. Published Permanent Surfaces\n\nWhen a wrapped family becomes part of a long-lived downstream workflow, use the wrapper as the authoring surface and publish ordinary views or tables from it.\n\nThat lets downstream consumers query the published objects without any preprocessor activation at all.\n\nFor the practical details, see [docs/installation.md](docs/installation.md#access-modes).\n\nFor notebook, pandas, and polars workflows, see [docs/python-dataframes.md](docs/python-dataframes.md).\n\nIf you want more control, the same flow is also available as separate commands:\n\n- `exasol-json-tables ingest`\n- `exasol-json-tables wrap generate`\n- `exasol-json-tables wrap install`\n- `exasol-json-tables wrap deploy`\n- `exasol-json-tables validate`\n- `exasol-json-tables structured-results ...`\n\nFor automation and autonomous agents, the major workflow commands also support `--json`. In that mode they emit a machine-readable summary on stdout with a stable success or failure envelope plus the important outputs, such as package paths, schema names, activation SQL, smoke-test SQL, validation probes, and wrapper-scope warnings. There is also a `describe` command for package- and wrapper-surface discovery. `structured-results preview-json` is the fast one-shot preview path and now uses the same temporary wrapper plus `TO_JSON(*)` outlet as the durable SQL surface; the primary final-output path remains `TO_JSON(...)` on the installed wrapper or result wrapper.\n\n## Further Reading\n\n- Installation: [docs/installation.md](docs/installation.md)\n- Python notebooks / pandas / polars: [docs/python-dataframes.md](docs/python-dataframes.md)\n- Ingest guide: [docs/ingest.md](docs/ingest.md)\n- Query surface reference: [docs/query-surface.md](docs/query-surface.md)\n- Structured results: [docs/structured-results.md](docs/structured-results.md)\n- Automation: [docs/automation.md](docs/automation.md)\n- Identifier conventions: [docs/identifier-conventions.md](docs/identifier-conventions.md)\n- Architecture: [docs/architecture.md](docs/architecture.md)\n- Testing and validation: [docs/testing.md](docs/testing.md)\n- Developer guide: [docs/developer-guide.md](docs/developer-guide.md)\n- Changelog: [CHANGELOG.md](CHANGELOG.md)\n\n## Skills\n\n- Ingest skill: [skills/exasol-json-tables-ingest/SKILL.md](skills/exasol-json-tables-ingest/SKILL.md)\n- Query skill: [skills/exasol-json-tables-query/SKILL.md](skills/exasol-json-tables-query/SKILL.md)\n- Reshape skill: [skills/exasol-json-tables-reshape/SKILL.md](skills/exasol-json-tables-reshape/SKILL.md)\n- MongoDB migration skill: [skills/mongodb-workload-migration/SKILL.md](skills/mongodb-workload-migration/SKILL.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexasol-labs%2Fexasol-json-tables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexasol-labs%2Fexasol-json-tables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexasol-labs%2Fexasol-json-tables/lists"}