{"id":16543315,"url":"https://github.com/codemation/pyql-rest","last_synced_at":"2025-03-04T07:14:15.694Z","repository":{"id":130201793,"uuid":"221066371","full_name":"codemation/pyql-rest","owner":"codemation","description":"A REST API for an PYQL db endpoint ","archived":false,"fork":false,"pushed_at":"2020-10-08T13:32:01.000Z","size":291,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-14T11:16:49.432Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codemation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2019-11-11T20:41:27.000Z","updated_at":"2020-07-02T22:08:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"d251e682-d6fb-4d39-8350-bf6981de6f80","html_url":"https://github.com/codemation/pyql-rest","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpyql-rest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpyql-rest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpyql-rest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2Fpyql-rest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codemation","download_url":"https://codeload.github.com/codemation/pyql-rest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241801257,"owners_count":20022390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-11T18:59:53.880Z","updated_at":"2025-03-04T07:14:15.665Z","avatar_url":"https://github.com/codemation.png","language":"Python","readme":"# pyql-rest\nREST API access to database using PYQL JSON query syntax\n\n## Requirements\n- Docker \n\n### Gather required environment variables: \n- PYQL_HOST - hostname / ip which will be used to access this rest endpoint\n- PYQL_PORT - port which this rest endpoint will listen for API requests\n- DB_HOST - hostname / ip for rest endpoint to access database\n- DB_PORT - database port which DB_HOST is listening for db connections\n- DB_NAMES - comma separated list of databases which rest endpoint will manage\n- DB_USER - user which will authenicate against DB_HOST Database - should have full access to specified database\n- DB_PASSWORD - password for DB_USER\n- DB_TYPE - mysql|sqlite3\nNote: Using a type 'sqlite3' database only requires PYQL_HOST, DB_NAMES \u0026 DB_TYPE vars\n\n\n### Standalone variables\nStandalone instances require a PYQL username / password used for authenticating the API requests \u0026 administering REST endpoint \n- PYQL_USER - user which will administer pyql rest endpoint or simply access rest endpoint data \n- PYQL_PASSWORD - password for PYQL_USER\n- PYQL_TYPE - default is K8s, use PYQL_TYPE=STANDALONE for standalone instances\n\n\n### Quick Start - Standalone - MYSQL\n- LOCAL_PATH - folder which pyql config database will be stored\n\n        EXAMPLE: LOCAL_PATH=$(pwd)/pyql-rest-mysql\n\n- LOCAL_PORT - local port mapped to container port - can often be the same port if not in use already\n\n        env1=\"-e PYQL_HOST=192.168.1.10 -e PYQL_PORT=8090 -e PYQL_USER=pyql_admin -e PYQL_TYPE=STANDALONE -e PYQL_PASSWORD='abcd1234' -e DB_TYPE=mysql\"\n\n        env2=\"-e DB_HOST=192.168.1.20 -e DB_PORT=3306 -e DB_NAMES=company -e DB_USER=db_admin -e DB_PASSWORD=$(echo -n $(cat ~/.secret))\"\n    \n        docker container run --name pyql-rest-mysql $env1 $env2 -p $LOCAL_PORT:$PYQL_PORT -v $LOCAL_PATH:/mnt/pyql-rest -d joshjamison/pyql-rest:latest\n\n\n### Quick Start - Standalone - sqlite3\n- LOCAL_PATH - folder which pyql config database will be stored\n\n        EXAMPLE: LOCAL_PATH=$(pwd)/pyql-rest-mysql\n\n- LOCAL_PORT - local port mapped to container port - can often be the same port if not in use already\n\n        env1=\"-e PYQL_HOST=192.168.1.10 -e PYQL_PORT=8090 -e PYQL_TYPE=STANDALONE -e PYQL_USER=pyql_admin -e PYQL_PASSWORD='abcd1234' -e DB_TYPE=sqlite3 -e DB_NAMES=company \"\n    \n        docker container run --name pyql-rest-mysql $env1 -p $LOCAL_PORT:$PYQL_PORT -v $LOCAL_PATH:/mnt/pyql-rest -d joshjamison/pyql-rest:latest\n\n## PYQL Rest Setup with PYQL Cluster\nA rest endpoint can be configured to join a collection of other rest endpoints (cluster), for the purposes of providing read load-balancing, data resilency, cross-database / hybrid or multi-cloud replicas. See  [pyql-cluster](https://github.com/codemation/pyql-cluster)\n\n### PYQL Rest - Cluster Variables\n- PYQL_TYPE - K8S\n- PYQL_CLUSTER_SVC - HOSTNAME_OR_IP:PORT - The external host \u0026 port used to access the pyql-cluster service\n- PYQL_CLUSTER_NAME - cluster to create or join\n- PYQL_CLUSTER_ACTION - 'init' or 'join'\n- PYQL_CLUSTER_TABLES - 'ALL' or comma separated list of tables to init / join cluster\n- PYQL_CLUSTER_JOIN_TOKEN - join token generated on pyql-cluster using existing pyql-cluster user credentials See  [pyql-cluster](https://github.com/codemation/pyql-cluster)\n\nNote: Instances may be started via docker run or within a kubernetes deployment using these variables. PYQL_HOST address must be a reachable by the pyql-cluster for an instance to correctly join / init. \n\nExample:\n\n        env1=\"-e PYQL_HOST=192.168.1.10 -e PYQL_PORT=8090 -e PYQL_USER=pyql_admin -e PYQL_PASSWORD='abcd1234' -e DB_TYPE=mysql\"\n\n        env2=\"-e DB_HOST=192.168.1.20 -e DB_PORT=3306 -e DB_NAMES=company -e DB_USER=db_admin -e DB_PASSWORD=$(echo -n $(cat ~/.secret))\"\n\n        env3=\"-e PYQL_CLUSTER_SVC=pyql-cluster.domain.local -e PYQL_CLUSTER_NAME=data PYQL_CLUSTER_ACTION=init \"\n\n        env4=\"-e PYQL_CLUSTER_TABLES=ALL -e PYQL_CLUSTER_JOIN_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6ImU3MjRjODQyLWIzNDQtMTFlYS05NjgxLTYyOGNhNTQ1MTNjYyIsImV4cGlyYXRpb24iOiJqb2luIiwiY3JlYXRlVGltZSI6MTU5Mjc0Njk5Ni4xNTQ5Mjk2fQ.E-G5qPpT2hqTjp8J7tq1ZXZDE0GG6wvu_YJgmOtYLLE\"\n\n        docker container run --name pyql-rest-mysql $env1 $env2 $env3 $env4 -p $LOCAL_PORT:$PYQL_PORT -v $LOCAL_PATH:/mnt/pyql-rest -d joshjamison/pyql-rest:latest\n\nSpecial Considerations:\n- DOCKER ONLY - PYQL_HOST must be reachable by all pyql-cluster endpoints, if pyql cluster spans multiple subnets consider use of an external address.\n\n\nK8s statefulSets \u0026 Deployments for pyql-clusters\n\nSee examples in See  [pyql-rest k8s](./k8s) and [pyql-cluster](https://github.com/codemation/pyql-cluster)\n\n## PYQL REST - API REFERENCE\n\n| ACTION | HTTP Verb | Path             | Request Content-Type | Request body | Response Content-Type | Example response body |\n|--------|-----------|------------------|----------------------|--------------|-----------------------|-----------------------|\n| CREATE Table | POST | /db/{database}/table/create | 'application/json' | {\"stocks\":{\"columns\":[{\"mods\":\"NOT NULL AUTO_INCREMENT\",\"name\":\"order_num\",\"type\":\"int\"},{\"mods\":\"\",\"name\":\"date\",\"type\":\"str\"},{\"mods\":\"\",\"name\":\"trans\",\"type\":\"str\"},{\"mods\":\"\",\"name\":\"symbol\",\"type\":\"str\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"qty\",\"type\":\"int\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"price\",\"type\":\"float\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"after_hours\",\"type\":\"bool\"}],\"foreign_keys\":null,\"primary_key\":\"order_num\"}} | {\"message\": \"table created successfuly\"} | \n| Get Table Config | GET | /db/{database}/table/{table}/config | - | - | 'application/json' | {\"stocks\":{\"columns\":[{\"mods\":\"NOT NULL AUTO_INCREMENT\",\"name\":\"order_num\",\"type\":\"int\"},{\"mods\":\"\",\"name\":\"date\",\"type\":\"str\"},{\"mods\":\"\",\"name\":\"trans\",\"type\":\"str\"},{\"mods\":\"\",\"name\":\"symbol\",\"type\":\"str\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"qty\",\"type\":\"int\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"price\",\"type\":\"float\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"after_hours\",\"type\":\"bool\"}],\"foreign_keys\":null,\"primary_key\":\"order_num\"}} | {\"message\": \"table created successfuly\"}\n| Sync / Load Table | POST | /db/{database}/table/{table}/sync | 'application/json' | {\"data\":[{\"after_hours\":true,\"date\":\"2006-01-05\",\"order_num\":2,\"price\":35.16,\"qty\":null,\"symbol\":null,\"trans\":{\"condition\":{\"limit\":\"36.00\",\"time\":\"end_of_trading_day\"},\"type\":\"BUY\"}},{\"after_hours\":true,\"date\":\"2006-01-06\",\"order_num\":3,\"price\":35.12,\"qty\":null,\"symbol\":null,\"trans\":{\"condition\":{\"limit\":\"36.00\",\"time\":\"end_of_trading_day\"},\"type\":\"BUY\"}}]}\n| List All Tables config | GET | /db/{database}/tables' | - | - | 'application/json' | {\"tables\": [{\"stocks\":{\"columns\":[{\"mods\":\"NOT NULL AUTO_INCREMENT\",\"name\":\"order_num\",\"type\":\"int\"},{\"mods\":\"\",\"name\":\"date\",\"type\":\"str\"},{\"mods\":\"\",\"name\":\"trans\",\"type\":\"str\"},{\"mods\":\"\",\"name\":\"symbol\",\"type\":\"str\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"qty\",\"type\":\"int\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"price\",\"type\":\"float\"},{\"mods\":\"DEFAULT NULL\",\"name\":\"after_hours\",\"type\":\"bool\"}],\"foreign_keys\":null,\"primary_key\":\"order_num\"}} | {\"message\": \"table created successfuly\"}, {\"keystore\":{\"columns\":[{\"mods\":\"NOT NULL\",\"name\":\"env\",\"type\":\"str\"},{\"mods\":\"\",\"name\":\"val\",\"type\":\"str\"}],\"foreign_keys\":null,\"primary_key\":\"env\"}}]}\n| Get All Rows | GET | /db/{database}/table/{table} | - | - | 'application/json' | {\"data\":[{\"after_hours\":true,\"date\":\"2006-01-05\",\"order_num\":2,\"price\":35.16,\"qty\":null,\"symbol\":null,\"trans\":{\"condition\":{\"limit\":\"36.00\",\"time\":\"end_of_trading_day\"},\"type\":\"BUY\"}},{\"after_hours\":true,\"date\":\"2006-01-06\",\"order_num\":3,\"price\":35.12,\"qty\":null,\"symbol\":null,\"trans\":{\"condition\":{\"limit\":\"36.00\",\"time\":\"end_of_trading_day\"},\"type\":\"BUY\"}}]}\n| Add row to table | POST, PUT | /db/{database}/table/{table} | 'application/json' | {\"after_hours\":true,\"date\":\"2006-01-05\",\"price\":35.16,\"qty\":null,\"symbol\":null,\"trans\":{\"condition\":{\"limit\":\"36.00\",\"time\":\"end_of_trading_day\"},\"type\":\"BUY\"}} | 'application/json' | {\"message\": \"items added\"}\n| Get Row with matching primary key | GET | /db/{database}/table/{table}/{key} | - | - | 'application/json' | {\"data\":[{\"after_hours\":true,\"date\":\"2006-01-06\",\"order_num\":3,\"price\":35.12,\"qty\":null,\"symbol\":null,\"trans\":{\"condition\":{\"limit\":\"36.00\",\"time\":\"end_of_trading_day\"},\"type\":\"BUY\"}}]}\n| Update Row with matching primary key | POST | /db/{database}/table/{table}/{key} | 'application/json' | {\"price\": 34:12} | 'application/json' | {\"message\": \"OK\"}\n| Delete Row with matching primary key | DELETE | /db/{database}/table/{table}/{key} | - | - | 'application/json' | {\"message\": \"OK\"}\n| Add row to table | POST | /db/{database}/table/{table}/insert | 'application/json' | {\"after_hours\":true,\"date\":\"2006-01-05\",\"order_num\":2,\"price\":35.16,\"qty\":null,\"symbol\":null,\"trans\":{\"condition\":{\"limit\":\"36.00\",\"time\":\"end_of_trading_day\"},\"type\":\"BUY\"}} | 'application/json' | {\"message\": \"items added\"}\n| Update Row with matching 'where' conditions | POST | /db/{database}/table/{table}/update | 'application/json' | {\"set\":{\"price\": 32:12},\"where\": {\"type\": \"BUY\"}} | 'application/json' | {\"message\": \"OK\"}\n| Delete Row with matching 'where' conditions | POST | /db/{database}/table/{table}/delete | 'application/json' | {\"where\": {\"after_hours\": True}} | 'application/json' | {\"message\": \"OK\"}\n| Select columns in rows, optionally matching 'where' conditions | POST | /db/{database}/table/{table}/select | 'application/json' | {\"select\":[\"order_num\",\"after_hours\"],\"where\":{\"price\":32.12}} | 'application/json' | {\"data\":[{\"after_hours\":true,\"order_num\":3}]}\n\n## Advanced Select Usage - PYQL JSON query syntax\n\n### Basic - Select \n| PYQL JSON | SQL |\n|--------|--------|\n|{\"select\":[\"*\"]} | select * from {table} |\n| {\"select\":[\"*\"],\"where\":{\"{column}:\"value\"}} | select * from {table} where {column}=\"value\"\n| {\"select\":[\"{column1}\",\"{column2}\",\"{column3}\"],\"where\":{\"{column1}:\"value1\",\"{column2}\":\"value2\"}} | select {column1}, {column2}, {column3} from {table} where {column1}=\"value\" and {column2}=\"value2\" |\n### Advanced - Select - Joins\n| PYQL JSON | SQL | Info |\n|--------|--------|-----|\n|{\"select\":[\"*\"], \"join\": \"{table2}\"} | select * from {table1} join {table2} on {table1}.foreign_key = {table2}.lKey | This PYQL JSON syntax assumes that {table1} has a foreign_key constraint with {table2} |\n| {\"select\":[\"*\"],\"join\":{\"{table2}\":{\"{table1}.{column1}\":\"{table2}.{column2}\"}} | select * from {table1} join {table2} on {table1}.{column1} = {table2}.{column2} | {table1} and {table2} do not require any foreign key constraints for this join | \n\n### Examples - PYQL JSON query syntax\n\n| ACTION | HTTP Verb | Path             | Request Content-Type | Request body | SQL Query | Response Content-Type | Example response body |\n|--------|-----------|------------------|----------------------|--------------|-----------|------------|-----------------------|\n| Join Select with Foreign Key constraint| POST | /db/company/table/employees/select | 'application/json' | {\"select\":[\"*\"],\"join\":\"positions\"} | \"select * from employees join positions on employees.position_id = positions.id\" | 'application/json' | {\"data\":[{\"employees.id\":1000,\"employees.name\":\"Jane Doe\",\"employees.position_id\":100101,\"positions.department_id\":1001,\"positions.name\":\"Director\"},{\"employees.id\":1001,\"employees.name\":\"Dale Smith\",\"employees.position_id\":100102,\"positions.department_id\":1001,\"positions.name\":\"Manager\"},{\"employees.id\":1002,\"employees.name\":\"Clara Carson\",\"employees.position_id\":100102,\"positions.department_id\":1001,\"positions.name\":\"Manager\"},{\"employees.id\":1003,\"employees.name\":\"Jill Carson\",\"employees.position_id\":100103,\"positions.department_id\":1001,\"positions.name\":\"Rep\"},{\"employees.id\":1004,\"employees.name\":\"Jane Adams\",\"employees.position_id\":100103,\"positions.department_id\":1001,\"positions.name\":\"Rep\"}, .. |\n| Join Select w/o Foreign Key constraint | POST | /db/company/table/positions/select | 'application/json' |{\"select\":[\"*\"],\"join\":{\"departments\":{\"positions.department_id\":\"departments.id\"}},\"where\":{\"departments.name\": \"HR\"}} | select * from positions join departments on positoins.departmentsId = departments.id where deparments.name=\"HR\" | 'application/json' | {\"data\":[{\"departments.name\":\"HR\",\"positions.department_id\":1001,\"positions.id\":100101,\"positions.name\":\"Director\"},{\"departments.name\":\"HR\",\"positions.department_id\":1001,\"positions.id\":100102,\"positions.name\":\"Manager\"},{\"departments.name\":\"HR\",\"positions.department_id\":1001,\"positions.id\":100103,\"positions.name\":\"Rep\"},{\"departments.name\":\"HR\",\"positions.department_id\":1001,\"positions.id\":100104,\"positions.name\":\"Intern\"}]}\n| Multi-Join Select | POST | /db/company/table/employees/select | 'application/json' | {\"select\":[\"employees.name\",\"positions.name\",\"departments.name\"],\"join\":{\"positions\":{\"employees.position_id\":\"positions.id\"},\"departments\":{\"positions.department_id\":\"departments.id\"}},\"where\":{\"positoins.name\":\"Director\"}} | SELECT employees.name,positions.name,departments.name FROM employees JOIN positions ON employees.position_id = positions.id JOIN departments ON positions.department_id = departments.id WHERE positions.name='Director' | 'application/json'| {\"data\":[{\"departments.name\":\"HR\",\"employees.name\":\"Jane Doe\",\"positions.name\":\"Director\"},{\"departments.name\":\"Sales\",\"employees.name\":\"Jane Adams\",\"positions.name\":\"Director\"},{\"departments.name\":\"Support\",\"employees.name\":\"Jane Doe\",\"positions.name\":\"Director\"},{\"departments.name\":\"Marketing\",\"employees.name\":\"Dale Wallace\",\"positions.name\":\"Director\"}]} |\n\n#### Additional PYQL information\nSee [pyql reference](https://github.com/codemation/pyql)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemation%2Fpyql-rest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodemation%2Fpyql-rest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemation%2Fpyql-rest/lists"}