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.Core.Tests/MSSQLTests.cs b/QueryDB.Core.Tests/MSSQLTests.cs index a2bedec..5df4bd7 100644 --- a/QueryDB.Core.Tests/MSSQLTests.cs +++ b/QueryDB.Core.Tests/MSSQLTests.cs @@ -310,6 +310,257 @@ 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); + } + + [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); >> + + [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); + } + + [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) >> [TestMethod] diff --git a/QueryDB.Core.Tests/MySQLTests.cs b/QueryDB.Core.Tests/MySQLTests.cs index a176ecc..ef00ffc 100644 --- a/QueryDB.Core.Tests/MySQLTests.cs +++ b/QueryDB.Core.Tests/MySQLTests.cs @@ -290,6 +290,257 @@ 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); + } + + [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); >> + + [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); + } + + [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) >> [TestMethod] @@ -347,7 +598,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..af5c9b8 100644 --- a/QueryDB.Core.Tests/OracleTests.cs +++ b/QueryDB.Core.Tests/OracleTests.cs @@ -292,6 +292,257 @@ 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); + } + + [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); >> + + [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); + } + + [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) >> [TestMethod] diff --git a/QueryDB.Core.Tests/PostgreSQLTests.cs b/QueryDB.Core.Tests/PostgreSQLTests.cs index ec88bea..73678d9 100644 --- a/QueryDB.Core.Tests/PostgreSQLTests.cs +++ b/QueryDB.Core.Tests/PostgreSQLTests.cs @@ -284,6 +284,257 @@ 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); + } + + [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); >> + + [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); + } + + [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) >> [TestMethod] @@ -341,7 +592,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..fbc45d0 100644 --- a/QueryDB/DBContext.cs +++ b/QueryDB/DBContext.cs @@ -146,6 +146,99 @@ 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) + { + 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; + 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) + { + 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); + 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. /// @@ -153,8 +246,8 @@ public List FetchData(string selectSql, bool upperCaseKeys = fal /// The number of rows affected. 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, + 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)) { @@ -201,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/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."; } } } 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. /// 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 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. /// diff --git a/README.md b/README.md index 02bc069..f5b43a5 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,36 @@ 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** - ( [_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. +- Execute scalar queries (returning a single value). +- Execute non-query database commands (e.g. `INSERT`, `UPDATE`, `DELETE`). +- Execute transactions while maintaining atomicity. + +## Getting Started +- Setup DBContext with the database of your choice + + ``` + var dbContext = new DBContext(DB., ); + ``` + +- Execute DBContext commands + + ``` + var result = dbContext.FetchData(); + var result = dbContext.FetchData(); + var result = dbContext.ExecuteScalar(); + var result = dbContext.ExecuteScalar(); + var result = dbContext.ExecuteCommand(); + var result = dbContext.ExecuteTransaction(); + ```