{ "info": { "author": "", "author_email": "", "bugtrack_url": null, "classifiers": [], "description": "# Hephaestus\n\n[![Build Status](https://travis-ci.org/expobrain/hephaestus.svg?branch=master)](https://travis-ci.org/expobrain/hephaestus)\n\n## Introduction\n\nHephaestus is a library to statically which parses a SQL query and return an AST.\n\nThis is useful for different purposes like:\n\n- statistic informations, i.e. table or field used, tipe of joins, filter conditions, etc\n- partial or full query comparison\n- query type detection\n\nThe SQL grammar is specific for [Exasol](https://www.exasol.com/en/), but it can be easily ported to support other grammars as well.\n\nHephaestus's parser is built in [Rust](https://www.rust-lang.org/) using the [lalrpop](https://github.com/lalrpop/lalrpop) crate for grammar's definition and [vervolg](https://github.com/hmwill/vervolg) used as a base for the SQL grammar.\n\n## Installation\n\nTo install the package you need to install the `nightly` version of the Rust compiler:\n\n```shell\ncurl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=nightly\n```\n\nthen install the package straight from Github:\n\n```shell\npip install git+https://github.com/expobrain/hephaestus@develop\n```\n\n> Note: until version 0.8 of `pyo3` you need to have the `python` binary available in your `PATH`; on some systems it will fail because only `python3` is present. In this case install the Python 2 package.\n\n## Usage\n\n### Parsing\n\nHephaestus exposes a single `parse()` function which given a SQl string returns a dictionary representing the SQL in an AST format:\n\n```python\n>>> import hephaestus\n>>> hephaestus.parse(\"SELECT 1\")\n{'_type': 'SelectStatement',\n 'common': [],\n 'expr': {'_type': 'QuerySetExpression',\n 'mode': {'_type': 'SelectAll'},\n 'columns': {'_type': 'ListResultColumn',\n 'values': [{'_type': 'ExprResultColumn',\n 'expr': {'_type': 'NumericLiteral', 'num': '1'},\n 'rename': None}]},\n 'from': [],\n 'where_expr': None,\n 'group_by': None},\n 'order_by': [],\n 'limit': None}\n```\n\nEvery node of the dictionary has a `_type` key which indicate the type of the node, i.e. `SelectStatement`, and a series of keys specific for the node's type which can contains scalars values like `str`, `int`, `None`, a dictionary representing a node or a list of scalar values or nodes.\n\n> For a full list of node types see `src/ast.rs` and `src/ast_py.rs`.\n\n### Traversing\n\nParsing the incoming SQL expression is only the first step and its not very useful without the ability to traverse the tree and inspect the nodes.\n\nInstead of writing from scratch the code to traverse the dictionary nested structure by yourself Hephaestus provides you a class to be used to walk through the tree and call a method for every node it encouters during the traverse.\n\nJust inherith from the `Visitor` class and implement methods in the form of `visit_` where `` is the type of the node in the `_type` key.\n\nThis example shows how to check if the given SQL statement is querying from the `DUAL` table:\n\n```python\nfrom typing import Dict\n\nfrom hephaestus.walk import Visitor\n\n\nclass MyVisitor(Visitor):\n has_dual_table = False\n\n def visit_NamedTableExpression(self, attr: str, node: Dict):\n self.has_dual_table = node[\"name\"] == [\"dual\"]\n\n\nvisitor = MyVisitor(\"SELECT 1 FROM dual\")\nvisitor.walk()\n\nassert visitor.has_dual_table is True\n```\n\nWhen the `NamedTableExpression` node is reached the `visit_NamedTableExpression` method is called and receives the parent node's attribute name `attr` and the node itself.\n\n## Testing\n\nThere are two set of tests, one for the Rust and one for the Python code.\n\n> Note: Unfortunately at the moment it's not possible to execute both test suites with the same `Cargo.toml` (looks like that the `extension-module` feature in `pyo3` interfere with the way the tests are linked with the Rust library), so it's necessary to switch to a different config before running the them.\n\nTo run the Rust tests:\n\n```shell\nmake test_rust\n```\n\nTo run the Python tests:\n\n```shell\nmake test_py\n```\n\n## Contribute\n\nIf you want to contribute to the Hephaestus project to extend the grammar follow this steps:\n\n1. switch to a pure Rust `Cargo.toml` with `make rust`\n1. write a test in `src/tests` to cover the cases\n1. extend the grammar in `src/sql.lalrpop`; please refer to the [LALR Book](http://lalrpop.github.io/lalrpop/)\n1. add the relative AST note to `src/ast.rs`\n1. in some cases, like defining a new Rust enumerator, it's necessary to add an explicit conversion form the Rust type to a Python-compatible type; in this add the relevant code into `src/ast_py.rs`\n\n## Caveats\n\n- not all the grammar of Exasol is supported, most of the functions and statements needs to be implemented\n- despite the fact that the AST returned by the `parse()` function can be manipulated at will at the moment there's no way to get back a SQL string", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "hephaestus", "package_url": "https://pypi.org/project/hephaestus/", "platform": "", "project_url": "https://pypi.org/project/hephaestus/", "project_urls": null, "release_url": "https://pypi.org/project/hephaestus/0.1.1/", "requires_dist": null, "requires_python": "", "summary": "", "version": "0.1.1" }, "last_serial": 5952260, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "8ddcf34aaf0d3e9888f2a92b922f44a9", "sha256": "62ed55df759f691db47cfe4fdaacbc6a44501d4aebc40642fc38985f4a1f3207" }, "downloads": -1, "filename": "hephaestus-0.1.0-cp37-cp37m-macosx_10_14_x86_64.whl", "has_sig": false, "md5_digest": "8ddcf34aaf0d3e9888f2a92b922f44a9", "packagetype": "bdist_wheel", "python_version": "cp37", "requires_python": null, "size": 578602, "upload_time": "2019-10-09T21:12:36", "url": "https://files.pythonhosted.org/packages/4d/0a/b55729e4ee73c259d3c40f4ec95f918f497e11550f13d68a767b5f9e284c/hephaestus-0.1.0-cp37-cp37m-macosx_10_14_x86_64.whl" }, { "comment_text": "", "digests": { "md5": "0b1745bb34a6125e59260c92403d7aca", "sha256": "034e77e171079d43441ebec9a107fb3f4c22f9d22b74320857623e8760025764" }, "downloads": -1, "filename": "hephaestus-0.1.0.tar.gz", "has_sig": false, "md5_digest": "0b1745bb34a6125e59260c92403d7aca", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 179660, "upload_time": "2019-10-09T21:12:42", "url": "https://files.pythonhosted.org/packages/f7/28/4b1767924b416aa94258fb3d2bfbdd6b538f2b76a4c2a735f3e523c7e40a/hephaestus-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "6b319aa1a9e554f3f35c66faf6b3ac07", "sha256": "135692aa81da3b9199f54b81eabbd5ffabe0221bbbecbc0c8099eb54e16cb7c7" }, "downloads": -1, "filename": "hephaestus-0.1.1-cp37-cp37m-macosx_10_14_x86_64.whl", "has_sig": false, "md5_digest": "6b319aa1a9e554f3f35c66faf6b3ac07", "packagetype": "bdist_wheel", "python_version": "cp37", "requires_python": null, "size": 580770, "upload_time": "2019-10-09T22:16:44", "url": "https://files.pythonhosted.org/packages/a8/b6/5159e632b35975a481c70b1ddfa8a9a53b8d423a152f0e8cfe802688b09a/hephaestus-0.1.1-cp37-cp37m-macosx_10_14_x86_64.whl" }, { "comment_text": "", "digests": { "md5": "c48f887b4896967abf253b141800d1e5", "sha256": "2c556eea54462a9ff1f8a17e312d1bfb34a2f4dad643ad65d4085e75345dc69b" }, "downloads": -1, "filename": "hephaestus-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c48f887b4896967abf253b141800d1e5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 179855, "upload_time": "2019-10-09T22:05:54", "url": "https://files.pythonhosted.org/packages/97/08/7db74089be1b216301df7ce37bf757ab032609fa9d8f01a1d3571d99772c/hephaestus-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6b319aa1a9e554f3f35c66faf6b3ac07", "sha256": "135692aa81da3b9199f54b81eabbd5ffabe0221bbbecbc0c8099eb54e16cb7c7" }, "downloads": -1, "filename": "hephaestus-0.1.1-cp37-cp37m-macosx_10_14_x86_64.whl", "has_sig": false, "md5_digest": "6b319aa1a9e554f3f35c66faf6b3ac07", "packagetype": "bdist_wheel", "python_version": "cp37", "requires_python": null, "size": 580770, "upload_time": "2019-10-09T22:16:44", "url": "https://files.pythonhosted.org/packages/a8/b6/5159e632b35975a481c70b1ddfa8a9a53b8d423a152f0e8cfe802688b09a/hephaestus-0.1.1-cp37-cp37m-macosx_10_14_x86_64.whl" }, { "comment_text": "", "digests": { "md5": "c48f887b4896967abf253b141800d1e5", "sha256": "2c556eea54462a9ff1f8a17e312d1bfb34a2f4dad643ad65d4085e75345dc69b" }, "downloads": -1, "filename": "hephaestus-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c48f887b4896967abf253b141800d1e5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 179855, "upload_time": "2019-10-09T22:05:54", "url": "https://files.pythonhosted.org/packages/97/08/7db74089be1b216301df7ce37bf757ab032609fa9d8f01a1d3571d99772c/hephaestus-0.1.1.tar.gz" } ] }