diff --git a/.jupyter/api_query/__init__.py b/.jupyter/api_query/__init__.py index 6856a5d62ced5a39416767fdee3f6b28e00ad8c5..125c6c436bf1a5a5bfd5c3c754895194c4450090 100644 --- a/.jupyter/api_query/__init__.py +++ b/.jupyter/api_query/__init__.py @@ -41,7 +41,6 @@ from api_query.models.query_dto import QueryDto from api_query.models.query_result_dto import QueryResultDto from api_query.models.table_csv_delete_dto import TableCsvDeleteDto from api_query.models.table_csv_dto import TableCsvDto -from api_query.models.table_csv_update_dto import TableCsvUpdateDto from api_query.models.table_dto import TableDto from api_query.models.table_history_dto import TableHistoryDto from api_query.models.user_dto import UserDto diff --git a/.jupyter/api_query/api/table_data_endpoint_api.py b/.jupyter/api_query/api/table_data_endpoint_api.py index 5a4d371279e1293b0c88d9f060d8a2260c455f3c..5cfffc839b17b76394c5abd0592da4b8df92e7fd 100644 --- a/.jupyter/api_query/api/table_data_endpoint_api.py +++ b/.jupyter/api_query/api/table_data_endpoint_api.py @@ -408,7 +408,7 @@ class TableDataEndpointApi(object): :param int id: (required) :param int database_id: (required) :param int table_id: (required) - :return: int + :return: None If the method is called asynchronously, returns the request thread. """ @@ -432,7 +432,7 @@ class TableDataEndpointApi(object): :param int id: (required) :param int database_id: (required) :param int table_id: (required) - :return: int + :return: None If the method is called asynchronously, returns the request thread. """ @@ -508,7 +508,7 @@ class TableDataEndpointApi(object): body=body_params, post_params=form_params, files=local_var_files, - response_type='int', # noqa: E501 + response_type=None, # noqa: E501 auth_settings=auth_settings, async_req=params.get('async_req'), _return_http_data_only=params.get('_return_http_data_only'), @@ -529,7 +529,7 @@ class TableDataEndpointApi(object): :param int id: (required) :param int database_id: (required) :param int table_id: (required) - :return: int + :return: None If the method is called asynchronously, returns the request thread. """ @@ -553,7 +553,7 @@ class TableDataEndpointApi(object): :param int id: (required) :param int database_id: (required) :param int table_id: (required) - :return: int + :return: None If the method is called asynchronously, returns the request thread. """ @@ -629,128 +629,7 @@ class TableDataEndpointApi(object): body=body_params, post_params=form_params, files=local_var_files, - response_type='int', # noqa: E501 - auth_settings=auth_settings, - async_req=params.get('async_req'), - _return_http_data_only=params.get('_return_http_data_only'), - _preload_content=params.get('_preload_content', True), - _request_timeout=params.get('_request_timeout'), - collection_formats=collection_formats) - - def update(self, body, id, database_id, table_id, **kwargs): # noqa: E501 - """Update data # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - >>> thread = api.update(body, id, database_id, table_id, async_req=True) - >>> result = thread.get() - - :param async_req bool - :param TableCsvUpdateDto body: (required) - :param int id: (required) - :param int database_id: (required) - :param int table_id: (required) - :return: int - If the method is called asynchronously, - returns the request thread. - """ - kwargs['_return_http_data_only'] = True - if kwargs.get('async_req'): - return self.update_with_http_info(body, id, database_id, table_id, **kwargs) # noqa: E501 - else: - (data) = self.update_with_http_info(body, id, database_id, table_id, **kwargs) # noqa: E501 - return data - - def update_with_http_info(self, body, id, database_id, table_id, **kwargs): # noqa: E501 - """Update data # noqa: E501 - - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - >>> thread = api.update_with_http_info(body, id, database_id, table_id, async_req=True) - >>> result = thread.get() - - :param async_req bool - :param TableCsvUpdateDto body: (required) - :param int id: (required) - :param int database_id: (required) - :param int table_id: (required) - :return: int - If the method is called asynchronously, - returns the request thread. - """ - - all_params = ['body', 'id', 'database_id', 'table_id'] # noqa: E501 - all_params.append('async_req') - all_params.append('_return_http_data_only') - all_params.append('_preload_content') - all_params.append('_request_timeout') - - params = locals() - for key, val in six.iteritems(params['kwargs']): - if key not in all_params: - raise TypeError( - "Got an unexpected keyword argument '%s'" - " to method update" % key - ) - params[key] = val - del params['kwargs'] - # verify the required parameter 'body' is set - if ('body' not in params or - params['body'] is None): - raise ValueError("Missing the required parameter `body` when calling `update`") # noqa: E501 - # verify the required parameter 'id' is set - if ('id' not in params or - params['id'] is None): - raise ValueError("Missing the required parameter `id` when calling `update`") # noqa: E501 - # verify the required parameter 'database_id' is set - if ('database_id' not in params or - params['database_id'] is None): - raise ValueError("Missing the required parameter `database_id` when calling `update`") # noqa: E501 - # verify the required parameter 'table_id' is set - if ('table_id' not in params or - params['table_id'] is None): - raise ValueError("Missing the required parameter `table_id` when calling `update`") # noqa: E501 - - collection_formats = {} - - path_params = {} - if 'id' in params: - path_params['id'] = params['id'] # noqa: E501 - if 'database_id' in params: - path_params['databaseId'] = params['database_id'] # noqa: E501 - if 'table_id' in params: - path_params['tableId'] = params['table_id'] # noqa: E501 - - query_params = [] - - header_params = {} - - form_params = [] - local_var_files = {} - - body_params = None - if 'body' in params: - body_params = params['body'] - # HTTP header `Accept` - header_params['Accept'] = self.api_client.select_header_accept( - ['*/*']) # noqa: E501 - - # HTTP header `Content-Type` - header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 - ['application/json']) # noqa: E501 - - # Authentication setting - auth_settings = ['bearerAuth'] # noqa: E501 - - return self.api_client.call_api( - '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'PUT', - path_params, - query_params, - header_params, - body=body_params, - post_params=form_params, - files=local_var_files, - response_type='int', # noqa: E501 + response_type=None, # noqa: E501 auth_settings=auth_settings, async_req=params.get('async_req'), _return_http_data_only=params.get('_return_http_data_only'), diff --git a/.jupyter/api_query/models/__init__.py b/.jupyter/api_query/models/__init__.py index 7aa0df469900aaa50e5a3c84087aed997ebf9324..2ce6fd387583c2a36c1cf6d2f4cfda8c070b0e4a 100644 --- a/.jupyter/api_query/models/__init__.py +++ b/.jupyter/api_query/models/__init__.py @@ -31,7 +31,6 @@ from api_query.models.query_dto import QueryDto from api_query.models.query_result_dto import QueryResultDto from api_query.models.table_csv_delete_dto import TableCsvDeleteDto from api_query.models.table_csv_dto import TableCsvDto -from api_query.models.table_csv_update_dto import TableCsvUpdateDto from api_query.models.table_dto import TableDto from api_query.models.table_history_dto import TableHistoryDto from api_query.models.user_dto import UserDto diff --git a/.jupyter/test.ipynb b/.jupyter/test.ipynb index d54a0256c97b3bc70c668de24edae06a4a607ed6..4c089d963961a0f28569fa0705c94948ad7239d2 100644 --- a/.jupyter/test.ipynb +++ b/.jupyter/test.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 107, + "execution_count": 118, "metadata": { "pycharm": { "name": "#%%\n" @@ -64,7 +64,7 @@ }, { "cell_type": "code", - "execution_count": 108, + "execution_count": 119, "metadata": { "pycharm": { "name": "#%%\n" @@ -115,7 +115,7 @@ }, { "cell_type": "code", - "execution_count": 109, + "execution_count": 120, "outputs": [], "source": [ "response = authentication.authenticate_user1({\n", @@ -154,13 +154,13 @@ }, { "cell_type": "code", - "execution_count": 110, + "execution_count": 121, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'created': datetime.datetime(2022, 7, 23, 12, 10, 34, 731000, tzinfo=tzutc()),\n", + "{'created': datetime.datetime(2022, 7, 25, 15, 15, 12, 611000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'authorities': None,\n", " 'email': 'someone@example.com',\n", @@ -172,11 +172,11 @@ " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'user'},\n", - " 'hash': 'a7ac6834e9c29d93a0c7049707bbb1350cbd87d9d2836fc4b19dfadc8bbe9724',\n", + " 'hash': 'eb62216417341804986f04e6a5c06e2983b16188632d4a3332df6d4166105026',\n", " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality-741b9886-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'internal_name': 'fda-userdb-airquality-93f209d0-0c2c-11ed-8e19-276c36d4e620',\n", " 'is_public': None,\n", - " 'name': 'Airquality 741b9886-0a80-11ed-95b6-4f6e5b6c5022'}\n" + " 'name': 'Airquality 93f209d0-0c2c-11ed-8e19-276c36d4e620'}\n" ] } ], @@ -210,13 +210,13 @@ }, { "cell_type": "code", - "execution_count": 111, + "execution_count": 122, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'created': datetime.datetime(2022, 7, 23, 12, 10, 34, 731000, tzinfo=tzutc()),\n", + "{'created': datetime.datetime(2022, 7, 25, 15, 15, 12, 611000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'authorities': None,\n", " 'email': 'someone@example.com',\n", @@ -228,11 +228,11 @@ " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'user'},\n", - " 'hash': 'a7ac6834e9c29d93a0c7049707bbb1350cbd87d9d2836fc4b19dfadc8bbe9724',\n", + " 'hash': 'eb62216417341804986f04e6a5c06e2983b16188632d4a3332df6d4166105026',\n", " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality-741b9886-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'internal_name': 'fda-userdb-airquality-93f209d0-0c2c-11ed-8e19-276c36d4e620',\n", " 'is_public': None,\n", - " 'name': 'Airquality 741b9886-0a80-11ed-95b6-4f6e5b6c5022'}\n" + " 'name': 'Airquality 93f209d0-0c2c-11ed-8e19-276c36d4e620'}\n" ] } ], @@ -264,13 +264,13 @@ }, { "cell_type": "code", - "execution_count": 112, + "execution_count": 123, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'container': {'created': datetime.datetime(2022, 7, 23, 12, 10, 34, 731000, tzinfo=tzutc()),\n", + "{'container': {'created': datetime.datetime(2022, 7, 25, 15, 15, 12, 611000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'authorities': None,\n", " 'email': 'someone@example.com',\n", @@ -282,12 +282,12 @@ " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'user'},\n", - " 'hash': 'a7ac6834e9c29d93a0c7049707bbb1350cbd87d9d2836fc4b19dfadc8bbe9724',\n", + " 'hash': 'eb62216417341804986f04e6a5c06e2983b16188632d4a3332df6d4166105026',\n", " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality-741b9886-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'internal_name': 'fda-userdb-airquality-93f209d0-0c2c-11ed-8e19-276c36d4e620',\n", " 'is_public': None,\n", - " 'name': 'Airquality 741b9886-0a80-11ed-95b6-4f6e5b6c5022'},\n", - " 'created': datetime.datetime(2022, 7, 23, 12, 10, 48, 550000, tzinfo=tzutc()),\n", + " 'name': 'Airquality 93f209d0-0c2c-11ed-8e19-276c36d4e620'},\n", + " 'created': datetime.datetime(2022, 7, 25, 15, 15, 19, 123000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'authorities': None,\n", " 'email': 'someone@example.com',\n", @@ -303,7 +303,7 @@ " 'engine': 'mariadb:10.5',\n", " 'id': 1,\n", " 'is_public': True,\n", - " 'name': 'Airquality 7c5e7aea-0a80-11ed-95b6-4f6e5b6c5022'}\n" + " 'name': 'Airquality 97bae546-0c2c-11ed-8e19-276c36d4e620'}\n" ] } ], @@ -337,25 +337,25 @@ }, { "cell_type": "code", - "execution_count": 113, + "execution_count": 124, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'contact': None,\n", - " 'container': {'created': datetime.datetime(2022, 7, 23, 12, 10, 34, 731000, tzinfo=tzutc()),\n", + " 'container': {'created': datetime.datetime(2022, 7, 25, 15, 15, 12, 611000, tzinfo=tzutc()),\n", " 'databases': None,\n", - " 'hash': 'a7ac6834e9c29d93a0c7049707bbb1350cbd87d9d2836fc4b19dfadc8bbe9724',\n", + " 'hash': 'eb62216417341804986f04e6a5c06e2983b16188632d4a3332df6d4166105026',\n", " 'id': 1,\n", " 'image': {'id': 1, 'repository': 'mariadb', 'tag': '10.5'},\n", - " 'internal_name': 'fda-userdb-airquality-741b9886-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'internal_name': 'fda-userdb-airquality-93f209d0-0c2c-11ed-8e19-276c36d4e620',\n", " 'ip_address': None,\n", " 'is_public': None,\n", - " 'name': 'Airquality 741b9886-0a80-11ed-95b6-4f6e5b6c5022',\n", - " 'port': 35981,\n", + " 'name': 'Airquality 93f209d0-0c2c-11ed-8e19-276c36d4e620',\n", + " 'port': 65245,\n", " 'state': None},\n", - " 'created': datetime.datetime(2022, 7, 23, 12, 10, 48, 550000, tzinfo=tzutc()),\n", + " 'created': datetime.datetime(2022, 7, 25, 15, 15, 19, 123000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'authorities': None,\n", " 'containers': None,\n", @@ -372,52 +372,52 @@ " 'username': 'user'},\n", " 'deleted': None,\n", " 'description': 'Hourly measurements in Zürich, Switzerland',\n", - " 'exchange': 'airquality_7c5e7aea-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'exchange': 'airquality_97bae546-0c2c-11ed-8e19-276c36d4e620',\n", " 'id': 1,\n", " 'image': {'compiled': None,\n", - " 'date_formats': [{'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 186000, tzinfo=tzutc()),\n", + " 'date_formats': [{'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 649000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d',\n", " 'example': '2022-01-30',\n", " 'has_time': False,\n", " 'id': 1,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 192000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 655000, tzinfo=tzutc()),\n", " 'database_format': '%d.%c.%Y',\n", " 'example': '30.01.2022',\n", " 'has_time': False,\n", " 'id': 2,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 195000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 658000, tzinfo=tzutc()),\n", " 'database_format': '%d.%c.%y',\n", " 'example': '30.01.22',\n", " 'has_time': False,\n", " 'id': 3,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 198000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 660000, tzinfo=tzutc()),\n", " 'database_format': '%c/%d/%Y',\n", " 'example': '01/30/2022',\n", " 'has_time': False,\n", " 'id': 4,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 201000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 662000, tzinfo=tzutc()),\n", " 'database_format': '%c/%d/%y',\n", " 'example': '01/30/22',\n", " 'has_time': False,\n", " 'id': 5,\n", " 'unix_format': 'yyyy-MM-dd'},\n", - " {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 203000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 664000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d %H:%i:%S.%f',\n", " 'example': '2022-01-30 13:44:25.0',\n", " 'has_time': True,\n", " 'id': 6,\n", " 'unix_format': 'yyyy-MM-dd HH:mm:ss.SSSSSS'},\n", - " {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 205000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 667000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d %H:%i:%S',\n", " 'example': '2022-01-30 13:44:25',\n", " 'has_time': True,\n", " 'id': 7,\n", " 'unix_format': 'yyyy-MM-dd HH:mm:ss'},\n", - " {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 208000, tzinfo=tzutc()),\n", + " {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 669000, tzinfo=tzutc()),\n", " 'database_format': '%d.%c.%Y %H:%i:%S',\n", " 'example': '30.01.2022 13:44:25',\n", " 'has_time': True,\n", @@ -448,11 +448,11 @@ " 'repository': 'mariadb',\n", " 'size': None,\n", " 'tag': '10.5'},\n", - " 'internal_name': 'airquality_7c5e7aea-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'internal_name': 'airquality_97bae546-0c2c-11ed-8e19-276c36d4e620',\n", " 'is_public': True,\n", " 'language': None,\n", " 'license': None,\n", - " 'name': 'Airquality 7c5e7aea-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'name': 'Airquality 97bae546-0c2c-11ed-8e19-276c36d4e620',\n", " 'publication': None,\n", " 'publisher': None,\n", " 'subjects': [],\n", @@ -486,13 +486,13 @@ }, { "cell_type": "code", - "execution_count": 114, + "execution_count": 125, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'container': {'created': datetime.datetime(2022, 7, 23, 12, 10, 34, 731000, tzinfo=tzutc()),\n", + "{'container': {'created': datetime.datetime(2022, 7, 25, 15, 15, 12, 611000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'authorities': None,\n", " 'email': 'someone@example.com',\n", @@ -504,12 +504,12 @@ " 'titles_after': None,\n", " 'titles_before': None,\n", " 'username': 'user'},\n", - " 'hash': 'a7ac6834e9c29d93a0c7049707bbb1350cbd87d9d2836fc4b19dfadc8bbe9724',\n", + " 'hash': 'eb62216417341804986f04e6a5c06e2983b16188632d4a3332df6d4166105026',\n", " 'id': 1,\n", - " 'internal_name': 'fda-userdb-airquality-741b9886-0a80-11ed-95b6-4f6e5b6c5022',\n", + " 'internal_name': 'fda-userdb-airquality-93f209d0-0c2c-11ed-8e19-276c36d4e620',\n", " 'is_public': None,\n", - " 'name': 'Airquality 741b9886-0a80-11ed-95b6-4f6e5b6c5022'},\n", - " 'created': datetime.datetime(2022, 7, 23, 12, 10, 48, 550000, tzinfo=tzutc()),\n", + " 'name': 'Airquality 93f209d0-0c2c-11ed-8e19-276c36d4e620'},\n", + " 'created': datetime.datetime(2022, 7, 25, 15, 15, 19, 123000, tzinfo=tzutc()),\n", " 'creator': {'affiliation': None,\n", " 'authorities': None,\n", " 'email': 'someone@example.com',\n", @@ -534,7 +534,7 @@ " 'engine': 'mariadb:10.5',\n", " 'id': 1,\n", " 'is_public': True,\n", - " 'name': 'Airquality 7c5e7aea-0a80-11ed-95b6-4f6e5b6c5022'}\n" + " 'name': 'Airquality 97bae546-0c2c-11ed-8e19-276c36d4e620'}\n" ] } ], @@ -573,7 +573,7 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": 126, "outputs": [ { "name": "stdout", @@ -591,8 +591,8 @@ " 'titles_before': None,\n", " 'username': 'user'},\n", " 'id': 1,\n", - " 'internal_name': 'airquality_8138a716-0a80-11ed-95b6-4f6e5b6c5022',\n", - " 'name': 'Airquality 8138a716-0a80-11ed-95b6-4f6e5b6c5022'}\n" + " 'internal_name': 'airquality_97bae547-0c2c-11ed-8e19-276c36d4e620',\n", + " 'name': 'Airquality 97bae547-0c2c-11ed-8e19-276c36d4e620'}\n" ] } ], @@ -669,7 +669,7 @@ }, { "cell_type": "code", - "execution_count": 116, + "execution_count": 127, "outputs": [ { "name": "stdout", @@ -695,7 +695,7 @@ " 'check_expression': None,\n", " 'column_concept': None,\n", " 'column_type': 'date',\n", - " 'date_format': {'created_at': datetime.datetime(2022, 7, 23, 12, 8, 54, 186000, tzinfo=tzutc()),\n", + " 'date_format': {'created_at': datetime.datetime(2022, 7, 25, 15, 3, 44, 649000, tzinfo=tzutc()),\n", " 'database_format': '%Y-%c-%d',\n", " 'example': '2022-01-30',\n", " 'has_time': False,\n", @@ -808,12 +808,12 @@ " 'name': 'Status',\n", " 'references': None,\n", " 'unique': False}],\n", - " 'created': datetime.datetime(2022, 7, 23, 12, 10, 56, 764000, tzinfo=tzutc()),\n", + " 'created': datetime.datetime(2022, 7, 25, 15, 15, 20, 946000, tzinfo=tzutc()),\n", " 'description': 'Airquality in Zürich, Switzerland',\n", " 'id': 1,\n", - " 'internal_name': 'airquality_8138a716-0a80-11ed-95b6-4f6e5b6c5022',\n", - " 'name': 'Airquality 8138a716-0a80-11ed-95b6-4f6e5b6c5022',\n", - " 'topic': 'airquality_8138a716-0a80-11ed-95b6-4f6e5b6c5022'}\n" + " 'internal_name': 'airquality_97bae547-0c2c-11ed-8e19-276c36d4e620',\n", + " 'name': 'Airquality 97bae547-0c2c-11ed-8e19-276c36d4e620',\n", + " 'topic': 'airquality_97bae547-0c2c-11ed-8e19-276c36d4e620'}\n" ] } ], @@ -844,13 +844,13 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 128, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "210192\n" + "None\n" ] } ], @@ -885,34 +885,34 @@ }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 129, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'id': 1,\n", - " 'result': [{'Date': '2021-01-01T00:00:00Z',\n", - " 'Interval': 'h1',\n", - " 'Location': 'Schimmelstrasse',\n", - " 'Parameter': 'NOx',\n", - " 'Status': 'tentative',\n", - " 'Unit': 'ppb',\n", - " 'Value': 41.66},\n", - " {'Date': '2021-01-01T00:00:00Z',\n", - " 'Interval': 'h1',\n", - " 'Location': 'Schimmelstrasse',\n", - " 'Parameter': 'NO',\n", - " 'Status': 'tentative',\n", - " 'Unit': 'µg/m3',\n", - " 'Value': 21.64},\n", - " {'Date': '2021-01-01T00:00:00Z',\n", - " 'Interval': 'h1',\n", - " 'Location': 'Schimmelstrasse',\n", - " 'Parameter': 'NO2',\n", - " 'Status': 'tentative',\n", - " 'Unit': 'µg/m3',\n", - " 'Value': 46.49}],\n", + " 'result': [{'date': '2021-01-01T00:00:00Z',\n", + " 'interval': 'h1',\n", + " 'location': 'Schimmelstrasse',\n", + " 'parameter': 'NOx',\n", + " 'status': 'tentative',\n", + " 'unit': 'ppb',\n", + " 'value': 41.66},\n", + " {'date': '2021-01-01T00:00:00Z',\n", + " 'interval': 'h1',\n", + " 'location': 'Schimmelstrasse',\n", + " 'parameter': 'NO',\n", + " 'status': 'tentative',\n", + " 'unit': 'µg/m3',\n", + " 'value': 21.64},\n", + " {'date': '2021-01-01T00:00:00Z',\n", + " 'interval': 'h1',\n", + " 'location': 'Schimmelstrasse',\n", + " 'parameter': 'NO2',\n", + " 'status': 'tentative',\n", + " 'unit': 'µg/m3',\n", + " 'value': 46.49}],\n", " 'result_number': 52548}\n" ] } @@ -945,16 +945,16 @@ }, { "cell_type": "code", - "execution_count": 98, + "execution_count": 130, "outputs": [ { "ename": "ApiException", - "evalue": "(400)\nReason: Bad Request\nHTTP response headers: HTTPHeaderDict({'transfer-encoding': 'chunked', 'Vary': 'Origin, Access-Control-Request-Method, Access-Control-Request-Headers', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'X-Frame-Options': 'DENY', 'Content-Type': 'application/json', 'Date': 'Sat, 23 Jul 2022 11:16:44 GMT'})\nHTTP response body: b'{\"status\":\"BAD_REQUEST\",\"message\":\"Query not valid for this database\",\"code\":\"error.query.malformed\"}'\n", + "evalue": "(400)\nReason: Bad Request\nHTTP response headers: HTTPHeaderDict({'transfer-encoding': 'chunked', 'Vary': 'Origin, Access-Control-Request-Method, Access-Control-Request-Headers', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'X-Frame-Options': 'DENY', 'Content-Type': 'application/json', 'Date': 'Mon, 25 Jul 2022 15:15:24 GMT'})\nHTTP response body: b'{\"status\":\"BAD_REQUEST\",\"message\":\"Failed to execute and map time-versioned query\",\"code\":\"error.table.malformed\"}'\n", "output_type": "error", "traceback": [ "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", "\u001B[0;31mApiException\u001B[0m Traceback (most recent call last)", - "Input \u001B[0;32mIn [98]\u001B[0m, in \u001B[0;36m<cell line: 1>\u001B[0;34m()\u001B[0m\n\u001B[0;32m----> 1\u001B[0m response \u001B[38;5;241m=\u001B[39m \u001B[43mquery\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mexecute\u001B[49m\u001B[43m(\u001B[49m\u001B[43m{\u001B[49m\n\u001B[1;32m 2\u001B[0m \u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mstatement\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mselect `date`, `location`, `parameter`, `interval`, `unit`, `value`, `status` from `\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m \u001B[49m\u001B[38;5;241;43m+\u001B[39;49m\u001B[43m \u001B[49m\u001B[43mtable_internal_name\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m+\u001B[39;49m\u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43m` where `foo` = \u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mbar\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\n\u001B[1;32m 3\u001B[0m \u001B[43m}\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcontainer_id\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mdatabase_id\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpage\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m0\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43msize\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m3\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m 4\u001B[0m \u001B[38;5;28mprint\u001B[39m(response)\n", + "Input \u001B[0;32mIn [130]\u001B[0m, in \u001B[0;36m<cell line: 1>\u001B[0;34m()\u001B[0m\n\u001B[0;32m----> 1\u001B[0m response \u001B[38;5;241m=\u001B[39m \u001B[43mquery\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mexecute\u001B[49m\u001B[43m(\u001B[49m\u001B[43m{\u001B[49m\n\u001B[1;32m 2\u001B[0m \u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mstatement\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m:\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mselect `date`, `location`, `parameter`, `interval`, `unit`, `value`, `status` from `\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m \u001B[49m\u001B[38;5;241;43m+\u001B[39;49m\u001B[43m \u001B[49m\u001B[43mtable_internal_name\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m+\u001B[39;49m\u001B[43m \u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43m` where `foo` = \u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mbar\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\n\u001B[1;32m 3\u001B[0m \u001B[43m}\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcontainer_id\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mdatabase_id\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpage\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m0\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43msize\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m3\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m 4\u001B[0m \u001B[38;5;28mprint\u001B[39m(response)\n", "File \u001B[0;32m~/Projects/fda-services/.jupyter/api_query/api/query_endpoint_api.py:57\u001B[0m, in \u001B[0;36mQueryEndpointApi.execute\u001B[0;34m(self, body, id, database_id, **kwargs)\u001B[0m\n\u001B[1;32m 55\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mexecute_with_http_info(body, \u001B[38;5;28mid\u001B[39m, database_id, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs) \u001B[38;5;66;03m# noqa: E501\u001B[39;00m\n\u001B[1;32m 56\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m---> 57\u001B[0m (data) \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mexecute_with_http_info\u001B[49m\u001B[43m(\u001B[49m\u001B[43mbody\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mid\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mdatabase_id\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m \u001B[38;5;66;03m# noqa: E501\u001B[39;00m\n\u001B[1;32m 58\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m data\n", "File \u001B[0;32m~/Projects/fda-services/.jupyter/api_query/api/query_endpoint_api.py:140\u001B[0m, in \u001B[0;36mQueryEndpointApi.execute_with_http_info\u001B[0;34m(self, body, id, database_id, **kwargs)\u001B[0m\n\u001B[1;32m 137\u001B[0m \u001B[38;5;66;03m# Authentication setting\u001B[39;00m\n\u001B[1;32m 138\u001B[0m auth_settings \u001B[38;5;241m=\u001B[39m [\u001B[38;5;124m'\u001B[39m\u001B[38;5;124mbearerAuth\u001B[39m\u001B[38;5;124m'\u001B[39m] \u001B[38;5;66;03m# noqa: E501\u001B[39;00m\n\u001B[0;32m--> 140\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mapi_client\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mcall_api\u001B[49m\u001B[43m(\u001B[49m\n\u001B[1;32m 141\u001B[0m \u001B[43m \u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43m/api/container/\u001B[39;49m\u001B[38;5;132;43;01m{id}\u001B[39;49;00m\u001B[38;5;124;43m/database/\u001B[39;49m\u001B[38;5;132;43;01m{databaseId}\u001B[39;49;00m\u001B[38;5;124;43m/query\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mPUT\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m,\u001B[49m\n\u001B[1;32m 142\u001B[0m \u001B[43m \u001B[49m\u001B[43mpath_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 143\u001B[0m \u001B[43m \u001B[49m\u001B[43mquery_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 144\u001B[0m \u001B[43m \u001B[49m\u001B[43mheader_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 145\u001B[0m \u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mbody_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 146\u001B[0m \u001B[43m \u001B[49m\u001B[43mpost_params\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mform_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 147\u001B[0m \u001B[43m \u001B[49m\u001B[43mfiles\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mlocal_var_files\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 148\u001B[0m \u001B[43m \u001B[49m\u001B[43mresponse_type\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mQueryResultDto\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;66;43;03m# noqa: E501\u001B[39;49;00m\n\u001B[1;32m 149\u001B[0m \u001B[43m \u001B[49m\u001B[43mauth_settings\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mauth_settings\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 150\u001B[0m \u001B[43m \u001B[49m\u001B[43masync_req\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mparams\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mget\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43masync_req\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 151\u001B[0m \u001B[43m \u001B[49m\u001B[43m_return_http_data_only\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mparams\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mget\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43m_return_http_data_only\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 152\u001B[0m \u001B[43m \u001B[49m\u001B[43m_preload_content\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mparams\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mget\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43m_preload_content\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43;01mTrue\u001B[39;49;00m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 153\u001B[0m \u001B[43m \u001B[49m\u001B[43m_request_timeout\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mparams\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mget\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43m_request_timeout\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 154\u001B[0m \u001B[43m \u001B[49m\u001B[43mcollection_formats\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mcollection_formats\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/Projects/fda-services/.jupyter/api_query/api_client.py:316\u001B[0m, in \u001B[0;36mApiClient.call_api\u001B[0;34m(self, resource_path, method, path_params, query_params, header_params, body, post_params, files, response_type, auth_settings, async_req, _return_http_data_only, collection_formats, _preload_content, _request_timeout)\u001B[0m\n\u001B[1;32m 279\u001B[0m \u001B[38;5;124;03m\"\"\"Makes the HTTP request (synchronous) and returns deserialized data.\u001B[39;00m\n\u001B[1;32m 280\u001B[0m \n\u001B[1;32m 281\u001B[0m \u001B[38;5;124;03mTo make an async request, set the async_req parameter.\u001B[39;00m\n\u001B[0;32m (...)\u001B[0m\n\u001B[1;32m 313\u001B[0m \u001B[38;5;124;03m then the method will return the response directly.\u001B[39;00m\n\u001B[1;32m 314\u001B[0m \u001B[38;5;124;03m\"\"\"\u001B[39;00m\n\u001B[1;32m 315\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m async_req:\n\u001B[0;32m--> 316\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m__call_api\u001B[49m\u001B[43m(\u001B[49m\u001B[43mresource_path\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mmethod\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 317\u001B[0m \u001B[43m \u001B[49m\u001B[43mpath_params\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mquery_params\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mheader_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 318\u001B[0m \u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mpost_params\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mfiles\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 319\u001B[0m \u001B[43m \u001B[49m\u001B[43mresponse_type\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mauth_settings\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 320\u001B[0m \u001B[43m \u001B[49m\u001B[43m_return_http_data_only\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mcollection_formats\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 321\u001B[0m \u001B[43m \u001B[49m\u001B[43m_preload_content\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m_request_timeout\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 322\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m 323\u001B[0m thread \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mpool\u001B[38;5;241m.\u001B[39mapply_async(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m__call_api, (resource_path,\n\u001B[1;32m 324\u001B[0m method, path_params, query_params,\n\u001B[1;32m 325\u001B[0m header_params, body,\n\u001B[0;32m (...)\u001B[0m\n\u001B[1;32m 329\u001B[0m collection_formats,\n\u001B[1;32m 330\u001B[0m _preload_content, _request_timeout))\n", @@ -962,7 +962,7 @@ "File \u001B[0;32m~/Projects/fda-services/.jupyter/api_query/api_client.py:366\u001B[0m, in \u001B[0;36mApiClient.request\u001B[0;34m(self, method, url, query_params, headers, post_params, body, _preload_content, _request_timeout)\u001B[0m\n\u001B[1;32m 358\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrest_client\u001B[38;5;241m.\u001B[39mPOST(url,\n\u001B[1;32m 359\u001B[0m query_params\u001B[38;5;241m=\u001B[39mquery_params,\n\u001B[1;32m 360\u001B[0m headers\u001B[38;5;241m=\u001B[39mheaders,\n\u001B[0;32m (...)\u001B[0m\n\u001B[1;32m 363\u001B[0m _request_timeout\u001B[38;5;241m=\u001B[39m_request_timeout,\n\u001B[1;32m 364\u001B[0m body\u001B[38;5;241m=\u001B[39mbody)\n\u001B[1;32m 365\u001B[0m \u001B[38;5;28;01melif\u001B[39;00m method \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mPUT\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n\u001B[0;32m--> 366\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrest_client\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mPUT\u001B[49m\u001B[43m(\u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 367\u001B[0m \u001B[43m \u001B[49m\u001B[43mquery_params\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mquery_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 368\u001B[0m \u001B[43m \u001B[49m\u001B[43mheaders\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mheaders\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 369\u001B[0m \u001B[43m \u001B[49m\u001B[43mpost_params\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mpost_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 370\u001B[0m \u001B[43m \u001B[49m\u001B[43m_preload_content\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m_preload_content\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 371\u001B[0m \u001B[43m \u001B[49m\u001B[43m_request_timeout\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m_request_timeout\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 372\u001B[0m \u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mbody\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 373\u001B[0m \u001B[38;5;28;01melif\u001B[39;00m method \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mPATCH\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n\u001B[1;32m 374\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mrest_client\u001B[38;5;241m.\u001B[39mPATCH(url,\n\u001B[1;32m 375\u001B[0m query_params\u001B[38;5;241m=\u001B[39mquery_params,\n\u001B[1;32m 376\u001B[0m headers\u001B[38;5;241m=\u001B[39mheaders,\n\u001B[0;32m (...)\u001B[0m\n\u001B[1;32m 379\u001B[0m _request_timeout\u001B[38;5;241m=\u001B[39m_request_timeout,\n\u001B[1;32m 380\u001B[0m body\u001B[38;5;241m=\u001B[39mbody)\n", "File \u001B[0;32m~/Projects/fda-services/.jupyter/api_query/rest.py:273\u001B[0m, in \u001B[0;36mRESTClientObject.PUT\u001B[0;34m(self, url, headers, query_params, post_params, body, _preload_content, _request_timeout)\u001B[0m\n\u001B[1;32m 271\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mPUT\u001B[39m(\u001B[38;5;28mself\u001B[39m, url, headers\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m, query_params\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m, post_params\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m,\n\u001B[1;32m 272\u001B[0m body\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m, _preload_content\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mTrue\u001B[39;00m, _request_timeout\u001B[38;5;241m=\u001B[39m\u001B[38;5;28;01mNone\u001B[39;00m):\n\u001B[0;32m--> 273\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrequest\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mPUT\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 274\u001B[0m \u001B[43m \u001B[49m\u001B[43mheaders\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mheaders\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 275\u001B[0m \u001B[43m \u001B[49m\u001B[43mquery_params\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mquery_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 276\u001B[0m \u001B[43m \u001B[49m\u001B[43mpost_params\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mpost_params\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 277\u001B[0m \u001B[43m \u001B[49m\u001B[43m_preload_content\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m_preload_content\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 278\u001B[0m \u001B[43m \u001B[49m\u001B[43m_request_timeout\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43m_request_timeout\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 279\u001B[0m \u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mbody\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/Projects/fda-services/.jupyter/api_query/rest.py:222\u001B[0m, in \u001B[0;36mRESTClientObject.request\u001B[0;34m(self, method, url, query_params, headers, body, post_params, _preload_content, _request_timeout)\u001B[0m\n\u001B[1;32m 219\u001B[0m logger\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mresponse body: \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m\"\u001B[39m, r\u001B[38;5;241m.\u001B[39mdata)\n\u001B[1;32m 221\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;241m200\u001B[39m \u001B[38;5;241m<\u001B[39m\u001B[38;5;241m=\u001B[39m r\u001B[38;5;241m.\u001B[39mstatus \u001B[38;5;241m<\u001B[39m\u001B[38;5;241m=\u001B[39m \u001B[38;5;241m299\u001B[39m:\n\u001B[0;32m--> 222\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m ApiException(http_resp\u001B[38;5;241m=\u001B[39mr)\n\u001B[1;32m 224\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m r\n", - "\u001B[0;31mApiException\u001B[0m: (400)\nReason: Bad Request\nHTTP response headers: HTTPHeaderDict({'transfer-encoding': 'chunked', 'Vary': 'Origin, Access-Control-Request-Method, Access-Control-Request-Headers', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'X-Frame-Options': 'DENY', 'Content-Type': 'application/json', 'Date': 'Sat, 23 Jul 2022 11:16:44 GMT'})\nHTTP response body: b'{\"status\":\"BAD_REQUEST\",\"message\":\"Query not valid for this database\",\"code\":\"error.query.malformed\"}'\n" + "\u001B[0;31mApiException\u001B[0m: (400)\nReason: Bad Request\nHTTP response headers: HTTPHeaderDict({'transfer-encoding': 'chunked', 'Vary': 'Origin, Access-Control-Request-Method, Access-Control-Request-Headers', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block', 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'X-Frame-Options': 'DENY', 'Content-Type': 'application/json', 'Date': 'Mon, 25 Jul 2022 15:15:24 GMT'})\nHTTP response body: b'{\"status\":\"BAD_REQUEST\",\"message\":\"Failed to execute and map time-versioned query\",\"code\":\"error.table.malformed\"}'\n" ] } ], diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java index 05b1aa764b67395f4759adab83c46cb356159427..97180b2d3011144b2e8c8cd9835acd69b809cb56 100644 --- a/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java +++ b/fda-authentication-service/services/src/main/java/at/tuwien/mapper/UserMapper.java @@ -60,6 +60,7 @@ public interface UserMapper { .titlesAfter(data.getTitlesAfter()) .emailVerified(data.getEmailVerified()) .affiliation(data.getAffiliation()) + .themeDark(data.getThemeDark()) .orcid(userToUncompressedOrcid(data)) .authorities(data.getRoles() .stream() diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java index 1a258e19c8873538d16de789d052bb5aeb353b50..e508c53cbd3ad921afb8af81567862f114d3581d 100644 --- a/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java +++ b/fda-authentication-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java @@ -101,6 +101,7 @@ public class UserServiceImpl implements UserService { final User user = userMapper.signupRequestDtoToUser(data); user.setEmailVerified(false); user.setRoles(List.of(RoleType.ROLE_RESEARCHER)); + user.setThemeDark(false); user.setPassword(passwordEncoder.encode(data.getPassword())); final User entity; try { diff --git a/fda-database-service/rest-service/src/test/java/at/tuwien/endpoint/EndpointUnitTest.java b/fda-database-service/rest-service/src/test/java/at/tuwien/endpoint/EndpointUnitTest.java deleted file mode 100644 index fd34f31193176025a6e452aa35aef7b4322a0bf0..0000000000000000000000000000000000000000 --- a/fda-database-service/rest-service/src/test/java/at/tuwien/endpoint/EndpointUnitTest.java +++ /dev/null @@ -1,256 +0,0 @@ -package at.tuwien.endpoint; - -import at.tuwien.BaseUnitTest; -import at.tuwien.api.database.DatabaseBriefDto; -import at.tuwien.api.database.DatabaseCreateDto; -import at.tuwien.api.database.DatabaseDto; -import at.tuwien.config.ReadyConfig; -import at.tuwien.endpoints.ContainerDatabaseEndpoint; -import at.tuwien.exception.*; -import at.tuwien.service.impl.MariaDbServiceImpl; -import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.api.exception.NotModifiedException; -import com.github.dockerjava.api.model.Network; -import lombok.extern.log4j.Log4j2; -import org.apache.http.auth.BasicUserPrincipal; -import org.junit.jupiter.api.*; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.security.Principal; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import static at.tuwien.config.DockerConfig.dockerClient; -import static at.tuwien.config.DockerConfig.hostConfig; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.BDDMockito.willThrow; -import static org.mockito.Mockito.when; - -@Log4j2 -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class EndpointUnitTest extends BaseUnitTest { - - @MockBean - private ReadyConfig readyConfig; - - @MockBean - private MariaDbServiceImpl databaseService; - - @Autowired - private ContainerDatabaseEndpoint databaseEndpoint; - - @MockBean - private RabbitTemplate rabbitTemplate; - - @BeforeAll - public static void beforeAll() throws InterruptedException { - afterAll(); - /* create networks */ - dockerClient.createNetworkCmd() - .withName("fda-userdb") - .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) - .withEnableIpv6(false) - .exec(); - dockerClient.createNetworkCmd() - .withName("fda-public") - .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) - .withEnableIpv6(false) - .exec(); - - /* create amqp */ - final CreateContainerResponse request = dockerClient.createContainerCmd(BROKER_IMAGE + ":" + BROKER_TAG) - .withHostConfig(hostConfig.withNetworkMode("fda-public")) - .withName(BROKER_NAME) - .withIpv4Address(BROKER_IP) - .withHostName(BROKER_HOSTNAME) - .exec(); - dockerClient.startContainerCmd(request.getId()) - .exec(); - Thread.sleep(12 * 1000); - } - - @AfterAll - public static void afterAll() { - /* stop containers and remove them */ - dockerClient.listContainersCmd() - .withShowAll(true) - .exec() - .forEach(container -> { - log.info("Delete container {}", Arrays.asList(container.getNames())); - try { - dockerClient.stopContainerCmd(container.getId()).exec(); - } catch (NotModifiedException e) { - // ignore - } - dockerClient.removeContainerCmd(container.getId()).exec(); - }); - /* remove networks */ - dockerClient.listNetworksCmd() - .exec() - .stream() - .filter(n -> n.getName().startsWith("fda")) - .forEach(network -> { - log.info("Delete network {}", network.getName()); - dockerClient.removeNetworkCmd(network.getId()).exec(); - }); - } - -// @Test -// public void findAll_succeeds() { -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* mock */ -// when(databaseService.findAll(CONTAINER_1_ID, principal)) -// .thenReturn(List.of(DATABASE_1)); -// -// final ResponseEntity<List<DatabaseBriefDto>> response = databaseEndpoint.findAll(CONTAINER_1_ID, principal); -// -// /* test */ -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertEquals(1, Objects.requireNonNull(response.getBody()).size()); -// } -// -// @Test -// public void create_succeeds() throws ImageNotSupportedException, ContainerNotFoundException, -// DatabaseMalformedException, AmqpException, ContainerConnectionException, UserNotFoundException { -// final DatabaseCreateDto request = DatabaseCreateDto.builder() -// .name(DATABASE_1_NAME) -// .description(DATABASE_1_DESCRIPTION) -// .build(); -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* mock */ -// when(databaseService.create(CONTAINER_1_ID, request, principal)) -// .thenReturn(DATABASE_1); -// -// final ResponseEntity<DatabaseDto> response = databaseEndpoint.create(CONTAINER_1_ID, request, principal); -// -// /* test */ -// assertEquals(HttpStatus.CREATED, response.getStatusCode()); -// assertEquals(DATABASE_1_ID, Objects.requireNonNull(response.getBody()).getId()); -// assertEquals(DATABASE_1_NAME, Objects.requireNonNull(response.getBody()).getName()); -// } -// -// @Test -// public void create_containerNotFound_fails() throws ImageNotSupportedException, ContainerNotFoundException, -// DatabaseMalformedException, AmqpException, ContainerConnectionException, UserNotFoundException { -// final DatabaseCreateDto request = DatabaseCreateDto.builder() -// .name(DATABASE_1_NAME) -// .description(DATABASE_1_DESCRIPTION) -// .build(); -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* test */ -// when(databaseService.create(CONTAINER_1_ID, request, principal)) -// .thenThrow(ContainerNotFoundException.class); -// -// /* test */ -// assertThrows(ContainerNotFoundException.class, () -> { -// databaseEndpoint.create(CONTAINER_1_ID, request, principal); -// }); -// } -// -// @Test -// public void create_imageNotSupported_fails() throws ImageNotSupportedException, ContainerNotFoundException, -// DatabaseMalformedException, AmqpException, ContainerConnectionException, UserNotFoundException { -// final DatabaseCreateDto request = DatabaseCreateDto.builder() -// .name(DATABASE_1_NAME) -// .description(DATABASE_1_DESCRIPTION) -// .build(); -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// when(databaseService.create(CONTAINER_1_ID, request, principal)) -// .thenThrow(ImageNotSupportedException.class); -// -// /* test */ -// assertThrows(ImageNotSupportedException.class, () -> { -// databaseEndpoint.create(CONTAINER_1_ID, request, principal); -// }); -// } -// -// @Test -// public void findById_succeeds() throws DatabaseNotFoundException { -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* mock */ -// when(databaseService.findById(CONTAINER_1_ID, DATABASE_1_ID, principal)) -// .thenReturn(DATABASE_1); -// -// final ResponseEntity<DatabaseDto> response = databaseEndpoint.findById(CONTAINER_1_ID, DATABASE_1_ID, principal); -// -// /* test */ -// assertEquals(HttpStatus.OK, response.getStatusCode()); -// assertEquals(DATABASE_1_ID, Objects.requireNonNull(response.getBody()).getId()); -// assertEquals(DATABASE_1_NAME, Objects.requireNonNull(response.getBody()).getName()); -// } -// -// @Test -// public void findById_notFound_fails() throws DatabaseNotFoundException { -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* mock */ -// when(databaseService.findById(CONTAINER_1_ID, DATABASE_1_ID, principal)) -// .thenThrow(DatabaseNotFoundException.class); -// -// /* test */ -// assertThrows(DatabaseNotFoundException.class, () -> { -// databaseEndpoint.findById(CONTAINER_1_ID, DATABASE_1_ID, principal); -// }); -// } -// -// @Test -// public void delete_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// DatabaseMalformedException, AmqpException, ContainerConnectionException { -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* test */ -// final ResponseEntity<?> response = databaseEndpoint.delete(CONTAINER_1_ID, DATABASE_1_ID, principal); -// assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); -// } -// -// @Test -// public void delete_invalidImage_fails() throws DatabaseNotFoundException, ImageNotSupportedException, -// DatabaseMalformedException, AmqpException, ContainerConnectionException { -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* mock */ -// willThrow(ImageNotSupportedException.class) -// .given(databaseService) -// .delete(CONTAINER_1_ID, DATABASE_1_ID, principal); -// -// /* test */ -// assertThrows(ImageNotSupportedException.class, () -> { -// databaseEndpoint.delete(CONTAINER_1_ID, DATABASE_1_ID, principal); -// }); -// } -// -// @Test -// public void delete_notFound_fails() throws DatabaseNotFoundException, ImageNotSupportedException, -// DatabaseMalformedException, AmqpException, ContainerConnectionException { -// final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); -// -// /* mock */ -// willThrow(DatabaseNotFoundException.class) -// .given(databaseService) -// .delete(CONTAINER_1_ID, DATABASE_1_ID, principal); -// -// /* test */ -// assertThrows(DatabaseNotFoundException.class, () -> { -// databaseEndpoint.delete(CONTAINER_1_ID, DATABASE_1_ID, principal); -// }); -// } - -} diff --git a/fda-database-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java b/fda-database-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java index cc7b682015709828d1cff623d54e20ff5e5c17af..749b9c7adc1eb78f935db03877e127b60affe02b 100644 --- a/fda-database-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java +++ b/fda-database-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java @@ -83,7 +83,7 @@ public abstract class HibernateConnector { return preparedStatement.executeQuery(); } catch (SQLException e) { log.error("Failed to execute statement"); - log.debug("failed to execute statement {}", statement); + log.debug("failed to execute statement [{}] reason: {}", statement, e.getMessage()); throw new DatabaseConnectionException("Failed to execute statement", e); } } diff --git a/fda-database-service/services/src/main/java/at/tuwien/service/impl/QueryStoreServiceImpl.java b/fda-database-service/services/src/main/java/at/tuwien/service/impl/QueryStoreServiceImpl.java index 3cceb88bc7366fd1003404797e7d6a98ca990d41..43b61c073efc3e529019b4995f19f24f6b228e52 100644 --- a/fda-database-service/services/src/main/java/at/tuwien/service/impl/QueryStoreServiceImpl.java +++ b/fda-database-service/services/src/main/java/at/tuwien/service/impl/QueryStoreServiceImpl.java @@ -30,7 +30,7 @@ public class QueryStoreServiceImpl extends HibernateConnector implements QuerySt execute(connection, "CREATE SEQUENCE IF NOT EXISTS `qs_queries_seq`"); execute(connection, "CREATE SEQUENCE IF NOT EXISTS `qs_tables_seq`"); execute(connection, "CREATE SEQUENCE IF NOT EXISTS `qs_columns_seq`"); - execute(connection, "CREATE TABLE `qs_queries` (`id` bigint not null primary key default nextval(`qs_queries_seq`), `cid` bigint not null, `created` datetime not null, `created_by` bigint not null, `dbid` bigint not null, `execution` datetime not null, `last_modified` datetime not null, `query` text not null, `query_hash` varchar(255) not null, `result_hash` varchar(255), `result_number` bigint)"); + execute(connection, "CREATE TABLE `qs_queries` (`id` bigint not null primary key default nextval(`qs_queries_seq`), `cid` bigint not null, `created` datetime not null default now(), `created_by` bigint not null, `dbid` bigint not null, `execution` datetime not null, `last_modified` datetime, `query` text not null, `query_normalized` text not null, `query_hash` varchar(255) not null, `result_hash` varchar(255), `result_number` bigint)"); execute(connection, "CREATE TABLE `qs_tables` (`id` bigint not null primary key default nextval(`qs_tables_seq`), `created` datetime not null, `dbid` bigint not null, `last_modified` datetime)"); execute(connection, "CREATE TABLE `qs_columns` (`id` bigint not null primary key default nextval(`qs_columns_seq`), `created` datetime not null, `dbid` bigint not null, `tid` bigint not null, `last_modified` datetime)"); log.info("Created query store in database with id {}", databaseId); diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java index 167d9e50be8f53725c2d6291b7c287478df691f6..1b27ee0e2228c2aafb310611f148bfb1d1aa1aa9 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java @@ -48,6 +48,11 @@ public class UserBriefDto { @Parameter(name = "orcid") private String orcid; + @NotNull + @JsonProperty("theme_dark") + @Parameter(name = "theme dark") + private Boolean themeDark; + @NotNull @Parameter(name = "mail address") private String email; diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java index de6281ff33bb3eb4ecd361d3051b5f4fc316ccd9..5aa97d86626eadd6684c1002932762129e7d21ac 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java @@ -49,6 +49,11 @@ public class UserDto { @Parameter(name = "orcid") private String orcid; + @NotNull + @JsonProperty("theme_dark") + @Parameter(name = "theme dark") + private Boolean themeDark; + @Parameter(name = "list of containers") private List<ContainerDto> containers; diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java index e7fb05063f277a21a62fd8bf0a4d11764c34d244..ecff2599956860bb4aad94293e721b207c3c6ad4 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserUpdateDto.java @@ -37,4 +37,9 @@ public class UserUpdateDto { @Parameter(name = "orcid") private String orcid; + @NotNull + @JsonProperty("theme_dark") + @Parameter(name = "theme dark") + private Boolean themeDark; + } diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java index 9024d66090faf539a87317ff08ab45193a0ec243..3dab1dcf848da3d5b51f9a2d163285318d682e84 100644 --- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java +++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java @@ -57,6 +57,9 @@ public class User { @Column private String orcid; + @Column(nullable = false) + private Boolean themeDark; + @Column(name = "main_email_verified", nullable = false) private Boolean emailVerified; diff --git a/fda-metadata-db/setup-schema.sql b/fda-metadata-db/setup-schema.sql index ed96b7636eaa9ccf37c0f586e076314714ff7939..ee7d2e43dc9daf782811bdfa8632ed79d08d5320 100644 --- a/fda-metadata-db/setup-schema.sql +++ b/fda-metadata-db/setup-schema.sql @@ -152,6 +152,7 @@ CREATE TABLE IF NOT EXISTS mdb_users Preceding_titles VARCHAR(255), Postpositioned_title VARCHAR(255), orcid VARCHAR(16), + theme_dark BOOLEAN NOT NULL DEFAULT false, affiliation VARCHAR(255), Main_Email VARCHAR(255) not null, main_email_verified bool not null default false, diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java index 8503ed53d16f0f837a8759afbc953f69a36e9eae..0f0fa58575c3337f602a542c99eab09eac60ffcd 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java @@ -44,7 +44,7 @@ public class ExportEndpoint extends AbstractEndpoint { @NotNull Principal principal) throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, ContainerNotFoundException, - FileStorageException, NotAllowedException { + FileStorageException, NotAllowedException, QueryMalformedException { if (!hasDatabasePermission(id, databaseId, "DATA_EXPORT", principal)) { log.error("Missing data export permission"); throw new NotAllowedException("Missing data export permission"); diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/StoreEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/StoreEndpoint.java index 72482b9bcb0e7eab7acb9c03fe26110cc5de008b..ebaa5999256fc2b92d79fe41527e4bb8bc157426 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/StoreEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/StoreEndpoint.java @@ -45,9 +45,10 @@ public class StoreEndpoint extends AbstractEndpoint { @Operation(summary = "Find queries", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<List<QueryDto>> findAll(@NotNull @PathVariable("id") Long containerId, @NotNull @PathVariable("databaseId") Long databaseId, - @NotNull Principal principal) + Principal principal) throws QueryStoreException, - DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, NotAllowedException { + DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, NotAllowedException, + DatabaseConnectionException, TableMalformedException { if (!hasDatabasePermission(containerId, databaseId, "QUERY_VIEW_ALL", principal)) { log.error("Missing view all queries permission"); throw new NotAllowedException("Missing view all queries permission"); @@ -62,10 +63,10 @@ public class StoreEndpoint extends AbstractEndpoint { public ResponseEntity<QueryDto> find(@NotNull @PathVariable("id") Long containerId, @NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable Long queryId, - @NotNull Principal principal) + Principal principal) throws DatabaseNotFoundException, ImageNotSupportedException, - QueryStoreException, QueryNotFoundException, ContainerNotFoundException, UserNotFoundException, - NotAllowedException { + QueryStoreException, QueryNotFoundException, UserNotFoundException, NotAllowedException, + DatabaseConnectionException { if (!hasQueryPermission(containerId, databaseId, queryId, "QUERY_VIEW", principal)) { log.error("Missing view query permission"); throw new NotAllowedException("Missing view query permission"); diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java index bb604fb5c4cf5ed6e3f1c0db85e058e2092d0815..65460e3db1d9057948f0b3ddad8f0bd237fbad0c 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java @@ -64,7 +64,7 @@ public class TableDataEndpoint extends AbstractEndpoint { @NotNull Principal principal) throws TableNotFoundException, DatabaseNotFoundException, TableMalformedException, ImageNotSupportedException, TupleDeleteException, NotAllowedException, ContainerNotFoundException, - DatabaseConnectionException { + DatabaseConnectionException, QueryMalformedException { if (!hasDatabasePermission(containerId, databaseId, "DATA_DELETE", principal)) { log.error("Missing data delete permission"); throw new NotAllowedException("Missing data delete permission"); @@ -83,7 +83,7 @@ public class TableDataEndpoint extends AbstractEndpoint { @NotNull @Valid @RequestBody ImportDto data, @NotNull Principal principal) throws TableNotFoundException, DatabaseNotFoundException, TableMalformedException, - ImageNotSupportedException, ContainerNotFoundException, NotAllowedException, DatabaseConnectionException { + ImageNotSupportedException, ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, QueryMalformedException { if (!hasDatabasePermission(containerId, databaseId, "DATA_INSERT", principal)) { log.error("Missing data insert permission"); throw new NotAllowedException("Missing data insert permission"); @@ -106,7 +106,7 @@ public class TableDataEndpoint extends AbstractEndpoint { @NotNull Principal principal) throws TableNotFoundException, DatabaseNotFoundException, DatabaseConnectionException, ImageNotSupportedException, TableMalformedException, PaginationException, ContainerNotFoundException, - QueryStoreException, NotAllowedException { + QueryStoreException, NotAllowedException, QueryMalformedException { if (!hasDatabasePermission(containerId, databaseId, "DATA_VIEW", principal)) { log.error("Missing data view permission"); throw new NotAllowedException("Missing data view permission"); diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableHistoryEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableHistoryEndpoint.java index b214dee04c2590d61c134c4ac3bf2312bc415f5f..7c23a49c1b51ed0c8a7a60dc9d1c224e8642a082 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableHistoryEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableHistoryEndpoint.java @@ -1,10 +1,7 @@ package at.tuwien.endpoint; import at.tuwien.api.database.table.TableHistoryDto; -import at.tuwien.exception.DatabaseNotFoundException; -import at.tuwien.exception.NotAllowedException; -import at.tuwien.exception.QueryMalformedException; -import at.tuwien.exception.TableNotFoundException; +import at.tuwien.exception.*; import at.tuwien.service.*; import io.swagger.v3.oas.annotations.Operation; import lombok.extern.log4j.Log4j2; @@ -39,7 +36,8 @@ public class TableHistoryEndpoint extends AbstractEndpoint { @NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, @NotNull Principal principal) - throws TableNotFoundException, QueryMalformedException, DatabaseNotFoundException, NotAllowedException { + throws TableNotFoundException, QueryMalformedException, DatabaseNotFoundException, NotAllowedException, + QueryStoreException, DatabaseConnectionException { if (!hasDatabasePermission(containerId, databaseId, "DATA_HISTORY", principal)) { log.error("Missing data history permission"); throw new NotAllowedException("Missing data history permission"); diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java index 21fe07151b7df3f37b021b608f59c3127d062ef2..2d438aad87ded46447f7b3409c16d092700e2091 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java @@ -38,7 +38,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest { @Test public void export_timestampNull_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, - PaginationException, ContainerNotFoundException, NotAllowedException { + PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException { final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); /* test */ @@ -51,7 +51,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest { @Test public void export_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, PaginationException, - ContainerNotFoundException, NotAllowedException { + ContainerNotFoundException, NotAllowedException, QueryMalformedException { final Instant request = Instant.now() .minusMillis(1000 * 1000); final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); @@ -67,7 +67,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest { @Test public void export_inFuture_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, - PaginationException, ContainerNotFoundException, NotAllowedException { + PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException { final Instant request = Instant.now() .plusMillis(1000 * 1000); final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java index 8b6df814fb489d86889a70b038619466a107242f..6631d0b6c1f52aa7374efa006a2587dde7c15f77 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java @@ -42,7 +42,7 @@ public class StoreEndpointUnitTest extends BaseUnitTest { @Test public void findAll_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException, - ContainerNotFoundException, NotAllowedException { + ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, TableMalformedException { final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); /* mock */ @@ -59,7 +59,7 @@ public class StoreEndpointUnitTest extends BaseUnitTest { @Test public void find_succeeds() throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, - ImageNotSupportedException, ContainerNotFoundException, UserNotFoundException, NotAllowedException { + ImageNotSupportedException, ContainerNotFoundException, UserNotFoundException, NotAllowedException, DatabaseConnectionException { final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); /* mock */ @@ -74,7 +74,7 @@ public class StoreEndpointUnitTest extends BaseUnitTest { @Test public void find_notFound_fails() throws QueryNotFoundException, DatabaseNotFoundException, - ImageNotSupportedException, ContainerNotFoundException, QueryStoreException { + ImageNotSupportedException, ContainerNotFoundException, QueryStoreException, DatabaseConnectionException { final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); /* mock */ @@ -89,7 +89,7 @@ public class StoreEndpointUnitTest extends BaseUnitTest { @Test public void find_dbNotFound_fails() throws QueryNotFoundException, DatabaseNotFoundException, - ImageNotSupportedException, ContainerNotFoundException, QueryStoreException { + ImageNotSupportedException, ContainerNotFoundException, QueryStoreException, DatabaseConnectionException { final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); /* mock */ diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java index 2b6ff4c866a39605a4807e5c146fc6ca9536df63..980d5d36f8a6c2df31f60010092770ec60e9ff0b 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java @@ -40,7 +40,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest { @Test public void insert_succeeds() throws TableNotFoundException, TableMalformedException, DatabaseNotFoundException, - ImageNotSupportedException, ContainerNotFoundException, NotAllowedException { + ImageNotSupportedException, ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, QueryMalformedException { final ImportDto request = ImportDto.builder() .location("test:csv/csv_01.csv") .build(); @@ -55,8 +55,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest { @Test public void insert_locationNull_succeeds() throws TableNotFoundException, TableMalformedException, - DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, ContainerNotFoundException, - NotAllowedException { + DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, + NotAllowedException, DatabaseConnectionException { final TableCsvDto request = TableCsvDto.builder() .data(Map.of("key", "value")) .build(); @@ -82,7 +82,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest { @Test public void getAll_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, ContainerNotFoundException, - QueryStoreException, NotAllowedException { + QueryStoreException, NotAllowedException, QueryMalformedException { final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); /* test */ @@ -92,7 +92,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest { @Test public void findAll_noPagination_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, - ContainerNotFoundException, QueryStoreException, NotAllowedException { + ContainerNotFoundException, QueryStoreException, NotAllowedException, QueryMalformedException { final Long page = null; final Long size = null; final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); @@ -188,7 +188,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest { @Test public void getAllTotal_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, - PaginationException, ContainerNotFoundException, QueryStoreException, NotAllowedException { + PaginationException, ContainerNotFoundException, QueryStoreException, NotAllowedException, + QueryMalformedException { final Instant timestamp = Instant.now(); final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); @@ -202,7 +203,8 @@ public class TableDataEndpointUnitTest extends BaseUnitTest { @Test public void getAllCount_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, - PaginationException, ContainerNotFoundException, QueryStoreException, NotAllowedException { + PaginationException, ContainerNotFoundException, QueryStoreException, NotAllowedException, + QueryMalformedException { final Instant timestamp = Instant.now(); final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java index 56e2964fe3ca33d797c4185709d719c98a3ff089..a76389ac94804d4ac5b29460429798fa16b86190 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java @@ -114,29 +114,4 @@ public class DataServiceIntegrationTest extends BaseUnitTest { tableRepository.save(TABLE_1); } - public void update_succeeds() throws TableNotFoundException, TableMalformedException, DatabaseNotFoundException, - ImageNotSupportedException, SQLException, ContainerNotFoundException { - /* modify rainfall 0.6 -> 1.3 */ - final TableCsvUpdateDto request = TableCsvUpdateDto.builder() - .keys(Map.ofEntries(Map.entry("id", 1))) - .data(Map.ofEntries( - Map.entry("date", "2008-12-01"), - Map.entry("location", "Albury"), - Map.entry("mintemp", 13.4), - Map.entry("rainfall", 1.3) - )) - .build(); - - /* mock */ - - /* test */ - queryService.update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request); - final List<List<String>> result = MariaDbConfig.select(TABLE_1, 10); - assertEquals("1", result.get(0).get(0)); - assertEquals("2008-12-01", result.get(0).get(1)); - assertEquals("Albury", result.get(0).get(2)); - assertEquals("13.4", result.get(0).get(3)); - assertEquals("1.3", result.get(0).get(4)); - } - } diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java index 369a1d7f487f81c70c551e98ddbf4cf6087d7b03..b4740ae3e28f3a3c17c68b61e7bbf77ac73df045 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java @@ -1,12 +1,8 @@ package at.tuwien.service; import at.tuwien.BaseUnitTest; -import at.tuwien.api.database.query.ExecuteStatementDto; -import at.tuwien.api.database.query.ImportDto; import at.tuwien.api.database.query.QueryResultDto; -import at.tuwien.api.database.table.TableCsvDto; import at.tuwien.config.DockerConfig; -import at.tuwien.config.MariaDbConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.exception.*; import at.tuwien.repository.jpa.*; @@ -27,10 +23,8 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; -import javax.persistence.PersistenceException; import java.io.File; import java.math.BigInteger; -import java.sql.SQLException; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; @@ -184,7 +178,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { @Test public void findAll_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, TableMalformedException, TableNotFoundException, DatabaseConnectionException, - PaginationException, ContainerNotFoundException { + PaginationException, ContainerNotFoundException, QueryMalformedException { /* test */ final QueryResultDto result = queryService.findAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, Instant.now(), @@ -207,424 +201,6 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { assertEquals(0.0, result.getResult().get(2).get(COLUMN_1_5_INTERNAL_NAME)); } -// @Test -// public void execute_succeeds() -// throws DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException, -// TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, null, null); -// assertEquals(3, response.getResult().size()); -// } -// -// /** -// * ref #135 https://gitlab.phaidra.org/fair-data-austria-db-repository/fda-services/-/issues/135 -// */ -// @Test -// public void execute_onlyNumber_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT `id` FROM `weather_aus`") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, null, null); -// assertEquals(3, response.getResult().size()); -// } -// -// @Test -// public void execute_onlyString_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT `location` FROM `weather_aus`") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, null, null); -// assertEquals(3, response.getResult().size()); -// } -// -// @Test -// public void execute_onlyDate_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT `date` FROM `weather_aus`") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, null, null); -// assertEquals(3, response.getResult().size()); -// } -// -// @Test -// public void execute_join_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT `mintemp`, l.`lat`, l.`lng` FROM `weather_aus` w JOIN `weather_location` l ON " + -// "w.location = l.location") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, null, null); -// assertEquals(3, response.getResultNumber()); -// assertEquals(13.4, response.getResult().get(0).get("MinTemp")); -// assertEquals(-36.0653583, response.getResult().get(0).get("lat")); -// assertEquals(146.9112214, response.getResult().get(0).get("lng")); -// assertEquals(7.4, response.getResult().get(1).get("MinTemp")); -// assertEquals(-36.0653583, response.getResult().get(1).get("lat")); -// assertEquals(146.9112214, response.getResult().get(1).get("lng")); -// assertEquals(12.9, response.getResult().get(2).get("MinTemp")); -// assertEquals(-36.0653583, response.getResult().get(2).get("lat")); -// assertEquals(146.9112214, response.getResult().get(2).get("lng")); -// } -// -// @Test -// public void execute_joinNotEscaped_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT mintemp, l.lat, l.lng FROM weather_aus w JOIN weather_location l ON " + -// "w.location = l.location") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, null, null); -// assertEquals(3, response.getResultNumber()); -// assertEquals(13.4, response.getResult().get(0).get("MinTemp")); -// assertEquals(-36.0653583, response.getResult().get(0).get("lat")); -// assertEquals(146.9112214, response.getResult().get(0).get("lng")); -// assertEquals(7.4, response.getResult().get(1).get("MinTemp")); -// assertEquals(-36.0653583, response.getResult().get(1).get("lat")); -// assertEquals(146.9112214, response.getResult().get(1).get("lng")); -// assertEquals(12.9, response.getResult().get(2).get("MinTemp")); -// assertEquals(-36.0653583, response.getResult().get(2).get("lat")); -// assertEquals(146.9112214, response.getResult().get(2).get("lng")); -// } -// -// @Test -// public void execute_join2_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT z.id FROM zoo z INNER JOIN names n ON n.id = z.id") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_2_ID, DATABASE_2_ID, request, null, null); -// assertEquals(5, response.getResultNumber()); -// assertEquals(BigInteger.valueOf(1L), response.getResult().get(0).get("id")); -// assertEquals(BigInteger.valueOf(2L), response.getResult().get(1).get("id")); -// assertEquals(BigInteger.valueOf(3L), response.getResult().get(2).get("id")); -// assertEquals(BigInteger.valueOf(4L), response.getResult().get(3).get("id")); -// assertEquals(BigInteger.valueOf(5L), response.getResult().get(4).get("id")); -// } -// -// @Test -// public void execute_joinWithSemicolon_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT z.id FROM zoo z INNER JOIN names n ON n.id = z.id;") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_2_ID, DATABASE_2_ID, request, null, null); -// assertEquals(5, response.getResultNumber()); -// assertEquals(BigInteger.valueOf(1L), response.getResult().get(0).get("id")); -// assertEquals(BigInteger.valueOf(2L), response.getResult().get(1).get("id")); -// assertEquals(BigInteger.valueOf(3L), response.getResult().get(2).get("id")); -// assertEquals(BigInteger.valueOf(4L), response.getResult().get(3).get("id")); -// assertEquals(BigInteger.valueOf(5L), response.getResult().get(4).get("id")); -// } -// -// @Test -// public void execute_joinColumnNotExists_fails() { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT z.id2 FROM zoo z INNER JOIN names n ON n.id = z.id") -// .build(); -// -// /* test */ -// assertThrows(QueryMalformedException.class, () -> { -// queryService.execute(CONTAINER_2_ID, DATABASE_2_ID, request, null, null); -// }); -// } -// -// @Test -// public void execute_joinWithWhere_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, -// QueryMalformedException, TableNotFoundException, QueryStoreException, ContainerNotFoundException, -// TableMalformedException, ColumnParseException { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT `mintemp`, l.`lat`, l.`lng` FROM `weather_aus` w JOIN `weather_location` l ON " + -// "w.location = l.location WHERE `mintemp` > 13") -// .build(); -// -// /* test */ -// final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, null, null); -// assertEquals(1, response.getResultNumber()); -// assertEquals(13.4, response.getResult().get(0).get("MinTemp")); -// assertEquals(-36.0653583, response.getResult().get(0).get("lat")); -// assertEquals(146.9112214, response.getResult().get(0).get("lng")); -// } -// -// @Test -// public void execute_modifyData_fails() { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("DELETE FROM `weather_aus`;") -// .build(); -// -// /* test */ -// assertThrows(QueryMalformedException.class, () -> { -// queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, 0L, 0L); -// }); -// } -// -// @Test -// @Disabled -// public void execute_databaseNotExists_fails() { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// -// /* test */ -// assertThrows(DatabaseNotFoundException.class, () -> { -// //FIXME -// queryService.execute(CONTAINER_1_ID, 9999L, request, 0L, 0L); -// }); -// } -// -// @Test -// @Disabled -// public void execute_tableNotFound_fails() { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// -// /* test */ -// assertThrows(PersistenceException.class, () -> { -// //FIXME -// queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, 0L, 0L); -// }); -// } -// -// @Test -// @Disabled -// public void execute_columnNotFound_fails() { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement("SELECT `local` FROM `weather_aus`") -// .build(); -// -// /* test */ -// assertThrows(PersistenceException.class, () -> { -// //FIXME -// queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, 0L, 0L); -// }); -// } -// -// @Test -// @Disabled -// public void execute_statementNull_fails() { -// final ExecuteStatementDto request = ExecuteStatementDto.builder() -// .statement(null) -// .build(); -// -// /* test */ -// assertThrows(QueryMalformedException.class, () -> { -// //FIXME -// queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request, 0L, 0L); -// }); -// } -// -// @Test -// @Disabled -// public void insert_succeeds() throws TableNotFoundException, DatabaseNotFoundException, -// TableMalformedException, ImageNotSupportedException, SQLException, ContainerNotFoundException { -// final ImportDto request = ImportDto.builder() -// .location("/tmp/csv_12.csv") -// .build(); -// -// /* test */ -// final Integer rows = queryService.insert(CONTAINER_1_ID, DATABASE_3_ID, TABLE_3_ID, request); -// assertEquals(9999, rows); -// final List<List<String>> response = MariaDbConfig.select(TABLE_3, 1); -// assertEquals("1", response.get(0).get(0)); -// assertEquals("2", response.get(0).get(1)); -// assertEquals("1", response.get(0).get(2)); -// assertEquals("2017-01-15", response.get(0).get(3)); -// assertEquals("2076", response.get(0).get(4)); -// assertEquals("6", response.get(0).get(5)); -// assertEquals("1", response.get(0).get(6)); -// assertEquals("6030", response.get(0).get(7)); -// assertEquals("0", response.get(0).get(8)); -// assertEquals("DEP4", response.get(0).get(9)); -// assertEquals("2017-01-15", response.get(0).get(10)); -// assertEquals("17580", response.get(0).get(11)); -// assertEquals("17562", response.get(0).get(12)); -// assertEquals("17580", response.get(0).get(13)); -// assertEquals("17562", response.get(0).get(14)); -// assertEquals("2", response.get(0).get(15)); -// assertEquals("1357", response.get(0).get(16)); -// assertEquals("1", response.get(0).get(17)); -// assertEquals("KALK", response.get(0).get(18)); -// assertEquals("2017-01-15", response.get(0).get(19)); -// assertEquals("17622", response.get(0).get(20)); -// assertEquals("17647", response.get(0).get(21)); -// assertEquals("17622", response.get(0).get(22)); -// assertEquals("17664", response.get(0).get(23)); -// assertEquals("8538", response.get(0).get(24)); -// assertEquals("41253", response.get(0).get(25)); -// assertEquals("15", response.get(0).get(26)); -// assertEquals("2", response.get(0).get(27)); -// assertEquals("15", response.get(0).get(28)); -// assertEquals("DEP4 - KALK", response.get(0).get(29)); -// assertEquals("135780", response.get(0).get(30)); -// assertEquals("2251", response.get(0).get(31)); -// assertEquals("1906", response.get(0).get(32)); -// assertEquals("12462", response.get(0).get(33)); -// assertEquals("10563", response.get(0).get(34)); -// -// } -// -// @Test -// @Disabled -// public void insert_large_succeeds() throws TableNotFoundException, DatabaseNotFoundException, -// TableMalformedException, ImageNotSupportedException, SQLException, ContainerNotFoundException { -// final ImportDto request = ImportDto.builder() -// .location("/tmp/csv_13.csv") -// .build(); -// -// /* test */ -// final Integer rows = queryService.insert(CONTAINER_1_ID, DATABASE_3_ID, TABLE_3_ID, request); -// assertEquals(1397856, rows); -// final List<List<String>> response = MariaDbConfig.select(TABLE_3, 1); -// assertEquals("1", response.get(0).get(0)); -// assertEquals("2", response.get(0).get(1)); -// assertEquals("1", response.get(0).get(2)); -// assertEquals("2017-01-15", response.get(0).get(3)); -// assertEquals("2076", response.get(0).get(4)); -// assertEquals("6", response.get(0).get(5)); -// assertEquals("1", response.get(0).get(6)); -// assertEquals("6030", response.get(0).get(7)); -// assertEquals("0", response.get(0).get(8)); -// assertEquals("DEP4", response.get(0).get(9)); -// assertEquals("2017-01-15", response.get(0).get(10)); -// assertEquals("17580", response.get(0).get(11)); -// assertEquals("17562", response.get(0).get(12)); -// assertEquals("17580", response.get(0).get(13)); -// assertEquals("17562", response.get(0).get(14)); -// assertEquals("2", response.get(0).get(15)); -// assertEquals("1357", response.get(0).get(16)); -// assertEquals("1", response.get(0).get(17)); -// assertEquals("KALK", response.get(0).get(18)); -// assertEquals("2017-01-15", response.get(0).get(19)); -// assertEquals("17622", response.get(0).get(20)); -// assertEquals("17647", response.get(0).get(21)); -// assertEquals("17622", response.get(0).get(22)); -// assertEquals("17664", response.get(0).get(23)); -// assertEquals("8538", response.get(0).get(24)); -// assertEquals("41253", response.get(0).get(25)); -// assertEquals("15", response.get(0).get(26)); -// assertEquals("2", response.get(0).get(27)); -// assertEquals("15", response.get(0).get(28)); -// assertEquals("DEP4 - KALK", response.get(0).get(29)); -// assertEquals("135780", response.get(0).get(30)); -// assertEquals("2251", response.get(0).get(31)); -// assertEquals("1906", response.get(0).get(32)); -// assertEquals("12462", response.get(0).get(33)); -// assertEquals("10563", response.get(0).get(34)); -// } -// -// @Test -// @Disabled -// public void insert_sensor_succeeds() throws TableNotFoundException, DatabaseNotFoundException, -// TableMalformedException, ImageNotSupportedException, SQLException, ContainerNotFoundException { -// final TableCsvDto request = TableCsvDto.builder() -// .data(new HashMap<>() {{ -// put("linie", 2); -// put("richtung", 1); -// put("betriebsdatum", "15.01.17"); -// put("fahrzeug", 2076); -// put("kurs", 6); -// put("seq_von", 1); -// put("halt_diva_von", 6030); -// put("halt_punkt_diva_von", 0); -// put("halt_kurz_von1", "DEP4"); -// put("datum_von", "15.01.17"); -// put("soll_an_von", 17580); -// put("ist_an_von", 17562); -// put("soll_ab_von", 17580); -// put("ist_ab_von", 17562); -// put("seq_nach", 2); -// put("halt_diva_nach", 1357); -// put("halt_punkt_diva_nach", 1); -// put("halt_kurz_nach1", "KALK"); -// put("datum_nach", "15.01.17"); -// put("soll_an_nach", 17622); -// put("ist_an_nach1", 17647); -// put("soll_ab_nach", 17622); -// put("ist_ab_nach", 17664); -// put("fahrt_id", 8538); -// put("fahrweg_id", 41253); -// put("fw_no", 15); -// put("fw_typ", 2); -// put("fw_kurz", 15); -// put("fw_lang", "DEP4 - KALK"); -// put("umlauf_von", 135780); -// put("halt_id_von", 2251); -// put("halt_id_nach", 1906); -// put("halt_punkt_id_von", 12462); -// put("halt_punkt_id_nach", 10563); -// }}) -// .build(); -// -// /* test */ -// final Integer rows = queryService.insert(CONTAINER_1_ID, DATABASE_3_ID, TABLE_3_ID, request); -// assertEquals(1, rows); -// final List<List<String>> response = MariaDbConfig.select(TABLE_3, 1); -// assertEquals("1", response.get(0).get(0)); -// assertEquals("2", response.get(0).get(1)); -// assertEquals("1", response.get(0).get(2)); -// assertEquals("2017-01-15", response.get(0).get(3)); -// assertEquals("2076", response.get(0).get(4)); -// assertEquals("6", response.get(0).get(5)); -// assertEquals("1", response.get(0).get(6)); -// assertEquals("6030", response.get(0).get(7)); -// assertEquals("0", response.get(0).get(8)); -// assertEquals("DEP4", response.get(0).get(9)); -// assertEquals("2017-01-15", response.get(0).get(10)); -// assertEquals("17580", response.get(0).get(11)); -// assertEquals("17562", response.get(0).get(12)); -// assertEquals("17580", response.get(0).get(13)); -// assertEquals("17562", response.get(0).get(14)); -// assertEquals("2", response.get(0).get(15)); -// assertEquals("1357", response.get(0).get(16)); -// assertEquals("1", response.get(0).get(17)); -// assertEquals("KALK", response.get(0).get(18)); -// assertEquals("2017-01-15", response.get(0).get(19)); -// assertEquals("17622", response.get(0).get(20)); -// assertEquals("17647", response.get(0).get(21)); -// assertEquals("17622", response.get(0).get(22)); -// assertEquals("17664", response.get(0).get(23)); -// assertEquals("8538", response.get(0).get(24)); -// assertEquals("41253", response.get(0).get(25)); -// assertEquals("15", response.get(0).get(26)); -// assertEquals("2", response.get(0).get(27)); -// assertEquals("15", response.get(0).get(28)); -// assertEquals("DEP4 - KALK", response.get(0).get(29)); -// assertEquals("135780", response.get(0).get(30)); -// assertEquals("2251", response.get(0).get(31)); -// assertEquals("1906", response.get(0).get(32)); -// assertEquals("12462", response.get(0).get(33)); -// assertEquals("10563", response.get(0).get(34)); -// } - @SneakyThrows private static Instant toInstant(String str) { final DateTimeFormatter formatter = new DateTimeFormatterBuilder() diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceUnitTest.java index f6b835fc30011ba3ba340d9476e924d18ad0835d..4aa314c293c47b93c1e55ce80fd18773631a0d4b 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceUnitTest.java @@ -26,7 +26,6 @@ import java.io.File; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.Optional; @@ -127,7 +126,7 @@ public class QueryServiceUnitTest extends BaseUnitTest { @Test public void selectAll_succeeds() throws TableNotFoundException, DatabaseConnectionException, DatabaseNotFoundException, ImageNotSupportedException, TableMalformedException, PaginationException, - ContainerNotFoundException { + ContainerNotFoundException, QueryMalformedException { final Long page = 0L; final Long size = 10L; @@ -196,7 +195,7 @@ public class QueryServiceUnitTest extends BaseUnitTest { @Test public void findAll_timestampMissing_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, - ContainerNotFoundException { + ContainerNotFoundException, QueryMalformedException { /* mock */ when(databaseRepository.findById(DATABASE_1_ID)) @@ -211,7 +210,7 @@ public class QueryServiceUnitTest extends BaseUnitTest { @Test public void findAll_timestampBeforeCreation_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, - ContainerNotFoundException { + ContainerNotFoundException, QueryMalformedException { final Instant timestamp = DATABASE_1_CREATED.minus(1, ChronoUnit.SECONDS); /* mock */ diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java index ea3d599a966aca43763e898a3dd59c3090a9755e..fe4ee84a35c9bf179439b0885c7f65ebb1068014 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java @@ -7,7 +7,6 @@ import at.tuwien.config.DockerConfig; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.exception.*; -import at.tuwien.querystore.Query; import at.tuwien.repository.jpa.TableRepository; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.exception.NotModifiedException; @@ -25,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional; import java.io.File; import java.sql.SQLException; -import java.time.Instant; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -50,7 +48,7 @@ public class StoreServiceIntegrationTest extends BaseUnitTest { private TableRepository tableRepository; @BeforeAll - public static void beforeAll() throws InterruptedException { + public static void beforeAll() { afterAll(); /* create network */ dockerClient.createNetworkCmd() @@ -110,54 +108,6 @@ public class StoreServiceIntegrationTest extends BaseUnitTest { tableRepository.save(TABLE_2); } -// @Test -// public void findAll_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException, -// InterruptedException, SQLException, ContainerNotFoundException { -// final QueryResultDto result = QueryResultDto.builder() -// .result(List.of(Map.of("key", "val"))) -// .build(); -// final ExecuteStatementDto statement1 = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// final ExecuteStatementDto statement2 = ExecuteStatementDto.builder() -// .statement(QUERY_2_STATEMENT) -// .build(); -// final Instant execution = Instant.now(); -// -// /* mock */ -// DockerConfig.startContainer(CONTAINER_1); -// MariaDbConfig.clearQueryStore(TABLE_1); -// storeService.insert(CONTAINER_1_ID, DATABASE_1_ID, result, statement1, execution); -// storeService.insert(CONTAINER_1_ID, DATABASE_1_ID, result, statement2, execution); -// -// /* test */ -// final List<Query> response = storeService.findAll(CONTAINER_1_ID, DATABASE_1_ID); -// assertEquals(2, response.size()); -// } -// -// @Test -// public void findOne_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException, -// QueryNotFoundException, InterruptedException, SQLException, ContainerNotFoundException { -// final QueryResultDto result = QueryResultDto.builder() -// .result(List.of(Map.of("key", "val"))) -// .build(); -// final ExecuteStatementDto statement = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// final Instant execution = Instant.now(); -// -// /* mock */ -// DockerConfig.startContainer(CONTAINER_1); -// MariaDbConfig.clearQueryStore(TABLE_1); -// storeService.insert(CONTAINER_1_ID, DATABASE_1_ID, result, statement, execution); -// -// /* test */ -// final Query response = storeService.findOne(CONTAINER_1_ID, DATABASE_1_ID, QUERY_1_ID); -// assertEquals(QUERY_1_ID, response.getId()); -// assertEquals(QUERY_1_STATEMENT, response.getQuery()); -// assertNotNull(response.getQueryHash()); -// } - @Test public void findOne_notFound_fails() throws InterruptedException, SQLException { final QueryResultDto result = QueryResultDto.builder() @@ -177,64 +127,4 @@ public class StoreServiceIntegrationTest extends BaseUnitTest { }); } -// @Test -// public void insert_succeeds() throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException, -// InterruptedException, SQLException, ContainerNotFoundException { -// final QueryResultDto result = QueryResultDto.builder() -// .result(List.of(Map.of("key", "val"))) -// .build(); -// final ExecuteStatementDto statement = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// final Instant execution = Instant.now(); -// -// /* mock */ -// DockerConfig.startContainer(CONTAINER_1); -// MariaDbConfig.clearQueryStore(TABLE_1); -// -// /* test */ -// final Query response = storeService.insert(CONTAINER_1_ID, DATABASE_1_ID, result, statement, execution); -// assertEquals(QUERY_1_ID, response.getId()); -// assertEquals(QUERY_1_STATEMENT, response.getQuery()); -// } - -// @Test -// public void insert_notRunning_fails() throws SQLException { -// final QueryResultDto result = QueryResultDto.builder() -// .result(List.of(Map.of("id", "1"))) -// .build(); -// final ExecuteStatementDto statement = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// final Instant execution = Instant.now(); -// -// /* mock */ -// DockerConfig.stopContainer(CONTAINER_1); -// -// /* test */ -// assertThrows(QueryStoreException.class, () -> { -// storeService.insert(CONTAINER_1_ID, DATABASE_1_ID, result, statement, execution); -// }); -// } -// -// @Test -// public void insert_dbNotFound_fails() throws InterruptedException, SQLException { -// final QueryResultDto result = QueryResultDto.builder() -// .result(List.of(Map.of("id", "1"))) -// .build(); -// final ExecuteStatementDto statement = ExecuteStatementDto.builder() -// .statement(QUERY_1_STATEMENT) -// .build(); -// final Instant execution = Instant.now(); -// -// /* mock */ -// DockerConfig.startContainer(CONTAINER_1); -// MariaDbConfig.clearQueryStore(TABLE_1); -// -// /* test */ -// assertThrows(DatabaseNotFoundException.class, () -> { -// storeService.insert(CONTAINER_1_ID, 9999L, result, statement, execution); -// }); -// } - } diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java index ab12123959ea50568002092ecbea7d1424664a81..132e01c36763eda375f0daf52af8c88ba173675d 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java +++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java @@ -9,6 +9,7 @@ import at.tuwien.api.database.table.TableHistoryDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.columns.TableColumnType; import at.tuwien.exception.QueryMalformedException; +import at.tuwien.exception.QueryStoreException; import at.tuwien.exception.TableMalformedException; import at.tuwien.querystore.Query; import at.tuwien.entities.database.table.Table; @@ -23,9 +24,7 @@ import org.mariadb.jdbc.MariaDbBlob; import org.springframework.transaction.annotation.Transactional; import java.math.BigInteger; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; +import java.sql.*; import java.text.Normalizer; import java.time.*; import java.time.format.DateTimeFormatter; @@ -77,20 +76,20 @@ public interface QueryMapper { log.trace("result has {} columns", columns.size()); while (result.next()) { /* map the result set to the columns through the stored metadata in the metadata database */ - int[] idx = new int[]{0}; + int[] idx = new int[]{1}; final Map<String, Object> map = new HashMap<>(); for (int i = 0; i < columns.size(); i++) { map.put(columns.get(i).getInternalName(), dataColumnToObject(result.getObject(idx[0]++), columns.get(i))); } - resultList.add(map); + resultList.add(map); } return QueryResultDto.builder() .result(resultList) .build(); } - default String generateTemporaryTableSQL(Table table) { - final StringBuilder generateTable = new StringBuilder("CREATE TABLE `") + default PreparedStatement generateTemporaryTableSQL(Connection connection, Table table) throws QueryMalformedException { + final StringBuilder statement = new StringBuilder("CREATE TABLE `") .append(table.getDatabase().getInternalName()) .append("`.`") .append(table.getInternalName()) @@ -100,24 +99,36 @@ public interface QueryMapper { .append("`.`") .append(table.getInternalName()) .append("`;"); - log.debug(generateTable.toString()); - return generateTable.toString(); + log.trace("mapped raw generate temporary table query [{}]", statement); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - default String dropTemporaryTableSQL(Table table) { - final StringBuilder t = new StringBuilder("DROP TABLE `") + default PreparedStatement dropTemporaryTableSQL(Connection connection, Table table) throws QueryMalformedException { + final StringBuilder statement = new StringBuilder("DROP TABLE `") .append(table.getDatabase().getInternalName()) .append("`.`") .append(table.getInternalName()) .append("_temporary`;"); - log.debug(t.toString()); - return t.toString(); + log.trace("mapped raw drop temporary table query [{}]", statement); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - default InsertTableRawQuery pathToRawInsertQuery(Table table, ImportDto data) { - final StringBuilder query = new StringBuilder("LOAD DATA LOCAL INFILE '") + default PreparedStatement pathToRawInsertQuery(Connection connection, Table table, ImportDto data) throws QueryMalformedException { + final StringBuilder statement = new StringBuilder("LOAD DATA LOCAL INFILE '") .append(data.getLocation()) .append("' INTO TABLE `") .append(table.getDatabase().getInternalName()) @@ -128,11 +139,11 @@ public interface QueryMapper { .append(data.getSeparator()) .append("'"); if (data.getQuote() != null) { - query.append(" OPTIONALLY ENCLOSED BY '") + statement.append(" OPTIONALLY ENCLOSED BY '") .append(data.getQuote()) .append("'"); } - query.append(data.getSkipLines() != null ? (" IGNORE " + data.getSkipLines() + " LINES") : "") + statement.append(data.getSkipLines() != null ? (" IGNORE " + data.getSkipLines() + " LINES") : "") .append(" ("); final StringBuilder set = new StringBuilder(); int[] idx = new int[]{0}; @@ -141,9 +152,9 @@ public interface QueryMapper { if (column.getAutoGenerated()) { return; } - query.append(idx[0] != 0 ? "," : ""); + statement.append(idx[0] != 0 ? "," : ""); /* format as variable */ - query.append("@") + statement.append("@") .append(column.getInternalName()); if (column.getDateFormat() != null) { /* reformat dates */ @@ -157,14 +168,18 @@ public interface QueryMapper { } idx[0]++; }); - query.append(")") + statement.append(")") .append(set.length() != 0 ? (" SET " + set) : "") .append(";"); log.debug("import csv {} for table {}", data.getLocation(), table); - log.trace("raw import query: [{}]", query); - return InsertTableRawQuery.builder() - .query(query.toString()) - .build(); + log.trace("raw import query: [{}]", statement); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } default void columnToBoolSet(ImportDto data, Table table, TableColumn column, StringBuilder set) { @@ -281,33 +296,39 @@ public interface QueryMapper { .append("')"); } - default String tableToRawExportQuery(Table table, Instant timestamp, String filename) { - final StringBuilder query = new StringBuilder("SELECT "); + default PreparedStatement tableToRawExportQuery(Connection connection, Table table, Instant timestamp, String filename) throws QueryMalformedException { + final StringBuilder statement = new StringBuilder("SELECT "); int[] idx = new int[]{0}; table.getColumns() .forEach(column -> { - query.append(idx[0] != 0 ? "," : "") + statement.append(idx[0] != 0 ? "," : "") .append("`") .append(column.getInternalName()) .append("`"); idx[0]++; }); - query.append("FROM `") + statement.append("FROM `") .append(table.getInternalName()) .append("`"); if (timestamp != null) { - query.append(" FOR SYSTEM_TIME AS OF TIMESTAMP'") + statement.append(" FOR SYSTEM_TIME AS OF TIMESTAMP'") .append(mariaDbFormatter.format(timestamp)) .append("'"); } - query.append(" INTO OUTFILE '/tmp/") + statement.append(" INTO OUTFILE '/tmp/") .append(filename) .append("' CHARACTER SET utf8"); - query.append(";"); - return query.toString(); + statement.append(";"); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - default String queryToRawExportQuery(Query query, String filename) throws QueryMalformedException { + default PreparedStatement queryToRawExportQuery(Connection connection, Query query, String filename) throws QueryMalformedException { if (query.getQuery().contains(";")) { log.trace("Remove ending ; from statement [{}]", query.getQuery()); query.setQuery(query.getQuery().substring(0, query.getQuery().indexOf(";"))); @@ -330,11 +351,17 @@ public interface QueryMapper { .append(filename) .append("' CHARACTER SET utf8 FIELDS TERMINATED BY ',';"); log.trace("raw export query: [{}]", statement); - return statement.toString(); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - default InsertTableRawQuery tableCsvDtoToRawInsertQuery(Table table, TableCsvDto data) - throws TableMalformedException, ImageNotSupportedException { + default PreparedStatement tableCsvDtoToRawInsertQuery(Connection connection, Table table, TableCsvDto data) + throws TableMalformedException, ImageNotSupportedException, QueryMalformedException { if (table.getColumns().size() == 0) { log.error("Column size is zero"); throw new TableMalformedException("Columns are not known"); @@ -345,7 +372,7 @@ public interface QueryMapper { throw new ImageNotSupportedException("Image not supported."); } /* parameterized query for prepared statement */ - final StringBuilder query = new StringBuilder("INSERT INTO `") + final StringBuilder statement = new StringBuilder("INSERT INTO `") .append(table.getInternalName()) .append("` (") .append(table.getColumns() @@ -355,33 +382,38 @@ public interface QueryMapper { .collect(Collectors.joining(","))) .append(") VALUES (?1);"); /* map all columns that are non-auto generated */ - final Collection<Object> values = table.getColumns() - .stream() - .filter(c -> !c.getAutoGenerated()) - .map(c -> { - final Optional<Map.Entry<String, Object>> tuple = data.getData() - .entrySet() - .stream() - .filter(d -> d.getKey().equals(c.getInternalName())) - .findFirst(); - if (tuple.isEmpty()) { - log.error("Tuple contains columns names that are not present in the database"); - log.debug("tuple column names are {}", data.getData().keySet()); - return null; - } - return dataColumnToObject(tuple.get() - .getValue(), c); - }) - .collect(Collectors.toList()); - log.trace("raw insert query: [{}] with data {}", query, values); - return InsertTableRawQuery.builder() - .query(query.toString()) - .data(values) - .build(); + final int[] idx = new int[]{0}; + try { + final PreparedStatement ps = connection.prepareStatement(statement.toString()); + for (int i = 0; i < table.getColumns().size(); i++) { + final TableColumn column = table.getColumns() + .get(i); + if (column.getAutoGenerated()) { + continue; + } + final Optional<Map.Entry<String, Object>> tuple = data.getData() + .entrySet() + .stream() + .filter(d -> d.getKey().equals(column.getInternalName())) + .findFirst(); + if (tuple.isEmpty()) { + log.error("Failed to map column names"); + log.debug("failed to map column names, tuple contains columns names that are not present in the database, tuple column names are {}", data.getData().keySet()); + throw new TableMalformedException("Failed to map column names"); + } + ps.setObject(idx[0]++, dataColumnToObject(tuple.get() + .getValue(), column)); + } + return ps; + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - default String tableCsvDtoToRawDeleteQuery(Table table, TableCsvDeleteDto data) - throws TableMalformedException, ImageNotSupportedException { + default PreparedStatement tableCsvDtoToRawDeleteQuery(Connection connection, Table table, TableCsvDeleteDto data) + throws TableMalformedException, ImageNotSupportedException, QueryMalformedException { if (table.getColumns().size() == 0) { log.error("Column size is zero"); throw new TableMalformedException("Columns are not known"); @@ -392,19 +424,25 @@ public interface QueryMapper { throw new ImageNotSupportedException("Image not supported."); } /* parameterized query for prepared statement */ - final StringBuilder query = new StringBuilder("DELETE FROM `") + final StringBuilder statement = new StringBuilder("DELETE FROM `") .append(table.getInternalName()) .append("` WHERE "); final int[] idx = new int[]{0}; data.getKeys() - .forEach((key, value) -> query.append(idx[0] == 0 ? "" : ", ") + .forEach((key, value) -> statement.append(idx[0] == 0 ? "" : ", ") .append("`") .append(key) .append("` = ?") .append(idx[0]++)); /* debug */ - log.trace("raw delete query: [{}] with data {}", query, data.getKeys().values()); - return query.toString(); + log.trace("raw delete query: [{}] with data {}", statement, data.getKeys().values()); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } default InsertTableRawQuery tableCsvDtoToRawUpdateQuery(Table table, TableCsvUpdateDto data) @@ -453,7 +491,7 @@ public interface QueryMapper { .build(); } - default String tableToRawCountAllQuery(Table table, Instant timestamp) throws ImageNotSupportedException { + default PreparedStatement tableToRawCountAllQuery(Connection connection, Table table, Instant timestamp) throws ImageNotSupportedException, QueryMalformedException { /* check image */ if (!table.getDatabase().getContainer().getImage().getRepository().equals("mariadb")) { log.error("Currently only MariaDB is supported"); @@ -462,14 +500,22 @@ public interface QueryMapper { if (timestamp == null) { timestamp = Instant.now(); } - return "SELECT COUNT(*) FROM `" + nameToInternalName(table.getName()) + - "` FOR SYSTEM_TIME AS OF TIMESTAMP '" + - LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna")) + - "';"; + final StringBuilder statement = new StringBuilder("SELECT COUNT(*) FROM `") + .append(nameToInternalName(table.getName())) + .append("` FOR SYSTEM_TIME AS OF TIMESTAMP '") + .append(LocalDateTime.ofInstant(timestamp, ZoneId.of("UTC"))) + .append("';"); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - default String queryToRawTimestampedCountQuery(String query, Database database, Instant timestamp) - throws ImageNotSupportedException { + default PreparedStatement queryToRawTimestampedCountQuery(Connection connection, String query, Database database, Instant timestamp) + throws ImageNotSupportedException, QueryMalformedException { /* param check */ if (!database.getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); @@ -479,28 +525,28 @@ public interface QueryMapper { } query = query.toLowerCase(Locale.ROOT) .split("from")[1]; - final StringBuilder sb = new StringBuilder(); - sb.append("select count(*) from"); + final StringBuilder original = new StringBuilder(); + original.append("SELECT COUNT(*) AS `total` FROM"); if (!query.contains("where")) { /* treat join queries as normal queries */ - sb.append(query); + original.append(query); } else { - sb.append(query.split("where")[0]); + original.append(query.split("where")[0]); } if (query.contains("join")) { /* put timestamp after "join" and each "on" (but before alias) */ } else { - sb.append("FOR SYSTEM_TIME AS OF TIMESTAMP '"); - sb.append(LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna"))); - sb.append("' "); + original.append("FOR SYSTEM_TIME AS OF TIMESTAMP '"); + original.append(LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna"))); + original.append("' "); } if (query.contains("where")) { - sb.append("where"); - sb.append(query.split("where")[1]); + original.append("where"); + original.append(query.split("where")[1]); } - sb.append(";"); + original.append(";"); /* replace timestamp for join query */ - String statement = sb.toString(); + String statement = original.toString(); if (query.contains("join")) { statement = statement.replaceFirst("from ([`a-z0-9_]+) ", "from $1 FOR SYSTEM_TIME AS OF TIMESTAMP '" + LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna")) @@ -510,11 +556,19 @@ public interface QueryMapper { + "' "); } log.debug("mapped raw view-only query [{}]", statement); - return statement; + try { + return connection.prepareStatement(statement); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - default String queryToRawTimestampedQuery(String query, Database database, Instant timestamp, Long page, Long size) - throws ImageNotSupportedException, QueryMalformedException { + default PreparedStatement queryToRawTimestampedQuery(Connection connection, + String query, Database database, Instant timestamp, Long page, + Long size) throws ImageNotSupportedException, + QueryMalformedException { /* param check */ if (!database.getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); @@ -568,7 +622,13 @@ public interface QueryMapper { + "' "); } log.debug("mapped raw view-only query [{}]", statement); - return statement; + try { + return connection.prepareStatement(statement); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } default Long resultSetToLong(ResultSet data) { @@ -582,8 +642,8 @@ public interface QueryMapper { return null; } - default String tableToRawFindAllQuery(Table table, Instant timestamp, Long size, Long page) - throws ImageNotSupportedException { + default PreparedStatement tableToRawFindAllQuery(Connection connection, Table table, Instant timestamp, Long size, Long page) + throws ImageNotSupportedException, QueryMalformedException { /* param check */ if (!table.getDatabase().getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); @@ -595,29 +655,35 @@ public interface QueryMapper { log.debug("timestamp provided {}", timestamp); } final int[] idx = new int[]{0}; - final StringBuilder query = new StringBuilder("SELECT "); + final StringBuilder statement = new StringBuilder("SELECT "); table.getColumns() - .forEach(column -> query.append(idx[0]++ > 0 ? "," : "") + .forEach(column -> statement.append(idx[0]++ > 0 ? "," : "") .append("`") .append(column.getInternalName()) .append("`")); - query.append(" FROM `") + statement.append(" FROM `") .append(nameToInternalName(table.getName())) .append("` FOR SYSTEM_TIME AS OF TIMESTAMP '") .append(LocalDateTime.ofInstant(timestamp, ZoneId.of("Europe/Vienna"))) .append("'"); if (size != null && page != null) { log.trace("pagination size/limit of {}", size); - query.append(" LIMIT ") + statement.append(" LIMIT ") .append(size); log.trace("pagination page/offset of {}", page); - query.append(" OFFSET ") + statement.append(" OFFSET ") .append(page * size) .append(";"); } - log.trace("raw select table query: [{}]", query); - return query.toString(); + log.trace("raw select table query: [{}]", statement); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } default QueryResultDto queryTableToQueryResultDto(ResultSet result, Table table) throws DateTimeException, SQLException { @@ -639,29 +705,31 @@ public interface QueryMapper { } @Transactional(readOnly = true) - default String historyRawQuery(Table data) { - final StringBuilder builder = new StringBuilder("SELECT") + default PreparedStatement historyRawQuery(Connection connection, Table data) throws QueryMalformedException { + final StringBuilder statement = new StringBuilder("SELECT") .append(" IF(`deleted_at` IS NULL, `inserted_at`, `deleted_at`) as `timestamp`") .append(", IF(`deleted_at` IS NULL, 'INSERT', 'DELETE') as `event`") .append(", COUNT(`inserted_at`) as `total` FROM `hs_") .append(data.getInternalName()) .append("` GROUP BY `inserted_at`, `deleted_at` ORDER BY `timestamp` ASC;"); - log.trace("mapped find all from history view query [{}]", builder); - return builder.toString(); + log.trace("mapped find all from history view query [{}]", statement); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } - @Transactional(readOnly = true) - default List<TableHistoryDto> resultListToTableHistoryDto(Table table, List<?> resultList) { - final Iterator<?> iterator = resultList.iterator(); + default List<TableHistoryDto> resultListToTableHistoryDto(ResultSet data) throws SQLException { final List<TableHistoryDto> history = new LinkedList<>(); - while (iterator.hasNext()) { - final int[] idx = new int[]{0}; - final Map<String, Object> primaryKeys = new HashMap<>(); - final Object[] row = (Object[]) iterator.next(); + while (data.next()) { history.add(TableHistoryDto.builder() - .timestamp(objectToInstant(row[idx[0]++])) - .event(String.valueOf(row[idx[0]++])) - .total(Long.parseLong(String.valueOf(row[idx[0]++]))) + .timestamp(data.getTimestamp(1) + .toInstant()) + .event(data.getString(2)) + .total(data.getLong(3)) .build()); } return history; @@ -727,6 +795,19 @@ public interface QueryMapper { return name; } + default Long resultSetToNumber(ResultSet data) throws TableMalformedException, QueryStoreException { + try { + if (!data.next()) { + log.error("Failed to map number"); + throw new TableMalformedException("Failed to map number"); + } + return data.getLong(1); + } catch (SQLException e) { + log.error("Failed to retrieve number"); + throw new QueryStoreException("Failed to retrieve number"); + } + } + default String selectItemToEscapedString(SelectItem data) { final String item = data.toString(); final int idx = item.indexOf('.'); @@ -742,37 +823,43 @@ public interface QueryMapper { * @param table * @return */ - default String generateInsertFromTemporaryTableSQL(Table table) { - final StringBuilder generateTable = new StringBuilder("INSERT INTO `") + default PreparedStatement generateInsertFromTemporaryTableSQL(Connection connection, Table table) throws QueryMalformedException { + final StringBuilder statement = new StringBuilder("INSERT INTO `") .append(table.getDatabase().getInternalName()) .append("`.`") .append(table.getInternalName()) .append("` SELECT "); for (TableColumn tc : table.getColumns()) { - generateTable.append("`"); - generateTable.append(tc.getInternalName()).append("`,"); + statement.append("`"); + statement.append(tc.getInternalName()).append("`,"); } - generateTable.deleteCharAt(generateTable.length() - 1); - generateTable.append(" FROM `") + statement.deleteCharAt(statement.length() - 1); + statement.append(" FROM `") .append(table.getDatabase().getInternalName()) .append("`.`") .append(table.getInternalName()) .append("_temporary`"); - generateTable.append(" ON DUPLICATE KEY UPDATE "); + statement.append(" ON DUPLICATE KEY UPDATE "); for (TableColumn tc : table.getColumns()) - generateTable.append("`") + statement.append("`") .append(tc.getInternalName()) .append("`") .append("=") .append("VALUES(`") .append(tc.getInternalName()) .append("`),"); - generateTable.deleteCharAt(generateTable.length() - 1); - generateTable.append(";"); - log.debug("Insert Query: {}", generateTable); - return generateTable.toString(); + statement.deleteCharAt(statement.length() - 1); + statement.append(";"); + log.trace("mapped raw insert query [{}]", statement); + try { + return connection.prepareStatement(statement.toString()); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryMalformedException("Failed to prepare statement", e); + } } default Instant objectToInstant(Object data) { diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/StoreMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/StoreMapper.java index 7392779d11eb968bd32e9baabe63b3f7151e65e7..5e3bfdf06f03c1b1d118a11ad380eb5a85d7776a 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/mapper/StoreMapper.java +++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/StoreMapper.java @@ -1,9 +1,19 @@ package at.tuwien.mapper; import at.tuwien.api.database.query.QueryResultDto; +import at.tuwien.exception.DatabaseConnectionException; +import at.tuwien.exception.QueryStoreException; +import at.tuwien.exception.TableMalformedException; +import at.tuwien.querystore.Query; import org.apache.commons.codec.digest.DigestUtils; import org.mapstruct.Mapper; +import java.sql.*; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.LinkedList; +import java.util.List; + @Mapper(componentModel = "spring") public interface StoreMapper { @@ -23,4 +33,142 @@ public interface StoreMapper { return DigestUtils.sha256Hex(data.getResult().toString()); } + default PreparedStatement queryStoreRawInsertQuery(Connection connection, Query data) throws QueryStoreException { + final String statement = "INSERT INTO `qs_queries` (`cid`, `dbid`, `query`, `query_normalized`, `query_hash`, `result_number`, `result_hash`, `execution`, `created`, `created_by`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING `id`"; + try { + final PreparedStatement ps = connection.prepareStatement(statement); + ps.setLong(1, data.getCid()); + ps.setLong(2, data.getDbid()); + ps.setString(3, data.getQuery()); + ps.setString(4, data.getQueryNormalized()); + ps.setString(5, data.getQueryHash()); + if (data.getResultNumber() == null) { + ps.setNull(6, Types.NULL); + } else { + ps.setLong(6, data.getResultNumber()); + } + if (data.getResultHash() == null) { + ps.setNull(7, Types.NULL); + } else { + ps.setString(7, data.getResultHash()); + } + ps.setTimestamp(8, Timestamp.from(data.getExecution())); + ps.setTimestamp(9, Timestamp.from(Instant.now())); + ps.setLong(10, data.getCreatedBy()); + return ps; + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryStoreException("Failed to prepare statement", e); + } + } + + default PreparedStatement queryStoreRawSelectAllQuery(Connection connection) throws QueryStoreException { + final String statement = "SELECT `id`, `cid`, `created`, `created_by`, `dbid`, `execution`, `last_modified`, `query`, `query_hash`, `result_hash`, `result_number` FROM `qs_queries`"; + try { + return connection.prepareStatement(statement); + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryStoreException("Failed to prepare statement", e); + } + } + + default PreparedStatement queryStoreRawSelectOneQuery(Connection connection, Long containerId, Long databaseId, Long queryId) throws QueryStoreException { + final String statement = "SELECT `id`, `cid`, `created`, `created_by`, `dbid`, `execution`, `last_modified`, `query`, `query_hash`, `result_hash`, `result_number` FROM `qs_queries` q WHERE q.`cid` = ? AND q.`dbid` = ? AND q.`id` = ?"; + try { + final PreparedStatement ps = connection.prepareStatement(statement); + ps.setLong(1, containerId); + ps.setLong(2, databaseId); + ps.setLong(3, queryId); + return ps; + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryStoreException("Failed to prepare statement", e); + } + } + + default PreparedStatement queryStoreRawUpdateQuery(Connection connection, Query data) throws QueryStoreException { + final String statement = "UPDATE `qs_queries` SET `execution` = ?, `last_modified` = ?, `query` = ?, `query_hash` = ?, `result_hash` = ?, `result_number` = ?, `query_normalized` = ? WHERE `cid` = ? AND `dbid` = ? AND `id` = ?"; + try { + final PreparedStatement ps = connection.prepareStatement(statement); + ps.setTimestamp(1, Timestamp.from(data.getExecution())); + ps.setTimestamp(2, Timestamp.from(Instant.now())); + ps.setString(3, data.getQuery()); + ps.setString(4, data.getQueryHash()); + ps.setString(5, data.getResultHash()); + ps.setLong(6, data.getResultNumber()); + ps.setString(7, data.getQueryNormalized()); + /* where */ + ps.setLong(8, data.getCid()); + ps.setLong(9, data.getDbid()); + ps.setLong(10, data.getId()); + return ps; + } catch (SQLException e) { + log.error("Failed to prepare statement"); + log.debug("failed to prepare statement {} reason {}", statement, e.getMessage()); + throw new QueryStoreException("Failed to prepare statement", e); + } + } + + default List<Query> resultSetToQueryList(ResultSet data) throws TableMalformedException { + final List<Query> list = new LinkedList<>(); + try { + while (data.next()) { + list.add(resultSetToQuery(data)); + } + } catch (SQLException e) { + log.error("Failed to map queries"); + throw new TableMalformedException("Failed to map queries", e); + } + return list; + } + + default Query resultSetToQuery(ResultSet data) throws SQLException { + return resultSetToQuery(data, false); + } + + default Long resultSetToId(ResultSet data) throws TableMalformedException, QueryStoreException { + try { + if (!data.next()) { + log.error("Failed to map id"); + throw new TableMalformedException("Failed to map id"); + } + return data.getLong(1); + } catch (SQLException e) { + log.error("Failed to retrieve id"); + throw new QueryStoreException("Failed to retrieve id"); + } + } + + /** + * Maps a result set row to an entity. + * + * @param data The result set row. + * @return The query. + * @throws SQLException The mapping does not exist + */ + default Query resultSetToQuery(ResultSet data, Boolean next) throws SQLException { + if (next && !data.next()) { + throw new SQLException("Tuple does not exist"); + } + return Query.builder() + .id(data.getLong(1)) + .cid(data.getLong(2)) + .created(data.getTimestamp(3) + .toInstant()) + .createdBy(data.getLong(4)) + .dbid(data.getLong(5)) + .execution(data.getTimestamp(6) + .toInstant()) + .lastModified(data.getTimestamp(7) != null ? data.getTimestamp(7) + .toInstant() : null) + .query(data.getString(8)) + .queryHash(data.getString(9)) + .resultHash(data.getString(10) != null ? data.getString(10) : null) + .resultNumber(data.getLong(11)) + .build(); + } + } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java index ae969cf385532cef65009dc11b427582b276a5b1..5c23fcdba8ec7131975ee4f875988b7642ba63ee 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java @@ -84,7 +84,7 @@ public interface QueryService { QueryResultDto findAll(Long containerId, Long databaseId, Long tableId, Instant timestamp, Long page, Long size) throws TableNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, DatabaseConnectionException, TableMalformedException, PaginationException, - ContainerNotFoundException; + ContainerNotFoundException, QueryMalformedException; /** * Select all data known in the database-table id tuple at a given time and return a downloadable input stream @@ -107,7 +107,7 @@ public interface QueryService { ExportResource findAll(Long containerId, Long databaseId, Long tableId, Instant timestamp) throws TableNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, DatabaseConnectionException, TableMalformedException, PaginationException, ContainerNotFoundException, - FileStorageException; + FileStorageException, QueryMalformedException; /** * Finds one query by container-database-query triple. @@ -144,7 +144,7 @@ public interface QueryService { */ Long count(Long containerId, Long databaseId, Long tableId, Instant timestamp) throws ContainerNotFoundException, DatabaseNotFoundException, TableNotFoundException, - TableMalformedException, ImageNotSupportedException, DatabaseConnectionException; + TableMalformedException, ImageNotSupportedException, DatabaseConnectionException, QueryMalformedException, QueryStoreException; /** * Insert data from AMQP client into a table of a table-database id tuple, we need the "root" role for this as the @@ -178,7 +178,7 @@ public interface QueryService { */ void delete(Long containerId, Long databaseId, Long tableId, TableCsvDeleteDto data) throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException, - TableNotFoundException, TupleDeleteException, ContainerNotFoundException, DatabaseConnectionException; + TableNotFoundException, TupleDeleteException, ContainerNotFoundException, DatabaseConnectionException, QueryMalformedException; /** * Insert data from a csv into a table of a table-database id tuple, we need the "root" role for this as the @@ -194,5 +194,5 @@ public interface QueryService { * @throws ContainerNotFoundException The container was not found in the metadata database. */ void insert(Long containerId, Long databaseId, Long tableId, ImportDto data) throws ImageNotSupportedException, - TableMalformedException, DatabaseNotFoundException, TableNotFoundException, ContainerNotFoundException, DatabaseConnectionException; + TableMalformedException, DatabaseNotFoundException, TableNotFoundException, ContainerNotFoundException, DatabaseConnectionException, QueryMalformedException; } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java b/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java index 4d1f56de583393922c7441508fd630d33af186f9..bd50d25c978c9e97ba29d65abfb27bc31acba99b 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/StoreService.java @@ -24,7 +24,7 @@ public interface StoreService { * @throws QueryStoreException The query store produced an invalid result */ List<Query> findAll(Long containerId, Long databaseId) throws DatabaseNotFoundException, ImageNotSupportedException, - QueryStoreException, ContainerNotFoundException; + QueryStoreException, ContainerNotFoundException, DatabaseConnectionException, TableMalformedException; /** * Finds a query in the query store of the given database id and query id. @@ -37,8 +37,8 @@ public interface StoreService { * @throws QueryStoreException The query store produced an invalid result * @throws QueryNotFoundException The query store did not return a query */ - Query findOne(Long containerId, Long databaseId, Long queryId) throws DatabaseNotFoundException, ImageNotSupportedException, - QueryStoreException, QueryNotFoundException, ContainerNotFoundException; + Query findOne(Long containerId, Long databaseId, Long queryId) throws DatabaseNotFoundException, + ImageNotSupportedException, DatabaseConnectionException, QueryNotFoundException, QueryStoreException; /** * Inserts a query and metadata to the query store of a given database id @@ -54,7 +54,7 @@ public interface StoreService { Query insert(Long containerId, Long databaseId, QueryResultDto result, SaveStatementDto metadata, Principal principal) throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException, - ContainerNotFoundException, UserNotFoundException; + ContainerNotFoundException, UserNotFoundException, DatabaseConnectionException, TableMalformedException; /** * Inserts a query and metadata to the query store of a given database id @@ -71,7 +71,7 @@ public interface StoreService { Query insert(Long containerId, Long databaseId, QueryResultDto result, ExecuteStatementDto metadata, Principal principal, Instant execution) throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException, - ContainerNotFoundException, UserNotFoundException; + ContainerNotFoundException, UserNotFoundException, DatabaseConnectionException, TableMalformedException; /** * @@ -88,5 +88,5 @@ public interface StoreService { */ Query update(Long containerId, Long databaseId, QueryResultDto result, Long resultNumber, Query metadata) throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException, - ContainerNotFoundException; + ContainerNotFoundException, DatabaseConnectionException; } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/TableService.java b/fda-query-service/services/src/main/java/at/tuwien/service/TableService.java index 08048f15aae34e58734d33fb96125278fb7d2853..2c6454d0dd335b4828488866c3d180fea3eb5a8a 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/TableService.java @@ -2,9 +2,7 @@ package at.tuwien.service; import at.tuwien.api.database.table.TableHistoryDto; import at.tuwien.entities.database.table.Table; -import at.tuwien.exception.DatabaseNotFoundException; -import at.tuwien.exception.QueryMalformedException; -import at.tuwien.exception.TableNotFoundException; +import at.tuwien.exception.*; import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -42,5 +40,5 @@ public interface TableService { * @throws TableNotFoundException The table is not found. */ List<TableHistoryDto> findHistory(Long containerId, Long databaseId, Long tableId) - throws DatabaseNotFoundException, QueryMalformedException, TableNotFoundException; + throws DatabaseNotFoundException, QueryMalformedException, TableNotFoundException, DatabaseConnectionException, QueryStoreException; } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java index 0bcd9658bfa9dc07d4f560dfe1120cef3a2225ca..d1df74668d020c09b890988ba0b94c6961c724b0 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/HibernateConnector.java @@ -11,17 +11,14 @@ import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Service; import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Collection; import java.util.stream.Collectors; @Log4j2 @Service public abstract class HibernateConnector { - protected static Connection getConnection(ContainerImage image, Container container, Database database) throws DatabaseConnectionException { + protected static ComboPooledDataSource getDataSource(ContainerImage image, Container container, Database database) throws DatabaseConnectionException { final ComboPooledDataSource dataSource = new ComboPooledDataSource(); final String url = "jdbc:" + image.getJdbcMethod() + "://" + container.getInternalName() + "/" + (database != null ? database.getInternalName() : ""); dataSource.setJdbcUrl(url); @@ -44,45 +41,7 @@ public abstract class HibernateConnector { dataSource.setAcquireIncrement(5); dataSource.setMaxPoolSize(20); dataSource.setMaxStatements(100); - final Connection connection; - try { - connection = dataSource.getConnection(); - } catch (SQLException e) { - log.error("Failed to connect to the database"); - log.debug("failed to connect to the database {}", database); - throw new DatabaseConnectionException("Failed to connect to the database"); - } - return connection; - } - - protected static Long activeConnection(Connection connection) throws DatabaseConnectionException { - final ResultSet resultSet = execute(connection, "SHOW STATUS LIKE 'threads_connected'"); - try { - if (resultSet.next()) { - return resultSet.getLong(2); - } - } catch (SQLException e) { - log.error("Failed to determine active connections"); - throw new DatabaseConnectionException("Failed to determine active connections", e); - } - log.error("Failed to determine active connections"); - throw new DatabaseConnectionException("Failed to determine active connections"); - } - - protected static ResultSet execute(Connection connection, String statement) throws DatabaseConnectionException { - return execute(connection, statement, null); - } - - protected static ResultSet execute(Connection connection, String statement, Collection<Object> data) throws DatabaseConnectionException { - final PreparedStatement preparedStatement; - try { - preparedStatement = connection.prepareStatement(statement, data); - return preparedStatement.executeQuery(); - } catch (SQLException e) { - log.error("Failed to execute statement"); - log.debug("failed to execute statement {}", statement); - throw new DatabaseConnectionException("Failed to execute statement", e); - } + return dataSource; } } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java index 26a347d35f773dea8537996b535d57d0d3fef924..1b8960b15b0869f709ca1b16ee04c1dd39ee28c5 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java @@ -1,7 +1,6 @@ package at.tuwien.service.impl; import at.tuwien.ExportResource; -import at.tuwien.InsertTableRawQuery; import at.tuwien.api.database.query.ExecuteStatementDto; import at.tuwien.api.database.query.ImportDto; import at.tuwien.api.database.query.QueryResultDto; @@ -14,6 +13,7 @@ import at.tuwien.exception.*; import at.tuwien.mapper.QueryMapper; import at.tuwien.querystore.Query; import at.tuwien.service.*; +import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserManager; @@ -32,12 +32,14 @@ import java.io.InputStream; import java.io.StringReader; import java.security.Principal; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.time.DateTimeException; import java.time.Instant; import java.time.format.DateTimeParseException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; @Log4j2 @@ -65,9 +67,9 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService throws DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException, QueryStoreException, ContainerNotFoundException, ColumnParseException, UserNotFoundException, DatabaseConnectionException, TableMalformedException { - Query q = storeService.insert(containerId, databaseId, null, statement, principal, Instant.now()); - final QueryResultDto result = this.reExecute(containerId, databaseId, q, page, size); - q = storeService.update(containerId, databaseId, result, result.getResultNumber(), q); + final Query query = storeService.insert(containerId, databaseId, null, statement, principal, Instant.now()); + final QueryResultDto result = this.reExecute(containerId, databaseId, query, page, size); + storeService.update(containerId, databaseId, result, result.getResultNumber(), query); return result; } @@ -75,16 +77,14 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService @Transactional(readOnly = true) public QueryResultDto reExecute(Long containerId, Long databaseId, Query query, Long page, Long size) throws QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, - ColumnParseException, DatabaseConnectionException, TableMalformedException { + ColumnParseException, DatabaseConnectionException, TableMalformedException, QueryStoreException { /* find */ final Database database = databaseService.find(containerId, databaseId); if (!database.getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); } /* run query */ - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); - final ResultSet resultSet = execute(connection, queryMapper.queryToRawTimestampedQuery(query.getQuery(), database, query.getExecution(), page, size)); - log.debug("number of active connections {}", activeConnection(connection)); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* map the result to the tables (with respective columns) from the statement metadata */ final List<TableColumn> columns; try { @@ -95,10 +95,17 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService } final QueryResultDto dto; try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.queryToRawTimestampedQuery(connection, + query.getQuery(), database, query.getExecution(), page, size); + final ResultSet resultSet = preparedStatement.executeQuery(); dto = queryMapper.resultListToQueryResultDto(columns, resultSet); } catch (SQLException e) { - log.error("Failed to map object"); - throw new TableMalformedException("Failed to map object", e); + log.error("Failed to execute and map time-versioned query"); + log.debug("failed to execute and map time-versioned query: {}", e.getMessage()); + throw new TableMalformedException("Failed to execute and map time-versioned query", e); + } finally { + dataSource.close(); } dto.setId(query.getId()); dto.setResultNumber(countQueryResults(containerId, databaseId, query)); @@ -110,15 +117,17 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService public QueryResultDto findAll(Long containerId, Long databaseId, Long tableId, Instant timestamp, Long page, Long size) throws TableNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, DatabaseConnectionException, TableMalformedException, PaginationException, - ContainerNotFoundException { + ContainerNotFoundException, QueryMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); final Table table = tableService.find(containerId, databaseId, tableId); /* run query */ - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); - final ResultSet resultSet = execute(connection, queryMapper.tableToRawFindAllQuery(table, timestamp, size, page)); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); final QueryResultDto result; try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.tableToRawFindAllQuery(connection, table, timestamp, size, page); + final ResultSet resultSet = preparedStatement.executeQuery(); result = queryMapper.queryTableToQueryResultDto(resultSet, table); } catch (DateTimeException e) { log.error("Failed to parse date from the one stored in the metadata database"); @@ -126,6 +135,8 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService } catch (SQLException e) { log.error("Failed to map object"); throw new TableMalformedException("Failed to map object", e); + } finally { + dataSource.close(); } return result; } @@ -135,20 +146,26 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService public ExportResource findAll(Long containerId, Long databaseId, Long tableId, Instant timestamp) throws TableNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, DatabaseConnectionException, TableMalformedException, PaginationException, ContainerNotFoundException, - FileStorageException { + FileStorageException, QueryMalformedException { final String filename = RandomStringUtils.randomAlphabetic(40) + ".csv"; /* find */ final Database database = databaseService.find(containerId, databaseId); final Table table = tableService.find(containerId, databaseId, tableId); /* run query */ - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); - execute(connection, queryMapper.tableToRawExportQuery(table, timestamp, filename)); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* read file */ final InputStream inputStream; try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.tableToRawExportQuery(connection, table, timestamp, filename); + preparedStatement.executeUpdate(); inputStream = FileUtils.openInputStream(new File("/tmp/" + filename)); - } catch (IOException e) { - throw new FileStorageException("Export file not present"); + } catch (IOException | SQLException e) { + log.error("Failed to execute query and/or export file"); + log.debug("failed to execute query and/or export file: {}", e.getMessage()); + throw new FileStorageException("Failed to execute query and/or export file", e); + } finally { + dataSource.close(); } return ExportResource.builder() .resource(new InputStreamResource(inputStream)) @@ -167,15 +184,20 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService final Database database = databaseService.find(containerId, databaseId); final Query query = storeService.findOne(containerId, databaseId, queryId); /* run query */ - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); - execute(connection, queryMapper.queryToRawExportQuery(query, filename)); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* read file */ final InputStream inputStream; try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.queryToRawExportQuery(connection, query, filename); + preparedStatement.executeUpdate(); inputStream = FileUtils.openInputStream(new File("/tmp/" + filename)); - } catch (IOException e) { - log.error("Export file not present"); - throw new FileStorageException("Export file not present", e); + } catch (IOException | SQLException e) { + log.error("Failed to execute query and/or export file"); + log.debug("failed to execute query and/or export file: {}", e.getMessage()); + throw new FileStorageException("Failed to execute query and/or export file", e); + } finally { + dataSource.close(); } final InputStreamResource resource = new InputStreamResource(inputStream); return ExportResource.builder() @@ -188,14 +210,23 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService @Transactional public Long count(Long containerId, Long databaseId, Long tableId, Instant timestamp) throws DatabaseNotFoundException, TableNotFoundException, - ImageNotSupportedException, DatabaseConnectionException { + ImageNotSupportedException, DatabaseConnectionException, QueryMalformedException, QueryStoreException, TableMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); final Table table = tableService.find(containerId, databaseId, tableId); /* run query */ - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); - final ResultSet resultSet = execute(connection, queryMapper.tableToRawCountAllQuery(table, timestamp)); - return queryMapper.resultSetToLong(resultSet); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); + try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.tableToRawCountAllQuery(connection, table, timestamp); + final ResultSet resultSet = preparedStatement.executeQuery(); + return queryMapper.resultSetToNumber(resultSet); + } catch (SQLException e) { + log.error("Failed to count tuples"); + throw new TableMalformedException("Failed to count tuples", e); + } finally { + dataSource.close(); + } } @Override @@ -208,56 +239,78 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService final Table table = tableService.find(containerId, databaseId, tableId); /* run query */ if (data.getData().size() == 0) return; - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* prepare the statement */ - final InsertTableRawQuery raw; try { - raw = queryMapper.tableCsvDtoToRawInsertQuery(table, data); + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.tableCsvDtoToRawInsertQuery(connection, table, data); + preparedStatement.executeUpdate(); } catch (DateTimeParseException e) { log.error("Failed to parse date: {}", e.getMessage()); - return; } catch (NumberFormatException e) { log.error("Failed to parse number: {}", e.getMessage()); - return; } catch (Exception e) { log.error("Failed for unknown reason: {}", e.getMessage()); - return; + } finally { + dataSource.close(); } - execute(connection, raw.getQuery(), raw.getData()); } @Override @Transactional public void delete(Long containerId, Long databaseId, Long tableId, TableCsvDeleteDto data) throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException, - TableNotFoundException, DatabaseConnectionException { + TableNotFoundException, DatabaseConnectionException, QueryMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); final Table table = tableService.find(containerId, databaseId, tableId); /* run query */ if (data.getKeys().size() == 0) return; - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* prepare the statement */ - execute(connection, queryMapper.tableCsvDtoToRawDeleteQuery(table, data), data.getKeys().values()); - log.info("Deleted tuple(s)"); - log.debug("Deleted tuple(s) {}", data); + final List<Object> values = new LinkedList<>(data.getKeys() + .values()); + try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.tableCsvDtoToRawDeleteQuery(connection, table, data); + for (int i = 0; i < data.getKeys().size(); i++) { + preparedStatement.setObject(i, values.get(i)); + } + } catch(SQLException e) { + log.error("Failed to delete tuples"); + throw new TableMalformedException("Failed to delete tuples"); + } finally { + dataSource.close(); + } } @Override @Transactional public void insert(Long containerId, Long databaseId, Long tableId, ImportDto data) throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException, - TableNotFoundException, ContainerNotFoundException, DatabaseConnectionException { + TableNotFoundException, ContainerNotFoundException, DatabaseConnectionException, QueryMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); final Table table = tableService.find(containerId, databaseId, tableId); /* preparing the statements */ - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* Create a temporary table, insert there, transfer with update on duplicate key and lastly drops the temporary table */ - execute(connection, queryMapper.generateTemporaryTableSQL(table)); - execute(connection, queryMapper.pathToRawInsertQuery(table, data).getQuery()); - execute(connection, queryMapper.generateInsertFromTemporaryTableSQL(table)); - execute(connection, queryMapper.dropTemporaryTableSQL(table)); + try { + final Connection connection = dataSource.getConnection(); + queryMapper.generateTemporaryTableSQL(connection, table) + .executeUpdate(); + queryMapper.pathToRawInsertQuery(connection, table, data) + .executeUpdate(); + queryMapper.generateInsertFromTemporaryTableSQL(connection, table) + .executeUpdate(); + queryMapper.dropTemporaryTableSQL(connection, table) + .executeUpdate(); + } catch(SQLException e) { + log.error("Failed to create/insert/drop temporary table"); + throw new TableMalformedException("Failed to create/insert/drop temporary table"); + } finally { + dataSource.close(); + } } /** @@ -357,13 +410,23 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService */ @Transactional(readOnly = true) protected Long countQueryResults(Long containerId, Long databaseId, Query query) - throws DatabaseNotFoundException, ImageNotSupportedException, DatabaseConnectionException { + throws DatabaseNotFoundException, ImageNotSupportedException, DatabaseConnectionException, + QueryMalformedException, QueryStoreException, TableMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); /* run query */ - final Connection connection = getConnection(database.getContainer().getImage(), database.getContainer(), database); - final ResultSet resultSet = execute(connection, queryMapper.queryToRawTimestampedCountQuery(query.getQuery(), database, query.getExecution())); - return queryMapper.resultSetToLong(resultSet); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); + try { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.queryToRawTimestampedCountQuery(connection, query.getQuery(), database, query.getExecution()); + final ResultSet resultSet = preparedStatement.executeQuery(); + return queryMapper.resultSetToNumber(resultSet); + } catch (SQLException e) { + log.error("Failed to count tuples"); + throw new TableMalformedException("Failed to count tuples", e); + } finally { + dataSource.close(); + } } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/RabbitMqServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/RabbitMqServiceImpl.java index b7398a6694ccbb9b3b7a38ed423efaff96c080ea..0e44adf399641fea249a6f976c0645febcb50104 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/RabbitMqServiceImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/RabbitMqServiceImpl.java @@ -97,6 +97,9 @@ public class RabbitMqServiceImpl implements MessageQueueService { } catch (ContainerNotFoundException e) { log.error("Failed to find container with id {}", containerId); /* ignore */ + } catch (DatabaseConnectionException e) { + log.error("Failed to connect to container with id {}", containerId); + /* ignore */ } } }); diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java index 2badbf8feeda07894cfb0c299e925889ce26e46f..e5c4eeeb223ddcc27de8971ec86277244240d89a 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/StoreServiceImpl.java @@ -12,15 +12,15 @@ import at.tuwien.querystore.Query; import at.tuwien.service.DatabaseService; import at.tuwien.service.StoreService; import at.tuwien.service.UserService; +import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; import org.apache.commons.codec.digest.DigestUtils; -import org.hibernate.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.persistence.PersistenceException; import java.security.Principal; +import java.sql.*; import java.time.Instant; import java.util.List; @@ -44,8 +44,9 @@ public class StoreServiceImpl extends HibernateConnector implements StoreService @Override @Transactional(readOnly = true) - public List<at.tuwien.querystore.Query> findAll(Long containerId, Long databaseId) throws DatabaseNotFoundException, - ImageNotSupportedException, QueryStoreException, ContainerNotFoundException { + public List<Query> findAll(Long containerId, Long databaseId) throws DatabaseNotFoundException, + ImageNotSupportedException, QueryStoreException, ContainerNotFoundException, DatabaseConnectionException, + TableMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); if (!database.getContainer().getImage().getRepository().equals("mariadb")) { @@ -53,95 +54,76 @@ public class StoreServiceImpl extends HibernateConnector implements StoreService } log.trace("find all queries in database id {}", databaseId); /* run query */ - final Session session = getCurrentSession(database.getContainer().getImage(), database.getContainer(), database); - final Transaction transaction = session.beginTransaction(); - activeConnection(session); - /* use jpq to select all */ - final org.hibernate.query.Query<at.tuwien.querystore.Query> queries = session.createQuery("select q from Query q", - at.tuwien.querystore.Query.class); - final List<Query> out; + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); + /* select all */ try { - out = queries.list(); - transaction.commit(); - return out; - } catch (PersistenceException e) { - log.error("Failed to find all queries"); - session.close(); - throw new QueryStoreException("Failed to find all queries"); + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = storeMapper.queryStoreRawSelectAllQuery(connection); + final ResultSet resultSet = preparedStatement.executeQuery(); + return storeMapper.resultSetToQueryList(resultSet); + } catch (SQLException e) { + log.error("Failed to find queries"); + log.debug("failed to find queries in container with id {} and database with id {}, reason {}", containerId, databaseId, e.getMessage()); + throw new QueryStoreException("Query not found"); } finally { - if (session.isOpen()) { - session.close(); - } + dataSource.close(); } + } @Override @Transactional(readOnly = true) - public at.tuwien.querystore.Query findOne(Long containerId, Long databaseId, Long queryId) throws DatabaseNotFoundException, - ImageNotSupportedException, QueryNotFoundException, QueryStoreException { + public Query findOne(Long containerId, Long databaseId, Long queryId) throws DatabaseNotFoundException, + ImageNotSupportedException, DatabaseConnectionException, QueryNotFoundException, QueryStoreException { /* find */ final Database database = databaseService.find(containerId, databaseId); if (!database.getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); } /* run query */ - final Session session = getCurrentSession(database.getContainer().getImage(), database.getContainer(), database); - final Transaction transaction = session.beginTransaction(); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* use jpa to select one */ - final org.hibernate.query.Query<at.tuwien.querystore.Query> query = session.createQuery( - "from Query where cid = :cid and dbid = :dbid and id = :id", - at.tuwien.querystore.Query.class); - query.setParameter("cid", containerId); - query.setParameter("dbid", databaseId); - query.setParameter("id", queryId); - final at.tuwien.querystore.Query result; + final Query query; try { - result = query.uniqueResult(); - activeConnection(session); - transaction.commit(); - } catch (PersistenceException e) { - log.error("Failed to find single query"); - session.close(); - throw new QueryStoreException("Failed to find single query", e); - } finally { - if (session.isOpen()) { - session.close(); - } - } - if (result == null) { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = storeMapper.queryStoreRawSelectOneQuery(connection, containerId, databaseId, queryId); + final ResultSet resultSet = preparedStatement.executeQuery(); + query = storeMapper.resultSetToQuery(resultSet, true); + return query; + } catch (SQLException e) { log.error("Query not found with id {}", queryId); throw new QueryNotFoundException("Query not found"); + } finally { + dataSource.close(); } - return result; } @Override @Transactional(readOnly = true) - public at.tuwien.querystore.Query insert(Long containerId, Long databaseId, QueryResultDto result, SaveStatementDto metadata, - Principal principal) + public Query insert(Long containerId, Long databaseId, QueryResultDto result, SaveStatementDto metadata, + Principal principal) throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException, - ContainerNotFoundException, UserNotFoundException { + ContainerNotFoundException, UserNotFoundException, DatabaseConnectionException, TableMalformedException { return insert(containerId, databaseId, result, queryMapper.saveStatementDtoToExecuteStatementDto(metadata), principal, null); } @Override @Transactional(readOnly = true) - public at.tuwien.querystore.Query insert(Long containerId, Long databaseId, QueryResultDto result, ExecuteStatementDto metadata, - Principal principal, Instant execution) + public Query insert(Long containerId, Long databaseId, QueryResultDto result, ExecuteStatementDto metadata, + Principal principal, Instant execution) throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException, - ContainerNotFoundException, UserNotFoundException { + ContainerNotFoundException, UserNotFoundException, DatabaseConnectionException, TableMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); if (!database.getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); } - log.debug("Insert into database id {}, metadata {}", databaseId, metadata); + log.trace("insert into database id {}, metadata {}", databaseId, metadata); /* user */ final User creator = userService.findByUsername(principal.getName()); /* save */ - final Session session = getCurrentSession(database.getContainer().getImage(), database.getContainer(), database); - final Transaction transaction = session.beginTransaction(); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); final at.tuwien.querystore.Query query = at.tuwien.querystore.Query.builder() .cid(containerId) .dbid(databaseId) @@ -154,59 +136,52 @@ public class StoreServiceImpl extends HibernateConnector implements StoreService .createdBy(creator.getId()) .build(); try { - session.save(query); - activeConnection(session); - transaction.commit(); - /* store the result in the query store */ - log.info("Saved query with id {}", query.getId()); - log.debug("saved query {}", query); + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = storeMapper.queryStoreRawInsertQuery(connection, query); + final ResultSet resultSet = preparedStatement.executeQuery(); + query.setId(storeMapper.resultSetToId(resultSet)); + log.info("Inserted query with id {} into the query store of database with id {}", query.getId(), databaseId); + log.debug("inserted query {} into the query store of database {}", query, database); return query; - } catch (PersistenceException e) { - log.error("Failed to save query"); - session.close(); - throw new QueryStoreException("Failed to save query", e); + } catch (SQLException e) { + log.error("Failed to execute query"); + log.debug("failed to execute query: {}", e.getMessage()); + throw new QueryStoreException("Failed to execute query", e); } finally { - if (session.isOpen()) { - session.close(); - } + dataSource.close(); } } @Override @Transactional(readOnly = true) - public at.tuwien.querystore.Query update(Long containerId, Long databaseId, QueryResultDto result, Long resultNumber, - at.tuwien.querystore.Query query) - throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException { + public Query update(Long containerId, Long databaseId, QueryResultDto result, Long resultNumber, Query query) + throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException, DatabaseConnectionException { /* find */ final Database database = databaseService.find(containerId, databaseId); if (!database.getContainer().getImage().getRepository().equals("mariadb")) { throw new ImageNotSupportedException("Currently only MariaDB is supported"); } - - log.debug("Update database id {}, metadata {}", databaseId, query); /* save */ - final Session session = getCurrentSession(database.getContainer().getImage(), database.getContainer(), database); - final Transaction transaction = session.beginTransaction(); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); query.setQueryHash(DigestUtils.sha256Hex(query.getQuery())); query.setResultNumber(resultNumber); query.setResultHash(storeMapper.queryResultDtoToString(result)); + final Query out; try { - session.update(query); - activeConnection(session); - transaction.commit(); - /* store the result in the query store */ - log.info("Update query with id {}", query.getId()); - log.debug("saved query {}", query); - return query; - } catch (PersistenceException e) { + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = storeMapper.queryStoreRawUpdateQuery(connection, query); + preparedStatement.executeUpdate(); + final PreparedStatement preparedStatement1 = storeMapper.queryStoreRawSelectOneQuery(connection, containerId, databaseId, query.getId()); + final ResultSet resultSet = preparedStatement1.executeQuery(); + out = storeMapper.resultSetToQuery(resultSet, true); + } catch (SQLException e) { log.error("Failed to update query"); - session.close(); + log.debug("failed to update query, reason: {}", e.getMessage()); throw new QueryStoreException("Failed to update query", e); } finally { - if (session.isOpen()) { - session.close(); - } + dataSource.close(); } + return out; } diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 9f7d7160f254a7556bc211c6067d0a41f71e301d..fe42b7d441c519b6b26f47819e0a6c9447c58e17 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -3,22 +3,21 @@ package at.tuwien.service.impl; import at.tuwien.api.database.table.TableHistoryDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; -import at.tuwien.exception.DatabaseNotFoundException; -import at.tuwien.exception.QueryMalformedException; -import at.tuwien.exception.TableNotFoundException; +import at.tuwien.exception.*; import at.tuwien.mapper.QueryMapper; import at.tuwien.repository.jpa.TableRepository; import at.tuwien.service.DatabaseService; import at.tuwien.service.TableService; +import com.mchange.v2.c3p0.ComboPooledDataSource; import lombok.extern.log4j.Log4j2; -import org.hibernate.Session; -import org.hibernate.Transaction; -import org.hibernate.query.NativeQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.persistence.PersistenceException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.*; @Log4j2 @@ -58,30 +57,25 @@ public class TableServiceImpl extends HibernateConnector implements TableService @Override @Transactional(readOnly = true) public List<TableHistoryDto> findHistory(Long containerId, Long databaseId, Long tableId) - throws DatabaseNotFoundException, QueryMalformedException, TableNotFoundException { + throws DatabaseNotFoundException, TableNotFoundException, DatabaseConnectionException, QueryStoreException, + QueryMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); final Table table = find(containerId, databaseId, tableId); /* run query */ - final Session session = getCurrentSession(database.getContainer().getImage(), database.getContainer(), database); - final Transaction transaction = session.beginTransaction(); + final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database); /* use jpa to select one */ - final NativeQuery<?> query = session.createSQLQuery(queryMapper.historyRawQuery(table)); - final List<?> result; try { - log.debug("affected tuples {}", query.executeUpdate()); - result = query.getResultList(); - transaction.commit(); - } catch (PersistenceException e) { - log.error("Failed to obtain query history"); - session.close(); - throw new QueryMalformedException("Failed to obtain query history", e); + final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = queryMapper.historyRawQuery(connection, table); + final ResultSet resultSet = preparedStatement.executeQuery(); + return queryMapper.resultListToTableHistoryDto(resultSet); + } catch (SQLException e) { + log.error("Failed to map table history"); + throw new QueryStoreException("Failed to map table history", e); } finally { - if (session.isOpen()) { - session.close(); - } + dataSource.close(); } - return queryMapper.resultListToTableHistoryDto(table, result); } } diff --git a/fda-ui/.env-docker b/fda-ui/.env-docker index 119bf7696eb61398aef50468de36b59aaa5014cf..1162dbf84aa1fbe6887c7bb4a64e3f39387d5eba 100644 --- a/fda-ui/.env-docker +++ b/fda-ui/.env-docker @@ -1,3 +1,2 @@ # GATEWAY SERVICE API="http://fda-gateway-service:9095" -URL="https://dbrepo.ossdip.at" diff --git a/fda-ui/.env.example b/fda-ui/.env.example index ff8d46041802fc476d7b300d118f1201eb1350ca..3a7cb6a745e4e05d95a6b67d783aff243ae8e57d 100644 --- a/fda-ui/.env.example +++ b/fda-ui/.env.example @@ -2,4 +2,3 @@ # - CORRECT: http://localhost:9095 # - WRONG: http://localhost:9095/ API="http://localhost:9095" -URL="http://localhost:3000" diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue index c601d0ecc88bcf0e2f78533b3dd765b302d8a656..292f620d62a1a2d506d05a386a85d3f797c0b075 100644 --- a/fda-ui/layouts/default.vue +++ b/fda-ui/layouts/default.vue @@ -61,10 +61,6 @@ :to="switchLocalePath(locale.code)"> <v-list-item-title>{{ locale.name }}</v-list-item-title> </v-list-item> - <v-list-item - @click="switchTheme()"> - {{ nextTheme }} Theme - </v-list-item> <v-list-item v-if="token" @click="logout"> @@ -186,9 +182,6 @@ export default { this.loadDB() }, methods: { - switchTheme () { - this.$vuetify.theme.dark = !this.$vuetify.theme.dark - }, logout () { this.$store.commit('SET_TOKEN', null) this.$store.commit('SET_USER', null) diff --git a/fda-ui/pages/container/_container_id/database/_database_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/info.vue index 0a3af4e5a74361841fd655645530d068bae5e266..d7b586ac145832845219a90836569c0fc7377282 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/info.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/info.vue @@ -10,21 +10,28 @@ <v-list-item> <v-list-item-content> <v-list-item-title> - Visibility + Database Visibility </v-list-item-title> <v-list-item-content> <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> <span v-if="!loading">{{ database.is_public ? 'Public' : 'Private' }}</span> </v-list-item-content> <v-list-item-title class="mt-2"> - Publisher + Database Publisher </v-list-item-title> <v-list-item-content> <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> <span v-if="!loading">{{ publisher }}</span> </v-list-item-content> <v-list-item-title class="mt-2"> - Description + Database Internal Name + </v-list-item-title> + <v-list-item-content> + <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> + <span v-if="!loading">{{ internal_name }}</span> + </v-list-item-content> + <v-list-item-title class="mt-2"> + Database Description </v-list-item-title> <v-list-item-content> <v-skeleton-loader v-if="loading" type="paragraph" width="50%" /> @@ -161,6 +168,9 @@ export default { language () { return this.database.language === null ? '(none)' : this.database.language }, + internal_name () { + return this.database.internal_name + }, publication () { return this.database.publication === null ? '(none)' : this.database.publication }, diff --git a/fda-ui/pages/user/index.vue b/fda-ui/pages/user/index.vue index 89747447928482575782806b6123304e131a3af7..b90d1ffd8403ef33c4ab6700f810435462e54135 100644 --- a/fda-ui/pages/user/index.vue +++ b/fda-ui/pages/user/index.vue @@ -114,6 +114,14 @@ label="ORCID" /> </v-col> </v-row> + <v-row dense> + <v-col cols="5"> + <v-switch + v-model="user.theme_dark" + inset + label="Dark Mode" /> + </v-col> + </v-row> <v-row dense> <v-col cols="5"> <v-btn @@ -179,7 +187,8 @@ export default { titles_before: null, email_verified: false, affiliation: null, - orcid: null + orcid: null, + theme_dark: null }, reset: { password: null