Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adql query parser function #696

Draft
wants to merge 48 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
5f710cd
adql query parser function
burnout87 Jun 24, 2024
5526e61
queryparser-python3 lib
burnout87 Jun 25, 2024
7d099aa
more error check
burnout87 Jun 25, 2024
fb87a08
adding info
burnout87 Jul 8, 2024
a90cc05
using sqlparse library
burnout87 Jul 18, 2024
ba08496
requirements
burnout87 Jul 18, 2024
6dcc1e2
using the two libraries combined
burnout87 Jul 18, 2024
eec215c
some where clauses extraction
burnout87 Jul 23, 2024
6759c7a
testing breadth-first
burnout87 Jul 26, 2024
0e24a34
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Jul 29, 2024
90c8e4f
using breadth-first
burnout87 Jul 29, 2024
2c0030b
no sqlparse
burnout87 Jul 30, 2024
16580c2
querying mysql gallery database
burnout87 Jul 30, 2024
30d1ed8
todo and removed commented lines
burnout87 Jul 31, 2024
27708b2
vo options in the dispatcher config
burnout87 Jul 31, 2024
83d119a
extracting mysql parameters from config
burnout87 Jul 31, 2024
89f46d6
no need for breadth first search
burnout87 Jul 31, 2024
b828910
sentry in case of error
burnout87 Jul 31, 2024
34bdea8
capturing general exception
burnout87 Jul 31, 2024
1ee31a1
dispatcher endpoint
burnout87 Jul 31, 2024
40dc17e
build product gallery path and jsonify the response
burnout87 Jul 31, 2024
60c9bff
var renaming
burnout87 Aug 12, 2024
bdc61b4
removed unused imports
burnout87 Aug 16, 2024
3d8d973
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Aug 16, 2024
841928f
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Aug 16, 2024
b31c634
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Sep 25, 2024
5342a7a
using postgresql
burnout87 Sep 26, 2024
bf1cd49
sanitize request values
burnout87 Sep 26, 2024
5d53425
using value var
burnout87 Sep 27, 2024
309e2ad
postgresql connector library
burnout87 Sep 27, 2024
08ad2ab
no query parsing
burnout87 Sep 27, 2024
ec8d018
not needed import
burnout87 Sep 27, 2024
f5df283
adapted conf example
burnout87 Sep 27, 2024
f9b934b
not needed requirements
burnout87 Sep 27, 2024
87256a9
not needed requirements
burnout87 Sep 27, 2024
db388d8
freezing version pytest-xdist
burnout87 Sep 27, 2024
d8d26a7
adapted config tests and new config test
burnout87 Sep 27, 2024
c81decd
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Oct 4, 2024
0dd8cb5
exception handling
burnout87 Oct 4, 2024
2c1baf4
logging
burnout87 Oct 4, 2024
73f9ede
fixing imports
burnout87 Oct 4, 2024
ebf7b24
missing fixture decorator
burnout87 Oct 4, 2024
f069dad
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Oct 15, 2024
ddbaadc
build file url
burnout87 Oct 17, 2024
77ad5f3
removed mysql stuff
burnout87 Oct 23, 2024
b26a5da
removed pgsql details from answer
burnout87 Oct 23, 2024
516c5c9
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Dec 6, 2024
0d31fb9
Merge branch 'master' into ivoa_helper-endpoint
burnout87 Dec 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions cdci_data_analysis/analysis/ivoa_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import json
Fixed Show fixed Hide fixed
import os.path

from black.lines import append_leaves
Fixed Show fixed Hide fixed
from queryparser.adql import ADQLQueryTranslator
from queryparser.mysql import MySQLQueryProcessor
from queryparser.exceptions import QuerySyntaxError

from mysql.connector import connect, Error

from ..flask_app.sentry import sentry
Fixed Show fixed Hide fixed
from ..app_logging import app_logging

logger = app_logging.getLogger('ivoa_helper')


def parse_adql_query(query):
try:
# queryparser
adt = ADQLQueryTranslator(query)
qp = MySQLQueryProcessor()
qp.set_query(adt.to_mysql())
qp.process_query()

output_obj = dict(
columns=qp.display_columns,
tables=qp.tables,
rest=qp,
mysql_query=qp.query
)

except QuerySyntaxError as qe:
logger.error(f'Error parsing ADQL query: {qe}')
output_obj = dict(
tables=None,
columns=None,
rest=None,
mysql_query=None
)
return output_obj


def run_ivoa_query(query, **kwargs):
parsed_query_obj = parse_adql_query(query)

# TODO use a specific dedicated table and schema to refer to the product_gallery DB ?
# tables = parsed_query_obj.get('tables', [])
# if len(tables) == 1 and tables[0] == 'product_gallery':
logger.info('Performing query on the product_gallery')
vo_mysql_pg_host = kwargs.get('vo_mysql_pg_host', None)
vo_mysql_pg_user = kwargs.get('vo_mysql_pg_user', None)
vo_mysql_pg_password = kwargs.get('vo_mysql_pg_password', None)
vo_mysql_pg_db = kwargs.get('vo_mysql_pg_db', None)
product_gallery_url = kwargs.get('product_gallery_url', None)
result_list = run_ivoa_query_from_product_gallery(parsed_query_obj,
vo_mysql_pg_host=vo_mysql_pg_host,
vo_mysql_pg_user=vo_mysql_pg_user,
vo_mysql_pg_password=vo_mysql_pg_password,
vo_mysql_pg_db=vo_mysql_pg_db,
product_gallery_url=product_gallery_url)
return result_list


def run_ivoa_query_from_product_gallery(parsed_query_obj,
vo_mysql_pg_host,
vo_mysql_pg_user,
vo_mysql_pg_password,
vo_mysql_pg_db,
product_gallery_url=None
):
result_list = []

try:
with connect(
host=vo_mysql_pg_host,
user=vo_mysql_pg_user,
password=vo_mysql_pg_password,
database=vo_mysql_pg_db
) as connection:
create_db_query = parsed_query_obj.get('mysql_query')
with connection.cursor(dictionary=True) as cursor:
cursor.execute(create_db_query)
for row in cursor:
if product_gallery_url is not None:
path = row.get('path', None)
if path is not None:
if path.startswith('/'):
path = path[1:]
row['path'] = os.path.join(product_gallery_url, path)
path_alias = row.get('path_alias', None)
if path_alias is not None:
if path_alias.startswith('/'):
path_alias = path_alias[1:]
row['path_alias'] = os.path.join(product_gallery_url, path_alias)
result_list.append(row)
# result_obj = cursor.fetchall()


except Error as e:
sentry.capture_message(f"Error when connecting to MySQL: {str(e)}")
logger.error(f"Error when connecting to MySQL: {str(e)}")

except Exception as e:
sentry.capture_message(f"Error when performing the mysql query to the product_gallery DB: {str(e)}")
logger.error(f"Error when performing the mysql query to the product_gallery DB: {str(e)}")

finally:
if connection is not None and connection.is_connected():
connection.close()
logger.info('MySQL connection closed')

return result_list
8 changes: 7 additions & 1 deletion cdci_data_analysis/config_dir/conf_env.yml.example
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,10 @@ dispatcher:
# url for the conversion of a given time, in UTC format, to the correspondent REVNUM
converttime_revnum_service_url: COVERTTIME_REVNUM_SERVICE_URL


# virtual observatory related configurations (eg mysql credentials)
vo_options:
# mysql credentials
vo_mysql_pg_host: MYSQL_PG_HOST
vo_mysql_pg_user: MYSQL_PG_USER
vo_mysql_pg_password: MYSQL_PG_PASSWORD
vo_mysql_pg_db: MYSQL_PG_DB
12 changes: 12 additions & 0 deletions cdci_data_analysis/configurer.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ def __init__(self, cfg_dict, origin=None):
disp_dict.get('renku_options', {}).get('renku_gitlab_repository_url', None),
disp_dict.get('renku_options', {}).get('renku_base_project_url', None),
disp_dict.get('renku_options', {}).get('ssh_key_path', None),
disp_dict.get('vo_options', {}).get('vo_mysql_pg_host', None),
disp_dict.get('vo_options', {}).get('vo_mysql_pg_user', None),
disp_dict.get('vo_options', {}).get('vo_mysql_pg_password', None),
disp_dict.get('vo_options', {}).get('vo_mysql_pg_db', None),
)

# not used?
Expand Down Expand Up @@ -344,6 +348,10 @@ def set_conf_dispatcher(self,
renku_gitlab_repository_url,
renku_base_project_url,
renku_gitlab_ssh_key_path,
vo_mysql_pg_host,
vo_mysql_pg_user,
vo_mysql_pg_password,
vo_mysql_pg_db
):
# Generic to dispatcher
#print(dispatcher_url, dispatcher_port)
Expand Down Expand Up @@ -395,6 +403,10 @@ def set_conf_dispatcher(self,
self.renku_gitlab_repository_url = renku_gitlab_repository_url
self.renku_gitlab_ssh_key_path = renku_gitlab_ssh_key_path
self.renku_base_project_url = renku_base_project_url
self.vo_mysql_pg_host = vo_mysql_pg_host
self.vo_mysql_pg_user = vo_mysql_pg_user
self.vo_mysql_pg_password = vo_mysql_pg_password
self.vo_mysql_pg_db = vo_mysql_pg_db

def get_data_serve_conf(self, instr_name):
if instr_name in self.data_server_conf_dict.keys():
Expand Down
33 changes: 32 additions & 1 deletion cdci_data_analysis/flask_app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import time as _time
from urllib.parse import urlencode, urlparse

from cdci_data_analysis.analysis import drupal_helper, tokenHelper, renku_helper, email_helper, matrix_helper
from cdci_data_analysis.analysis import drupal_helper, tokenHelper, renku_helper, email_helper, matrix_helper, ivoa_helper
from .logstash import logstash_message
from .schemas import QueryOutJSON, dispatcher_strict_validate
from marshmallow.exceptions import ValidationError
Expand Down Expand Up @@ -415,6 +415,37 @@
"Our team is notified and is working on it.")


@app.route('/run_adql_query')
def run_adql_query():
logger.info("request.args: %s ", request.args)
Fixed Show fixed Hide fixed

token = request.args.get('token', None)
app_config = app.config.get('conf')
secret_key = app_config.secret_key

output, output_code = tokenHelper.validate_token_from_request(token=token, secret_key=secret_key,
required_roles=['ivoa_user'],
action="run an ADQL query")

if output_code is not None:
return make_response(output, output_code)

adql_query = request.args.get('adql_query', None)
vo_mysql_pg_host = app_config.vo_mysql_pg_host
vo_mysql_pg_user = app_config.vo_mysql_pg_user
vo_mysql_pg_password = app_config.vo_mysql_pg_password
vo_mysql_pg_db = app_config.vo_mysql_pg_db
product_gallery_url = app_config.product_gallery_url

result_query = ivoa_helper.run_ivoa_query(adql_query,
vo_mysql_pg_host=vo_mysql_pg_host,
vo_mysql_pg_user=vo_mysql_pg_user,
vo_mysql_pg_password=vo_mysql_pg_password,
vo_mysql_pg_db=vo_mysql_pg_db,
product_gallery_url=product_gallery_url)

return jsonify(result_query)


@app.route('/run_analysis', methods=['POST', 'GET'])
def run_analysis():
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ GitPython
nbformat
sentry-sdk
pytest-sentry
sqlparse
queryparser-python3
-e git+https://github.com/oda-hub/oda_api.git#egg=oda_api

MarkupSafe==2.0.1
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
"black>=22.10.0",
"bs4",
"GitPython",
"sqlparse",
"queryparser-python3",
"nbformat",
"giturlparse",
"sentry-sdk",
Expand Down
Loading