From d26ac6540778c189c41cd9493a8d99ca979dcc5f Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 16:12:38 +1100 Subject: [PATCH 1/9] Addition - Execute Scalar --- QueryDB.Core.Tests/MSSQLTests.cs | 177 +++++++++++++++++++++++++ QueryDB.Core.Tests/MySQLTests.cs | 179 +++++++++++++++++++++++++- QueryDB.Core.Tests/OracleTests.cs | 177 +++++++++++++++++++++++++ QueryDB.Core.Tests/PostgreSQLTests.cs | 179 +++++++++++++++++++++++++- QueryDB.Core.Tests/Queries.cs | 44 +++++++ QueryDB/DBContext.cs | 89 ++++++++++++- QueryDB/IDBContext.cs | 15 +++ QueryDB/MSSQL/Adapter.cs | 40 +++++- QueryDB/MySQL/Adapter.cs | 39 ++++++ QueryDB/Oracle/Adapter.cs | 39 ++++++ QueryDB/PostgreSQL/Adapter.cs | 39 ++++++ 11 files changed, 1013 insertions(+), 4 deletions(-) diff --git a/QueryDB.Core.Tests/MSSQLTests.cs b/QueryDB.Core.Tests/MSSQLTests.cs index a2bedec..8eb3682 100644 --- a/QueryDB.Core.Tests/MSSQLTests.cs +++ b/QueryDB.Core.Tests/MSSQLTests.cs @@ -310,6 +310,183 @@ public void Test_MSSQL_FetchData_Entity_Strict_Error_Check() #endregion + #region Execute Scalar Tests - << string ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MSSQL_TESTS)] + public void Test_MSSQL_ExecuteScalar_As_StringReturn_Scalar_Queries() + { + var countOfRecords = Queries.MSSQLQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.MSSQLQueries.TestDB.ScalarQueries.Max; + var min = Queries.MSSQLQueries.TestDB.ScalarQueries.Min; + var sum = Queries.MSSQLQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.MSSQLQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.MSSQLQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.MSSQL, MSSQLConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual("12", count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual("10000.00", maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual("3000.00", minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual("161000.00", sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual("6520.000000", avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MSSQL_TESTS)] + public void Test_MSSQL_ExecuteScalar_As_StringReturn_DefaultValue() + { + var noValueReturned = Queries.MSSQLQueries.TestDB.ScalarQueries.No_Value_Returned; + var dBNullValue = Queries.MSSQLQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.MSSQL, MSSQLConnectionString); + + var result = dbContext.ExecuteScalar(noValueReturned); + Assert.IsInstanceOfType(result); + Assert.AreEqual("", result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(string.Empty, result); + } + + #endregion + + #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MSSQL_TESTS)] + public void Test_MSSQL_ExecuteScalar_As_TypedReturn_Scalar_Queries() + { + var countOfRecords = Queries.MSSQLQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.MSSQLQueries.TestDB.ScalarQueries.Max; + var min = Queries.MSSQLQueries.TestDB.ScalarQueries.Min; + var sum = Queries.MSSQLQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.MSSQLQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.MSSQLQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.MSSQL, MSSQLConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual(12, count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual(10000.00, maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual(3000.00, minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual(161000.00, sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual((decimal)6520.000000, avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MSSQL_TESTS)] + public void Test_MSSQL_ExecuteScalar_As_TypedReturn_DefaultValue() + { + var dBNullValue = Queries.MSSQLQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.MSSQL, MSSQLConnectionString); + + dynamic result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(int), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(long), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(short), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(uint), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ulong), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ushort), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(decimal), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(double), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(float), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(byte), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(bool), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(DateTime), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(Guid), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(string), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(int?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(long?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(short?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(decimal?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(double?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(float?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(bool?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(DateTime?), result); + } + + #endregion + #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> [TestMethod] diff --git a/QueryDB.Core.Tests/MySQLTests.cs b/QueryDB.Core.Tests/MySQLTests.cs index a176ecc..4697ba8 100644 --- a/QueryDB.Core.Tests/MySQLTests.cs +++ b/QueryDB.Core.Tests/MySQLTests.cs @@ -290,6 +290,183 @@ public void Test_MySQL_FetchData_Entity_Strict_Error_Check() #endregion + #region Execute Scalar Tests - << string ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MYSQL_TESTS)] + public void Test_MySQL_ExecuteScalar_As_StringReturn_Scalar_Queries() + { + var countOfRecords = Queries.MySQLQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.MySQLQueries.TestDB.ScalarQueries.Max; + var min = Queries.MySQLQueries.TestDB.ScalarQueries.Min; + var sum = Queries.MySQLQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.MySQLQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.MySQLQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.MySQL, MySQLConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual("12", count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual("10000.00", maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual("3000.00", minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual("161000.00", sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual("6520.000000", avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MYSQL_TESTS)] + public void Test_MySQL_ExecuteScalar_As_StringReturn_DefaultValue() + { + var noValueReturned = Queries.MySQLQueries.TestDB.ScalarQueries.No_Value_Returned; + var dBNullValue = Queries.MySQLQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.MySQL, MySQLConnectionString); + + var result = dbContext.ExecuteScalar(noValueReturned); + Assert.IsInstanceOfType(result); + Assert.AreEqual("", result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(string.Empty, result); + } + + #endregion + + #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MYSQL_TESTS)] + public void Test_MySQL_ExecuteScalar_As_TypedReturn_Scalar_Queries() + { + var countOfRecords = Queries.MySQLQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.MySQLQueries.TestDB.ScalarQueries.Max; + var min = Queries.MySQLQueries.TestDB.ScalarQueries.Min; + var sum = Queries.MySQLQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.MySQLQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.MySQLQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.MySQL, MySQLConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual(12, count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual(10000.00, maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual(3000.00, minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual(161000.00, sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual((decimal)6520.000000, avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MYSQL_TESTS)] + public void Test_MySQL_ExecuteScalar_As_TypedReturn_DefaultValue() + { + var dBNullValue = Queries.MySQLQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.MySQL, MySQLConnectionString); + + dynamic result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(int), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(long), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(short), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(uint), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ulong), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ushort), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(decimal), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(double), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(float), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(byte), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(bool), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(DateTime), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(Guid), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(string), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(int?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(long?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(short?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(decimal?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(double?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(float?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(bool?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(DateTime?), result); + } + + #endregion + #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> [TestMethod] @@ -347,7 +524,7 @@ public void Test_MySQL_ExecuteCommand_DML_Queries() var insertSql = Queries.MySQLQueries.TestDB.DML.InsertSql; var updateSql = Queries.MySQLQueries.TestDB.DML.UpdateSql; var deleteSql = Queries.MySQLQueries.TestDB.DML.DeleteSql; - var verifyDMLExecution = Queries.MSSQLQueries.TestDB.DML.VerifyDMLExecution; + var verifyDMLExecution = Queries.MySQLQueries.TestDB.DML.VerifyDMLExecution; var dbContext = new DBContext(DB.MySQL, MySQLConnectionString); diff --git a/QueryDB.Core.Tests/OracleTests.cs b/QueryDB.Core.Tests/OracleTests.cs index a471859..6dde601 100644 --- a/QueryDB.Core.Tests/OracleTests.cs +++ b/QueryDB.Core.Tests/OracleTests.cs @@ -292,6 +292,183 @@ public void Test_Oracle_FetchData_Entity_Strict_Error_Check() #endregion + #region Execute Scalar Tests - << string ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(ORACLE_TESTS)] + public void Test_Oracle_ExecuteScalar_As_StringReturn_Scalar_Queries() + { + var countOfRecords = Queries.OracleQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.OracleQueries.TestDB.ScalarQueries.Max; + var min = Queries.OracleQueries.TestDB.ScalarQueries.Min; + var sum = Queries.OracleQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.OracleQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.OracleQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.Oracle, OracleConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual("12", count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual("10000", maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual("3000", minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual("161000", sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual("6520", avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(ORACLE_TESTS)] + public void Test_Oracle_ExecuteScalar_As_StringReturn_DefaultValue() + { + var noValueReturned = Queries.OracleQueries.TestDB.ScalarQueries.No_Value_Returned; + var dBNullValue = Queries.OracleQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.Oracle, OracleConnectionString); + + var result = dbContext.ExecuteScalar(noValueReturned); + Assert.IsInstanceOfType(result); + Assert.AreEqual("", result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(string.Empty, result); + } + + #endregion + + #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(ORACLE_TESTS)] + public void Test_Oracle_ExecuteScalar_As_TypedReturn_Scalar_Queries() + { + var countOfRecords = Queries.OracleQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.OracleQueries.TestDB.ScalarQueries.Max; + var min = Queries.OracleQueries.TestDB.ScalarQueries.Min; + var sum = Queries.OracleQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.OracleQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.OracleQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.Oracle, OracleConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual(12, count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual(10000.00, maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual(3000.00, minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual(161000.00, sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual((decimal)6520.000000, avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(ORACLE_TESTS)] + public void Test_Oracle_ExecuteScalar_As_TypedReturn_DefaultValue() + { + var dBNullValue = Queries.OracleQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.Oracle, OracleConnectionString); + + dynamic result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(int), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(long), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(short), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(uint), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ulong), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ushort), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(decimal), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(double), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(float), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(byte), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(bool), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(DateTime), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(Guid), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(string), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(int?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(long?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(short?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(decimal?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(double?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(float?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(bool?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(DateTime?), result); + } + + #endregion + #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> [TestMethod] diff --git a/QueryDB.Core.Tests/PostgreSQLTests.cs b/QueryDB.Core.Tests/PostgreSQLTests.cs index ec88bea..28d7cce 100644 --- a/QueryDB.Core.Tests/PostgreSQLTests.cs +++ b/QueryDB.Core.Tests/PostgreSQLTests.cs @@ -284,6 +284,183 @@ public void Test_PostgreSQL_FetchData_Entity_Strict_Error_Check() #endregion + #region Execute Scalar Tests - << string ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(POSTGRESQL_TESTS)] + public void Test_PostgreSQL_ExecuteScalar_As_StringReturn_Scalar_Queries() + { + var countOfRecords = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Max; + var min = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Min; + var sum = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.PostgreSQL, PostgreSQLConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual("12", count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual("10000.00", maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual("3000.00", minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual("161000.00", sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual("6520.0000000000000000", avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(POSTGRESQL_TESTS)] + public void Test_PostgreSQL_ExecuteScalar_As_StringReturn_DefaultValue() + { + var noValueReturned = Queries.PostgreSQLQueries.TestDB.ScalarQueries.No_Value_Returned; + var dBNullValue = Queries.PostgreSQLQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.PostgreSQL, PostgreSQLConnectionString); + + var result = dbContext.ExecuteScalar(noValueReturned); + Assert.IsInstanceOfType(result); + Assert.AreEqual("", result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(string.Empty, result); + } + + #endregion + + #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(POSTGRESQL_TESTS)] + public void Test_PostgreSQL_ExecuteScalar_As_TypedReturn_Scalar_Queries() + { + var countOfRecords = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Count_Of_Records; + var max = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Max; + var min = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Min; + var sum = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Sum; + var avg = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Avg; + var singleValueSelect = Queries.PostgreSQLQueries.TestDB.ScalarQueries.Single_Value_Select; + + var dbContext = new DBContext(DB.PostgreSQL, PostgreSQLConnectionString); + + var count = dbContext.ExecuteScalar(countOfRecords); + Assert.AreEqual(12, count); + var maxValue = dbContext.ExecuteScalar(max); + Assert.AreEqual(10000.00, maxValue); + var minValue = dbContext.ExecuteScalar(min); + Assert.AreEqual(3000.00, minValue); + var sumValue = dbContext.ExecuteScalar(sum); + Assert.AreEqual(161000.00, sumValue); + var avgValue = dbContext.ExecuteScalar(avg); + Assert.AreEqual((decimal)6520.0000000000000000, avgValue); + var singleValue = dbContext.ExecuteScalar(singleValueSelect); + Assert.AreEqual("2", singleValue); + } + + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(POSTGRESQL_TESTS)] + public void Test_PostgreSQL_ExecuteScalar_As_TypedReturn_DefaultValue() + { + var dBNullValue = Queries.PostgreSQLQueries.TestDB.ScalarQueries.DB_Null_Value; + + var dbContext = new DBContext(DB.PostgreSQL, PostgreSQLConnectionString); + + dynamic result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(int), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(long), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(short), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(uint), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ulong), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(ushort), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(decimal), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(double), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(float), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(byte), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(bool), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(DateTime), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsInstanceOfType(result); + Assert.AreEqual(default(Guid), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(string), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(int?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(long?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(short?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(decimal?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(double?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(float?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(bool?), result); + + result = dbContext.ExecuteScalar(dBNullValue); + Assert.IsNull(result); + Assert.AreEqual(default(DateTime?), result); + } + + #endregion + #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> [TestMethod] @@ -341,7 +518,7 @@ public void Test_PostgreSQL_ExecuteCommand_DML_Queries() var insertSql = Queries.PostgreSQLQueries.TestDB.DML.InsertSql; var updateSql = Queries.PostgreSQLQueries.TestDB.DML.UpdateSql; var deleteSql = Queries.PostgreSQLQueries.TestDB.DML.DeleteSql; - var verifyDMLExecution = Queries.MSSQLQueries.TestDB.DML.VerifyDMLExecution; + var verifyDMLExecution = Queries.PostgreSQLQueries.TestDB.DML.VerifyDMLExecution; var dbContext = new DBContext(DB.PostgreSQL, PostgreSQLConnectionString); diff --git a/QueryDB.Core.Tests/Queries.cs b/QueryDB.Core.Tests/Queries.cs index 4dfa599..f526765 100644 --- a/QueryDB.Core.Tests/Queries.cs +++ b/QueryDB.Core.Tests/Queries.cs @@ -21,6 +21,17 @@ internal static class TestDB internal static string SelectSql_Strict = @"SELECT A.Agent_Code, A.Agent_Name AS Agent, C.Cust_Code, C.Cust_Name AS Customer, O.Ord_Num, O.Ord_Amount FROM Agents A INNER JOIN Customer C ON C.Agent_Code = A.Agent_Code INNER JOIN Orders O ON O.Cust_Code = C.Cust_Code AND O.Agent_Code = A.Agent_Code"; + internal static class ScalarQueries + { + internal static string Count_Of_Records = @"SELECT COUNT(*) FROM Agents"; + internal static string Max = @"SELECT MAX(Opening_Amt) FROM Customer"; + internal static string Min = @"SELECT MIN(Opening_Amt) FROM Customer"; + internal static string Sum = @"SELECT Sum(Opening_Amt) FROM Customer"; + internal static string Avg = @"SELECT Avg(Payment_Amt) FROM Customer"; + internal static string Single_Value_Select = @"SELECT Grade FROM Customer WHERE Cust_Code = 'C00001'"; + internal static string No_Value_Returned = @"SELECT ''"; + internal static string DB_Null_Value = @"SELECT CAST(NULL AS VARCHAR)"; + } internal static class DDL { internal static string Create_Table = @"CREATE TABLE Employee (EmployeeID INT PRIMARY KEY, FirstName NVARCHAR(50), LastName NVARCHAR(50))"; @@ -77,6 +88,17 @@ internal static class TestDB internal static string SelectSql_Strict = @"SELECT A.Agent_Code, A.Agent_Name AS Agent, C.Cust_Code, C.Cust_Name AS Customer, O.Ord_Num, O.Ord_Amount FROM Agents A INNER JOIN Customer C ON C.Agent_Code = A.Agent_Code INNER JOIN Orders O ON O.Cust_Code = C.Cust_Code AND O.Agent_Code = A.Agent_Code"; + internal static class ScalarQueries + { + internal static string Count_Of_Records = @"SELECT COUNT(*) FROM Agents"; + internal static string Max = @"SELECT MAX(Opening_Amt) FROM Customer"; + internal static string Min = @"SELECT MIN(Opening_Amt) FROM Customer"; + internal static string Sum = @"SELECT Sum(Opening_Amt) FROM Customer"; + internal static string Avg = @"SELECT Avg(Payment_Amt) FROM Customer"; + internal static string Single_Value_Select = @"SELECT Grade FROM Customer WHERE Cust_Code = 'C00001'"; + internal static string No_Value_Returned = @"SELECT ''"; + internal static string DB_Null_Value = @"SELECT CAST(NULL AS CHAR)"; + } internal static class DDL { internal static string Create_Table = @"CREATE TABLE Employee (EmployeeID INT PRIMARY KEY, FirstName NVARCHAR(50), LastName NVARCHAR(50))"; @@ -128,6 +150,17 @@ internal static class TestDB internal static string SelectSql_Strict = @"SELECT A.Agent_Code, A.Agent_Name AS Agent, C.Cust_Code, C.Cust_Name AS Customer, O.Ord_Num, O.Ord_Amount FROM Agents A INNER JOIN Customer C ON C.Agent_Code = A.Agent_Code INNER JOIN Orders O ON O.Cust_Code = C.Cust_Code AND O.Agent_Code = A.Agent_Code"; + internal static class ScalarQueries + { + internal static string Count_Of_Records = @"SELECT COUNT(*) FROM Agents"; + internal static string Max = @"SELECT MAX(Opening_Amt) FROM Customer"; + internal static string Min = @"SELECT MIN(Opening_Amt) FROM Customer"; + internal static string Sum = @"SELECT Sum(Opening_Amt) FROM Customer"; + internal static string Avg = @"SELECT Avg(Payment_Amt) FROM Customer"; + internal static string Single_Value_Select = @"SELECT Grade FROM Customer WHERE Cust_Code = 'C00001'"; + internal static string No_Value_Returned = @"SELECT '' FROM DUAL"; + internal static string DB_Null_Value = @"SELECT CAST(NULL AS VARCHAR2(4)) FROM DUAL"; + } internal static class DDL { internal static string Create_Table = @"CREATE TABLE Employee (EmployeeID NUMBER PRIMARY KEY, FirstName NVARCHAR2(50), LastName NVARCHAR2(50))"; @@ -180,6 +213,17 @@ internal static class TestDB internal static string SelectSql_Strict = @"SELECT A.Agent_Code, A.Agent_Name AS Agent, C.Cust_Code, C.Cust_Name AS Customer, O.Ord_Num, O.Ord_Amount FROM Agents A INNER JOIN Customer C ON C.Agent_Code = A.Agent_Code INNER JOIN Orders O ON O.Cust_Code = C.Cust_Code AND O.Agent_Code = A.Agent_Code"; + internal static class ScalarQueries + { + internal static string Count_Of_Records = @"SELECT COUNT(*) FROM Agents"; + internal static string Max = @"SELECT MAX(Opening_Amt) FROM Customer"; + internal static string Min = @"SELECT MIN(Opening_Amt) FROM Customer"; + internal static string Sum = @"SELECT Sum(Opening_Amt) FROM Customer"; + internal static string Avg = @"SELECT Avg(Payment_Amt) FROM Customer"; + internal static string Single_Value_Select = @"SELECT Grade FROM Customer WHERE Cust_Code = 'C00001'"; + internal static string No_Value_Returned = @"SELECT ''"; + internal static string DB_Null_Value = @"SELECT CAST(NULL AS VARCHAR)"; + } internal static class DDL { internal static string Create_Table = @"CREATE TABLE Employee (EmployeeID INT PRIMARY KEY, FirstName VARCHAR(50), LastName VARCHAR(50))"; diff --git a/QueryDB/DBContext.cs b/QueryDB/DBContext.cs index 2da0106..924119b 100644 --- a/QueryDB/DBContext.cs +++ b/QueryDB/DBContext.cs @@ -146,6 +146,93 @@ public List FetchData(string selectSql, bool upperCaseKeys = fal return dataList; } + /// + /// Executes a SQL query and returns the result as a string. + /// + /// The SQL query to execute. + /// A string representing the result of the query. If the result is DBNull, an empty string is returned. + public string ExecuteScalar(string sqlStatement) + { + var value = string.Empty; + if (Database.Equals(DB.MSSQL)) + { + using (var msSqlDBConnection = GetSqlServerConnection()) + { + var _systemAdapter = new MSSQL.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, msSqlDBConnection.SqlConnection); + } + } + else if (Database.Equals(DB.MySQL)) + { + using (var mySqlDBConnection = GetMySqlConnection()) + { + var _systemAdapter = new MySQL.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, mySqlDBConnection.MySqlConnection); + } + } + else if (Database.Equals(DB.Oracle)) + { + using (var oracleDBConnection = GetOracleConnection()) + { + var _systemAdapter = new Oracle.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, oracleDBConnection.OracleConnection); + } + } + else if (Database.Equals(DB.PostgreSQL)) + { + using (var postgreSqlDBConnection = GetPostgreSqlConnection()) + { + var _systemAdapter = new PostgreSQL.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, postgreSqlDBConnection.PostgreSQLConnection); + } + } + return value; + } + + /// + /// Executes a SQL query and returns the result as the specified type. + /// + /// The type to which the result should be converted. + /// The SQL query to execute. + /// The result of the query, converted to the specified type. If the result is DBNull, the default value for the type is returned. + public T ExecuteScalar(string sqlStatement) + { + var value = default(T); + if (Database.Equals(DB.MSSQL)) + { + using (var msSqlDBConnection = GetSqlServerConnection()) + { + var _systemAdapter = new MSSQL.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, msSqlDBConnection.SqlConnection); + } + } + else if (Database.Equals(DB.MySQL)) + { + using (var mySqlDBConnection = GetMySqlConnection()) + { + var _systemAdapter = new MySQL.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, mySqlDBConnection.MySqlConnection); + } + } + else if (Database.Equals(DB.Oracle)) + { + using (var oracleDBConnection = GetOracleConnection()) + { + var _systemAdapter = new Oracle.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, oracleDBConnection.OracleConnection); + } + } + else if (Database.Equals(DB.PostgreSQL)) + { + using (var postgreSqlDBConnection = GetPostgreSqlConnection()) + { + var _systemAdapter = new PostgreSQL.Adapter(); + value = _systemAdapter.ExecuteScalar(sqlStatement, postgreSqlDBConnection.PostgreSQLConnection); + } + } + return value; + } + /// /// Executes SQL commands. /// @@ -154,7 +241,7 @@ public List FetchData(string selectSql, bool upperCaseKeys = fal public int ExecuteCommand(string sqlStatement) { if (Regex.IsMatch(sqlStatement, "^\\s*SELECT\\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) - throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedSelectExecuteCommand, + throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedSelectExecuteCommand, QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedSelectExecuteCommand); if (Database.Equals(DB.MSSQL)) { diff --git a/QueryDB/IDBContext.cs b/QueryDB/IDBContext.cs index 1186eb2..f14d694 100644 --- a/QueryDB/IDBContext.cs +++ b/QueryDB/IDBContext.cs @@ -25,6 +25,21 @@ interface IDBContext /// List of data rows mapped into object entity into a list for multiple rows of data. List FetchData(string selectSql, bool strict = false) where T : new(); + /// + /// Executes a SQL query and returns the result as a string. + /// + /// The SQL query to execute. + /// A string representing the result of the query. If the result is DBNull, an empty string is returned. + string ExecuteScalar(string sqlStatement); + + /// + /// Executes a SQL query and returns the result as the specified type. + /// + /// The type to which the result should be converted. + /// The SQL query to execute. + /// The result of the query, converted to the specified type. If the result is DBNull, the default value for the type is returned. + T ExecuteScalar(string sqlStatement); + /// /// Executes SQL commands. /// diff --git a/QueryDB/MSSQL/Adapter.cs b/QueryDB/MSSQL/Adapter.cs index fe4de1d..4fd939d 100644 --- a/QueryDB/MSSQL/Adapter.cs +++ b/QueryDB/MSSQL/Adapter.cs @@ -125,6 +125,45 @@ internal List FetchData(string selectSql, SqlConnection connecti return dataList; } + /// + /// Executes the provided SQL statement using the given SQL connection and returns the first column of the first row in the result set. + /// If the result is DBNull, an empty string is returned. + /// + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// A representing the value of the first column of the first row in the result set, + /// or an empty string if the result is DBNull. + /// + internal string ExecuteScalar(string sqlStatement, SqlConnection connection) + { + using (var sqlCommand = GetSqlCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == DBNull.Value ? string.Empty : result.ToString(); + } + } + + /// + /// Executes the provided SQL statement using the given SQL connection and returns the first column of the first row in the result set, + /// converted to the specified type . If the result is DBNull, the default value of is returned. + /// + /// The type to which the result should be converted. + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// The value of the first column of the first row in the result set, converted to type , + /// or the default value of if the result is DBNull. + /// + internal T ExecuteScalar(string sqlStatement, SqlConnection connection) + { + using (var sqlCommand = GetSqlCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == DBNull.Value ? default : (T)Convert.ChangeType(result, typeof(T)); + } + } + /// /// Executes SQL commands. /// @@ -151,7 +190,6 @@ internal int ExecuteCommand(string sqlStatement, SqlConnection connection) /// /// Logs and handles exceptions if any SQL command execution fails. /// - internal static bool ExecuteTransaction(List sqlStatements, SqlConnection connection) { using (SqlTransaction transaction = GetSqlTransaction(connection)) diff --git a/QueryDB/MySQL/Adapter.cs b/QueryDB/MySQL/Adapter.cs index 8721533..c3081dc 100644 --- a/QueryDB/MySQL/Adapter.cs +++ b/QueryDB/MySQL/Adapter.cs @@ -125,6 +125,45 @@ internal List FetchData(string selectSql, MySqlConnection connec return dataList; } + /// + /// Executes the provided SQL statement using the given MySQL connection and returns the first column of the first row in the result set. + /// If the result is DBNull, an empty string is returned. + /// + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// A representing the value of the first column of the first row in the result set, + /// or an empty string if the result is DBNull. + /// + internal string ExecuteScalar(string sqlStatement, MySqlConnection connection) + { + using (var sqlCommand = GetMySqlCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == DBNull.Value ? string.Empty : result.ToString(); + } + } + + /// + /// Executes the provided SQL statement using the given MySQL connection and returns the first column of the first row in the result set, + /// converted to the specified type . If the result is DBNull, the default value of is returned. + /// + /// The type to which the result should be converted. + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// The value of the first column of the first row in the result set, converted to type , + /// or the default value of if the result is DBNull. + /// + internal T ExecuteScalar(string sqlStatement, MySqlConnection connection) + { + using (var sqlCommand = GetMySqlCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == DBNull.Value ? default : (T)Convert.ChangeType(result, typeof(T)); + } + } + /// /// Executes SQL commands. /// diff --git a/QueryDB/Oracle/Adapter.cs b/QueryDB/Oracle/Adapter.cs index 1890fd5..526d25c 100644 --- a/QueryDB/Oracle/Adapter.cs +++ b/QueryDB/Oracle/Adapter.cs @@ -131,6 +131,45 @@ internal List FetchData(string selectSql, OracleConnection conne return dataList; } + /// + /// Executes the provided SQL statement using the given Oracle connection and returns the first column of the first row in the result set. + /// If the result is DBNull, an empty string is returned. + /// + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// A representing the value of the first column of the first row in the result set, + /// or an empty string if the result is DBNull. + /// + internal string ExecuteScalar(string sqlStatement, OracleConnection connection) + { + using (var sqlCommand = GetOracleCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == DBNull.Value ? string.Empty : result.ToString(); + } + } + + /// + /// Executes the provided SQL statement using the given Oracle connection and returns the first column of the first row in the result set, + /// converted to the specified type . If the result is DBNull, the default value of is returned. + /// + /// The type to which the result should be converted. + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// The value of the first column of the first row in the result set, converted to type , + /// or the default value of if the result is DBNull. + /// + internal T ExecuteScalar(string sqlStatement, OracleConnection connection) + { + using (var sqlCommand = GetOracleCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == null || result == DBNull.Value ? default : (T)Convert.ChangeType(result, typeof(T)); + } + } + /// /// Executes SQL commands. /// diff --git a/QueryDB/PostgreSQL/Adapter.cs b/QueryDB/PostgreSQL/Adapter.cs index 3077b44..1239630 100644 --- a/QueryDB/PostgreSQL/Adapter.cs +++ b/QueryDB/PostgreSQL/Adapter.cs @@ -125,6 +125,45 @@ internal List FetchData(string selectSql, NpgsqlConnection conne return dataList; } + /// + /// Executes the provided SQL statement using the given PostgreSQL connection and returns the first column of the first row in the result set. + /// If the result is DBNull, an empty string is returned. + /// + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// A representing the value of the first column of the first row in the result set, + /// or an empty string if the result is DBNull. + /// + internal string ExecuteScalar(string sqlStatement, NpgsqlConnection connection) + { + using (var sqlCommand = GetPostgreSqlCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == null || result == DBNull.Value ? string.Empty : result.ToString(); + } + } + + /// + /// Executes the provided SQL statement using the given PostgreSQL connection and returns the first column of the first row in the result set, + /// converted to the specified type . If the result is DBNull, the default value of is returned. + /// + /// The type to which the result should be converted. + /// The SQL statement to execute. It should be a query that returns a single value. + /// The to use for executing the SQL statement. + /// + /// The value of the first column of the first row in the result set, converted to type , + /// or the default value of if the result is DBNull. + /// + internal T ExecuteScalar(string sqlStatement, NpgsqlConnection connection) + { + using (var sqlCommand = GetPostgreSqlCommand(sqlStatement, connection, CommandType.Text)) + { + var result = sqlCommand.ExecuteScalar(); + return result == null || result == DBNull.Value ? default : (T)Convert.ChangeType(result, typeof(T)); + } + } + /// /// Executes SQL commands. /// From 6d806390488713ae5453026b289b4c6eaba0900c Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 16:56:14 +1100 Subject: [PATCH 2/9] Readme Update --- README.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 02bc069..42bb45f 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,35 @@ QueryDB is a flexible database query framework designed to simplify querying and - [MSSQL](https://www.microsoft.com/en-us/sql-server) - [MySQL](https://www.mysql.com/) - [Oracle](https://www.oracle.com/) -- [PostgreSQL](https://www.postgresql.org/) \ No newline at end of file +- [PostgreSQL](https://www.postgresql.org/) + +## Download +The package is available and can be downloaded using [nuget.org](https://www.nuget.org/) package manager. +- Package Name - [QueryDB](https://www.nuget.org/packages/QueryDB). + +## .NET Supported Versions + +Built on [**.NET Standard 2.0**](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0#tabpanel_1_net-standard-2-0) + +## Features +- Retrieve data from database. +- Execute scalar database commands. +- Execute database commands. +- Execute transactions while maintaining atomicity. + +## Getting Started +- Setup DBContext with the database of your choice + + ``` + var dbContext = new DBContext(DB., ); + ``` + +- Execute DBContext commands + + ``` + var dbContext = new DBContext(DB., ); + var result = dbContext.ExecuteTransaction(); + ``` + ``` + new DBContext(DB., ).ExecuteTransaction(); + ``` \ No newline at end of file From 52edf45e5c7f69896b5dc61cb0fd32df2ff37a1e Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 17:07:30 +1100 Subject: [PATCH 3/9] Readme Update --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 42bb45f..9feb53d 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,18 @@ Built on [**.NET Standard 2.0**](https://learn.microsoft.com/en-us/dotnet/standa - Execute DBContext commands ``` - var dbContext = new DBContext(DB., ); - var result = dbContext.ExecuteTransaction(); + var result = dbContext.FetchData(); + var result = dbContext.FetchData(); + var result = dbContext.ExecuteScalar(); + var result = dbContext.ExecuteScalar(); + var result = dbContext.ExecuteCommand(); + var result = dbContext.ExecuteTransaction(); ``` ``` - new DBContext(DB., ).ExecuteTransaction(); + var result = new DBContext(DB., ).FetchData(); + var result = new DBContext(DB., ).FetchData(); + var result = new DBContext(DB., ).ExecuteScalar(); + var result = new DBContext(DB., ).ExecuteScalar(); + var result = new DBContext(DB., ).ExecuteCommand(); + var result = new DBContext(DB., ).ExecuteTransaction(); ``` \ No newline at end of file From 30a2265973f9830093d75a225b01ec0ccd3f4b59 Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 19:49:15 +1100 Subject: [PATCH 4/9] Execute Scalar - Unsupported Commands --- QueryDB.Core.Tests/MSSQLTests.cs | 74 ++++++++++++++++++++++++++ QueryDB.Core.Tests/MySQLTests.cs | 74 ++++++++++++++++++++++++++ QueryDB.Core.Tests/OracleTests.cs | 74 ++++++++++++++++++++++++++ QueryDB.Core.Tests/PostgreSQLTests.cs | 74 ++++++++++++++++++++++++++ QueryDB/DBContext.cs | 6 +++ QueryDB/Exceptions/QueryDBException.cs | 10 ++++ 6 files changed, 312 insertions(+) diff --git a/QueryDB.Core.Tests/MSSQLTests.cs b/QueryDB.Core.Tests/MSSQLTests.cs index 8eb3682..5df4bd7 100644 --- a/QueryDB.Core.Tests/MSSQLTests.cs +++ b/QueryDB.Core.Tests/MSSQLTests.cs @@ -357,6 +357,43 @@ public void Test_MSSQL_ExecuteScalar_As_StringReturn_DefaultValue() Assert.AreEqual(string.Empty, result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MSSQL_TESTS)] + public void Test_MSSQL_ExecuteScalar_As_StringReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.MSSQLQueries.TestDB.DDL.Create_Table, + Queries.MSSQLQueries.TestDB.DDL.Alter_Table, + Queries.MSSQLQueries.TestDB.DDL.Comment_Table, + Queries.MSSQLQueries.TestDB.DDL.Truncate_Table, + Queries.MSSQLQueries.TestDB.DDL.Drop_Table, + + Queries.MSSQLQueries.TestDB.DML.InsertSql, + Queries.MSSQLQueries.TestDB.DML.UpdateSql, + Queries.MSSQLQueries.TestDB.DML.DeleteSql, + + Queries.MSSQLQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.MSSQLQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.MSSQL, MSSQLConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> @@ -485,6 +522,43 @@ public void Test_MSSQL_ExecuteScalar_As_TypedReturn_DefaultValue() Assert.AreEqual(default(DateTime?), result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MSSQL_TESTS)] + public void Test_MSSQL_ExecuteScalar_As_TypedReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.MSSQLQueries.TestDB.DDL.Create_Table, + Queries.MSSQLQueries.TestDB.DDL.Alter_Table, + Queries.MSSQLQueries.TestDB.DDL.Comment_Table, + Queries.MSSQLQueries.TestDB.DDL.Truncate_Table, + Queries.MSSQLQueries.TestDB.DDL.Drop_Table, + + Queries.MSSQLQueries.TestDB.DML.InsertSql, + Queries.MSSQLQueries.TestDB.DML.UpdateSql, + Queries.MSSQLQueries.TestDB.DML.DeleteSql, + + Queries.MSSQLQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.MSSQLQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.MSSQL, MSSQLConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> diff --git a/QueryDB.Core.Tests/MySQLTests.cs b/QueryDB.Core.Tests/MySQLTests.cs index 4697ba8..ef00ffc 100644 --- a/QueryDB.Core.Tests/MySQLTests.cs +++ b/QueryDB.Core.Tests/MySQLTests.cs @@ -337,6 +337,43 @@ public void Test_MySQL_ExecuteScalar_As_StringReturn_DefaultValue() Assert.AreEqual(string.Empty, result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MYSQL_TESTS)] + public void Test_MySQL_ExecuteScalar_As_StringReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.MySQLQueries.TestDB.DDL.Create_Table, + Queries.MySQLQueries.TestDB.DDL.Alter_Table, + Queries.MySQLQueries.TestDB.DDL.Comment_Table, + Queries.MySQLQueries.TestDB.DDL.Truncate_Table, + Queries.MySQLQueries.TestDB.DDL.Drop_Table, + + Queries.MySQLQueries.TestDB.DML.InsertSql, + Queries.MySQLQueries.TestDB.DML.UpdateSql, + Queries.MySQLQueries.TestDB.DML.DeleteSql, + + Queries.MySQLQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.MySQLQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.MySQL, MySQLConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> @@ -465,6 +502,43 @@ public void Test_MySQL_ExecuteScalar_As_TypedReturn_DefaultValue() Assert.AreEqual(default(DateTime?), result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(MYSQL_TESTS)] + public void Test_MySQL_ExecuteScalar_As_TypedReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.MySQLQueries.TestDB.DDL.Create_Table, + Queries.MySQLQueries.TestDB.DDL.Alter_Table, + Queries.MySQLQueries.TestDB.DDL.Comment_Table, + Queries.MySQLQueries.TestDB.DDL.Truncate_Table, + Queries.MySQLQueries.TestDB.DDL.Drop_Table, + + Queries.MySQLQueries.TestDB.DML.InsertSql, + Queries.MySQLQueries.TestDB.DML.UpdateSql, + Queries.MySQLQueries.TestDB.DML.DeleteSql, + + Queries.MySQLQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.MySQLQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.MySQL, MySQLConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> diff --git a/QueryDB.Core.Tests/OracleTests.cs b/QueryDB.Core.Tests/OracleTests.cs index 6dde601..af5c9b8 100644 --- a/QueryDB.Core.Tests/OracleTests.cs +++ b/QueryDB.Core.Tests/OracleTests.cs @@ -339,6 +339,43 @@ public void Test_Oracle_ExecuteScalar_As_StringReturn_DefaultValue() Assert.AreEqual(string.Empty, result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(ORACLE_TESTS)] + public void Test_Oracle_ExecuteScalar_As_StringReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.OracleQueries.TestDB.DDL.Create_Table, + Queries.OracleQueries.TestDB.DDL.Alter_Table, + Queries.OracleQueries.TestDB.DDL.Comment_Table, + Queries.OracleQueries.TestDB.DDL.Truncate_Table, + Queries.OracleQueries.TestDB.DDL.Drop_Table, + + Queries.OracleQueries.TestDB.DML.InsertSql, + Queries.OracleQueries.TestDB.DML.UpdateSql, + Queries.OracleQueries.TestDB.DML.DeleteSql, + + Queries.OracleQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.OracleQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.Oracle, OracleConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> @@ -467,6 +504,43 @@ public void Test_Oracle_ExecuteScalar_As_TypedReturn_DefaultValue() Assert.AreEqual(default(DateTime?), result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(ORACLE_TESTS)] + public void Test_Oracle_ExecuteScalar_As_TypedReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.OracleQueries.TestDB.DDL.Create_Table, + Queries.OracleQueries.TestDB.DDL.Alter_Table, + Queries.OracleQueries.TestDB.DDL.Comment_Table, + Queries.OracleQueries.TestDB.DDL.Truncate_Table, + Queries.OracleQueries.TestDB.DDL.Drop_Table, + + Queries.OracleQueries.TestDB.DML.InsertSql, + Queries.OracleQueries.TestDB.DML.UpdateSql, + Queries.OracleQueries.TestDB.DML.DeleteSql, + + Queries.OracleQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.OracleQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.Oracle, OracleConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> diff --git a/QueryDB.Core.Tests/PostgreSQLTests.cs b/QueryDB.Core.Tests/PostgreSQLTests.cs index 28d7cce..73678d9 100644 --- a/QueryDB.Core.Tests/PostgreSQLTests.cs +++ b/QueryDB.Core.Tests/PostgreSQLTests.cs @@ -331,6 +331,43 @@ public void Test_PostgreSQL_ExecuteScalar_As_StringReturn_DefaultValue() Assert.AreEqual(string.Empty, result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(POSTGRESQL_TESTS)] + public void Test_PostgreSQL_ExecuteScalar_As_StringReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.PostgreSQLQueries.TestDB.DDL.Create_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Alter_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Comment_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Truncate_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Drop_Table, + + Queries.PostgreSQLQueries.TestDB.DML.InsertSql, + Queries.PostgreSQLQueries.TestDB.DML.UpdateSql, + Queries.PostgreSQLQueries.TestDB.DML.DeleteSql, + + Queries.PostgreSQLQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.PostgreSQLQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.PostgreSQL, PostgreSQLConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Scalar Tests - << T ExecuteScalar(string sqlStatement); >> @@ -459,6 +496,43 @@ public void Test_PostgreSQL_ExecuteScalar_As_TypedReturn_DefaultValue() Assert.AreEqual(default(DateTime?), result); } + [TestMethod] + [TestCategory(DB_TESTS), TestCategory(POSTGRESQL_TESTS)] + public void Test_PostgreSQL_ExecuteScalar_As_TypedReturn_UnsupportedCommands() + { + var sqlStatements = new List + { + Queries.PostgreSQLQueries.TestDB.DDL.Create_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Alter_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Comment_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Truncate_Table, + Queries.PostgreSQLQueries.TestDB.DDL.Drop_Table, + + Queries.PostgreSQLQueries.TestDB.DML.InsertSql, + Queries.PostgreSQLQueries.TestDB.DML.UpdateSql, + Queries.PostgreSQLQueries.TestDB.DML.DeleteSql, + + Queries.PostgreSQLQueries.TestDB.DCL.GrantSql_Command_Table_User, + Queries.PostgreSQLQueries.TestDB.DCL.RevokeSql_Command_Table_User + }; + + foreach (var sqlStatement in sqlStatements) + { + try + { + var dbContext = new DBContext(DB.PostgreSQL, PostgreSQLConnectionString); + dbContext.ExecuteScalar(sqlStatement); + Assert.Fail("No Exception"); + } + catch (QueryDBException ex) + { + Assert.AreEqual("Only SELECT queries are supported here.", ex.Message); + Assert.AreEqual("UnsupportedCommand", ex.ErrorType); + Assert.AreEqual("'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return.", ex.AdditionalInfo); + } + } + } + #endregion #region Execute Command Tests - << int ExecuteCommand(string sqlStatement) >> diff --git a/QueryDB/DBContext.cs b/QueryDB/DBContext.cs index 924119b..6b6cc32 100644 --- a/QueryDB/DBContext.cs +++ b/QueryDB/DBContext.cs @@ -153,6 +153,9 @@ public List FetchData(string selectSql, bool upperCaseKeys = fal /// A string representing the result of the query. If the result is DBNull, an empty string is returned. public string ExecuteScalar(string sqlStatement) { + if (!Regex.IsMatch(sqlStatement, @"^\s*SELECT\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) + throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedExecuteScalarCommand, + QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedExecuteScalarCommand); var value = string.Empty; if (Database.Equals(DB.MSSQL)) { @@ -197,6 +200,9 @@ public string ExecuteScalar(string sqlStatement) /// The result of the query, converted to the specified type. If the result is DBNull, the default value for the type is returned. public T ExecuteScalar(string sqlStatement) { + if (!Regex.IsMatch(sqlStatement, @"^\s*SELECT\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) + throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedExecuteScalarCommand, + QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedExecuteScalarCommand); var value = default(T); if (Database.Equals(DB.MSSQL)) { diff --git a/QueryDB/Exceptions/QueryDBException.cs b/QueryDB/Exceptions/QueryDBException.cs index 08a0d96..7f09c07 100644 --- a/QueryDB/Exceptions/QueryDBException.cs +++ b/QueryDB/Exceptions/QueryDBException.cs @@ -70,6 +70,11 @@ internal static class ErrorMessage /// Error message indicating that SELECT queries are not supported in 'ExecuteTransaction'. /// internal static readonly string UnsupportedSelectExecuteTransaction = "SELECT queries are not supported here."; + + /// + /// Error message indicating that SELECT queries are only supported in 'ExecuteScalar'. + /// + internal static readonly string UnsupportedExecuteScalarCommand = "Only SELECT queries are supported here."; } /// @@ -86,6 +91,11 @@ internal static class AdditionalInfo /// Additional information about unsupported SELECT queries in 'ExecuteTransaction'. /// internal static readonly string UnsupportedSelectExecuteTransaction = "'ExecuteTransaction' doesn't support SELECT queries."; + + /// + /// Error message indicating that SELECT queries are only supported in 'ExecuteScalar'. + /// + internal static readonly string UnsupportedExecuteScalarCommand = "'ExecuteScalar' only supports SELECT queries that have a scalar (single value) return."; } } } From b2f0701c827c69e88f4b6ac01e421adbede40f56 Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 20:07:10 +1100 Subject: [PATCH 5/9] CQ - Define a constant instead of using literal multiple times --- QueryDB/DBContext.cs | 8 ++++---- QueryDB/Resources/Utils.cs | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/QueryDB/DBContext.cs b/QueryDB/DBContext.cs index 6b6cc32..fbc45d0 100644 --- a/QueryDB/DBContext.cs +++ b/QueryDB/DBContext.cs @@ -153,7 +153,7 @@ public List FetchData(string selectSql, bool upperCaseKeys = fal /// A string representing the result of the query. If the result is DBNull, an empty string is returned. public string ExecuteScalar(string sqlStatement) { - if (!Regex.IsMatch(sqlStatement, @"^\s*SELECT\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) + if (!Regex.IsMatch(sqlStatement, Utils.SelectQueryPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedExecuteScalarCommand, QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedExecuteScalarCommand); var value = string.Empty; @@ -200,7 +200,7 @@ public string ExecuteScalar(string sqlStatement) /// The result of the query, converted to the specified type. If the result is DBNull, the default value for the type is returned. public T ExecuteScalar(string sqlStatement) { - if (!Regex.IsMatch(sqlStatement, @"^\s*SELECT\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) + if (!Regex.IsMatch(sqlStatement, Utils.SelectQueryPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedExecuteScalarCommand, QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedExecuteScalarCommand); var value = default(T); @@ -246,7 +246,7 @@ public T ExecuteScalar(string sqlStatement) /// The number of rows affected. public int ExecuteCommand(string sqlStatement) { - if (Regex.IsMatch(sqlStatement, "^\\s*SELECT\\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) + if (Regex.IsMatch(sqlStatement, Utils.SelectQueryPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))) throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedSelectExecuteCommand, QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedSelectExecuteCommand); if (Database.Equals(DB.MSSQL)) @@ -294,7 +294,7 @@ public int ExecuteCommand(string sqlStatement) /// public bool ExecuteTransaction(List sqlStatements) { - var selectExists = sqlStatements.Any(sqlStatement => Regex.IsMatch(sqlStatement, "^\\s*SELECT\\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))); + var selectExists = sqlStatements.Any(sqlStatement => Regex.IsMatch(sqlStatement, Utils.SelectQueryPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5))); if (selectExists) throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedSelectExecuteTransaction, QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedSelectExecuteTransaction); diff --git a/QueryDB/Resources/Utils.cs b/QueryDB/Resources/Utils.cs index 8f8be26..8a4bdf1 100644 --- a/QueryDB/Resources/Utils.cs +++ b/QueryDB/Resources/Utils.cs @@ -9,6 +9,11 @@ namespace QueryDB.Resources /// internal static class Utils { + /// + /// Regex pattern to validate that a SQL query starts with 'SELECT'. + /// + internal static readonly string SelectQueryPattern = @"^\s*SELECT\s+.*"; + /// /// Checks if a specified column exists in the given data reader. /// From 50ff183b9988d8c3cf9136fd3407e7a1f922c9eb Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 20:56:49 +1100 Subject: [PATCH 6/9] Readme Update --- README.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/README.md b/README.md index 9feb53d..a62658c 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The package is available and can be downloaded using [nuget.org](https://www.nug ## .NET Supported Versions -Built on [**.NET Standard 2.0**](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0#tabpanel_1_net-standard-2-0) +Built on **.NET Standard 2.0** - ([_Supported Versions_](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0#tabpanel_1_net-standard-2-0)) ## Features - Retrieve data from database. @@ -50,11 +50,3 @@ Built on [**.NET Standard 2.0**](https://learn.microsoft.com/en-us/dotnet/standa var result = dbContext.ExecuteCommand(); var result = dbContext.ExecuteTransaction(); ``` - ``` - var result = new DBContext(DB., ).FetchData(); - var result = new DBContext(DB., ).FetchData(); - var result = new DBContext(DB., ).ExecuteScalar(); - var result = new DBContext(DB., ).ExecuteScalar(); - var result = new DBContext(DB., ).ExecuteCommand(); - var result = new DBContext(DB., ).ExecuteTransaction(); - ``` \ No newline at end of file From 002987785d779fda2adb431fef1ebd5af3486c8e Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 21:00:48 +1100 Subject: [PATCH 7/9] Readme Update --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a62658c..690bea1 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ The package is available and can be downloaded using [nuget.org](https://www.nug Built on **.NET Standard 2.0** - ([_Supported Versions_](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0#tabpanel_1_net-standard-2-0)) ## Features -- Retrieve data from database. -- Execute scalar database commands. -- Execute database commands. +- Retrieve data from the database. +- Execute scalar queries (returning a single value). +- Execute non-query database commands (e.g. `INSERT`, `UPDATE`, `DELETE`). - Execute transactions while maintaining atomicity. ## Getting Started From c1ffd61e95e0383c14d3e1d6146323c080476336 Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Wed, 19 Feb 2025 21:04:37 +1100 Subject: [PATCH 8/9] Readme Update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 690bea1..f5b43a5 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The package is available and can be downloaded using [nuget.org](https://www.nug ## .NET Supported Versions -Built on **.NET Standard 2.0** - ([_Supported Versions_](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0#tabpanel_1_net-standard-2-0)) +Built on **.NET Standard 2.0** - ( [_Supported Versions_](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0#tabpanel_1_net-standard-2-0:~:text=Select%20.NET%20Standard%20version) ) ## Features - Retrieve data from the database. From 07f4c163914c69fb3ba1ad1c669df631db559597 Mon Sep 17 00:00:00 2001 From: abhinavminhas Date: Thu, 20 Feb 2025 23:07:18 +1100 Subject: [PATCH 9/9] Nuget package creation - v1.1.0 --- .github/workflows/publish-nuget-Package.yml | 2 +- CHANGELOG.md | 6 +++++- QueryDB/QueryDB.csproj | 14 +++++++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-nuget-Package.yml b/.github/workflows/publish-nuget-Package.yml index db9f86a..46f5a75 100644 --- a/.github/workflows/publish-nuget-Package.yml +++ b/.github/workflows/publish-nuget-Package.yml @@ -1,7 +1,7 @@ name: Publish Nuget Package env: - NUGET_PACKAGE_NAME_VERSION: "QueryDB.1.0.0.nupkg" + NUGET_PACKAGE_NAME_VERSION: "QueryDB.1.1.0.nupkg" on: workflow_dispatch: diff --git a/CHANGELOG.md b/CHANGELOG.md index dec4197..315d9d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,4 +8,8 @@ All notable changes to this project documented here. - QueryDB framework for simplified querying and executing transactions across multiple database systems. - Retrieve data from database. - Execute database commands. - - Execute transactions while maintaining atomicity. \ No newline at end of file + - Execute transactions while maintaining atomicity. + +## [1.1.0](https://www.nuget.org/packages/QueryDB/1.1.0) - 2025-02-20 +### Added +- Execute scalar queries (returning a single value). \ No newline at end of file diff --git a/QueryDB/QueryDB.csproj b/QueryDB/QueryDB.csproj index 868421b..90e834f 100644 --- a/QueryDB/QueryDB.csproj +++ b/QueryDB/QueryDB.csproj @@ -9,16 +9,20 @@ Supported Databases: - MSSQL - MySQL - Oracle -- PostgreSQL +- PostgreSQL + +Features: +- Retrieve data from the database. +- Execute scalar queries (returning a single value). +- Execute non-query database commands. +- Execute transactions while maintaining atomicity. https://github.com/abhinavminhas/QueryDB.NET https://github.com/abhinavminhas/QueryDB.NET git LICENSE sql, query, rdbms, database, mssql, sqlserver, mysql, oracle, postgresql - QueryDB framework for simplified querying and executing transactions across multiple database systems. -- Retrieve data from database. -- Execute database commands. -- Execute transactions while maintaining atomicity. + 1. Execute scalar queries (returning a single value). + 1.1.0