Skip to content

Commit

Permalink
Merge pull request #52 from PrediktorAS/fix/query-execution
Browse files Browse the repository at this point in the history
Fix the execution of the query by passing the parameters instead of c…
  • Loading branch information
jNormaster committed Nov 24, 2023
2 parents 920f651 + bb90afd commit bdf5d23
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 86 deletions.
5 changes: 3 additions & 2 deletions src/pyprediktormapclient/dwh/context/enercast.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ def upsert_forecast_data(
self, enercast_forecast_data: Dict, forecast_type_key: Union[int, None] = None
) -> List[Any]:
enercast_forecast_data_json = json.dumps({"results": enercast_forecast_data})
query = f"EXEC dwetl.UpsertEnercastForecastData {enercast_forecast_data_json}, {forecast_type_key}"
return self.dwh.execute(query)

query = "EXEC dwetl.UpsertEnercastForecastData ?, ?"
return self.dwh.execute(query, enercast_forecast_data_json, forecast_type_key)
22 changes: 11 additions & 11 deletions src/pyprediktormapclient/dwh/context/plant.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ def get_optimal_tracker_angles(self, facility_name: str) -> List[Any]:
def upsert_optimal_tracker_angles(self, facility_data: Dict) -> List[Any]:
facility_data_json = json.dumps(facility_data)
facility_data_json.replace("'", '"')
query = f"EXEC dwetl.UpsertOptimalTrackerAngles @json = {facility_data_json}"
return self.dwh.execute(query)

query = "EXEC dwetl.UpsertOptimalTrackerAngles @json = ?"
return self.dwh.execute(query, facility_data_json)

@validate_call
def insert_log(
Expand All @@ -33,13 +34,12 @@ def insert_log(
has_thrown_error: bool = False,
message: str = "",
) -> List[Any]:
result = "ERROR" if has_thrown_error else "OK"
query = (
f"EXEC dwetl.InsertExtDataUpdateLog "
+ f"@plantname = {plantname}, "
+ f"@extkey = {ext_forecast_type_key}, "
+ f"@DataType = {data_type}, "
+ f"@Message = {message}, "
+ f"@Result = {result}"
query = "EXEC dwetl.InsertExtDataUpdateLog @plantname = ?, @extkey = ?, @DataType = ?, @Message = ?, @Result = ?"
return self.dwh.execute(
query,
plantname,
ext_forecast_type_key,
data_type,
message,
"ERROR" if has_thrown_error else "OK",
)
return self.dwh.execute(query)
5 changes: 3 additions & 2 deletions src/pyprediktormapclient/dwh/context/solcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ def upsert_forecast_data(
}
}
)
query = f"EXEC dwetl.UpsertSolcastForecastData {solcast_forecast_data_json}, {forecast_type_key}"
return self.dwh.execute(query)

query = "EXEC dwetl.UpsertSolcastForecastData ?, ?"
return self.dwh.execute(query, solcast_forecast_data_json, forecast_type_key)
10 changes: 5 additions & 5 deletions src/pyprediktormapclient/dwh/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def fetch(self, query: str, to_dataframe: bool = False) -> List[Any]:
return data_sets if len(data_sets) > 1 else data_sets[0]

@validate_call
def execute(self, query: str, commit: bool = True) -> List[Any]:
def execute(self, query: str, *args, **kwargs) -> List[Any]:
"""Execute the SQL query and return the results.
For instance, if we create a new record in DWH by calling
Expand All @@ -134,17 +134,17 @@ def execute(self, query: str, commit: bool = True) -> List[Any]:
Args:
query (str): The SQL query to execute.
commit (bool): If True, commit the changes to the database.
*args: Variable length argument list to pass to cursor.execute().
**kwargs: Arbitrary keyword arguments to pass to cursor.execute().
Returns:
List[Any]: The results of the query.
"""
self.__connect()
self.cursor.execute(query)
self.cursor.execute(query, *args, **kwargs)

result = self.cursor.fetchall()
if commit:
self.__commit()
self.__commit()

return result

Expand Down
2 changes: 1 addition & 1 deletion src/pyprediktormapclient/dwh/idwh.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ def fetch(self, query: str, to_dataframe: bool = False) -> List[Any]:
pass

@abstractmethod
def execute(self, query: str, commit: bool = True) -> List[Any]:
def execute(self, query: str, *args, **kwargs) -> List[Any]:
pass
6 changes: 4 additions & 2 deletions tests/dwh/context/test_enercast.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test_upsert_forecast_data(monkeypatch):
forecast_type_key = 1

enercast_forecast_data_json = json.dumps({"results": enercast_forecast_data})
expected_query = f"EXEC dwetl.UpsertEnercastForecastData {enercast_forecast_data_json}, {forecast_type_key}"
expected_query = f"EXEC dwetl.UpsertEnercastForecastData ?, ?"
expected_result = []

mock_dwh = Mock(spec=IDWH)
Expand All @@ -112,5 +112,7 @@ def test_upsert_forecast_data(monkeypatch):
enercast_forecast_data, forecast_type_key
)

mock_dwh.execute.assert_called_once_with(expected_query)
mock_dwh.execute.assert_called_once_with(
expected_query, enercast_forecast_data_json, forecast_type_key
)
assert actual_result == expected_result
34 changes: 18 additions & 16 deletions tests/dwh/context/test_plant.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ def test_upsert_optimal_tracker_angles(monkeypatch):
facility_data_json = json.dumps(facility_data)

facility_data_json.replace("'", '"')
expected_query = (
f"EXEC dwetl.UpsertOptimalTrackerAngles @json = {facility_data_json}"
)
expected_query = f"EXEC dwetl.UpsertOptimalTrackerAngles @json = ?"
expected_result = []

mock_dwh = Mock(spec=IDWH)
Expand All @@ -60,7 +58,7 @@ def test_upsert_optimal_tracker_angles(monkeypatch):
plant = Plant(mock_dwh)
actual_result = plant.upsert_optimal_tracker_angles(facility_data)

mock_dwh.execute.assert_called_once_with(expected_query)
mock_dwh.execute.assert_called_once_with(expected_query, facility_data_json)
assert actual_result == expected_result


Expand All @@ -78,11 +76,11 @@ def test_insert_log_when_has_thrown_error_is_false_then_result_is_ok(monkeypatch

expected_query = (
f"EXEC dwetl.InsertExtDataUpdateLog "
+ f"@plantname = {plantname}, "
+ f"@extkey = {ext_forecast_type_key}, "
+ f"@DataType = {data_type}, "
+ f"@Message = {message}, "
+ f"@Result = OK"
+ f"@plantname = ?, "
+ f"@extkey = ?, "
+ f"@DataType = ?, "
+ f"@Message = ?, "
+ f"@Result = ?"
)
expected_result = []

Expand All @@ -94,7 +92,9 @@ def test_insert_log_when_has_thrown_error_is_false_then_result_is_ok(monkeypatch
plantname, ext_forecast_type_key, data_type, has_thrown_error, message
)

mock_dwh.execute.assert_called_once_with(expected_query)
mock_dwh.execute.assert_called_once_with(
expected_query, plantname, ext_forecast_type_key, data_type, message, "OK"
)
assert actual_result == expected_result


Expand All @@ -107,11 +107,11 @@ def test_insert_log_when_has_thrown_error_is_true_then_result_is_error(monkeypat

expected_query = (
f"EXEC dwetl.InsertExtDataUpdateLog "
+ f"@plantname = {plantname}, "
+ f"@extkey = {ext_forecast_type_key}, "
+ f"@DataType = {data_type}, "
+ f"@Message = {message}, "
+ f"@Result = ERROR"
+ f"@plantname = ?, "
+ f"@extkey = ?, "
+ f"@DataType = ?, "
+ f"@Message = ?, "
+ f"@Result = ?"
)
expected_result = []

Expand All @@ -123,5 +123,7 @@ def test_insert_log_when_has_thrown_error_is_true_then_result_is_error(monkeypat
plantname, ext_forecast_type_key, data_type, has_thrown_error, message
)

mock_dwh.execute.assert_called_once_with(expected_query)
mock_dwh.execute.assert_called_once_with(
expected_query, plantname, ext_forecast_type_key, data_type, message, "ERROR"
)
assert actual_result == expected_result
6 changes: 4 additions & 2 deletions tests/dwh/context/test_solcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def test_upsert_forecast_data(monkeypatch):
}
}
)
expected_query = f"EXEC dwetl.UpsertSolcastForecastData {solcast_forecast_data_json}, {forecast_type_key}"
expected_query = f"EXEC dwetl.UpsertSolcastForecastData ?, ?"
expected_result = {
"data": [
{
Expand Down Expand Up @@ -119,5 +119,7 @@ def test_upsert_forecast_data(monkeypatch):
plantname, solcast_forecast_data, forecast_type_key
)

mock_dwh.execute.assert_called_once_with(expected_query)
mock_dwh.execute.assert_called_once_with(
expected_query, solcast_forecast_data_json, forecast_type_key
)
assert actual_result == expected_result
55 changes: 10 additions & 45 deletions tests/dwh/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,15 +723,18 @@ def test_execute_when_init_db_connection_is_successfull_but_fails_when_calling_e
db.execute(query)


def test_execute_when_commit_is_true_then_fetch_results_commit_and_return_data(
def test_execute_when_parameter_passed_then_fetch_results_and_return_data(
monkeypatch,
):
query = "INSERT INTO mytable VALUES (1, 'test')"
query = "INSERT INTO mytable VALUES (?, ?)"
param_one = "John"
param_two = "Smith"
driver_index = 0
expected_result = [(1, "test")]
expected_result = [{"id": 13}]

# Mock the cursor
# Mock the cursor and execute
mock_cursor = Mock()
mock_execute = Mock()

# Mock the connection method to return a mock connection with a mock cursor
mock_connection = Mock()
Expand All @@ -742,52 +745,14 @@ def test_execute_when_commit_is_true_then_fetch_results_commit_and_return_data(
Mock(return_value=mock_connection),
)

# Mock the commit method
mock_commit = Mock()
mock_connection.commit = mock_commit

# Mock the fetch method
mock_fetch = Mock(return_value=expected_result)
mock_cursor.fetchall = mock_fetch

db = Db(grs(), grs(), grs(), grs(), driver_index)
actual_result = db.execute(query, commit=True)

mock_fetch.assert_called_once()
mock_commit.assert_called_once()
assert actual_result == expected_result


def test_execute_when_commit_is_false_then_fetch_results_do_not_commit_but_return_data(
monkeypatch,
):
query = "INSERT INTO mytable VALUES (1, 'test')"
driver_index = 0
expected_result = [(1, "test")]

# Mock the cursor
mock_cursor = Mock()

# Mock the connection method to return a mock connection with a mock cursor
mock_connection = Mock()
mock_connection.cursor.return_value = mock_cursor

monkeypatch.setattr(
"pyodbc.connect",
Mock(return_value=mock_connection),
)

# Mock the commit method
mock_commit = Mock()
mock_connection.commit = mock_commit

# Mock the fetch method
mock_fetch = Mock(return_value=expected_result)
mock_cursor.execute = mock_execute
mock_cursor.fetchall = mock_fetch

db = Db(grs(), grs(), grs(), grs(), driver_index)
actual_result = db.execute(query, commit=False)
actual_result = db.execute(query, param_one, param_two)

mock_execute.assert_called_once_with(query, param_one, param_two)
mock_fetch.assert_called_once()
mock_commit.assert_not_called()
assert actual_result == expected_result

0 comments on commit bdf5d23

Please sign in to comment.