From b4ae0b457bfff05d4dedc01714e8032d4392a5e7 Mon Sep 17 00:00:00 2001
From: Starbeamrainbowlabs <sbrl@starbeamrainbowlabs.com>
Date: Sat, 22 Jun 2019 11:50:23 +0100
Subject: [PATCH] Optimise some queries using the new datetime computed column,
 but there's more work to do.

The fetch-data query in particular is using the wrong index.
---
 logic/Database.php                            |  6 +-
 .../MariaDBMeasurementDataRepository.php      | 62 +++++--------------
 2 files changed, 21 insertions(+), 47 deletions(-)

diff --git a/logic/Database.php b/logic/Database.php
index 979d1f6..699decb 100644
--- a/logic/Database.php
+++ b/logic/Database.php
@@ -53,12 +53,14 @@ class Database
 	}
 	
 	public function query($sql, $variables = []) {
+		// Replace tabs with spaces for debugging purposes
+		$sql = str_replace("\t", "    ", $sql);
+		
 		if($this->settings->get("env.mode") == "development")
 			error_log("[Database/SQL] $sql");
 		
 		// FUTURE: Optionally cache prepared statements?
-		// Note that we replace tabs with spaces for debugging purposes
-		$statement = $this->connection->prepare(str_replace("\t", "    ", $sql));
+		$statement = $this->connection->prepare($sql);
 		$statement->execute($variables);
 		return $statement; // fetchColumn(), fetchAll(), etc. are defined on the statement, not the return value of execute()
 	}
diff --git a/logic/Repositories/MariaDBMeasurementDataRepository.php b/logic/Repositories/MariaDBMeasurementDataRepository.php
index d1b3e1f..4188927 100644
--- a/logic/Repositories/MariaDBMeasurementDataRepository.php
+++ b/logic/Repositories/MariaDBMeasurementDataRepository.php
@@ -20,6 +20,11 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
 	public static $column_metadata_id = "id";
 	public static $column_metadata_storedon = "storedon";
 	public static $column_metadata_recordedon = "recordedon";
+	/**
+	 * A coaleasce of storedon and recorded on.
+	 * @var string
+	 */
+	public static $column_metadata_datetime = "datetime";
 	public static $column_metadata_device_id = "device_id";
 	public static $column_metadata_lat = "reading_latitude";
 	public static $column_metadata_long = "reading_longitude";
@@ -78,26 +83,17 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
 				{$s("table_name_values")}.{$s("column_values_reading_id")},
 				
 				{$s("table_name_metadata")}.{$s("column_metadata_device_id")},
-				COALESCE(
-					{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-					{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-				) AS datetime,
+				{$s("table_name_metadata")}.{$s("column_metadata_datetime")} AS datetime,
 				COUNT({$s("table_name_metadata")}.{$s("column_metadata_device_id")}) AS record_count
 			FROM {$s("table_name_values")}
 			JOIN {$s("table_name_metadata")} ON {$s("table_name_values")}.{$s("column_values_reading_id")} = {$s("table_name_metadata")}.id
 			WHERE
-			COALESCE(
-				{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-				{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-			) >= :start_datetime AND
-			COALESCE(
-				{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-				{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-			) <= :end_datetime
+			{$s("table_name_metadata")}.{$s("column_metadata_datetime")} >= :start_datetime AND
+			{$s("table_name_metadata")}.{$s("column_metadata_datetime")} <= :end_datetime
 			AND 
 				{$s("table_name_values")}.{$s("column_values_reading_type")} = :reading_type
 			GROUP BY {$s("table_name_metadata")}.{$s("column_metadata_device_id")}
-			ORDER BY {$s("table_name_metadata")}.{$s("column_metadata_recordedon")}
+			ORDER BY {$s("table_name_metadata")}.{$s("column_metadata_datetime")}
 				", [
 				"reading_type" => $type_id,
 				// The database likes strings, not PHP DateTime() instances
@@ -111,14 +107,8 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
 		$s = $this->get_static;
 		return $this->database->query(
 			"SELECT
-				MIN(COALESCE(
-					{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-					{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-				)) AS start,
-				MAX(COALESCE(
-					{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-					{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-				)) AS end
+				MIN({$s("table_name_metadata")}.{$s("column_metadata_datetime")}) AS start,
+				MAX({$s("table_name_metadata")}.{$s("column_metadata_datetime")}) AS end
 			FROM {$s("table_name_metadata")}
 			WHERE {$s("table_name_metadata")}.{$s("column_metadata_device_id")} = :device_id;", [
 				"device_id" => $device_id
@@ -135,10 +125,7 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
 				AVG({$s("table_name_values")}.{$s("column_values_value")}) AS {$s("column_values_value")},
 				MIN({$s("table_name_values")}.{$s("column_values_reading_id")}) AS {$s("column_values_reading_id")},
 				
-				MIN(COALESCE(
-					{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-					{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-				)) AS datetime
+				MIN({$s("table_name_metadata")}.{$s("column_metadata_datetime")}) AS datetime
 			FROM {$s("table_name_values")}
 			JOIN {$s("table_name_metadata")} ON
 				{$s("table_name_metadata")}.{$s("column_metadata_id")} = {$s("table_name_values")}.{$s("column_values_reading_id")}
@@ -146,18 +133,9 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
 				{$s("table_name_metadata")}.{$s("column_metadata_device_id")} = :device_id AND
 				{$s("table_name_values")}.{$s("column_values_reading_type")} = :reading_type AND
 				
-				COALESCE(
-					{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-					{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-				) >= :start_datetime AND
-				COALESCE(
-					{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-					{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-				) <= :end_datetime
-			GROUP BY CEIL(UNIX_TIMESTAMP(COALESCE(
-				{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-				{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-			)) / :average_seconds);", [
+				{$s("table_name_metadata")}.{$s("column_metadata_datetime")} >= :start_datetime AND
+				{$s("table_name_metadata")}.{$s("column_metadata_datetime")} <= :end_datetime
+			GROUP BY CEIL(UNIX_TIMESTAMP({$s("table_name_metadata")}.{$s("column_metadata_datetime")}) / :average_seconds);", [
 				"device_id" => $device_id,
 				"reading_type" => $type_id,
 				"start_datetime" => $start->format(\DateTime::ISO8601),
@@ -176,20 +154,14 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
 				{$s("table_name_values")}.{$s("column_values_value")} AS {$s("column_values_value")},
 				{$s("table_name_values")}.{$s("column_values_reading_id")} AS {$s("column_values_reading_id")},
 				
-				COALESCE(
-					{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-					{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-				) AS datetime
+				{$s("table_name_metadata")}.{$s("column_metadata_datetime")} AS datetime
 			FROM {$s("table_name_values")}
 			JOIN {$s("table_name_metadata")} ON
 				{$s("table_name_metadata")}.{$s("column_metadata_id")} = {$s("table_name_values")}.{$s("column_values_reading_id")}
 			WHERE
 				{$s("table_name_metadata")}.{$s("column_metadata_device_id")} = :device_id AND
 				{$s("table_name_values")}.{$s("column_values_reading_type")} = :reading_type
-			ORDER BY COALESCE(
-				{$s("table_name_metadata")}.{$s("column_metadata_recordedon")},
-				{$s("table_name_metadata")}.{$s("column_metadata_storedon")}
-			) DESC
+			ORDER BY {$s("table_name_metadata")}.{$s("column_metadata_datetime")} DESC
 			LIMIT :count;", [
 				"device_id" => $device_id,
 				"reading_type" => $type_id,
