diff --git a/Database/Database.cs b/Database/Database.cs index c248752..3b6d39c 100644 --- a/Database/Database.cs +++ b/Database/Database.cs @@ -1476,6 +1476,30 @@ public ConnectionController Connection return pobjConnection; } } + + /// + /// All keys are returned in lower case. + /// + /// If the connection string is in an invalid format. + protected static IDictionary GetDictionaryFromConnectionString(string strConnectionString) + { + var objDictionary = new Dictionary(); + string[] strPropertyValueArray; + + foreach (string strPropertyValue in strConnectionString.Split(';')) + { + if (!String.IsNullOrEmpty(strPropertyValue)) + { + strPropertyValueArray = strPropertyValue.Split('='); + if (strPropertyValueArray.Length == 2) + objDictionary.Add(strPropertyValueArray[0].Trim().ToLower(), strPropertyValueArray[1].Trim()); + else + throw new FormatException("Invalid key property definition for '" + strPropertyValue + "' from '" + strConnectionString + "'"); + } + } + + return objDictionary; + } /// -------------------------------------------------------------------------------- /// @@ -2044,7 +2068,7 @@ private static IDbConnection CreateConnection(string strConnectionString) { //Searches for an occurance of 'Provider=' //If found then it is assumed to be an OLEDB connection otherwise an ODBC connection - if (SQL.Misc.GetDictionaryFromConnectionString(strConnectionString).ContainsKey("provider")) + if (GetDictionaryFromConnectionString(strConnectionString).ContainsKey("provider")) return new System.Data.OleDb.OleDbConnection(strConnectionString); else return new System.Data.Odbc.OdbcConnection(strConnectionString); diff --git a/Database/MicrosoftSQLServerDatabase.cs b/Database/MicrosoftSQLServerDatabase.cs index 5d4875a..3350fc6 100644 --- a/Database/MicrosoftSQLServerDatabase.cs +++ b/Database/MicrosoftSQLServerDatabase.cs @@ -69,7 +69,7 @@ public string Name /// If the connection string is in an invalid format. public static MicrosoftSQLServerDatabase Parse(string strConnectionString) { - var objDictionary = SQL.Misc.GetDictionaryFromConnectionString(strConnectionString); + var objDictionary = GetDictionaryFromConnectionString(strConnectionString); if (objDictionary.ContainsKey("integrated security")) return new MicrosoftSQLServerDatabase(GetDataSource(objDictionary), GetDatabase(objDictionary)); diff --git a/DatabaseObjects.csproj b/DatabaseObjects.csproj index 33c2862..fe1bef9 100644 --- a/DatabaseObjects.csproj +++ b/DatabaseObjects.csproj @@ -214,6 +214,15 @@ + + + + + + + + + @@ -223,9 +232,6 @@ Code - - Code - Code diff --git a/SQL/Amend/SQLDelete.cs b/SQL/Amend/SQLDelete.cs index a565939..e2cb3d6 100644 --- a/SQL/Amend/SQLDelete.cs +++ b/SQL/Amend/SQLDelete.cs @@ -56,22 +56,12 @@ public SQLConditions Where pobjConditions = value; } } - + public override string SQL { - get + get { - string strSQL; - - if (String.IsNullOrEmpty(TableName)) - throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); - - strSQL = "DELETE FROM " + Misc.SQLConvertIdentifierName(this.TableName, this.ConnectionType); - - if (pobjConditions != null && !pobjConditions.IsEmpty) - strSQL += " WHERE " + pobjConditions.SQL(this.ConnectionType); - - return strSQL; + return base.Serializer.SerializeDelete(this); } } } diff --git a/SQL/Amend/SQLFieldValues.cs b/SQL/Amend/SQLFieldValues.cs index 5360c00..99862bd 100644 --- a/SQL/Amend/SQLFieldValues.cs +++ b/SQL/Amend/SQLFieldValues.cs @@ -13,7 +13,7 @@ namespace DatabaseObjects.SQL { - public class SQLFieldValues : IEnumerable + public class SQLFieldValues : IEnumerable { protected List pobjFields = new List(); @@ -92,7 +92,12 @@ private bool Equals(SQLFieldValue fieldValue, string strFieldName) return fieldValue.Name.Equals(strFieldName, StringComparison.InvariantCultureIgnoreCase); } - public System.Collections.IEnumerator GetEnumerator() + IEnumerator IEnumerable.GetEnumerator() + { + return pobjFields.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { return pobjFields.GetEnumerator(); } diff --git a/SQL/Amend/SQLInsert.cs b/SQL/Amend/SQLInsert.cs index 3e59363..22fbf9c 100644 --- a/SQL/Amend/SQLInsert.cs +++ b/SQL/Amend/SQLInsert.cs @@ -48,43 +48,12 @@ public SQLFieldValues Fields pobjFields = value; } } - + public override string SQL { - get + get { - string strFields = string.Empty; - string strFieldValues = string.Empty; - - if (String.IsNullOrEmpty(TableName)) - throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); - - if (pobjFields.Count == 0) - throw new Exceptions.DatabaseObjectsException("Field values have not been set."); - - for (int intIndex = 0; intIndex < pobjFields.Count; intIndex++) - { - strFields += Misc.SQLConvertIdentifierName(pobjFields[intIndex].Name, this.ConnectionType); - if (intIndex != pobjFields.Count - 1) - strFields += ","; - } - - SQLFieldValue objField; - - for (int intIndex = 0; intIndex < pobjFields.Count; intIndex++) - { - objField = pobjFields[intIndex]; - - if (objField.Value is SQLExpression) - strFieldValues += ((SQLExpression) objField.Value).SQL(this.ConnectionType); - else - strFieldValues += Misc.SQLConvertValue(pobjFields[intIndex].Value, this.ConnectionType); - - if (intIndex != pobjFields.Count - 1) - strFieldValues += ","; - } - - return "INSERT INTO " + Misc.SQLConvertIdentifierName(this.TableName, this.ConnectionType) + " " + "(" + strFields + ") VALUES (" + strFieldValues + ")"; + return base.Serializer.SerializeInsert(this); } } } diff --git a/SQL/Amend/SQLInsertFromSelect.cs b/SQL/Amend/SQLInsertFromSelect.cs index 52fc257..933bf48 100644 --- a/SQL/Amend/SQLInsertFromSelect.cs +++ b/SQL/Amend/SQLInsertFromSelect.cs @@ -106,32 +106,12 @@ public SQLSelect Source pobjSourceSelect = value; } } - + public override string SQL { - get + get { - string strFields = string.Empty; - - if (String.IsNullOrEmpty(TableName)) - throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); - - if (pobjInsertIntoFields.Count > 0) - { - for (int intIndex = 0; intIndex < pobjInsertIntoFields.Count; intIndex++) - { - strFields += Misc.SQLConvertIdentifierName(System.Convert.ToString(pobjInsertIntoFields[intIndex]), this.ConnectionType); - if (intIndex != pobjInsertIntoFields.Count - 1) - { - strFields += ", "; - } - } - strFields = "(" + strFields + ") "; - } - - pobjSourceSelect.ConnectionType = base.ConnectionType; - - return "INSERT INTO " + Misc.SQLConvertIdentifierName(this.TableName, this.ConnectionType) + " " + strFields + pobjSourceSelect.SQL; + return base.Serializer.SerializeInsertFromSelect(this); } } } diff --git a/SQL/Amend/SQLUpdate.cs b/SQL/Amend/SQLUpdate.cs index 3275050..ce2606b 100644 --- a/SQL/Amend/SQLUpdate.cs +++ b/SQL/Amend/SQLUpdate.cs @@ -77,45 +77,12 @@ public SQLConditions Where pobjConditions = value; } } - + public override string SQL { - get + get { - string strSQL; - string strFieldValues = string.Empty; - - if (String.IsNullOrEmpty(TableName)) - throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); - else if (pobjFields.Count == 0) - throw new Exceptions.DatabaseObjectsException("Field values have not been set."); - - SQLFieldValue objField; - - for (int intIndex = 0; intIndex < pobjFields.Count; intIndex++) - { - objField = pobjFields[intIndex]; - //Check the field name has been set. Can't really check whether the value has been set or not. - if (String.IsNullOrEmpty(objField.Name)) - throw new Exceptions.DatabaseObjectsException("Field Name has not been set."); - - if (objField is SQLUpdateField) - strFieldValues += Misc.SQLConvertIdentifierName(objField.Name, this.ConnectionType) + " = " + ((SQLUpdateField) objField).Value.SQL(this.ConnectionType); - else if (objField is SQLFieldValue) - strFieldValues += Misc.SQLConvertIdentifierName(objField.Name, this.ConnectionType) + " = " + Misc.SQLConvertValue(objField.Value, this.ConnectionType); - else - throw new NotSupportedException(objField.GetType().Name); - - if (intIndex != pobjFields.Count - 1) - strFieldValues += ", "; - } - - strSQL = "UPDATE " + Misc.SQLConvertIdentifierName(this.TableName, this.ConnectionType) + " " + "SET " + strFieldValues; - - if (pobjConditions != null && !pobjConditions.IsEmpty) - strSQL += " WHERE " + pobjConditions.SQL(this.ConnectionType); - - return strSQL; + return base.Serializer.SerializeUpdate(this); } } } diff --git a/SQL/Expressions/SQLAggregateExpression.cs b/SQL/Expressions/SQLAggregateExpression.cs index 7bc38d4..5884aa9 100644 --- a/SQL/Expressions/SQLAggregateExpression.cs +++ b/SQL/Expressions/SQLAggregateExpression.cs @@ -13,14 +13,30 @@ namespace DatabaseObjects.SQL { public class SQLAggregateExpression : SQLFunctionExpression { + private AggregateFunction aggregate; + public SQLAggregateExpression(AggregateFunction aggregate, string fieldName) : this(aggregate, new SQLFieldExpression(fieldName)) { } public SQLAggregateExpression(AggregateFunction aggregate, SQLExpression expression) - : base(Misc.SQLConvertAggregate(aggregate), expression) + : base(expression) + { + this.aggregate = aggregate; + } + + public AggregateFunction Aggregate + { + get + { + return aggregate; + } + } + + internal override string SQL(Serializers.Serializer serializer) { + return serializer.SerializeAggregateExpression(this); } } } diff --git a/SQL/Expressions/SQLAllFieldsExpression.cs b/SQL/Expressions/SQLAllFieldsExpression.cs index 7d4f0d2..3283ce1 100644 --- a/SQL/Expressions/SQLAllFieldsExpression.cs +++ b/SQL/Expressions/SQLAllFieldsExpression.cs @@ -41,12 +41,12 @@ public SQLSelectTable Table } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { string strSQL = string.Empty; if (pobjTable != null) - strSQL += Misc.SQLTablePrefix(pobjTable, eConnectionType) + "."; + strSQL += serializer.SerializeTablePrefix(pobjTable) + "."; return strSQL + "*"; } diff --git a/SQL/Expressions/SQLArithmeticExpression.cs b/SQL/Expressions/SQLArithmeticExpression.cs index 5b463a0..25f9f97 100644 --- a/SQL/Expressions/SQLArithmeticExpression.cs +++ b/SQL/Expressions/SQLArithmeticExpression.cs @@ -92,30 +92,9 @@ public ArithmeticOperator Operator } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - if (pobjLeft == null) - throw new ArgumentNullException(this.GetType().Name + ".LeftExpression"); - else if (pobjRight == null) - throw new ArgumentNullException(this.GetType().Name + ".RightExpression"); - - return "(" + pobjLeft.SQL(eConnectionType) + " " + OperatorString(peOperator) + " " + pobjRight.SQL(eConnectionType) + ")"; - } - - private string OperatorString(SQL.ArithmeticOperator eOperator) - { - if (eOperator == ArithmeticOperator.Add) - return "+"; - else if (eOperator == ArithmeticOperator.Subtract) - return "-"; - else if (eOperator == ArithmeticOperator.Divide) - return "/"; - else if (eOperator == ArithmeticOperator.Multiply) - return "*"; - else if (eOperator == ArithmeticOperator.Modulus) - return "%"; - else - throw new NotSupportedException(typeof(SQL.ArithmeticOperator).Name); + return serializer.SerializeArithmeticExpression(this); } } } diff --git a/SQL/Expressions/SQLBitwiseExpression.cs b/SQL/Expressions/SQLBitwiseExpression.cs index 719fa79..376b95e 100644 --- a/SQL/Expressions/SQLBitwiseExpression.cs +++ b/SQL/Expressions/SQLBitwiseExpression.cs @@ -89,24 +89,9 @@ public BitwiseOperator Operator } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - if (pobjLeft == null) - throw new ArgumentNullException(this.GetType().Name + ".LeftExpression"); - else if (pobjRight == null) - throw new ArgumentNullException(this.GetType().Name + ".RightExpression"); - - return "(" + pobjLeft.SQL(eConnectionType) + " " + OperatorString(peOperator) + " " + pobjRight.SQL(eConnectionType) + ")"; - } - - private string OperatorString(SQL.BitwiseOperator eOperator) - { - if (eOperator == BitwiseOperator.And) - return "&"; - else if (eOperator == BitwiseOperator.Or) - return "|"; - else - throw new NotSupportedException(typeof(SQL.BitwiseOperator).Name); + return serializer.SerializeBitwiseExpression(this); } } } diff --git a/SQL/Expressions/SQLCaseExpression.cs b/SQL/Expressions/SQLCaseExpression.cs index e4e90d7..ee809da 100644 --- a/SQL/Expressions/SQLCaseExpression.cs +++ b/SQL/Expressions/SQLCaseExpression.cs @@ -30,7 +30,7 @@ namespace DatabaseObjects.SQL /// public class SQLCaseExpression : SQLExpression { - public class CasesCollection + public class CasesCollection : IEnumerable { private List pobjCases = new List(); @@ -43,13 +43,15 @@ public void Add(Case objCase) { pobjCases.Add(objCase); } - - internal string SQL(Database.ConnectionType eConnectionType) + + IEnumerator IEnumerable.GetEnumerator() { - if (pobjCases.Count == 0) - throw new InvalidOperationException("There are no cases for the CASE statement"); - - return string.Join(" ", pobjCases.Select(objCase => objCase.SQL(eConnectionType)).ToArray()); + return pobjCases.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return pobjCases.GetEnumerator(); } } @@ -71,10 +73,21 @@ public Case(SQLExpression objWhenCondition, SQLExpression objResult) pobjWhenCondition = objWhenCondition; pobjResult = objResult; } - - internal string SQL(Database.ConnectionType eConnectionType) + + public SQLExpression WhenCondition + { + get + { + return pobjWhenCondition; + } + } + + public SQLExpression Result { - return "WHEN " + pobjWhenCondition.SQL(eConnectionType) + " THEN " + pobjResult.SQL(eConnectionType); + get + { + return pobjResult; + } } } @@ -114,22 +127,18 @@ public SQLExpression ElseResult pobjElseResult = value; } } + + public SQLExpression InputExpression + { + get + { + return pobjInputExpression; + } + } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - string strSQL = "CASE"; - - if (pobjInputExpression != null) - strSQL += " " + pobjInputExpression.SQL(eConnectionType); - - strSQL += " " + pobjCases.SQL(eConnectionType); - - if (pobjElseResult != null) - strSQL += " ELSE " + pobjElseResult.SQL(eConnectionType); - - strSQL += " END"; - - return strSQL; + return serializer.SerializeCaseExpression(this); } } } diff --git a/SQL/Expressions/SQLCastFieldExpression.cs b/SQL/Expressions/SQLCastFieldExpression.cs index 0ca531a..d9a71f6 100644 --- a/SQL/Expressions/SQLCastFieldExpression.cs +++ b/SQL/Expressions/SQLCastFieldExpression.cs @@ -33,6 +33,22 @@ public SQLCastExpression(string strFieldName, DataType eCastAsType, int intSize) { this.Size = intSize; } + + public DataType ToDataType + { + get + { + return peCastAsType; + } + } + + public string FieldName + { + get + { + return pstrFieldName; + } + } /// /// The size of the character data type. @@ -41,7 +57,7 @@ public int Size { set { - Misc.DataTypeEnsureIsCharacter(peCastAsType); + DataTypeExtensions.EnsureIsCharacter(peCastAsType); if (value <= 1) throw new ArgumentException(); @@ -51,7 +67,7 @@ public int Size get { - Misc.DataTypeEnsureIsCharacter(peCastAsType); + DataTypeExtensions.EnsureIsCharacter(peCastAsType); return pintSize; } @@ -67,14 +83,14 @@ public int ScaleLength { get { - Misc.DataTypeEnsureIsDecimal(peCastAsType); + DataTypeExtensions.EnsureIsDecimal(peCastAsType); return pintScale; } set { - Misc.DataTypeEnsureIsDecimal(peCastAsType); + DataTypeExtensions.EnsureIsDecimal(peCastAsType); if (value <= 0) throw new ArgumentException(); @@ -93,14 +109,14 @@ public int Precision { get { - Misc.DataTypeEnsureIsDecimal(peCastAsType); + DataTypeExtensions.EnsureIsDecimal(peCastAsType); return pintPrecision; } set { - Misc.DataTypeEnsureIsDecimal(peCastAsType); + DataTypeExtensions.EnsureIsDecimal(peCastAsType); if (value <= 0) throw new ArgumentException(); @@ -109,9 +125,9 @@ public int Precision } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - return "CAST(" + Misc.SQLConvertIdentifierName(pstrFieldName, eConnectionType) + " AS " + Misc.SQLConvertDataTypeString(eConnectionType, peCastAsType, pintSize, pintPrecision, pintScale) + ")"; + return serializer.SerializeCastExpression(this); } } } diff --git a/SQL/Expressions/SQLExpression.cs b/SQL/Expressions/SQLExpression.cs index 1185e07..2539894 100644 --- a/SQL/Expressions/SQLExpression.cs +++ b/SQL/Expressions/SQLExpression.cs @@ -13,7 +13,7 @@ namespace DatabaseObjects.SQL { public abstract class SQLExpression { - internal abstract string SQL(Database.ConnectionType eConnectionType); + internal abstract string SQL(Serializers.Serializer serializer); public static SQLArithmeticExpression operator +(SQLExpression left, SQLExpression right) { diff --git a/SQL/Expressions/SQLFieldAggregateExpression.cs b/SQL/Expressions/SQLFieldAggregateExpression.cs index 347a9c5..31ba8a7 100644 --- a/SQL/Expressions/SQLFieldAggregateExpression.cs +++ b/SQL/Expressions/SQLFieldAggregateExpression.cs @@ -48,19 +48,9 @@ public SQL.AggregateFunction AggregateFunction } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - if (this.AggregateFunction == AggregateFunction.None) - throw new InvalidOperationException("AggregateFunction unspecified for " + this.GetType().Name); - - string strFieldName = string.Empty; - - if (this.AggregateFunction == AggregateFunction.Count) - strFieldName = "*"; - else - strFieldName = base.SQL(eConnectionType); - - return Misc.SQLConvertAggregate(this.AggregateFunction) + "(" + strFieldName + ")"; + return serializer.SerializeFieldAggregateExpression(this); } } } diff --git a/SQL/Expressions/SQLFieldExpression.cs b/SQL/Expressions/SQLFieldExpression.cs index 2d72f31..79d7657 100644 --- a/SQL/Expressions/SQLFieldExpression.cs +++ b/SQL/Expressions/SQLFieldExpression.cs @@ -57,16 +57,9 @@ public SQLSelectTable Table } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - string strSQL = string.Empty; - - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("Field Name has not been set."); - - strSQL += Misc.SQLFieldNameAndTablePrefix(pobjTable, pstrFieldName, eConnectionType); - - return strSQL; + return serializer.SerializeFieldExpression(this); } } } diff --git a/SQL/Expressions/SQLFunctionExpression.cs b/SQL/Expressions/SQLFunctionExpression.cs index 10af4cc..26842e5 100644 --- a/SQL/Expressions/SQLFunctionExpression.cs +++ b/SQL/Expressions/SQLFunctionExpression.cs @@ -9,6 +9,7 @@ using System; using System.Data; using System.Linq; +using DatabaseObjects.SQL.Serializers; namespace DatabaseObjects.SQL { @@ -20,25 +21,17 @@ namespace DatabaseObjects.SQL /// public class SQLFunctionExpression : SQLExpression { - private string pstrFunctionName; private SQLExpression[] pobjFunctionArguments; - + + private string functionName; public bool IncludeParenthesesWhenArgumentsEmpty = false; - - public SQLFunctionExpression(string strFunctionName) - { - if (string.IsNullOrEmpty(strFunctionName)) - throw new ArgumentNullException(); - - pstrFunctionName = strFunctionName; - } - - public SQLFunctionExpression(string strFunctionName, params SQLExpression[] arguments) - : this(strFunctionName) + + public SQLFunctionExpression(string functionName, params SQLExpression[] arguments) + : this(arguments) { - InitializeArguments(arguments); + this.functionName = functionName; } - + /// /// Used when the arguments are known but the function name is dependant on the connection type. /// Typically, in this scenario the FunctionName() will be overridden. @@ -57,23 +50,26 @@ private void InitializeArguments(params SQLExpression[] arguments) pobjFunctionArguments = arguments; } - - protected virtual string FunctionName(Database.ConnectionType eConnectionType) + + public SQLExpression[] Arguments { - return pstrFunctionName; + get + { + return pobjFunctionArguments; + } } - - internal override string SQL(Database.ConnectionType eConnectionType) + + public bool HasArguments { - string strArguments = string.Empty; - - if (pobjFunctionArguments != null) - strArguments = String.Join(", ", pobjFunctionArguments.Select(argument => argument.SQL(eConnectionType)).ToArray()); - - if ((IncludeParenthesesWhenArgumentsEmpty && pobjFunctionArguments == null) || pobjFunctionArguments != null) - strArguments = "(" + strArguments + ")"; - - return this.FunctionName(eConnectionType) + strArguments; + get + { + return pobjFunctionArguments.Length > 0; + } + } + + internal override string SQL(Serializer serializer) + { + return this.functionName + serializer.SerializeFunctionExpressionArguments(this); } } } diff --git a/SQL/Expressions/SQLGetDateFunctionExpression.cs b/SQL/Expressions/SQLGetDateFunctionExpression.cs index 0cdc482..c0afb46 100644 --- a/SQL/Expressions/SQLGetDateFunctionExpression.cs +++ b/SQL/Expressions/SQLGetDateFunctionExpression.cs @@ -13,25 +13,9 @@ namespace DatabaseObjects.SQL { public class SQLGetDateFunctionExpression : SQLExpression { - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - switch (eConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - return "Now()"; - case Database.ConnectionType.SQLServer: - return "GetDate()"; - case Database.ConnectionType.SQLServerCompactEdition: - return "GetDate()"; - case Database.ConnectionType.MySQL: - return "CURDATE()"; - case Database.ConnectionType.Pervasive: - throw new NotImplementedException(); - break; - default: - throw new NotSupportedException(); - break; - } + return serializer.SerializeGetDateFunctionExpression(this); } } } diff --git a/SQL/Expressions/SQLLeftFunctionExpression.cs b/SQL/Expressions/SQLLeftFunctionExpression.cs index 051b149..79ee274 100644 --- a/SQL/Expressions/SQLLeftFunctionExpression.cs +++ b/SQL/Expressions/SQLLeftFunctionExpression.cs @@ -1,7 +1,7 @@ // ___________________________________________________ // // (c) Hi-Integrity Systems 2010. All rights reserved. -// www.hisystems.com.au - Toby Wicks +// www.hisystems.com.au - Toby Wicks // ___________________________________________________ // @@ -22,10 +22,15 @@ public SQLLeftFunctionExpression(string strFieldName, int intLength) } public SQLLeftFunctionExpression(SQLExpression objExpression, int intLength) - : base("LEFT", objExpression, new SQLValueExpression(intLength)) + : base(objExpression, new SQLValueExpression(intLength)) { if (intLength < 0) throw new ArgumentException("Length: " + intLength.ToString()); } + + internal override string SQL(Serializers.Serializer serializer) + { + return serializer.SerializeLeftFunctionExpression(this); + } } } diff --git a/SQL/Expressions/SQLLengthFunctionExpression.cs b/SQL/Expressions/SQLLengthFunctionExpression.cs index 0352df1..227918c 100644 --- a/SQL/Expressions/SQLLengthFunctionExpression.cs +++ b/SQL/Expressions/SQLLengthFunctionExpression.cs @@ -21,21 +21,9 @@ public SQLLengthFunctionExpression(SQLExpression objExpression) { } - protected override string FunctionName(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - switch (eConnectionType) - { - case Database.ConnectionType.MySQL: - return "LENGTH"; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.MicrosoftAccess: - return "LEN"; - default: - throw new NotImplementedException(eConnectionType.ToString()); - break; - } - - return base.FunctionName(eConnectionType); + return serializer.SerializeLengthFunctionExpression(this); } } } diff --git a/SQL/Expressions/SQLRightFunctionExpression.cs b/SQL/Expressions/SQLRightFunctionExpression.cs index 1f6e83b..886e51b 100644 --- a/SQL/Expressions/SQLRightFunctionExpression.cs +++ b/SQL/Expressions/SQLRightFunctionExpression.cs @@ -19,10 +19,15 @@ public SQLRightFunctionExpression(string strFieldName, int intLength) } public SQLRightFunctionExpression(SQLExpression objExpression, int intLength) - : base("RIGHT", objExpression, new SQLValueExpression(intLength)) + : base(objExpression, new SQLValueExpression(intLength)) { if (intLength < 0) throw new ArgumentException("Length: " + intLength.ToString()); } + + internal override string SQL(Serializers.Serializer serializer) + { + return serializer.SerializeRightFunctionExpression(this); + } } } diff --git a/SQL/Expressions/SQLStringConcatExpression.cs b/SQL/Expressions/SQLStringConcatExpression.cs index ed98331..f06ebd0 100644 --- a/SQL/Expressions/SQLStringConcatExpression.cs +++ b/SQL/Expressions/SQLStringConcatExpression.cs @@ -64,14 +64,9 @@ public SQLExpression RightExpression } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - if (left == null) - throw new ArgumentNullException(this.GetType().Name + ".LeftExpression"); - else if (right == null) - throw new ArgumentNullException(this.GetType().Name + ".RightExpression"); - - return left.SQL(eConnectionType) + " + " + right.SQL(eConnectionType); + return serializer.SerializeStringContactExpression(this); } public static SQLExpression ConcatenateAll(params SQLExpression[] sqlExpressions) diff --git a/SQL/Expressions/SQLValueExpression.cs b/SQL/Expressions/SQLValueExpression.cs index 3421964..24dbda1 100644 --- a/SQL/Expressions/SQLValueExpression.cs +++ b/SQL/Expressions/SQLValueExpression.cs @@ -34,10 +34,10 @@ public object Value return pobjValue; } } - - internal override string SQL(Database.ConnectionType eConnectionType) + + internal override string SQL(Serializers.Serializer serializer) { - return Misc.SQLConvertValue(pobjValue, eConnectionType); + return serializer.SerializeValue(pobjValue); } } } diff --git a/SQL/Misc.cs b/SQL/Misc.cs deleted file mode 100644 index 55f589b..0000000 --- a/SQL/Misc.cs +++ /dev/null @@ -1,932 +0,0 @@ -// ___________________________________________________ -// -// © Hi-Integrity Systems 2010. All rights reserved. -// www.hisystems.com.au - Toby Wicks -// ___________________________________________________ -// - -using System.Collections; -using System; -using System.Data; -using System.Collections.Generic; - -namespace DatabaseObjects.SQL -{ - internal static class Misc - { - public static string SQLConvertIdentifierName(string strIdentifierName, Database.ConnectionType eConnectionType) - { - //This function places tags around a field name or table name to ensure it doesn't - //conflict with a reserved word or if it contains spaces it is not misinterpreted - - switch (eConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - return "[" + strIdentifierName + "]"; - case Database.ConnectionType.MySQL: - return "`" + strIdentifierName + "`"; - case Database.ConnectionType.Pervasive: - return "\"" + strIdentifierName + "\""; - case Database.ConnectionType.HyperSQL: - return "\"" + strIdentifierName + "\""; - default: - throw new NotImplementedException(eConnectionType.ToString()); - } - } - - public static string SQLConvertValue(object objValue, Database.ConnectionType eConnectionType) - { - if (SQLValueIsNull(objValue)) - return "NULL"; - else if (objValue is bool) - { - if ((bool)objValue) - return "1"; - else - return "0"; - } - else if (objValue is char) - { - char chChar = (char) objValue; - - if (chChar == '\'') - { - switch (eConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - case Database.ConnectionType.Pervasive: - case Database.ConnectionType.HyperSQL: - return @"''''"; - case Database.ConnectionType.MySQL: - return @"'\''"; - default: - throw new NotImplementedException(eConnectionType.ToString()); - break; - } - } - else if (chChar.Equals(@"\")) - { - switch (eConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - case Database.ConnectionType.Pervasive: - case Database.ConnectionType.HyperSQL: - return @"\"; - case Database.ConnectionType.MySQL: - return @"\\"; - default: - throw new NotImplementedException(eConnectionType.ToString()); - break; - } - } - else - return "'" + chChar + "'"; - } - else if (objValue is DateTime) - { - DateTime dtDate = (DateTime)objValue; - string strDate; - - //If the date hasn't been set then set to the 1899-12-30 so that - //the date isn't set to 2001-01-01 - if (dtDate.Day == 1 && dtDate.Month == 1 && dtDate.Year == 1) - strDate = "1899-12-30"; - else - strDate = System.Convert.ToString(dtDate.Year + "-" + dtDate.Month + "-" + dtDate.Day); - - if (dtDate.Hour != 0 || dtDate.Minute != 0 || dtDate.Second != 0) - strDate += " " + dtDate.Hour + ":" + dtDate.Minute + ":" + dtDate.Second + "." + dtDate.Millisecond; - - switch (eConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - return "#" + strDate + "#"; - case Database.ConnectionType.MySQL: - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - case Database.ConnectionType.Pervasive: - case Database.ConnectionType.HyperSQL: - return "\'" + strDate + "\'"; - default: - throw new NotImplementedException(eConnectionType.ToString()); - } - } - else if (objValue is string) - { - switch (eConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - case Database.ConnectionType.Pervasive: - case Database.ConnectionType.HyperSQL: - return "'" + ((string)objValue).Replace(@"'", @"''") + "'"; - case Database.ConnectionType.MySQL: - //Replace the \ escape character with \\ and replace single quotes with two single quotes - return "'" + ((string)objValue).Replace(@"\", @"\\").Replace(@"'", @"\'") + "'"; - default: - throw new NotImplementedException(eConnectionType.ToString()); - break; - } - } - else if (objValue is byte[]) - { - switch (eConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - case Database.ConnectionType.Pervasive: - case Database.ConnectionType.MySQL: - return SQLConvertBinaryArray("0x", (byte[])objValue, string.Empty); - case Database.ConnectionType.HyperSQL: - return SQLConvertBinaryArray("x'", (byte[])objValue, "'"); - default: - throw new NotImplementedException(eConnectionType.ToString()); - } - } - else if (objValue is System.Guid) - { - return "'" + ((System.Guid) objValue).ToString("D") + "'"; - } - else - { - return System.Convert.ToString(objValue); - } - } - - private static string SQLConvertBinaryArray(string strHexPrefix, byte[] bytData, string strHexSuffix) - { - System.Text.StringBuilder objHexData = new System.Text.StringBuilder(strHexPrefix, System.Convert.ToInt32((bytData.Length * 2) + strHexPrefix.Length + strHexSuffix.Length)); - - foreach (byte bytByte in bytData) - objHexData.Append(string.Format("{0:X2}", bytByte)); - - objHexData.Append(strHexSuffix); - - return objHexData.ToString(); - } - - public static bool SQLValueIsNull(object objValue) - { - if (objValue == null) - return true; - else if (objValue == DBNull.Value) - return true; - else - return false; - } - - public static string SQLConvertAggregate(SQL.AggregateFunction eAggregate) - { - switch (eAggregate) - { - case AggregateFunction.Average: - return "AVG"; - case AggregateFunction.Count: - return "COUNT"; - case AggregateFunction.Sum: - return "SUM"; - case AggregateFunction.Minimum: - return "MIN"; - case AggregateFunction.Maximum: - return "MAX"; - case AggregateFunction.StandardDeviation: - return "STDEV"; - case AggregateFunction.Variance: - return "VAR"; - default: - throw new NotSupportedException(); - } - } - - public static string SQLConvertCompare(SQL.ComparisonOperator eCompare) - { - switch (eCompare) - { - case ComparisonOperator.EqualTo: - return "="; - case ComparisonOperator.NotEqualTo: - return "<>"; - case ComparisonOperator.LessThan: - return "<"; - case ComparisonOperator.LessThanOrEqualTo: - return "<="; - case ComparisonOperator.GreaterThan: - return ">"; - case ComparisonOperator.GreaterThanOrEqualTo: - return ">="; - case ComparisonOperator.Like: - return "LIKE"; - case ComparisonOperator.NotLike: - return "NOT LIKE"; - default: - throw new NotSupportedException(); - } - } - - public static string SQLConvertLogicalOperator(SQL.LogicalOperator eLogicalOperator) - { - string strLogicalOperator; - - if (eLogicalOperator == LogicalOperator.And) - strLogicalOperator = "AND"; - else if (eLogicalOperator == LogicalOperator.Or) - strLogicalOperator = "OR"; - else - throw new NotSupportedException(); - - return strLogicalOperator; - } - - public static string SQLFieldNameAndTablePrefix(SQLSelectTable objTable, string strFieldName, Database.ConnectionType eConnectionType) - { - string strTablePrefix = string.Empty; - - if (objTable != null) - strTablePrefix = SQLTablePrefix(objTable, eConnectionType) + "."; - - return strTablePrefix + SQLConvertIdentifierName(strFieldName, eConnectionType); - } - - /// - /// Returns the table alias or if the alias is not set the table's name. - /// - public static string SQLTablePrefix(SQLSelectTable objTable, Database.ConnectionType eConnectionType) - { - if (!String.IsNullOrEmpty(objTable.Alias)) - return SQLConvertIdentifierName(objTable.Alias, eConnectionType); - else - return SQLConvertIdentifierName(objTable.Name, eConnectionType); - } - - public static object SQLConditionValue(object objValue) - { - if (objValue is SQLFieldValue) - return ((SQLFieldValue)objValue).Value; - else - return objValue; - } - - public static void CompareValuePairAssertValid(SQL.ComparisonOperator eCompare, object objValue) - { - if (!(objValue is string) && (eCompare == ComparisonOperator.Like || eCompare == ComparisonOperator.NotLike)) - throw new Exceptions.DatabaseObjectsException("The LIKE operator cannot be used in conjunction with a non-string data type"); - else if (objValue is bool&& !(eCompare == ComparisonOperator.EqualTo || eCompare == ComparisonOperator.NotEqualTo)) - throw new Exceptions.DatabaseObjectsException("A boolean value can only be used in conjunction with the " + ComparisonOperator.EqualTo.ToString() + " or " + ComparisonOperator.NotEqualTo.ToString() + " operators"); - } - - public static void SQLConvertBooleanValue(ref object objValue, ref SQL.ComparisonOperator eCompare) - { - // If a boolean variable set to true then use the NOT - // operator and compare it to 0. ie. if the condition is 'field = true' then - // SQL code should be 'field <> 0' - // -1 is true in MSAccess and 1 is true in SQLServer. - - if (objValue is bool) - { - if (((bool)objValue) == true) - { - if (eCompare == ComparisonOperator.EqualTo) - eCompare = ComparisonOperator.NotEqualTo; - else - eCompare = ComparisonOperator.EqualTo; - - objValue = false; - } - } - } - - public static string SQLConvertCondition(ComparisonOperator eCompare, object objValue, Database.ConnectionType eConnectionType) - { - string strSQL = string.Empty; - - SQLConvertBooleanValue(ref objValue, ref eCompare); - - //Return 'IS NULL' rather than '= NULL' - if (SQLValueIsNull(objValue)) - { - if (eCompare == ComparisonOperator.EqualTo) - strSQL += "IS " + SQLConvertValue(objValue, eConnectionType); - else if (eCompare == ComparisonOperator.NotEqualTo) - strSQL += "IS NOT " + SQLConvertValue(objValue, eConnectionType); - else - throw new Exceptions.DatabaseObjectsException("DBNull or Nothing/null specified as an SQLCondition value using the " + eCompare.ToString() + " operator"); - } - else - strSQL += SQLConvertCompare(eCompare) + " " + SQLConvertValue(objValue, eConnectionType); - - return strSQL; - } - - public static string SQLConvertDataTypeString(Database.ConnectionType eConnection, DataType eDataType, int intSize, int intPrecision, int intScale) - { - string strDataType = string.Empty; - - switch (eDataType) - { - case DataType.TinyInteger: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "BYTE"; - break; - case Database.ConnectionType.MySQL: - strDataType = "TINYINT UNSIGNED"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "TINYINT"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "TINYINT"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "TINYINT"; - break; - } - break; - - case DataType.SmallInteger: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "SMALLINT"; - break; - case Database.ConnectionType.MySQL: - strDataType = "SMALLINT"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "SMALLINT"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "SMALLINT"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "SMALLINT"; - break; - } - break; - - case DataType.Integer: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "INTEGER"; - break; - case Database.ConnectionType.MySQL: - strDataType = "INT"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "INTEGER"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "INTEGER"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "INT"; - break; - } - break; - - case DataType.BigInteger: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "NUMERIC(19,0)"; - break; - case Database.ConnectionType.MySQL: - strDataType = "BIGINT"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "BIGINT"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "BIGINT"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "BIGINT"; - break; - } - break; - - case DataType.Character: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "TEXT(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.MySQL: - strDataType = "CHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "CHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "CHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "CHAR(" + intSize.ToString() + ")"; - break; - } - break; - - case DataType.UnicodeCharacter: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - //Unicode is only supported in Microsoft Access 2000+ - strDataType = "TEXT(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.MySQL: - strDataType = "NCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "NCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.Pervasive: - //Unable to verify this is correct. - strDataType = "CHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "CHAR(" + intSize.ToString() + ")"; - break; - } - break; - - case DataType.VariableCharacter: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "TEXT(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.MySQL: - strDataType = "VARCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.SQLServer: - strDataType = "VARCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "VARCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "VARCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "VARCHAR(" + intSize.ToString() + ")"; - break; - } - break; - - case DataType.UnicodeVariableCharacter: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - //Unicode is only supported in Microsoft Access 2000+ - strDataType = "TEXT(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.MySQL: - strDataType = "NVARCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "NVARCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.Pervasive: - //Unable to verify this is correct. - strDataType = "VARCHAR(" + intSize.ToString() + ")"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "VARCHAR(" + intSize.ToString() + ")"; - break; - } - break; - - case DataType.Decimal: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "NUMERIC(" + intPrecision.ToString() + "," + intScale.ToString() + ")"; - break; - case Database.ConnectionType.MySQL: - strDataType = "DECIMAL(" + intPrecision.ToString() + "," + intScale.ToString() + ")"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "NUMERIC(" + intPrecision.ToString() + "," + intScale.ToString() + ")"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "NUMERIC(" + intPrecision.ToString() + "," + intScale.ToString() + ")"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "NUMBER(" + intPrecision.ToString() + "," + intScale.ToString() + ")"; - break; - } - break; - - case DataType.Real: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "REAL"; - break; - case Database.ConnectionType.MySQL: - strDataType = "FLOAT"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "REAL"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "REAL"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "DOUBLE"; - break; - } - break; - - case DataType.Float: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "FLOAT"; - break; - case Database.ConnectionType.MySQL: - strDataType = "DOUBLE"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "FLOAT"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "FLOAT"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "DOUBLE"; - break; - } - break; - - case DataType.SmallMoney: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "NUMERIC(10,4)"; - break; - case Database.ConnectionType.MySQL: - strDataType = "DECIMAL(10,4)"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "SMALLMONEY"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "DECIMAL(10,4)"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "NUMBER(10,4)"; - break; - } - break; - - case DataType.Money: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "NUMERIC(19,4)"; - break; - case Database.ConnectionType.MySQL: - strDataType = "DECIMAL(19,4)"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "MONEY"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "DECIMAL(19,4)"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "NUMBER(19,4)"; - break; - } - break; - - case DataType.Boolean: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "YESNO"; - break; - case Database.ConnectionType.MySQL: - strDataType = "BIT"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "BIT"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "BIT"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "BOOLEAN"; - break; - } - break; - - case DataType.SmallDateTime: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.MySQL: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.SQLServer: - strDataType = "SMALLDATETIME"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "DATE"; - break; - } - break; - - case DataType.DateTime: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.MySQL: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "DATETIME"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "DATE"; - break; - } - break; - - case DataType.TimeStamp: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - throw new NotSupportedException("TIMESTAMP"); - break; - case Database.ConnectionType.MySQL: - strDataType = "TIMESTAMP"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "TIMESTAMP"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "TIMESTAMP"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "TIMESTAMP"; - break; - } - break; - - case DataType.Text: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "MEMO"; - break; - case Database.ConnectionType.MySQL: - strDataType = "LONGTEXT"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "TEXT"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "LONGVARCHAR"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "CLOB(2G)"; - break; - } - break; - - case DataType.UnicodeText: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - //Unicode is only supported in Microsoft Access 2000+ - strDataType = "MEMO"; - break; - case Database.ConnectionType.MySQL: - strDataType = "LONGTEXT CHARACTER SET UTF8"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "NTEXT"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "LONGVARCHAR"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "CLOB(2G)"; - break; - } - break; - - case DataType.Binary: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "OLEOBJECT"; - break; - case Database.ConnectionType.MySQL: - strDataType = "BLOB"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "BINARY"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "BINARY"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "BINARY(8000)"; - break; - } - break; - - case DataType.VariableBinary: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "OLEOBJECT"; - break; - case Database.ConnectionType.MySQL: - strDataType = "BLOB"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "VARBINARY"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "LONGVARBINARY"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "VARBINARY(8000)"; - break; - } - break; - - case DataType.Image: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "IMAGE"; - break; - case Database.ConnectionType.MySQL: - strDataType = "LONGBLOB"; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "IMAGE"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "LONGVARBINARY"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "BLOB(2G)"; - break; - } - break; - - case DataType.UniqueIdentifier: - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - strDataType = "UNIQUEIDENTIFIER"; - break; - case Database.ConnectionType.MySQL: - strDataType = "UNIQUEIDENTIFIER"; - break; - case Database.ConnectionType.Pervasive: - strDataType = "UNIQUEIDENTIFIER"; - break; - case Database.ConnectionType.SQLServer: - strDataType = "UNIQUEIDENTIFIER"; - break; - case Database.ConnectionType.SQLServerCompactEdition: - strDataType = "UNIQUEIDENTIFIER"; - break; - case Database.ConnectionType.HyperSQL: - strDataType = "UNIQUEIDENTIFIER"; - break; - } - break; - - default: - throw new NotImplementedException("Data type " + eDataType.ToString()); - break; - } - - if (String.IsNullOrEmpty(strDataType)) - throw new NotImplementedException("Data type " + eDataType.ToString() + " is not implemented for connection type " + eConnection.ToString()); - - return strDataType; - } - - public static void DataTypeEnsureIsDecimal(DataType eDataType) - { - if (eDataType != DataType.Decimal) - throw new Exceptions.MethodLockedException("First set Type to " + DataType.Decimal.ToString()); - } - - public static void DataTypeEnsureIsCharacter(SQL.DataType eDataType) - { - if (!DataTypeIsCharacter(eDataType)) - throw new Exceptions.MethodLockedException("Data type is not character based"); - } - - public static void DataTypeEnsureIsInteger(SQL.DataType eDataType) - { - if (!DataTypeIsInteger(eDataType)) - throw new Exceptions.MethodLockedException(); - } - - public static bool DataTypeIsInteger(SQL.DataType eDataType) - { - switch (eDataType) - { - case DataType.BigInteger: - case DataType.Integer: - case DataType.SmallInteger: - case DataType.TinyInteger: - return true; - default: - return false; - } - } - - public static bool DataTypeIsCharacter(DataType eDataType) - { - switch (eDataType) - { - case DataType.Character: - case DataType.UnicodeCharacter: - case DataType.VariableCharacter: - case DataType.UnicodeVariableCharacter: - return true; - default: - return false; - } - } - - /// - /// All keys are returned in lower case. - /// - /// If the connection string is in an invalid format. - internal static IDictionary GetDictionaryFromConnectionString(string strConnectionString) - { - var objDictionary = new Dictionary(); - string[] strPropertyValueArray; - - foreach (string strPropertyValue in strConnectionString.Split(';')) - { - if (!String.IsNullOrEmpty(strPropertyValue)) - { - strPropertyValueArray = strPropertyValue.Split('='); - if (strPropertyValueArray.Length == 2) - objDictionary.Add(strPropertyValueArray[0].Trim().ToLower(), strPropertyValueArray[1].Trim()); - else - throw new FormatException("Invalid key property definition for '" + strPropertyValue + "' from '" + strConnectionString + "'"); - } - } - - return objDictionary; - } - } -} diff --git a/SQL/SQL.cs b/SQL/SQL.cs index 7a0a4e2..389a03f 100644 --- a/SQL/SQL.cs +++ b/SQL/SQL.cs @@ -290,4 +290,53 @@ public enum FieldValueAutoAssignmentType /// NewUniqueIdentifier } + + internal static class DataTypeExtensions + { + public static void EnsureIsDecimal(DataType eDataType) + { + if (eDataType != DataType.Decimal) + throw new Exceptions.MethodLockedException("First set Type to " + DataType.Decimal.ToString()); + } + + public static void EnsureIsCharacter(SQL.DataType eDataType) + { + if (!IsCharacter(eDataType)) + throw new Exceptions.MethodLockedException("Data type is not character based"); + } + + public static void EnsureIsInteger(SQL.DataType eDataType) + { + if (!IsInteger(eDataType)) + throw new Exceptions.MethodLockedException(); + } + + public static bool IsInteger(SQL.DataType eDataType) + { + switch (eDataType) + { + case DataType.BigInteger: + case DataType.Integer: + case DataType.SmallInteger: + case DataType.TinyInteger: + return true; + default: + return false; + } + } + + public static bool IsCharacter(DataType eDataType) + { + switch (eDataType) + { + case DataType.Character: + case DataType.UnicodeCharacter: + case DataType.VariableCharacter: + case DataType.UnicodeVariableCharacter: + return true; + default: + return false; + } + } + } } diff --git a/SQL/SQLStatement.cs b/SQL/SQLStatement.cs index 9b44ccb..074ada2 100644 --- a/SQL/SQLStatement.cs +++ b/SQL/SQLStatement.cs @@ -58,6 +58,17 @@ public Database.ConnectionType ConnectionType peConnectionType = value; } } + + /// + /// Returns the serializer to be used based on the connection type. + /// + internal Serializers.Serializer Serializer + { + get + { + return Serializers.Serializers.Items[peConnectionType]; + } + } public override string ToString() { diff --git a/SQL/Select/SQLAutoIncrementValue.cs b/SQL/Select/SQLAutoIncrementValue.cs index 87041d5..4910d45 100644 --- a/SQL/Select/SQLAutoIncrementValue.cs +++ b/SQL/Select/SQLAutoIncrementValue.cs @@ -39,24 +39,7 @@ public override string SQL { get { - switch (this.ConnectionType) - { - case Database.ConnectionType.SQLServer: - return "SELECT SCOPE_IDENTITY() AS " + Misc.SQLConvertIdentifierName(this.ReturnFieldName, this.ConnectionType); - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.Pervasive: - case Database.ConnectionType.SQLServerCompactEdition: - return "SELECT @@IDENTITY AS " + Misc.SQLConvertIdentifierName(this.ReturnFieldName, this.ConnectionType); - case Database.ConnectionType.MySQL: - //The @@IDENTITY function is supported by MySQL from version 3.23.25 - //but I've put the original function here just in case - return "SELECT LAST_INSERT_ID() AS " + Misc.SQLConvertIdentifierName(this.ReturnFieldName, this.ConnectionType); - case Database.ConnectionType.HyperSQL: - return "SELECT IDENTITY() AS " + Misc.SQLConvertIdentifierName(this.ReturnFieldName, this.ConnectionType); - default: - throw new NotImplementedException(this.ConnectionType.ToString()); - break; - } + return base.Serializer.SerializeAutoIncrementValue(this); } } } diff --git a/SQL/Select/SQLCondition.cs b/SQL/Select/SQLCondition.cs index 4753e8d..f481511 100644 --- a/SQL/Select/SQLCondition.cs +++ b/SQL/Select/SQLCondition.cs @@ -77,15 +77,16 @@ public object Value set { - pobjValue = Misc.SQLConditionValue(value); + pobjValue = GetConditionValue(value); } } - - internal string SQL(Database.ConnectionType eConnectionType) + + internal static object GetConditionValue(object objValue) { - Misc.CompareValuePairAssertValid(this.Compare, pobjValue); - - return Misc.SQLFieldNameAndTablePrefix(this.Table, this.FieldName, eConnectionType) + " " + Misc.SQLConvertCondition(this.Compare, this.Value, eConnectionType); + if (objValue is SQLFieldValue) + return ((SQLFieldValue)objValue).Value; + else + return objValue; } } } diff --git a/SQL/Select/SQLConditionExpression.cs b/SQL/Select/SQLConditionExpression.cs index 4300de3..6f6381d 100644 --- a/SQL/Select/SQLConditionExpression.cs +++ b/SQL/Select/SQLConditionExpression.cs @@ -73,26 +73,9 @@ public SQLExpression RightExpression } } - internal override string SQL(Database.ConnectionType eConnectionType) + internal override string SQL(Serializers.Serializer serializer) { - if (pobjLeftExpression == null) - throw new InvalidOperationException("Left expression is not set"); - else if (pobjRightExpression == null) - throw new InvalidOperationException("Right expression is not set"); - - return Condition(pobjLeftExpression, peCompare, pobjRightExpression, eConnectionType); - } - - private string Condition(SQLExpression objLeftExpression, ComparisonOperator eCompare, SQLExpression objRightExpression, Database.ConnectionType eConnectionType) - { - string strSQL = pobjLeftExpression.SQL(eConnectionType) + " "; - - if (objRightExpression is SQLValueExpression) - strSQL += Misc.SQLConvertCondition(eCompare, ((SQLValueExpression) objRightExpression).Value, eConnectionType); - else - strSQL += Misc.SQLConvertCompare(eCompare) + " " + objRightExpression.SQL(eConnectionType); - - return strSQL; + return serializer.SerializeConditionExpression(this); } } } diff --git a/SQL/Select/SQLConditionFieldCompare.cs b/SQL/Select/SQLConditionFieldCompare.cs index 82077d6..b8e0c5c 100644 --- a/SQL/Select/SQLConditionFieldCompare.cs +++ b/SQL/Select/SQLConditionFieldCompare.cs @@ -83,16 +83,5 @@ public string FieldName2 pstrFieldName2 = value; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - if (String.IsNullOrEmpty(FieldName1)) - throw new ArgumentException("FieldName1 not set."); - - if (String.IsNullOrEmpty(FieldName2)) - throw new ArgumentException("FieldName2 not set."); - - return Misc.SQLFieldNameAndTablePrefix(this.Table1, this.FieldName1, eConnectionType) + " " + Misc.SQLConvertCompare(this.Compare) + " " + Misc.SQLFieldNameAndTablePrefix(this.Table2, this.FieldName2, eConnectionType); - } } } diff --git a/SQL/Select/SQLConditionInSelect.cs b/SQL/Select/SQLConditionInSelect.cs index 653f7f2..274f39e 100644 --- a/SQL/Select/SQLConditionInSelect.cs +++ b/SQL/Select/SQLConditionInSelect.cs @@ -73,25 +73,5 @@ public bool NotInSelect pbNotInSelect = value; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - if (String.IsNullOrEmpty(FieldName)) - throw new Exceptions.DatabaseObjectsException("FieldName not set."); - - if (Select == null) - throw new Exceptions.DatabaseObjectsException("SelectSet not set."); - - Select.ConnectionType = eConnectionType; - - string strIn; - - if (pbNotInSelect) - strIn = "NOT IN"; - else - strIn = "IN"; - - return Misc.SQLFieldNameAndTablePrefix(this.Table, this.FieldName, eConnectionType) + " " + strIn + " (" + Select.SQL + ")"; - } } } diff --git a/SQL/Select/SQLConditionSelect.cs b/SQL/Select/SQLConditionSelect.cs index 1078a45..22d8534 100644 --- a/SQL/Select/SQLConditionSelect.cs +++ b/SQL/Select/SQLConditionSelect.cs @@ -59,26 +59,8 @@ public object Value set { - pobjValue = Misc.SQLConditionValue(value); + pobjValue = SQLCondition.GetConditionValue(value); } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - if (this.Select == null) - throw new Exceptions.DatabaseObjectsException("Select is not set."); - - Misc.CompareValuePairAssertValid(this.Compare, pobjValue); - - this.Select.ConnectionType = eConnectionType; - return Condition(this.Select, this.Compare, pobjValue, eConnectionType); - } - - private string Condition(SQLSelect objSelect, ComparisonOperator eCompare, object vValue, Database.ConnectionType eConnectionType) - { - Misc.SQLConvertBooleanValue(ref vValue, ref eCompare); - - return "(" + objSelect.SQL + ") " + Misc.SQLConvertCompare(eCompare) + " " + Misc.SQLConvertValue(vValue, eConnectionType); - } } } diff --git a/SQL/Select/SQLConditions.cs b/SQL/Select/SQLConditions.cs index 7beffa4..c5b4869 100644 --- a/SQL/Select/SQLConditions.cs +++ b/SQL/Select/SQLConditions.cs @@ -207,35 +207,15 @@ public void Delete(ref SQLCondition objCondition) pobjSQLConditions.Remove(objCondition); objCondition = null; } - - internal string SQL(Database.ConnectionType eConnectionType) + + internal LogicalOperator[] LogicalOperators { - string strSQL = string.Empty; - - for (int intIndex = 0; intIndex < pobjSQLConditions.Count; intIndex++) + get { - if (intIndex > 0) - strSQL += " " + Misc.SQLConvertLogicalOperator(pobjLogicalOperators[intIndex - 1]) + " "; - - if (pobjSQLConditions[intIndex] is SQLCondition) - strSQL += ((SQLCondition)(pobjSQLConditions[intIndex])).SQL(eConnectionType); - else if (pobjSQLConditions[intIndex] is SQLConditions) - strSQL += "(" + ((SQLConditions)(pobjSQLConditions[intIndex])).SQL(eConnectionType) + ")"; - else if (pobjSQLConditions[intIndex] is SQLConditionInSelect) - strSQL += ((SQLConditionInSelect)(pobjSQLConditions[intIndex])).SQL(eConnectionType); - else if (pobjSQLConditions[intIndex] is SQLConditionSelect) - strSQL += ((SQLConditionSelect)(pobjSQLConditions[intIndex])).SQL(eConnectionType); - else if (pobjSQLConditions[intIndex] is SQLConditionFieldCompare) - strSQL += ((SQLConditionFieldCompare)(pobjSQLConditions[intIndex])).SQL(eConnectionType); - else if (pobjSQLConditions[intIndex] is SQLConditionExpression) - strSQL += ((SQLConditionExpression)(pobjSQLConditions[intIndex])).SQL(eConnectionType); - else - throw new NotImplementedException(pobjSQLConditions[intIndex].GetType().FullName); + return this.pobjLogicalOperators.ToArray(); } - - return strSQL; } - + public System.Collections.IEnumerator GetEnumerator() { return pobjSQLConditions.GetEnumerator(); diff --git a/SQL/Select/SQLSelect.cs b/SQL/Select/SQLSelect.cs index 2e35d24..93a052f 100644 --- a/SQL/Select/SQLSelect.cs +++ b/SQL/Select/SQLSelect.cs @@ -172,110 +172,13 @@ public SQLSelectGroupByFields GroupBy pobjGroupByFields = value; } } - + public override string SQL { - get + get { - string strSQL; - - if (pobjTables.Count == 0) - throw new Exceptions.DatabaseObjectsException("The table has not been set."); - - strSQL = "SELECT " + DistinctClause(); - - switch (base.ConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - break; - case Database.ConnectionType.SQLServer: - break; - case Database.ConnectionType.SQLServerCompactEdition: - strSQL += TopClause(); - break; - } - - strSQL += pobjFields.SQL(this.ConnectionType) + " FROM " + pobjTables.SQL(this.ConnectionType); - - if (pbPerformLocking) - { - switch (this.ConnectionType) - { - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - strSQL += " WITH (HOLDLOCK, ROWLOCK)"; - break; - case Database.ConnectionType.MySQL: - case Database.ConnectionType.Pervasive: - break; - //Done below - case Database.ConnectionType.HyperSQL: - case Database.ConnectionType.MicrosoftAccess: - throw new NotSupportedException("Locking is not supported for " + this.ConnectionType.ToString()); - break; - default: - throw new NotImplementedException(this.ConnectionType.ToString()); - break; - } - } - - if (pobjConditions != null && !pobjConditions.IsEmpty) - strSQL += " WHERE " + pobjConditions.SQL(this.ConnectionType); - - if (pobjGroupByFields != null && !pobjGroupByFields.IsEmpty) - strSQL += " GROUP BY " + pobjGroupByFields.SQL(this.ConnectionType); - - if (pobjOrderByFields != null && !pobjOrderByFields.IsEmpty) - strSQL += " ORDER BY " + pobjOrderByFields.SQL(this.ConnectionType); - - if (pobjHavingConditions != null && !pobjHavingConditions.IsEmpty) - strSQL += " HAVING " + pobjHavingConditions.SQL(this.ConnectionType); - - if (pbPerformLocking) - { - switch (this.ConnectionType) - { - case Database.ConnectionType.MySQL: - case Database.ConnectionType.Pervasive: - strSQL += " FOR UPDATE"; - break; - } - } - - if (pintTop > 0) - { - switch (this.ConnectionType) - { - case Database.ConnectionType.MySQL: - case Database.ConnectionType.Pervasive: - strSQL += " LIMIT " + pintTop.ToString(); - break; - } - } - - return strSQL; + return base.Serializer.SerializeSelect(this); } } - - private string TopClause() - { - if (pintTop > 0) - { - if (base.ConnectionType == Database.ConnectionType.SQLServerCompactEdition) - return "TOP(" + pintTop.ToString() + ") "; - else - return "TOP " + pintTop.ToString() + " "; - } - else - return string.Empty; - } - - private string DistinctClause() - { - if (pbDistinct) - return "DISTINCT "; - else - return string.Empty; - } } } diff --git a/SQL/Select/SQLSelectExpression.cs b/SQL/Select/SQLSelectExpression.cs index 5bd4458..0d467b2 100644 --- a/SQL/Select/SQLSelectExpression.cs +++ b/SQL/Select/SQLSelectExpression.cs @@ -22,12 +22,20 @@ public SQLSelectExpression(SQL.SQLExpression objExpression) pobjExpression = objExpression; } + + public SQL.SQLExpression Expression + { + get + { + return pobjExpression; + } + } public override string SQL { get { - return "SELECT " + pobjExpression.SQL(base.ConnectionType); + return base.Serializer.SerializeSelectExpression(this); } } } diff --git a/SQL/Select/SQLSelectField.cs b/SQL/Select/SQLSelectField.cs index d66586d..4b6cdb0 100644 --- a/SQL/Select/SQLSelectField.cs +++ b/SQL/Select/SQLSelectField.cs @@ -44,15 +44,5 @@ public string Alias pstrAlias = value; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - string strSQL = pobjExpression.SQL(eConnectionType); - - if (!String.IsNullOrEmpty(this.Alias)) - strSQL += " AS " + Misc.SQLConvertIdentifierName(this.Alias, eConnectionType); - - return strSQL; - } } } diff --git a/SQL/Select/SQLSelectFields.cs b/SQL/Select/SQLSelectFields.cs index 93e0329..1d546b8 100644 --- a/SQL/Select/SQLSelectFields.cs +++ b/SQL/Select/SQLSelectFields.cs @@ -107,27 +107,6 @@ public void Clear() pobjFieldNames.Clear(); } - internal string SQL(Database.ConnectionType eConnectionType) - { - string strSQL = string.Empty; - - if (this.Count == 0) - strSQL = "*"; - else - { - for (int intIndex = 0; intIndex < this.Count; intIndex++) - { - strSQL += this[intIndex].SQL(eConnectionType); - if (intIndex != this.Count - 1) - { - strSQL += ", "; - } - } - } - - return strSQL; - } - public bool Exists(string strFieldName) { return FieldNameIndex(strFieldName) >= 0; diff --git a/SQL/Select/SQLSelectGroupByField.cs b/SQL/Select/SQLSelectGroupByField.cs index 8cdc41d..d7af887 100644 --- a/SQL/Select/SQLSelectGroupByField.cs +++ b/SQL/Select/SQLSelectGroupByField.cs @@ -30,10 +30,5 @@ internal SQLExpression Expression return pobjExpression; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - return pobjExpression.SQL(eConnectionType); - } } } diff --git a/SQL/Select/SQLSelectGroupByFields.cs b/SQL/Select/SQLSelectGroupByFields.cs index 31b57d4..6e95648 100644 --- a/SQL/Select/SQLSelectGroupByFields.cs +++ b/SQL/Select/SQLSelectGroupByFields.cs @@ -71,21 +71,7 @@ public int Count return pobjGroupByFields.Count; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - string strSQL = string.Empty; - - for (int intIndex = 0; intIndex < this.Count; intIndex++) - { - strSQL += this[intIndex].SQL(eConnectionType); - if (intIndex != this.Count - 1) - strSQL += ", "; - } - - return strSQL; - } - + public bool Exists(string strFieldName) { return FieldNameIndex(strFieldName) >= 0; diff --git a/SQL/Select/SQLSelectHavingCondition.cs b/SQL/Select/SQLSelectHavingCondition.cs index d79af9f..3c0f299 100644 --- a/SQL/Select/SQLSelectHavingCondition.cs +++ b/SQL/Select/SQLSelectHavingCondition.cs @@ -28,10 +28,34 @@ public SQLSelectHavingCondition(SQLExpression objLeftHandExpression, ComparisonO peCompare = eCompare; pobjRightHandExpression = objRightHandExpression; } - - internal override string SQL(Database.ConnectionType eConnectionType) + + internal ComparisonOperator Compare + { + get + { + return peCompare; + } + } + + internal SQLExpression LeftExpression + { + get + { + return pobjLeftHandExpression; + } + } + + internal SQLExpression RightExpression + { + get + { + return pobjRightHandExpression; + } + } + + internal override string SQL(Serializers.Serializer serializer) { - return pobjLeftHandExpression.SQL(eConnectionType) + " " + Misc.SQLConvertCompare(peCompare) + " " + pobjRightHandExpression.SQL(eConnectionType); + return serializer.SerializeSelectHavingCondition(this); } } } diff --git a/SQL/Select/SQLSelectHavingConditions.cs b/SQL/Select/SQLSelectHavingConditions.cs index 253c48e..8a0a8ee 100644 --- a/SQL/Select/SQLSelectHavingConditions.cs +++ b/SQL/Select/SQLSelectHavingConditions.cs @@ -12,7 +12,7 @@ namespace DatabaseObjects.SQL { - public class SQLSelectHavingConditions + public class SQLSelectHavingConditions : IEnumerable { private ArrayList pobjConditions = new ArrayList(); private List pobjLogicalOperators = new List(); @@ -67,6 +67,14 @@ public bool IsEmpty return pobjConditions.Count == 0; } } + + internal LogicalOperator[] LogicalOperators + { + get + { + return pobjLogicalOperators.ToArray(); + } + } private void EnsurePreviousLogicalOperatorExists() { @@ -82,25 +90,10 @@ public void AddLogicalOperator(LogicalOperator eLogicalOperator) pobjLogicalOperators.Add(eLogicalOperator); } - - internal string SQL(Database.ConnectionType eConnectionType) + + IEnumerator IEnumerable.GetEnumerator() { - string strSQL = string.Empty; - - for (int intIndex = 0; intIndex < pobjConditions.Count; intIndex++) - { - if (intIndex > 0) - strSQL += " " + Misc.SQLConvertLogicalOperator(pobjLogicalOperators[intIndex - 1]) + " "; - - if (pobjConditions[intIndex] is SQLSelectHavingCondition) - strSQL += ((SQLSelectHavingCondition) (pobjConditions[intIndex])).SQL(eConnectionType); - else if (pobjConditions[intIndex] is SQLSelectHavingConditions) - strSQL += "(" + ((SQLSelectHavingConditions) (pobjConditions[intIndex])).SQL(eConnectionType) + ")"; - else - throw new NotImplementedException(pobjConditions[intIndex].GetType().FullName); - } - - return strSQL; + return pobjConditions.GetEnumerator(); } } } diff --git a/SQL/Select/SQLSelectOrderByField.cs b/SQL/Select/SQLSelectOrderByField.cs index 49be60f..5ddf914 100644 --- a/SQL/Select/SQLSelectOrderByField.cs +++ b/SQL/Select/SQLSelectOrderByField.cs @@ -79,32 +79,5 @@ public SQLSelectTable Table pobjTable = value; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - string strSQL = string.Empty; - - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("Order By field has not been set."); - - if (this.AggregateFunction > 0) - strSQL = Misc.SQLConvertAggregate(this.AggregateFunction) + "("; - - strSQL += Misc.SQLFieldNameAndTablePrefix(this.Table, this.Name, eConnectionType); - - if (this.AggregateFunction > 0) - strSQL += ")"; - - switch (this.Order) - { - case OrderBy.Ascending: - break; - case OrderBy.Descending: - strSQL += " DESC"; - break; - } - - return strSQL; - } } } diff --git a/SQL/Select/SQLSelectOrderByFields.cs b/SQL/Select/SQLSelectOrderByFields.cs index f8391ad..e592853 100644 --- a/SQL/Select/SQLSelectOrderByFields.cs +++ b/SQL/Select/SQLSelectOrderByFields.cs @@ -100,20 +100,6 @@ public bool IsEmpty } } - internal string SQL(Database.ConnectionType eConnectionType) - { - string strSQL = string.Empty; - - for (int intIndex = 0; intIndex < this.Count; intIndex++) - { - strSQL += this[intIndex].SQL(eConnectionType); - if (intIndex != this.Count - 1) - strSQL += ", "; - } - - return strSQL; - } - public bool Exists(string strFieldName) { return this.SingleOrDefault(field => Equals(field, strFieldName)) != null; diff --git a/SQL/Select/SQLSelectTable.cs b/SQL/Select/SQLSelectTable.cs index b1b4727..ac488e1 100644 --- a/SQL/Select/SQLSelectTable.cs +++ b/SQL/Select/SQLSelectTable.cs @@ -73,21 +73,10 @@ public string Name pstrName = value; } } - - protected override string Source(Database.ConnectionType eConnectionType) + + internal override string Source(Serializers.Serializer serializer) { - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("Table has not been set."); - - string strSQL = string.Empty; - - if (!String.IsNullOrEmpty(pstrDatabaseName)) - strSQL += Misc.SQLConvertIdentifierName(pstrDatabaseName, eConnectionType) + "."; - - if (!String.IsNullOrEmpty(pstrSchemaName)) - strSQL += Misc.SQLConvertIdentifierName(pstrSchemaName, eConnectionType) + "."; - - return strSQL + Misc.SQLConvertIdentifierName(this.Name, eConnectionType); + return serializer.SerializeSelectTable(this); } } } diff --git a/SQL/Select/SQLSelectTableBase.cs b/SQL/Select/SQLSelectTableBase.cs index df1d54e..563e59b 100644 --- a/SQL/Select/SQLSelectTableBase.cs +++ b/SQL/Select/SQLSelectTableBase.cs @@ -13,7 +13,7 @@ namespace DatabaseObjects.SQL { public abstract class SQLSelectTableBase { - protected abstract string Source(Database.ConnectionType eConnectionType); + internal abstract string Source(Serializers.Serializer serializer); private string pstrAlias = string.Empty; @@ -33,15 +33,5 @@ public virtual string Alias pstrAlias = value; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - string strSQL = this.Source(eConnectionType); - - if (!String.IsNullOrEmpty(this.Alias)) - strSQL += " " + Misc.SQLConvertIdentifierName(this.Alias, eConnectionType); - - return strSQL; - } } } diff --git a/SQL/Select/SQLSelectTableFromSelect.cs b/SQL/Select/SQLSelectTableFromSelect.cs index 1ee6852..17164a4 100644 --- a/SQL/Select/SQLSelectTableFromSelect.cs +++ b/SQL/Select/SQLSelectTableFromSelect.cs @@ -25,12 +25,18 @@ public SQLSelectTableFromSelect(SQLSelect objSelect, string strAlias) pobjSelect = objSelect; base.Alias = strAlias; } - - protected override string Source(Database.ConnectionType eConnectionType) - { - pobjSelect.ConnectionType = eConnectionType; - return "(" + pobjSelect.SQL + ")"; + public SQLSelect Select + { + get + { + return pobjSelect; + } + } + + internal override string Source(Serializers.Serializer serializer) + { + return serializer.SerializeSelectTableFromSelect(this); } } } diff --git a/SQL/Select/SQLSelectTableJoin.cs b/SQL/Select/SQLSelectTableJoin.cs index 52ead6d..acc735b 100644 --- a/SQL/Select/SQLSelectTableJoin.cs +++ b/SQL/Select/SQLSelectTableJoin.cs @@ -90,30 +90,10 @@ public SQLSelectTableJoinConditions Where pobjConditions = value; } } - - protected override string Source(Database.ConnectionType eConnectionType) - { - string strSQL = pobjLeftTable.SQL(eConnectionType) + " " + GetJoinString(this.TheType) + " " + pobjRightTable.SQL(eConnectionType); - - if (pobjConditions != null && !pobjConditions.IsEmpty) - strSQL += " ON " + pobjConditions.SQL(eConnectionType); - - //Surround the join with parentheses - MS Access won't accept it otherwise - return "(" + strSQL + ")"; - } - - private static string GetJoinString(Type eJoinType) + + internal override string Source(Serializers.Serializer serializer) { - if (eJoinType == SQLSelectTableJoin.Type.Inner) - return "INNER JOIN"; - else if (eJoinType == SQLSelectTableJoin.Type.FullOuter) - return "FULL OUTER JOIN"; - else if (eJoinType == SQLSelectTableJoin.Type.LeftOuter) - return "LEFT OUTER JOIN"; - else if (eJoinType == SQLSelectTableJoin.Type.RightOuter) - return "RIGHT OUTER JOIN"; - else - throw new NotImplementedException(eJoinType.ToString()); + return serializer.SerializeSelectTableJoin(this); } } } diff --git a/SQL/Select/SQLSelectTableJoinCondition.cs b/SQL/Select/SQLSelectTableJoinCondition.cs index 88169a1..4345891 100644 --- a/SQL/Select/SQLSelectTableJoinCondition.cs +++ b/SQL/Select/SQLSelectTableJoinCondition.cs @@ -61,14 +61,5 @@ public SQLExpression LeftExpression pobjLeftExpression = value; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - //Account for the situation where EqualTo to NULL is appropriately translated to 'IS NULL' - if (pobjRightExpression is SQLValueExpression) - return pobjLeftExpression.SQL(eConnectionType) + " " + Misc.SQLConvertCondition(Compare, ((SQLValueExpression)pobjRightExpression).Value, eConnectionType); - else - return pobjLeftExpression.SQL(eConnectionType) + " " + Misc.SQLConvertCompare(Compare) + " " + pobjRightExpression.SQL(eConnectionType); - } } } diff --git a/SQL/Select/SQLSelectTableJoinConditions.cs b/SQL/Select/SQLSelectTableJoinConditions.cs index f54dde9..0bd3c3a 100644 --- a/SQL/Select/SQLSelectTableJoinConditions.cs +++ b/SQL/Select/SQLSelectTableJoinConditions.cs @@ -12,7 +12,7 @@ namespace DatabaseObjects.SQL { - public class SQLSelectTableJoinConditions + public class SQLSelectTableJoinConditions : IEnumerable { private List pobjLogicalOperators = new List(); private ArrayList pobjConditions = new ArrayList(); @@ -118,6 +118,14 @@ public int Count return pobjConditions.Count; } } + + internal LogicalOperator[] LogicalOperators + { + get + { + return pobjLogicalOperators.ToArray(); + } + } public void Delete(ref SQLSelectTableJoinConditions objConditions) { @@ -136,28 +144,10 @@ public void Delete(ref SQLSelectTableJoinCondition objOrderByField) pobjConditions.Remove(objOrderByField); objOrderByField = null; } - - internal string SQL(Database.ConnectionType eConnectionType) + + IEnumerator IEnumerable.GetEnumerator() { - string strSQL = string.Empty; - int intIndex = 0; - - foreach (object objCondition in pobjConditions) - { - if (intIndex > 0) - strSQL += " " + Misc.SQLConvertLogicalOperator((LogicalOperator) (pobjLogicalOperators[intIndex - 1])) + " "; - - if (objCondition is SQLSelectTableJoinConditions) - strSQL += "(" + ((SQLSelectTableJoinConditions) objCondition).SQL(eConnectionType) + ")"; - else if (objCondition is SQLSelectTableJoinCondition) - strSQL += ((SQLSelectTableJoinCondition) objCondition).SQL(eConnectionType); - else - throw new NotImplementedException(objCondition.GetType().FullName); - - intIndex++; - } - - return strSQL; + return pobjConditions.GetEnumerator(); } } } diff --git a/SQL/Select/SQLSelectTableJoins.cs b/SQL/Select/SQLSelectTableJoins.cs index b0af3c0..e633164 100644 --- a/SQL/Select/SQLSelectTableJoins.cs +++ b/SQL/Select/SQLSelectTableJoins.cs @@ -79,15 +79,6 @@ public void Delete(SQLSelectTableJoin objJoin) objJoin = null; } - internal string SQL(Database.ConnectionType eConnectionType) - { - if (this.Count > 0) - //recurse through the joins from right to left - return this[this.Count - 1].SQL(eConnectionType); - else - return string.Empty; - } - public System.Collections.IEnumerator GetEnumerator() { return pobjJoins.GetEnumerator(); diff --git a/SQL/Select/SQLSelectTables.cs b/SQL/Select/SQLSelectTables.cs index 0dd5d48..6d8a328 100644 --- a/SQL/Select/SQLSelectTables.cs +++ b/SQL/Select/SQLSelectTables.cs @@ -134,43 +134,7 @@ public void Delete(ref SQLSelectTable objTable) pobjTables.Remove(objTable); objTable = null; } - - internal string SQL(Database.ConnectionType eConnectionType) - { - string strSQL = string.Empty; - bool bAddTable; - - for (int intIndex = 0; intIndex < this.Count; intIndex++) - { - //Include the table if it's not being used in a join - if (pobjJoins == null) - bAddTable = true; - else if (!pobjJoins.Exists(this[intIndex])) - bAddTable = true; - else - bAddTable = false; - - if (bAddTable) - { - strSQL += this[intIndex].SQL(eConnectionType); - if (intIndex != this.Count - 1) - strSQL += ", "; - } - } - - if (pobjJoins != null) - { - string strJoinsSQL = pobjJoins.SQL(eConnectionType); - - if (strJoinsSQL != string.Empty && strSQL != string.Empty) - strSQL += " "; - - strSQL += strJoinsSQL; - } - - return strSQL; - } - + private bool Equals(SQLSelectTable table, string strTableName) { return table.Name.Equals(strTableName, StringComparison.InvariantCultureIgnoreCase); diff --git a/SQL/Select/SQLUnion.cs b/SQL/Select/SQLUnion.cs index 0b861dd..cb37726 100644 --- a/SQL/Select/SQLUnion.cs +++ b/SQL/Select/SQLUnion.cs @@ -9,6 +9,7 @@ using System; using System.Data; using System.Collections.Generic; +using System.Linq; namespace DatabaseObjects.SQL { @@ -68,6 +69,14 @@ public SQLSelectOrderByFields OrderBy pobjOrderByFields = value; } } + + internal SQLUnion.Type[] UnionTypes + { + get + { + return pobjUnionType.Cast().ToArray(); + } + } internal SQL.SQLSelect[] SelectStatements { @@ -88,35 +97,7 @@ public override string SQL { get { - if (pobjSelectStatements.Count == 0) - throw new Exceptions.DatabaseObjectsException("The table has not been set."); - - string strSQL = string.Empty; - SQLSelect objSelect; - string strOrderBy; - - for (int intIndex = 0; intIndex < pobjSelectStatements.Count; intIndex++) - { - if (intIndex > 0) - { - strSQL += " UNION "; - if (((SQLUnion.Type)pobjUnionType[intIndex - 1]) == Type.All) - strSQL += "ALL "; - } - - objSelect = pobjSelectStatements[intIndex]; - objSelect.ConnectionType = this.ConnectionType; - strSQL += "(" + objSelect.SQL + ")"; - } - - if (pobjOrderByFields != null) - { - strOrderBy = pobjOrderByFields.SQL(this.ConnectionType); - if (strOrderBy != string.Empty) - strSQL += " ORDER BY " + strOrderBy; - } - - return strSQL; + return base.Serializer.SerializeUnion(this); } } } diff --git a/SQL/Serializers/HyperSqlSerializer.cs b/SQL/Serializers/HyperSqlSerializer.cs new file mode 100644 index 0000000..cfa7b09 --- /dev/null +++ b/SQL/Serializers/HyperSqlSerializer.cs @@ -0,0 +1,139 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + internal class HyperSqlSerializer : Serializer + { + public override Database.ConnectionType Type + { + get + { + return Database.ConnectionType.HyperSQL; + } + } + + public override string SerializeViewExists(SQLViewExists viewExists) + { + var select = new SQLSelect(); + + select.Tables.Add("VIEWS").SchemaName = "INFORMATION_SCHEMA"; + select.Where.Add("TABLE_SCHEMA", ComparisonOperator.EqualTo, "PUBLIC"); + select.Where.Add("TABLE_NAME", ComparisonOperator.EqualTo, viewExists.ViewName); + + return SerializeSelect(select); + } + + public override string SerializeRollbackTransaction(SQLRollbackTransaction rollbackTransaction) + { + return "ROLLBACK"; + } + + public override string SerializeCommitTransaction(SQLCommitTransaction commitTransaction) + { + return "COMMIT"; + } + + public override string SerializeBeingTransaction(SQLBeginTransaction beginTransaction) + { + return "START TRANSACTION"; + } + + public override string SerializeTableExists(SQLTableExists tableExists) + { + var select = new SQLSelect(); + select.Tables.Add("SYSTEM_TABLES").SchemaName = "INFORMATION_SCHEMA"; + select.Where.Add("TABLE_SCHEM", ComparisonOperator.EqualTo, "PUBLIC"); + select.Where.Add("TABLE_NAME", ComparisonOperator.EqualTo, tableExists.Name); + + return SerializeSelect(select); + } + + public override string SerializeIdentifier(string strIdentifierName) + { + return "\"" + strIdentifierName + "\""; + } + + public override string SerializeByteArray(byte[] data) + { + return SerializeByteArray("x'", data, "'"); + } + + public override string SerializeAutoIncrementValue(SQLAutoIncrementValue autoIncrementValue) + { + return "SELECT IDENTITY() AS " + SerializeIdentifier(autoIncrementValue.ReturnFieldName); + } + + public override string SerializeTableFieldDataType(SQLTableField field) + { + if (field.AutoIncrements) + return base.SerializeTableFieldDataType(field) + " GENERATED BY DEFAULT AS IDENTITY(START WITH 1 INCREMENT BY 1)"; + else + return base.SerializeTableFieldDataType(field); + } + + public override string SerializeDataType(SQL.DataType dataType, int size, int precision, int scale) + { + switch (dataType) + { + case DataType.TinyInteger: + return "TINYINT"; + case DataType.SmallInteger: + return "SMALLINT"; + case DataType.Integer: + return "INT"; + case DataType.BigInteger: + return "BIGINT"; + case DataType.Character: + return "CHAR(" + size.ToString() + ")"; + case DataType.UnicodeCharacter: + return "CHAR(" + size.ToString() + ")"; + case DataType.VariableCharacter: + return "VARCHAR(" + size.ToString() + ")"; + case DataType.UnicodeVariableCharacter: + return "VARCHAR(" + size.ToString() + ")"; + case DataType.Decimal: + return "NUMBER(" + precision.ToString() + "," + scale.ToString() + ")"; + case DataType.Real: + return "DOUBLE"; + case DataType.Float: + return "DOUBLE"; + case DataType.SmallMoney: + return "NUMBER(10,4)"; + case DataType.Money: + return "NUMBER(19,4)"; + case DataType.Boolean: + return "BOOLEAN"; + case DataType.SmallDateTime: + return "DATE"; + case DataType.DateTime: + return "DATE"; + case DataType.TimeStamp: + return "TIMESTAMP"; + case DataType.Text: + return "CLOB(2G)"; + case DataType.UnicodeText: + return "CLOB(2G)"; + case DataType.Binary: + return "BINARY(8000)"; + case DataType.VariableBinary: + return "VARBINARY(8000)"; + case DataType.Image: + return "BLOB(2G)"; + case DataType.UniqueIdentifier: + return "UNIQUEIDENTIFIER"; + } + + return base.SerializeDataType(dataType, size, precision, scale); + } + } +} diff --git a/SQL/Serializers/MicrosoftAccessSerializer.cs b/SQL/Serializers/MicrosoftAccessSerializer.cs new file mode 100644 index 0000000..89502d8 --- /dev/null +++ b/SQL/Serializers/MicrosoftAccessSerializer.cs @@ -0,0 +1,109 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + internal class MicrosoftAccessSerializer : MicrosoftSerializer + { + public override Database.ConnectionType Type + { + get + { + return Database.ConnectionType.MicrosoftAccess; + } + } + + public override string SerializeViewExists(SQLViewExists viewExists) + { + throw new NotSupportedException(); + } + + public override string SerializeTableExists(SQLTableExists tableExists) + { + var select = new SQLSelect(); + + select.Tables.Add("msysobjects"); + select.Where.Add("Name", ComparisonOperator.EqualTo, tableExists.Name); + select.Where.Add("Type", ComparisonOperator.EqualTo, 1); + + return SerializeSelect(select); + } + + public override string SerializeDateTime(DateTime dateTime) + { + return "#" + base.SerializeDateTimeValue(dateTime) + "#"; + } + + public override string SerializeGetDateFunctionExpression(SQLGetDateFunctionExpression expression) + { + return "Now()"; + } + + public override string SerializeAfterSelectTables(SQLSelect select) + { + if (select.PerformLocking) + throw new NotSupportedException("Locking is not supported for " + this.Type.ToString()); + + return base.SerializeAfterSelectTables(select); + } + + public override string SerializeBoolean(bool value) + { + if (value) + return "-1"; + else + return "0"; + } + + public override string SerializeDataType(SQL.DataType dataType, int size, int precision, int scale) + { + switch (dataType) + { + case DataType.TinyInteger: + return "BYTE"; + case DataType.BigInteger: + return "NUMERIC(19,0)"; + case DataType.Character: + return "TEXT(" + size.ToString() + ")"; + case DataType.UnicodeCharacter: + //Unicode is only supported in Microsoft Access 2000+ + return "TEXT(" + size.ToString() + ")"; + case DataType.VariableCharacter: + return "TEXT(" + size.ToString() + ")"; + case DataType.UnicodeVariableCharacter: + //Unicode is only supported in Microsoft Access 2000+ + return "TEXT(" + size.ToString() + ")"; + case DataType.SmallMoney: + return "NUMERIC(10,4)"; + case DataType.Money: + return "NUMERIC(19,4)"; + case DataType.Boolean: + return "YESNO"; + case DataType.SmallDateTime: + return "DATETIME"; + case DataType.TimeStamp: + throw new NotSupportedException("TIMESTAMP"); + case DataType.Text: + return "MEMO"; + case DataType.UnicodeText: + //Unicode is only supported in Microsoft Access 2000+ + return "MEMO"; + case DataType.Binary: + return "OLEOBJECT"; + case DataType.VariableBinary: + return "OLEOBJECT"; + default: + return base.SerializeDataType(dataType, size, precision, scale); + } + } + } +} diff --git a/SQL/Serializers/MicrosoftSerializer.cs b/SQL/Serializers/MicrosoftSerializer.cs new file mode 100644 index 0000000..db085d3 --- /dev/null +++ b/SQL/Serializers/MicrosoftSerializer.cs @@ -0,0 +1,120 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + /// + /// Serializes an DatabaseObjects.SQL.* object into an SQL string ready for execution. + /// This class manages Microsoft oriented database systems; SQL Server, Access, Compact Edition. + /// Methods can be overridden if a database system serializes differently. + /// + internal abstract class MicrosoftSerializer : Serializer + { + public override string SerializeBeforeSelectFields(SQLSelect select) + { + var topClause = select.Top > 0 ? "TOP(" + select.Top.ToString() + ") " : String.Empty; + + return base.SerializeBeforeSelectFields(select) + topClause; + } + + public override string SerializeTableFieldDataType(SQLTableField field) + { + if (field.AutoIncrements) + return base.SerializeTableFieldDataType(field) + " IDENTITY"; + else + return base.SerializeTableFieldDataType(field); + } + + public override string SerializeIdentifier(string strIdentifierName) + { + return "[" + strIdentifierName + "]"; + } + + public override string SerializeAfterSelectTables(SQLSelect select) + { + if (select.PerformLocking) + return "WITH (HOLDLOCK, ROWLOCK)"; + else + return String.Empty; + } + + public override string SerializeGetDateFunctionExpression(SQLGetDateFunctionExpression expression) + { + return "GetDate()"; + } + + public override string SerializeSelectExpression(SQLSelectExpression selectExpression) + { + return "SELECT " + selectExpression.Expression.SQL(this); + } + + public override string SerializeLengthFunctionExpression(SQLLengthFunctionExpression expression) + { + return "LEN" + SerializeFunctionExpressionArguments(expression); + } + + public override string SerializeDataType(DataType dataType, int size, int precision, int scale) + { + switch (dataType) + { + case DataType.TinyInteger: + return "TINYINT"; + case DataType.SmallInteger: + return "SMALLINT"; + case DataType.Integer: + return "INTEGER"; + case DataType.BigInteger: + return "BIGINT"; + case DataType.Character: + return "CHAR(" + size.ToString() + ")"; + case DataType.UnicodeCharacter: + return "NCHAR(" + size.ToString() + ")"; + case DataType.VariableCharacter: + return "VARCHAR(" + size.ToString() + ")"; + case DataType.UnicodeVariableCharacter: + return "NVARCHAR(" + size.ToString() + ")"; + case DataType.Decimal: + return "NUMERIC(" + precision.ToString() + "," + scale.ToString() + ")"; + case DataType.Real: + return "REAL"; + case DataType.Float: + return "FLOAT"; + case DataType.SmallMoney: + return "SMALLMONEY"; + case DataType.Money: + return "MONEY"; + case DataType.Boolean: + return "BIT"; + case DataType.SmallDateTime: + return "SMALLDATETIME"; + case DataType.DateTime: + return "DATETIME"; + case DataType.TimeStamp: + return "TIMESTAMP"; + case DataType.Text: + return "TEXT"; + case DataType.UnicodeText: + return "NTEXT"; + case DataType.Binary: + return "BINARY"; + case DataType.VariableBinary: + return "VARBINARY"; + case DataType.Image: + return "IMAGE"; + case DataType.UniqueIdentifier: + return "UNIQUEIDENTIFIER"; + default: + return base.SerializeDataType(dataType, size, precision, scale); + } + } + } +} diff --git a/SQL/Serializers/MicrosoftSqlServerCompactEditionSerializer.cs b/SQL/Serializers/MicrosoftSqlServerCompactEditionSerializer.cs new file mode 100644 index 0000000..4608ff2 --- /dev/null +++ b/SQL/Serializers/MicrosoftSqlServerCompactEditionSerializer.cs @@ -0,0 +1,56 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + internal class MicrosoftSqlServerCompactEditionSerializer : MicrosoftSerializer + { + public override Database.ConnectionType Type + { + get + { + return Database.ConnectionType.SQLServerCompactEdition; + } + } + + public override string SerializeViewExists(SQLViewExists viewExists) + { + throw new NotSupportedException(); + } + + public override string SerializeTableExists(SQLTableExists tableExists) + { + throw new NotSupportedException("Use SELECT COUNT(*) FROM table to determine if a record exists"); + } + + public override string SerializeDataType(DataType dataType, int size, int precision, int scale) + { + switch (dataType) + { + case DataType.SmallDateTime: + return "DATETIME"; + default: + return base.SerializeDataType(dataType, size, precision, scale); + } + } + + public override string SerializeDropIndex(SQLDropIndex dropIndex) + { + if (String.IsNullOrEmpty(dropIndex.Name)) + throw new Exceptions.DatabaseObjectsException("IndexName has not been set."); + else if (String.IsNullOrEmpty(dropIndex.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName has not been set."); + + return "DROP INDEX " + SerializeIdentifier(dropIndex.TableName) + "." + SerializeIdentifier(dropIndex.Name); + } + } +} diff --git a/SQL/Serializers/MicrosoftSqlServerSerializer.cs b/SQL/Serializers/MicrosoftSqlServerSerializer.cs new file mode 100644 index 0000000..dd82676 --- /dev/null +++ b/SQL/Serializers/MicrosoftSqlServerSerializer.cs @@ -0,0 +1,69 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + internal class MicrosoftSqlServerSerializer : MicrosoftSerializer + { + public override Database.ConnectionType Type + { + get + { + return Database.ConnectionType.SQLServer; + } + } + + public override string SerializeViewExists(SQLViewExists viewExists) + { + var select = new SQLSelect(); + + select.Tables.Add("sysobjects"); + select.Where.Add("Name", ComparisonOperator.EqualTo, viewExists.ViewName); + select.Where.Add("XType", ComparisonOperator.EqualTo, "V"); //V = User defined view + + return SerializeSelect(select); + } + + public override string SerializeIsolationLevel(System.Data.IsolationLevel isolationLevel) + { + if (isolationLevel == System.Data.IsolationLevel.Snapshot) + return "SNAPSHOT"; + else + return base.SerializeIsolationLevel(isolationLevel); + } + + public override string SerializeTableExists(SQLTableExists tableExists) + { + var select = new SQLSelect(); + select.Tables.Add("sysobjects"); + select.Where.Add("Name", ComparisonOperator.EqualTo, tableExists.Name); + select.Where.Add("XType", ComparisonOperator.EqualTo, "U"); // U = User defined table + + return SerializeSelect(select); + } + + public override string SerializeAutoIncrementValue(SQLAutoIncrementValue autoIncrementValue) + { + return "SELECT SCOPE_IDENTITY() AS " + SerializeIdentifier(autoIncrementValue.ReturnFieldName); + } + + public override string SerializeDropIndex(SQLDropIndex dropIndex) + { + if (String.IsNullOrEmpty(dropIndex.Name)) + throw new Exceptions.DatabaseObjectsException("IndexName has not been set."); + else if (String.IsNullOrEmpty(dropIndex.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName has not been set."); + + return "DROP INDEX " + SerializeIdentifier(dropIndex.TableName) + "." + SerializeIdentifier(dropIndex.Name); + } + } +} diff --git a/SQL/Serializers/MySqlSerializer.cs b/SQL/Serializers/MySqlSerializer.cs new file mode 100644 index 0000000..0e4c195 --- /dev/null +++ b/SQL/Serializers/MySqlSerializer.cs @@ -0,0 +1,204 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + internal class MySqlSerializer : Serializer + { + public override Database.ConnectionType Type + { + get + { + return Database.ConnectionType.MySQL; + } + } + + public override string SerializeViewExists(SQLViewExists viewExists) + { + var select = new SQLSelect(); + + select.Tables.Add("Tables").SchemaName = "INFORMATION_SCHEMA"; + select.Where.Add("Table_Type", ComparisonOperator.EqualTo, "View"); + select.Where.Add("TABLE_NAME", ComparisonOperator.Like, viewExists.ViewName); + + return SerializeSelect(select); + } + + public override string SerializeRollbackTransaction(SQLRollbackTransaction rollbackTransaction) + { + return "ROLLBACK"; + } + + public override string SerializeCommitTransaction(SQLCommitTransaction commitTransaction) + { + return "COMMIT"; + } + + public override string SerializeBeingTransaction(SQLBeginTransaction beginTransaction) + { + return "START TRANSACTION"; + } + + public override string SerializeTableExists(SQLTableExists tableExists) + { + return "SHOW TABLES LIKE " + SerializeValue(tableExists.Name); + } + + public override string SerializeSelect(SQLSelect select) + { + var tokens = new TokenSerializer(); + + tokens.Add(base.SerializeSelect(select)); + + if (select.PerformLocking) + tokens.Add("FOR UPDATE"); + + if (select.Top > 0) + tokens.Add("LIMIT " + select.Top.ToString()); + + return tokens.ToString(); + } + + public override string SerializeIdentifier(string strIdentifierName) + { + return "`" + strIdentifierName + "`"; + } + + public override string SerializeSingleQuoteCharacter() + { + return @"'\''"; + } + + public override string SerializeBackslashCharacter() + { + return @"\\"; + } + + public override string SerializeString(string stringValue) + { + return "'" + stringValue.Replace(@"\", @"\\").Replace(@"'", @"\'") + "'"; + } + + public override string SerializeGetDateFunctionExpression(SQLGetDateFunctionExpression expression) + { + return "CURDATE()"; + } + + public override string SerializeLengthFunctionExpression(SQLLengthFunctionExpression expression) + { + return "LENGTH" + SerializeFunctionExpressionArguments(expression); + } + + public override string SerializeAlterTableFieldsModifier(SQLTableFields.AlterModeType alterMode) + { + // For MySQL the modifiers are added for each column not for all of the columns. + // So override the SerializeAlterTableFieldModifier instead. + return String.Empty; + } + + public override string SerializeAlterTableFieldModifier(SQLTableFields.AlterModeType alterMode) + { + // For MySQL the modifiers are added for each column not for all of the columns. + return SerializeColumnAlterMode(alterMode); + } + + public override string SerializeColumnAlterMode(SQLTableFields.AlterModeType alterMode) + { + switch (alterMode) + { + case SQLTableFields.AlterModeType.Modify: + return "MODIFY COLUMN"; + default: + return base.SerializeColumnAlterMode(alterMode); + } + } + + public override string SerializeAutoIncrementValue(SQLAutoIncrementValue autoIncrementValue) + { + // The @@IDENTITY function is supported by MySQL from version 3.23.25. + // The original function is being used just in case. + return "SELECT LAST_INSERT_ID() AS " + SerializeIdentifier(autoIncrementValue.ReturnFieldName); + } + + public override string SerializeTableFieldDataType(SQLTableField field) + { + if (field.AutoIncrements) + return base.SerializeTableFieldDataType(field) + " AUTO_INCREMENT"; + else + return base.SerializeTableFieldDataType(field); + } + + public override string SerializeTableFieldKeyTypeOption(SQLTableField field) + { + // must be set to a key type if it is an auto increment field + if (field.AutoIncrements && field.KeyType == KeyType.None) + return "UNIQUE"; + else + return base.SerializeTableFieldKeyTypeOption(field); + } + + public override string SerializeDataType(DataType dataType, int size, int precision, int scale) + { + switch (dataType) + { + case DataType.TinyInteger: + return "TINYINT UNSIGNED"; + case DataType.SmallInteger: + return "SMALLINT"; + case DataType.Integer: + return "INT"; + case DataType.BigInteger: + return "BIGINT"; + case DataType.Character: + return "CHAR(" + size.ToString() + ")"; + case DataType.UnicodeCharacter: + return "NCHAR(" + size.ToString() + ")"; + case DataType.VariableCharacter: + return "VARCHAR(" + size.ToString() + ")"; + case DataType.UnicodeVariableCharacter: + return "NVARCHAR(" + size.ToString() + ")"; + case DataType.Decimal: + return "DECIMAL(" + precision.ToString() + "," + scale.ToString() + ")"; + case DataType.Real: + return "FLOAT"; + case DataType.Float: + return "DOUBLE"; + case DataType.SmallMoney: + return "DECIMAL(10,4)"; + case DataType.Money: + return "DECIMAL(19,4)"; + case DataType.Boolean: + return "BIT"; + case DataType.SmallDateTime: + return "DATETIME"; + case DataType.DateTime: + return "DATETIME"; + case DataType.TimeStamp: + return "TIMESTAMP"; + case DataType.Text: + return "LONGTEXT"; + case DataType.UnicodeText: + return "LONGTEXT CHARACTER SET UTF8"; + case DataType.Binary: + return "BLOB"; + case DataType.VariableBinary: + return "BLOB"; + case DataType.Image: + return "LONGBLOB"; + case DataType.UniqueIdentifier: + return "UNIQUEIDENTIFIER"; + default: + return base.SerializeDataType(dataType, size, precision, scale); + } + } + } +} diff --git a/SQL/Serializers/PervasiveSerializer.cs b/SQL/Serializers/PervasiveSerializer.cs new file mode 100644 index 0000000..7d590e5 --- /dev/null +++ b/SQL/Serializers/PervasiveSerializer.cs @@ -0,0 +1,158 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + internal class PervasiveSerializer : Serializer + { + public override Database.ConnectionType Type + { + get + { + return Database.ConnectionType.Pervasive; + } + } + + public override string SerializeViewExists(SQLViewExists viewExists) + { + throw new NotSupportedException(); + } + + public override string SerializeRollbackTransaction(SQLRollbackTransaction rollbackTransaction) + { + return "ROLLBACK"; + } + + public override string SerializeCommitTransaction(SQLCommitTransaction commitTransaction) + { + return "COMMIT"; + } + + public override string SerializeBeingTransaction(SQLBeginTransaction beginTransaction) + { + return "START TRANSACTION"; + } + + public override string SerializeTableExists(SQLTableExists tableExists) + { + var select = new SQLSelect(); + select.Tables.Add("X$FILE"); + select.Where.Add("Xf$name", ComparisonOperator.EqualTo, tableExists.Name); + + return SerializeSelect(select); + } + + public override string SerializeSelect(SQLSelect select) + { + var tokens = new TokenSerializer(); + + tokens.Add(base.SerializeSelect(select)); + + if (select.PerformLocking) + tokens.Add("FOR UPDATE"); + + if (select.Top > 0) + tokens.Add("LIMIT " + select.Top.ToString()); + + return tokens.ToString(); + } + + public override string SerializeIdentifier(string strIdentifierName) + { + return "\"" + strIdentifierName + "\""; + } + + public override string SerializeColumnAlterMode(SQLTableFields.AlterModeType alterMode) + { + switch (alterMode) + { + case SQLTableFields.AlterModeType.Modify: + return "MODIFY COLUMN"; + default: + return base.SerializeColumnAlterMode(alterMode); + } + } + + public override string SerializeTableFieldNullableOption(SQLTableField field) + { + if (field.AutoIncrements) + return String.Empty; // NULL/NOT NULL is not required if it's an IDENTITY field + else + return base.SerializeTableFieldNullableOption(field); + } + + public override string SerializeTableFieldDataType(SQLTableField field) + { + if (field.AutoIncrements) + return "IDENTITY"; + else + return base.SerializeTableFieldDataType(field); + } + + public override string SerializeDataType(DataType dataType, int size, int precision, int scale) + { + switch (dataType) + { + case DataType.TinyInteger: + return "TINYINT"; + case DataType.SmallInteger: + return "SMALLINT"; + case DataType.Integer: + return "INTEGER"; + case DataType.BigInteger: + return "BIGINT"; + case DataType.Character: + return "CHAR(" + size.ToString() + ")"; + case DataType.UnicodeCharacter: + //Unable to verify this is correct. + return "CHAR(" + size.ToString() + ")"; + case DataType.VariableCharacter: + return "VARCHAR(" + size.ToString() + ")"; + case DataType.UnicodeVariableCharacter: + //Unable to verify this is correct. + return "VARCHAR(" + size.ToString() + ")"; + case DataType.Decimal: + return "NUMERIC(" + precision.ToString() + "," + scale.ToString() + ")"; + case DataType.Real: + return "REAL"; + case DataType.Float: + return "FLOAT"; + case DataType.SmallMoney: + return "DECIMAL(10,4)"; + case DataType.Money: + return "DECIMAL(19,4)"; + case DataType.Boolean: + return "BIT"; + case DataType.SmallDateTime: + return "DATETIME"; + case DataType.DateTime: + return "DATETIME"; + case DataType.TimeStamp: + return "TIMESTAMP"; + case DataType.Text: + return "LONGVARCHAR"; + case DataType.UnicodeText: + return "LONGVARCHAR"; + case DataType.Binary: + return "BINARY"; + case DataType.VariableBinary: + return "LONGVARBINARY"; + case DataType.Image: + return "LONGVARBINARY"; + case DataType.UniqueIdentifier: + return "UNIQUEIDENTIFIER"; + default: + return base.SerializeDataType(dataType, size, precision, scale); + } + } + } +} diff --git a/SQL/Serializers/Serializer.cs b/SQL/Serializers/Serializer.cs new file mode 100644 index 0000000..9ebf3fb --- /dev/null +++ b/SQL/Serializers/Serializer.cs @@ -0,0 +1,1262 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; + +namespace DatabaseObjects.SQL.Serializers +{ + /// + /// Serializes an DatabaseObjects.SQL.* object into an SQL string ready for execution. + /// This class manages generic SQL serialisation that applies to all database systems. + /// Methods can be overridden if a database system serializes differently. + /// + internal abstract class Serializer + { + /// + /// Joins all of the strings and ensures that there are spaces between each item if the item not blank. + /// + protected class TokenSerializer + { + private string separator; + private List tokens = new List(); + + public TokenSerializer() + : this(separator: " ") + { + } + + public TokenSerializer(string separator) + { + if (String.IsNullOrEmpty(separator)) + throw new ArgumentNullException(); + + this.separator = separator; + } + + public void Add(string token) + { + tokens.Add(token); + } + + /// + /// Joins all of the strings and ensures that there are spaces between each item if the item not blank. + /// + public override string ToString() + { + return String.Join(this.separator, tokens.Where(token => !String.IsNullOrEmpty(token)).ToArray()); + } + } + + /// + /// Indicates the serialization type to utilise. + /// + public abstract Database.ConnectionType Type { get; } + + /// + /// Should place tags around a field name or table name to ensure it doesn't + /// conflict with a reserved word or if it contains spaces it is not misinterpreted + /// + public abstract string SerializeIdentifier(string strIdentifierName); + + /// + /// Should return the SELECT statement that when executed returns a row. + /// If a row is returned then the table exists. + /// + public abstract string SerializeTableExists(SQLTableExists tableExists); + + /// + /// Should return the SELECT statement for determining whether a view exists. + /// If a row is returned then the view exists. + /// + public abstract string SerializeViewExists(SQLViewExists viewExists); + + public string SerializeInsert(SQLInsert insert) + { + if (String.IsNullOrEmpty(insert.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); + else if (insert.Fields.Count == 0) + throw new Exceptions.DatabaseObjectsException("Field values have not been set."); + + string fieldNames = String.Join(", ", insert.Fields.Select(field => SerializeIdentifier(field.Name)).ToArray()); + string fieldValues = String.Join(", ", insert.Fields.Select(field => SerializeValue(field.Value)).ToArray()); + + var tokens = new TokenSerializer(); + + tokens.Add("INSERT INTO"); + tokens.Add(SerializeIdentifier(insert.TableName)); + tokens.Add("(" + fieldNames + ")"); + tokens.Add("VALUES"); + tokens.Add("(" + fieldValues + ")"); + + return tokens.ToString(); + } + + public virtual string SerializeUpdate(SQLUpdate update) + { + if (String.IsNullOrEmpty(update.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); + else if (update.Fields.Count == 0) + throw new Exceptions.DatabaseObjectsException("Field values have not been set."); + else if (update.Fields.Any(field => String.IsNullOrEmpty(field.Name))) + throw new Exceptions.DatabaseObjectsException("Field Name has not been set."); + + var fieldNameAndValues = String.Join(", ", update.Fields.Select(field => SerializeIdentifier(field.Name) + " = " + SerializeValue(field.Value)).ToArray()); + + var tokens = new TokenSerializer(); + + tokens.Add("UPDATE"); + tokens.Add(SerializeIdentifier(update.TableName)); + tokens.Add("SET"); + tokens.Add(fieldNameAndValues); + + if (update.Where != null && !update.Where.IsEmpty) + { + tokens.Add("WHERE"); + tokens.Add(SerializeConditions(update.Where)); + } + + return tokens.ToString(); + } + + public string SerializeInsertFromSelect(SQLInsertFromSelect insertFromSelect) + { + if (String.IsNullOrEmpty(insertFromSelect.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); + + var tokens = new TokenSerializer(); + tokens.Add("INSERT INTO"); + tokens.Add(SerializeIdentifier(insertFromSelect.TableName)); + + if (insertFromSelect.Fields.Count > 0) + { + var fields = String.Join(", ", insertFromSelect.Fields.Cast().Select(fieldName => SerializeIdentifier(fieldName)).ToArray()); + tokens.Add("(" + fields + ")"); + } + + tokens.Add(SerializeSelect(insertFromSelect.Source)); + + return tokens.ToString(); + } + + public virtual string SerializeDelete(SQLDelete delete) + { + if (String.IsNullOrEmpty(delete.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName property has not been set."); + + var tokens = new TokenSerializer(); + + tokens.Add("DELETE FROM"); + tokens.Add(SerializeIdentifier(delete.TableName)); + + if (delete.Where != null && !delete.Where.IsEmpty) + { + tokens.Add("WHERE"); + tokens.Add(SerializeConditions(delete.Where)); + } + + return tokens.ToString(); + } + + public virtual string SerializeSelect(SQLSelect select) + { + if (select.Tables.Count == 0) + throw new Exceptions.DatabaseObjectsException("The table has not been set."); + + var tokens = new TokenSerializer(); + + tokens.Add("SELECT"); + tokens.Add(SerializeBeforeSelectFields(select)); + tokens.Add(SerializeSelectFields(select.Fields)); + tokens.Add("FROM"); + tokens.Add(SerializeSelectTables(select.Tables)); + tokens.Add(SerializeAfterSelectTables(select)); + + if (select.Where != null && !select.Where.IsEmpty) + { + tokens.Add("WHERE"); + tokens.Add(SerializeConditions(select.Where)); + } + + if (select.GroupBy != null && !select.GroupBy.IsEmpty) + { + tokens.Add("GROUP BY"); + tokens.Add(SerializeSelectGroupByFields(select.GroupBy)); + } + + if (select.OrderBy != null && !select.OrderBy.IsEmpty) + { + tokens.Add("ORDER BY"); + tokens.Add(SerializeSelectOrderByFields(select.OrderBy)); + } + + if (select.Having != null && !select.Having.IsEmpty) + { + tokens.Add("HAVING"); + tokens.Add(SerializeSelectHavingConditions(select.Having)); + } + + return tokens.ToString(); + } + + public virtual string SerializeDropView(SQLDropView dropView) + { + return "DROP VIEW " + SerializeIdentifier(dropView.ViewName); + } + + public virtual string SerializeCreateView(SQLCreateView createView) + { + if (string.IsNullOrEmpty(createView.Name)) + throw new Exceptions.DatabaseObjectsException("View name has not been set"); + else if (createView.Select == null) + throw new Exceptions.DatabaseObjectsException("Select statement has not been set"); + + return "CREATE VIEW " + SerializeIdentifier(createView.Name) + " AS " + SerializeSelect(createView.Select); + } + + public virtual string SerializeSetTransactionIsolationLevel(SQLSetTransactionIsolationLevel level) + { + return "SET TRANSACTION ISOLATION LEVEL " + SerializeIsolationLevel(level.Value); + } + + public virtual string SerializeIsolationLevel(System.Data.IsolationLevel isolationLevel) + { + switch (isolationLevel) + { + case IsolationLevel.ReadCommitted: + return "READ COMMITTED"; + case IsolationLevel.ReadUncommitted: + return "READ UNCOMMITTED"; + case IsolationLevel.RepeatableRead: + return "REPEATABLE READ"; + case IsolationLevel.Serializable: + return "SERIALIZABLE"; + default: + throw new NotSupportedException("Snapshots isolation level is not supported for " + isolationLevel.ToString()); + } + } + + public virtual string SerializeRollbackTransaction(SQLRollbackTransaction rollbackTransaction) + { + return "ROLLBACK TRANSACTION"; + } + + public virtual string SerializeCommitTransaction(SQLCommitTransaction commitTransaction) + { + return "COMMIT TRANSACTION"; + } + + public virtual string SerializeBeingTransaction(SQLBeginTransaction beginTransaction) + { + return "BEGIN TRANSACTION"; + } + + public virtual string SerializeSelectHavingConditions(SQLSelectHavingConditions havingConditions) + { + int index = 0; + string strSQL = string.Empty; + + foreach (var condition in havingConditions) + { + if (index > 0) + strSQL += " " + SerializeLogicalOperator(havingConditions.LogicalOperators[index - 1]) + " "; + + if (condition is SQLSelectHavingCondition) + strSQL += ((SQLSelectHavingCondition)condition).SQL(this); + else if (condition is SQLSelectHavingConditions) + strSQL += "(" + SerializeSelectHavingConditions((SQLSelectHavingConditions)condition) + ")"; + else + throw new NotImplementedException(condition.GetType().FullName); + + index++; + } + + return strSQL; + } + + public virtual string SerializeSelectOrderByFields(SQLSelectOrderByFields orderByFields) + { + return String.Join(", ", orderByFields.Select(field => SerializeSelectOrderByField(field)).ToArray()); + } + + public virtual string SerializeSelectOrderByField(SQLSelectOrderByField orderByField) + { + if (String.IsNullOrEmpty(orderByField.Name)) + throw new Exceptions.DatabaseObjectsException("Order By field has not been set."); + + string strSQL = string.Empty; + + if (orderByField.AggregateFunction > 0) + strSQL = SerializeAggregateFunction(orderByField.AggregateFunction) + "("; + + strSQL += SerializeFieldNameAndTablePrefix(orderByField.Table, orderByField.Name); + + if (orderByField.AggregateFunction > 0) + strSQL += ")"; + + switch (orderByField.Order) + { + case OrderBy.Ascending: + break; + case OrderBy.Descending: + strSQL += " DESC"; + break; + } + + return strSQL; + } + + public virtual string SerializeSelectGroupByFields(SQLSelectGroupByFields groupByFields) + { + return String.Join(", ", groupByFields.Select(field => field.Expression.SQL(this)).ToArray()); + } + + public string SerializeConditions(SQLConditions conditions) + { + int index = 0; + string strSQL = string.Empty; + + foreach (var condition in conditions) + { + if (index > 0) + strSQL += " " + SerializeLogicalOperator(conditions.LogicalOperators[index - 1]) + " "; + + if (condition is SQLCondition) + strSQL += SerializeCondition((SQLCondition)condition); + else if (condition is SQLConditions) + strSQL += "(" + SerializeConditions((SQLConditions)condition) + ")"; + else if (condition is SQLConditionInSelect) + strSQL += SerializeConditionInSelect((SQLConditionInSelect)condition); + else if (condition is SQLConditionSelect) + strSQL += SerializeConditionSelect((SQLConditionSelect)condition); + else if (condition is SQLConditionFieldCompare) + strSQL += SerializeConditionFieldCompare((SQLConditionFieldCompare)condition); + else if (condition is SQLConditionExpression) + strSQL += ((SQLConditionExpression)condition).SQL(this); + else + throw new NotImplementedException(condition.GetType().FullName); + + index++; + } + + return strSQL; + } + + public virtual string SerializeConditionFieldCompare(SQLConditionFieldCompare fieldCompare) + { + if (String.IsNullOrEmpty(fieldCompare.FieldName1)) + throw new ArgumentException("FieldName1 not set."); + else if (String.IsNullOrEmpty(fieldCompare.FieldName2)) + throw new ArgumentException("FieldName2 not set."); + + return SerializeFieldNameAndTablePrefix(fieldCompare.Table1, fieldCompare.FieldName1) + " " + SerializeComparisonOperator(fieldCompare.Compare) + " " + SerializeFieldNameAndTablePrefix(fieldCompare.Table2, fieldCompare.FieldName2); + } + + public string SerializeArithmeticOperator(SQL.ArithmeticOperator @operator) + { + switch (@operator) + { + case ArithmeticOperator.Add: + return "+"; + case ArithmeticOperator.Subtract: + return "-"; + case ArithmeticOperator.Multiply: + return "*"; + case ArithmeticOperator.Divide: + return "/"; + case ArithmeticOperator.Modulus: + return "%"; + default: + throw new NotSupportedException(@operator.ToString()); + } + } + + public virtual string SerializeArithmeticExpression(SQLArithmeticExpression arithmeticExpression) + { + if (arithmeticExpression.LeftExpression == null) + throw new ArgumentNullException(arithmeticExpression.GetType().Name + ".LeftExpression"); + else if (arithmeticExpression.RightExpression == null) + throw new ArgumentNullException(arithmeticExpression.GetType().Name + ".RightExpression"); + + return "(" + arithmeticExpression.LeftExpression.SQL(this) + " " + SerializeArithmeticOperator(arithmeticExpression.Operator) + " " + arithmeticExpression.RightExpression.SQL(this) + ")"; + } + + public virtual string SerializeAggregateExpression(SQLAggregateExpression aggregateExpression) + { + return SerializeAggregateFunction(aggregateExpression.Aggregate) + SerializeFunctionExpressionArguments(aggregateExpression); + } + + public virtual string SerializeConditionSelect(SQLConditionSelect conditionSelect) + { + if (conditionSelect.Select == null) + throw new Exceptions.DatabaseObjectsException("Select is not set."); + + return "(" + SerializeSelect(conditionSelect.Select) + ") " + SerializeCondition(conditionSelect.Compare, conditionSelect.Value); + } + + public virtual string SerializeConditionInSelect(SQLConditionInSelect conditionInSelect) + { + if (String.IsNullOrEmpty(conditionInSelect.FieldName)) + throw new Exceptions.DatabaseObjectsException("FieldName not set."); + else if (conditionInSelect.Select == null) + throw new Exceptions.DatabaseObjectsException("SelectSet not set."); + + string strIn; + + if (conditionInSelect.NotInSelect) + strIn = "NOT IN"; + else + strIn = "IN"; + + return SerializeFieldNameAndTablePrefix(conditionInSelect.Table, conditionInSelect.FieldName) + " " + strIn + " (" + SerializeSelect(conditionInSelect.Select) + ")"; + } + + /// + /// Serializes all of the tables from the SELECT statment. + /// + public virtual string SerializeSelectTables(SQLSelectTables selectTables) + { + var strSQL = String.Join(", ", + selectTables + .Where(table => selectTables.Joins == null || !selectTables.Joins.Exists(table)) + .Select(table => SerializeSelectTableBase(table)) + .ToArray()); + + if (selectTables.Joins != null) + { + string strJoinsSQL = SerializeSelectTableJoins(selectTables.Joins); + + if (strJoinsSQL != string.Empty && strSQL != string.Empty) + strSQL += " "; + + strSQL += strJoinsSQL; + } + + return strSQL; + } + + public virtual string SerializeAfterSelectTables(SQLSelect select) + { + return String.Empty; + } + + public virtual string SerializeSelectTableFromSelect(SQLSelectTableFromSelect tableFromSelect) + { + return "(" + SerializeSelect(tableFromSelect.Select) + ")"; + } + + public virtual string SerializeSelectHavingCondition(SQLSelectHavingCondition havingCondition) + { + return havingCondition.LeftExpression.SQL(this) + " " + SerializeComparisonOperator(havingCondition.Compare) + " " + havingCondition.RightExpression.SQL(this); + } + + public virtual string SerializeTableFieldComputed(SQLTableFieldComputed tableFieldComputed, SQLTableFields.AlterModeType alterMode) + { + if (alterMode == SQLTableFields.AlterModeType.Drop) + throw new InvalidOperationException("Computed columns cannot be used for dropping fields"); + + return tableFieldComputed.NameAsExpression.SQL(this) + " AS (" + tableFieldComputed.Computation.SQL(this) + ")"; + } + + public virtual string SerializeCreateTable(SQLCreateTable createTable) + { + if (String.IsNullOrEmpty(createTable.Name)) + throw new Exceptions.DatabaseObjectsException("TableName has not been set."); + + var tokens = new TokenSerializer(); + tokens.Add("CREATE TABLE"); + tokens.Add(SerializeIdentifier(createTable.Name)); + tokens.Add("(" + SerializeTableFields(createTable.Fields, includeColumnModifier: false) + ")"); + + return tokens.ToString(); + } + + public virtual string SerializeDropTable(SQLDropTable dropTable) + { + if (String.IsNullOrEmpty(dropTable.Name)) + throw new Exceptions.DatabaseObjectsException("TableName has not been set."); + + return "DROP TABLE " + SerializeIdentifier(dropTable.Name); + } + + public virtual string SerializeDropIndex(SQLDropIndex dropIndex) + { + if (String.IsNullOrEmpty(dropIndex.Name)) + throw new Exceptions.DatabaseObjectsException("IndexName has not been set."); + else if (String.IsNullOrEmpty(dropIndex.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName has not been set."); + + return "DROP INDEX " + SerializeIdentifier(dropIndex.Name) + " ON " + SerializeIdentifier(dropIndex.TableName); + } + + public virtual string SerializeCreateIndex(SQLCreateIndex createIndex) + { + //Although the index name is optional with SQL Server it is not optional with MySQL or Pervasive + if (String.IsNullOrEmpty(createIndex.Name)) + throw new Exceptions.DatabaseObjectsException("IndexName has not been set."); + else if (String.IsNullOrEmpty(createIndex.TableName)) + throw new Exceptions.DatabaseObjectsException("TableName has not been set."); + + var tokens = new TokenSerializer(); + tokens.Add("CREATE"); + tokens.Add(SerializeCreateIndexModifier(createIndex)); + tokens.Add("INDEX"); + tokens.Add(SerializeIdentifier(createIndex.Name)); + tokens.Add("ON"); + tokens.Add(SerializeIdentifier(createIndex.TableName)); + tokens.Add("(" + SerializeIndexFields(createIndex.Fields) + ")"); + + return tokens.ToString(); + } + + public virtual string SerializeCreateIndexModifier(SQLCreateIndex createIndex) + { + if (createIndex.IsUnique) + return "UNIQUE"; + else + return String.Empty; + } + + public virtual string SerializeIndexFields(SQLIndexFields fields) + { + var tokens = new TokenSerializer(", "); + + foreach (SQLIndexField objField in fields) + tokens.Add(SerializeIndexField(objField)); + + return tokens.ToString(); + } + + public virtual string SerializeIndexField(SQLIndexField indexField) + { + var tokens = new TokenSerializer(); + + tokens.Add(SerializeIdentifier(indexField.Name)); + tokens.Add(SerializeOrderBy(indexField.Order)); + + return tokens.ToString(); + } + + public virtual string SerializeOrderBy(OrderBy orderBy) + { + switch (orderBy) + { + case OrderBy.None: + case OrderBy.Ascending: + return String.Empty; + case OrderBy.Descending: + return "DESC"; + default: + throw new NotImplementedException(); + } + } + + public virtual string SerializeAlterTable(SQLAlterTable alterTable) + { + if (String.IsNullOrEmpty(alterTable.Name)) + throw new Exceptions.DatabaseObjectsException("TableName has not been set."); + + return "ALTER TABLE " + SerializeIdentifier(alterTable.Name) + " " + SerializeTableFields(alterTable.Fields, includeColumnModifier: true); + } + + /// + /// + /// + /// Indicates whether the ADD, MODIFY or DROP modifiers are required for each column. + /// When utilised from SQLCreateTable this will always be false. However, for SQLAlterTable this will be true. + /// + public virtual string SerializeTableFields(SQLTableFields tableFields, bool includeColumnModifier) + { + var tokens = new TokenSerializer(); + + //Include mode when altering a table, otherwise when creating a table the mode is not required. + if (includeColumnModifier) + tokens.Add(SerializeAlterTableFieldsModifier(tableFields.AlterMode)); + + var fieldsTokens = new TokenSerializer(", "); + + foreach (SQLTableFieldBase field in tableFields) + { + var fieldToken = new TokenSerializer(); + + if (includeColumnModifier) + fieldToken.Add(SerializeAlterTableFieldModifier(tableFields.AlterMode)); + + fieldToken.Add(field.SQL(this, tableFields.AlterMode)); + + fieldsTokens.Add(fieldToken.ToString()); + } + + tokens.Add(fieldsTokens.ToString()); + + return tokens.ToString(); + } + + /// + /// The field modifier that is used before all of the fields modifications are listed. + /// Typically used by SQL Server to indicate the type of operation to be performed on ALL fields. + /// + /// + /// + public virtual string SerializeAlterTableFieldsModifier(SQLTableFields.AlterModeType alterMode) + { + return SerializeColumnAlterMode(alterMode); + } + + /// + /// The field modifier that is used before each field that is being modified. + /// Typically used by MySQL the type of operation to be performed on each field. + /// + /// + /// + public virtual string SerializeAlterTableFieldModifier(SQLTableFields.AlterModeType alterMode) + { + return String.Empty; + } + + public virtual string SerializeColumnAlterMode(SQLTableFields.AlterModeType alterMode) + { + switch (alterMode) + { + case SQLTableFields.AlterModeType.Add: + return "ADD"; + case SQLTableFields.AlterModeType.Modify: + return "ALTER COLUMN"; + case SQLTableFields.AlterModeType.Drop: + return "DROP COLUMN"; + default: + throw new NotImplementedException(); + } + } + + public virtual string SerializeSelectTableJoins(SQLSelectTableJoins tableJoins) + { + if (tableJoins.Count > 0) + //recurse through the joins from right to left + return SerializeSelectTableJoin(tableJoins[tableJoins.Count - 1]); + else + return string.Empty; + } + + public virtual string SerializeTableFieldAsName(SQLTableField field) + { + return field.NameAsExpression.SQL(this); + } + + public virtual string SerializeTableField(SQLTableField field, SQLTableFields.AlterModeType alterMode) + { + var tokens = new TokenSerializer(); + + if (alterMode == SQLTableFields.AlterModeType.Drop) + tokens.Add(SerializeTableFieldAsName(field)); + else + { + tokens.Add(SerializeTableFieldAsName(field)); + tokens.Add(SerializeTableFieldDataType(field)); + tokens.Add(SerializeTableFieldDefaultOption(field)); + tokens.Add(SerializeTableFieldNullableOption(field)); + tokens.Add(SerializeTableFieldKeyTypeOption(field)); + } + + return tokens.ToString(); + } + + public virtual string SerializeTableFieldDataType(SQLTableField field) + { + return SerializeDataType(field.DataType, field.Size, field.Precision, field.ScaleLength); + } + + public virtual string SerializeTableFieldDefaultOption(SQLTableField field) + { + if (field.Default != null) + return "DEFAULT " + SerializeValue(field.Default); + else + return String.Empty; + } + + public virtual string SerializeTableFieldNullableOption(SQLTableField field) + { + if (field.AcceptsNull) + return "NULL"; + else + return "NOT NULL"; + } + + public virtual string SerializeTableFieldKeyTypeOption(SQLTableField field) + { + if (field.KeyType == KeyType.Primary) + return "PRIMARY KEY"; + else if (field.KeyType == KeyType.Unique) + return "UNIQUE"; + else + return String.Empty; + } + + public virtual string SerializeSelectTable(SQLSelectTable table) + { + if (String.IsNullOrEmpty(table.Name)) + throw new Exceptions.DatabaseObjectsException("Table has not been set."); + + string strSQL = string.Empty; + + if (!String.IsNullOrEmpty(table.DatabaseName)) + strSQL += SerializeIdentifier(table.DatabaseName) + "."; + + if (!String.IsNullOrEmpty(table.SchemaName)) + strSQL += SerializeIdentifier(table.SchemaName) + "."; + + return strSQL + SerializeIdentifier(table.Name); + } + + public virtual string SerializeSelectTableJoin(SQLSelectTableJoin table) + { + string strSQL = SerializeSelectTableBase(table.LeftTable) + " " + SerializeTableJoinType(table.TheType) + " " + SerializeSelectTableBase(table.RightTable); + + var conditions = table.Where; + + if (conditions != null && !conditions.IsEmpty) + strSQL += " ON " + SerializeSelectTableJoinConditions(conditions); + + //Surround the join with parentheses - MS Access won't accept it otherwise + return "(" + strSQL + ")"; + } + + public virtual string SerializeSelectTableJoinConditions(SQLSelectTableJoinConditions joinConditions) + { + string strSQL = string.Empty; + int intIndex = 0; + + foreach (object objCondition in joinConditions) + { + if (intIndex > 0) + strSQL += " " + SerializeLogicalOperator(joinConditions.LogicalOperators[intIndex - 1]) + " "; + + if (objCondition is SQLSelectTableJoinConditions) + strSQL += "(" + SerializeSelectTableJoinConditions((SQLSelectTableJoinConditions)objCondition) + ")"; + else if (objCondition is SQLSelectTableJoinCondition) + strSQL += SerializeSelectTableJoinCondition((SQLSelectTableJoinCondition)objCondition); + else + throw new NotImplementedException(objCondition.GetType().FullName); + + intIndex++; + } + + return strSQL; + } + + public virtual string SerializeSelectTableJoinCondition(SQLSelectTableJoinCondition joinCondition) + { + //Account for the situation where EqualTo to NULL is appropriately translated to 'IS NULL' + if (joinCondition.RightExpression is SQLValueExpression) + return joinCondition.LeftExpression.SQL(this) + " " + SerializeCondition(joinCondition.Compare, ((SQLValueExpression)joinCondition.RightExpression).Value); + else + return joinCondition.LeftExpression.SQL(this) + " " + SerializeComparisonOperator(joinCondition.Compare) + " " + joinCondition.RightExpression.SQL(this); + } + + public virtual string SerializeCaseExpressionCase(SQLCaseExpression.Case expressionCase) + { + return "WHEN " + expressionCase.WhenCondition.SQL(this) + " THEN " + expressionCase.Result.SQL(this); + } + + public virtual string SerializeCaseExpression(SQLCaseExpression expression) + { + if (expression.Cases.Count() == 0) + throw new InvalidOperationException("There are no cases for the CASE statement"); + + var tokens = new TokenSerializer(); + + tokens.Add("CASE"); + + if (expression.InputExpression != null) + tokens.Add(expression.InputExpression.SQL(this)); + + var cases = string.Join(" ", expression.Cases.Select(objCase => SerializeCaseExpressionCase(objCase)).ToArray()); + tokens.Add(cases); + + if (expression.ElseResult != null) + { + tokens.Add("ELSE"); + tokens.Add(expression.ElseResult.SQL(this)); + } + + tokens.Add("END"); + + return tokens.ToString(); + } + + public virtual string SerializeCastExpression(SQLCastExpression expression) + { + return "CAST(" + SerializeIdentifier(expression.FieldName) + " AS " + SerializeDataType(expression.ToDataType, expression.Size, expression.Precision, expression.ScaleLength) + ")"; + } + + public virtual string SerializeDataType(SQL.DataType dataType, int intSize, int intPrecision, int intScale) + { + throw new NotImplementedException("Data type " + dataType.ToString() + " is not implemented for " + this.GetType().Name); + } + + public virtual string SerializeBitwiseExpression(SQLBitwiseExpression expression) + { + if (expression.LeftExpression == null) + throw new ArgumentNullException(expression.GetType().Name + ".LeftExpression"); + else if (expression.RightExpression == null) + throw new ArgumentNullException(expression.GetType().Name + ".RightExpression"); + + return "(" + expression.LeftExpression.SQL(this) + " " + SerializeBitwiseOperator(expression.Operator) + " " + expression.RightExpression.SQL(this) + ")"; + } + + public virtual string SerializeFieldAggregateExpression(SQLFieldAggregateExpression expression) + { + if (expression.AggregateFunction == AggregateFunction.None) + throw new InvalidOperationException("AggregateFunction unspecified for " + this.GetType().Name); + + string strFieldName = string.Empty; + + if (expression.AggregateFunction == AggregateFunction.Count) + strFieldName = "*"; + else + strFieldName = SerializeFieldExpression(expression); + + return SerializeAggregateFunction(expression.AggregateFunction) + "(" + strFieldName + ")"; + } + + /// + /// Includes parentheses around arguments if required. + /// + /// + public virtual string SerializeFunctionExpressionArguments(SQLFunctionExpression functionExpression) + { + string strArguments = string.Empty; + + if (functionExpression.Arguments != null) + strArguments = String.Join(", ", functionExpression.Arguments.Select(argument => argument.SQL(this)).ToArray()); + + if ((functionExpression.IncludeParenthesesWhenArgumentsEmpty && !functionExpression.HasArguments) || functionExpression.HasArguments) + strArguments = "(" + strArguments + ")"; + + return strArguments; + } + + /// + /// Should return a SELECT statement that can be used to obtain the value from a auto increment / identity field + /// after an INSERT statement. + /// + public virtual string SerializeAutoIncrementValue(SQLAutoIncrementValue autoIncrementValue) + { + return "SELECT @@IDENTITY AS " + SerializeIdentifier(autoIncrementValue.ReturnFieldName); + } + + public virtual string SerializeSelectExpression(SQLSelectExpression selectExpression) + { + return "SELECT " + selectExpression.Expression.SQL(this); + } + + public virtual string SerializeSelectField(SQLSelectField field) + { + string strSQL = field.Expression.SQL(this); + + if (!String.IsNullOrEmpty(field.Alias)) + strSQL += " AS " + SerializeIdentifier(field.Alias); + + return strSQL; + } + + public virtual string SerializeStringContactExpression(SQLStringConcatExpression expression) + { + if (expression.LeftExpression == null) + throw new ArgumentNullException(expression.GetType().Name + ".LeftExpression"); + else if (expression.RightExpression == null) + throw new ArgumentNullException(expression.GetType().Name + ".RightExpression"); + + return expression.LeftExpression.SQL(this) + " + " + expression.RightExpression.SQL(this); + } + + public virtual string SerializeLengthFunctionExpression(SQLLengthFunctionExpression expression) + { + throw new NotImplementedException(); + } + + public virtual string SerializeLeftFunctionExpression(SQLLeftFunctionExpression expression) + { + return "LEFT" + SerializeFunctionExpressionArguments(expression); + } + + public virtual string SerializeRightFunctionExpression(SQLRightFunctionExpression expression) + { + return "RIGHT" + SerializeFunctionExpressionArguments(expression); + } + + public virtual string SerializeGetDateFunctionExpression(SQLGetDateFunctionExpression expression) + { + throw new NotImplementedException(); + } + + public virtual string SerializeFieldExpression(SQLFieldExpression fieldExpression) + { + if (String.IsNullOrEmpty(fieldExpression.Name)) + throw new Exceptions.DatabaseObjectsException("Field Name has not been set."); + + return SerializeFieldNameAndTablePrefix(fieldExpression.Table, fieldExpression.Name); + } + + public virtual string SerializeBitwiseOperator(SQL.BitwiseOperator eOperator) + { + if (eOperator == BitwiseOperator.And) + return "&"; + else if (eOperator == BitwiseOperator.Or) + return "|"; + else + throw new NotSupportedException(eOperator.ToString()); + } + + public virtual string SerializeUnion(SQLUnion union) + { + if (union.SelectStatements.Count() < 2) + throw new Exceptions.DatabaseObjectsException("The select statements have not been set"); + + var tokens = new TokenSerializer(); + int index = 0; + + foreach (var statement in union.SelectStatements) + { + if (index > 0) + tokens.Add(SerializeUnionType(union.UnionTypes[index - 1])); + + tokens.Add("(" + SerializeSelect(statement) + ")"); + index++; + } + + if (union.OrderBy != null && !union.OrderBy.IsEmpty) + { + tokens.Add("ORDER BY"); + tokens.Add(SerializeSelectOrderByFields(union.OrderBy)); + } + + return tokens.ToString(); + } + + public virtual string SerializeUnionType(SQLUnion.Type type) + { + switch (type) + { + case SQLUnion.Type.Distinct: + return "UNION"; + case SQLUnion.Type.All: + return "UNION ALL"; + default: + throw new NotImplementedException(type.ToString()); + } + } + + public string SerializeConditionExpression(SQLConditionExpression expression) + { + if (expression.LeftExpression == null) + throw new InvalidOperationException("Left expression is not set"); + else if (expression.RightExpression == null) + throw new InvalidOperationException("Right expression is not set"); + + string strSQL = expression.LeftExpression.SQL(this) + " "; + + if (expression.RightExpression is SQLValueExpression) + strSQL += SerializeCondition(expression.Compare, ((SQLValueExpression)expression.RightExpression).Value); + else + strSQL += SerializeComparisonOperator(expression.Compare) + " " + expression.RightExpression.SQL(this); + + return strSQL; + } + + private static void EnsureCompareValuePairValid(SQL.ComparisonOperator eCompare, object objValue) + { + if (!(objValue is string) && (eCompare == ComparisonOperator.Like || eCompare == ComparisonOperator.NotLike)) + throw new Exceptions.DatabaseObjectsException("The LIKE operator cannot be used in conjunction with a non-string data type"); + else if (objValue is bool && !(eCompare == ComparisonOperator.EqualTo || eCompare == ComparisonOperator.NotEqualTo)) + throw new Exceptions.DatabaseObjectsException("A boolean value can only be used in conjunction with the " + ComparisonOperator.EqualTo.ToString() + " or " + ComparisonOperator.NotEqualTo.ToString() + " operators"); + } + + public virtual string SerializeCondition(SQLCondition condition) + { + return SerializeFieldNameAndTablePrefix(condition.Table, condition.FieldName) + " " + SerializeCondition(condition.Compare, condition.Value); + } + + protected string SerializeCondition(ComparisonOperator eCompare, object objValue) + { + EnsureCompareValuePairValid(eCompare, objValue); + + string strSQL = string.Empty; + + //Return 'IS NULL' rather than '= NULL' + if (ValueIsNull(objValue)) + { + if (eCompare == ComparisonOperator.EqualTo) + strSQL += "IS " + SerializeValue(objValue); + else if (eCompare == ComparisonOperator.NotEqualTo) + strSQL += "IS NOT " + SerializeValue(objValue); + else + throw new Exceptions.DatabaseObjectsException("DBNull or Nothing/null was specified as a value using the " + eCompare.ToString() + " operator"); + } + else + strSQL += SerializeComparisonOperator(eCompare) + " " + SerializeValue(objValue); + + return strSQL; + } + + public virtual string SerializeLogicalOperator(SQL.LogicalOperator eLogicalOperator) + { + string strLogicalOperator; + + if (eLogicalOperator == LogicalOperator.And) + strLogicalOperator = "AND"; + else if (eLogicalOperator == LogicalOperator.Or) + strLogicalOperator = "OR"; + else + throw new NotSupportedException(eLogicalOperator.ToString()); + + return strLogicalOperator; + } + + private static string SerializeTableJoinType(SQLSelectTableJoin.Type joinType) + { + switch (joinType) + { + case SQLSelectTableJoin.Type.Inner: + return "INNER JOIN"; + case SQLSelectTableJoin.Type.FullOuter: + return "FULL OUTER JOIN"; + case SQLSelectTableJoin.Type.LeftOuter: + return "LEFT OUTER JOIN"; + case SQLSelectTableJoin.Type.RightOuter: + return "RIGHT OUTER JOIN"; + default: + throw new NotImplementedException(joinType.ToString()); + } + } + + public virtual string SerializeSelectTableBase(SQLSelectTableBase tableBase) + { + string strSQL = tableBase.Source(this); + + if (!String.IsNullOrEmpty(tableBase.Alias)) + strSQL += " " + SerializeIdentifier(tableBase.Alias); + + return strSQL; + } + + /// + /// Serializes any commands that must be placed before the field listing + /// but after the SELECT command. + /// + public virtual string SerializeBeforeSelectFields(SQLSelect select) + { + return select.Distinct ? "DISTINCT" : String.Empty; + } + + /// + /// Serializes the list of fields as a comma separated string. + /// i.e. Field1, Field2, Field3. + /// + public virtual string SerializeSelectFields(SQLSelectFields selectFields) + { + if (selectFields.Count == 0) + return "*"; + else + return String.Join(", ", selectFields.Select(field => SerializeSelectField(field)).ToArray()); + } + + public virtual string SerializeAggregateFunction(SQL.AggregateFunction aggregate) + { + switch (aggregate) + { + case AggregateFunction.Average: + return "AVG"; + case AggregateFunction.Count: + return "COUNT"; + case AggregateFunction.Sum: + return "SUM"; + case AggregateFunction.Minimum: + return "MIN"; + case AggregateFunction.Maximum: + return "MAX"; + case AggregateFunction.StandardDeviation: + return "STDEV"; + case AggregateFunction.Variance: + return "VAR"; + default: + throw new NotSupportedException(aggregate.ToString()); + } + } + + public virtual string SerializeComparisonOperator(SQL.ComparisonOperator compare) + { + switch (compare) + { + case ComparisonOperator.EqualTo: + return "="; + case ComparisonOperator.NotEqualTo: + return "<>"; + case ComparisonOperator.LessThan: + return "<"; + case ComparisonOperator.LessThanOrEqualTo: + return "<="; + case ComparisonOperator.GreaterThan: + return ">"; + case ComparisonOperator.GreaterThanOrEqualTo: + return ">="; + case ComparisonOperator.Like: + return "LIKE"; + case ComparisonOperator.NotLike: + return "NOT LIKE"; + default: + throw new NotSupportedException(compare.ToString()); + } + } + + public virtual string SerializeBoolean(bool value) + { + return value ? "1" : "0"; + } + + public virtual string SerializeCharacter(char value) + { + if (value == '\'') + return SerializeSingleQuoteCharacter(); + else if (value == '\\') + return SerializeBackslashCharacter(); + else + return "'" + value + "'"; + } + + public virtual string SerializeSingleQuoteCharacter() + { + return @"''''"; + } + + public virtual string SerializeBackslashCharacter() + { + return @"\"; + } + + public virtual string SerializeNull() + { + return "NULL"; + } + + /// + /// Should serialize the binary data to string for writing to the database. + /// Can use the helper function Serializer.SerializeBinaryArray(). + /// + public virtual string SerializeByteArray(byte[] bytData) + { + return SerializeByteArray("0x", bytData, String.Empty); + } + + public virtual string SerializeDateTime(DateTime dateTime) + { + return "\'" + SerializeDateTimeValue(dateTime) + "\'"; + } + + /// + /// Serializes just the value - not any surrounding tags such as ' or #. + /// If the time part is 0:00 then the time is not serialized. + /// + public virtual string SerializeDateTimeValue(DateTime dateTime) + { + string dateTimeString; + + // If the date hasn't been set then set to the 1899-12-30 so that + // the date isn't set to 2001-01-01 + if (dateTime.Day == 1 && dateTime.Month == 1 && dateTime.Year == 1) + dateTimeString = "1899-12-30"; + else + dateTimeString = dateTime.Year + "-" + dateTime.Month + "-" + dateTime.Day; + + if (dateTime.Hour != 0 || dateTime.Minute != 0 || dateTime.Second != 0) + dateTimeString += " " + dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second + "." + dateTime.Millisecond; + + return dateTimeString; + } + + /// + /// Serializes a string and replaces and special characters such as ' with ''. + /// + public virtual string SerializeString(string stringValue) + { + return "'" + stringValue.Replace(@"'", @"''") + "'"; + } + + public virtual string SerializeGuid(Guid guid) + { + return "'" + guid.ToString("D") + "'"; + } + + public virtual string SerializeValue(object value) + { + if (ValueIsNull(value)) + return SerializeNull(); + else if (value is bool) + return SerializeBoolean((bool)value); + else if (value is char) + return SerializeCharacter((char)value); + else if (value is DateTime) + return SerializeDateTime((DateTime)value); + else if (value is string) + return SerializeString((string)value); + else if (value is byte[]) + return SerializeByteArray((byte[])value); + else if (value is System.Guid) + return SerializeGuid((Guid)value); + else if (value is SQLExpression) + return ((SQLExpression)value).SQL(this); + else + return value.ToString(); + } + + public virtual string SerializeFieldNameAndTablePrefix(SQLSelectTable objTable, string strFieldName) + { + string strTablePrefix = string.Empty; + + if (objTable != null) + strTablePrefix = SerializeTablePrefix(objTable) + "."; + + return strTablePrefix + SerializeIdentifier(strFieldName); + } + + /// + /// Returns the table alias or if the alias is not set the table's name. + /// + public virtual string SerializeTablePrefix(SQLSelectTable objTable) + { + if (!String.IsNullOrEmpty(objTable.Alias)) + return SerializeIdentifier(objTable.Alias); + else + return SerializeIdentifier(objTable.Name); + } + + protected string SerializeByteArray(string strHexPrefix, byte[] bytData, string strHexSuffix) + { + System.Text.StringBuilder objHexData = new System.Text.StringBuilder(strHexPrefix, System.Convert.ToInt32((bytData.Length * 2) + strHexPrefix.Length + strHexSuffix.Length)); + + foreach (byte bytByte in bytData) + objHexData.Append(string.Format("{0:X2}", bytByte)); + + objHexData.Append(strHexSuffix); + + return objHexData.ToString(); + } + + private bool ValueIsNull(object objValue) + { + if (objValue == null) + return true; + else if (objValue == DBNull.Value) + return true; + else + return false; + } + } +} diff --git a/SQL/Serializers/Serializers.cs b/SQL/Serializers/Serializers.cs new file mode 100644 index 0000000..754f07a --- /dev/null +++ b/SQL/Serializers/Serializers.cs @@ -0,0 +1,29 @@ +// ___________________________________________________ +// +// © Hi-Integrity Systems 2012. All rights reserved. +// www.hisystems.com.au - Toby Wicks +// ___________________________________________________ +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DatabaseObjects.SQL.Serializers +{ + internal static class Serializers + { + public readonly static Dictionary Items = new Dictionary(); + + static Serializers() + { + Items.Add(Database.ConnectionType.SQLServer, new MicrosoftSqlServerSerializer()); + Items.Add(Database.ConnectionType.SQLServerCompactEdition, new MicrosoftSqlServerCompactEditionSerializer()); + Items.Add(Database.ConnectionType.MicrosoftAccess, new MicrosoftAccessSerializer()); + Items.Add(Database.ConnectionType.MySQL, new MySqlSerializer()); + Items.Add(Database.ConnectionType.HyperSQL, new HyperSqlSerializer()); + Items.Add(Database.ConnectionType.Pervasive, new PervasiveSerializer()); + } + } +} diff --git a/SQL/TableDefinition/SQLAlterTable.cs b/SQL/TableDefinition/SQLAlterTable.cs index a16458c..dd97c12 100644 --- a/SQL/TableDefinition/SQLAlterTable.cs +++ b/SQL/TableDefinition/SQLAlterTable.cs @@ -45,10 +45,7 @@ public override string SQL { get { - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("TableName has not been set."); - - return "ALTER TABLE " + Misc.SQLConvertIdentifierName(this.Name, this.ConnectionType) + " " + pobjFields.SQL(this.ConnectionType, true); + return base.Serializer.SerializeAlterTable(this); } } } diff --git a/SQL/TableDefinition/SQLCreateIndex.cs b/SQL/TableDefinition/SQLCreateIndex.cs index 84b0695..633e56f 100644 --- a/SQL/TableDefinition/SQLCreateIndex.cs +++ b/SQL/TableDefinition/SQLCreateIndex.cs @@ -89,28 +89,9 @@ public override string SQL { get { - string strSQL = string.Empty; - - //Although the index name is optional with SQL Server it is not optional with MySQL or Pervasive - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("IndexName has not been set."); - - if (String.IsNullOrEmpty(this.TableName)) - throw new Exceptions.DatabaseObjectsException("TableName has not been set."); - - strSQL = "CREATE " + UniqueString() + "INDEX " + Misc.SQLConvertIdentifierName(this.Name, this.ConnectionType) + " ON " + Misc.SQLConvertIdentifierName(this.TableName, this.ConnectionType) + " (" + pobjFields.SQL(this.ConnectionType) + ")"; - - return strSQL; + return base.Serializer.SerializeCreateIndex(this); } } - - private string UniqueString() - { - if (pbIsUnique) - return "UNIQUE "; - else - return ""; - } } public class SQLIndexFields : IEnumerable @@ -143,18 +124,6 @@ public SQLIndexField Add(string strFieldName, OrderBy eOrder) return objField; } - internal string SQL(Database.ConnectionType eConnectionType) - { - const string cstrSeperator = ", "; - - string strSQL = string.Empty; - - foreach (SQLIndexField objField in pobjFields) - strSQL += objField.SQL(eConnectionType) + cstrSeperator; - - return strSQL.Substring(0, strSQL.Length - cstrSeperator.Length); //remove the last comma and space - } - IEnumerator IEnumerable.GetEnumerator() { return pobjFields.GetEnumerator(); @@ -200,18 +169,5 @@ public OrderBy Order peOrder = value; } } - - internal string SQL(Database.ConnectionType eConnectionType) - { - return Misc.SQLConvertIdentifierName(this.Name, eConnectionType) + OrderString(); - } - - private string OrderString() - { - if (peOrder == OrderBy.Descending) - return " DESC"; - else - return ""; - } } } diff --git a/SQL/TableDefinition/SQLCreateTable.cs b/SQL/TableDefinition/SQLCreateTable.cs index 4854d99..f2cbb0f 100644 --- a/SQL/TableDefinition/SQLCreateTable.cs +++ b/SQL/TableDefinition/SQLCreateTable.cs @@ -47,10 +47,7 @@ public override string SQL { get { - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("TableName has not been set."); - - return "CREATE TABLE " + Misc.SQLConvertIdentifierName(this.Name, this.ConnectionType) + " (" + pobjFields.SQL(this.ConnectionType, false) + ")"; + return base.Serializer.SerializeCreateTable(this); } } } diff --git a/SQL/TableDefinition/SQLDropIndex.cs b/SQL/TableDefinition/SQLDropIndex.cs index 882318f..2823cec 100644 --- a/SQL/TableDefinition/SQLDropIndex.cs +++ b/SQL/TableDefinition/SQLDropIndex.cs @@ -56,24 +56,7 @@ public override string SQL { get { - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("IndexName has not been set."); - else if (String.IsNullOrEmpty(this.TableName)) - throw new Exceptions.DatabaseObjectsException("TableName has not been set."); - - switch (this.ConnectionType) - { - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - return "DROP INDEX " + Misc.SQLConvertIdentifierName(this.TableName, this.ConnectionType) + "." + Misc.SQLConvertIdentifierName(this.Name, this.ConnectionType); - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.MySQL: - case Database.ConnectionType.Pervasive: - return "DROP INDEX " + Misc.SQLConvertIdentifierName(this.Name, this.ConnectionType) + " ON " + Misc.SQLConvertIdentifierName(this.TableName, this.ConnectionType); - default: - throw new NotSupportedException(); - break; - } + return base.Serializer.SerializeDropIndex(this); } } } diff --git a/SQL/TableDefinition/SQLDropTable.cs b/SQL/TableDefinition/SQLDropTable.cs index 2c740a3..55e1ad4 100644 --- a/SQL/TableDefinition/SQLDropTable.cs +++ b/SQL/TableDefinition/SQLDropTable.cs @@ -41,10 +41,7 @@ public override string SQL { get { - if (String.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("TableName has not been set."); - - return "DROP TABLE " + Misc.SQLConvertIdentifierName(this.Name, this.ConnectionType); + return base.Serializer.SerializeDropTable(this); } } } diff --git a/SQL/TableDefinition/SQLTableExists.cs b/SQL/TableDefinition/SQLTableExists.cs index eaeff4f..db29590 100644 --- a/SQL/TableDefinition/SQLTableExists.cs +++ b/SQL/TableDefinition/SQLTableExists.cs @@ -48,54 +48,7 @@ public override string SQL { get { - string strSQL = string.Empty; - SQLSelect objSelect; - - switch (this.ConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - objSelect = new SQLSelect(); - objSelect.ConnectionType = this.ConnectionType; - objSelect.Tables.Add("msysobjects"); - objSelect.Where.Add("Name", ComparisonOperator.EqualTo, this.Name); - objSelect.Where.Add("Type", ComparisonOperator.EqualTo, 1); - strSQL = objSelect.SQL; - break; - case Database.ConnectionType.MySQL: - strSQL = "SHOW TABLES LIKE " + Misc.SQLConvertValue(this.Name, this.ConnectionType); - break; - case Database.ConnectionType.SQLServer: - objSelect = new SQLSelect(); - objSelect.ConnectionType = this.ConnectionType; - objSelect.Tables.Add("sysobjects"); - objSelect.Where.Add("Name", ComparisonOperator.EqualTo, this.Name); - objSelect.Where.Add("XType", ComparisonOperator.EqualTo, "U"); //U = User defined table - strSQL = objSelect.SQL; - break; - case Database.ConnectionType.Pervasive: - objSelect = new SQLSelect(); - objSelect.ConnectionType = this.ConnectionType; - objSelect.Tables.Add("X$FILE"); - objSelect.Where.Add("Xf$name", ComparisonOperator.EqualTo, this.Name); - strSQL = objSelect.SQL; - break; - case Database.ConnectionType.HyperSQL: - objSelect = new SQLSelect(); - objSelect.ConnectionType = this.ConnectionType; - objSelect.Tables.Add("SYSTEM_TABLES").SchemaName = "INFORMATION_SCHEMA"; - objSelect.Where.Add("TABLE_SCHEM", ComparisonOperator.EqualTo, "PUBLIC"); - objSelect.Where.Add("TABLE_NAME", ComparisonOperator.EqualTo, this.Name); - strSQL = objSelect.SQL; - break; - case Database.ConnectionType.SQLServerCompactEdition: - throw new NotSupportedException("Use SELECT COUNT(*) FROM table to determine if a record exists"); - break; - default: - throw new NotImplementedException(this.ConnectionType.ToString()); - break; - } - - return strSQL; + return base.Serializer.SerializeTableExists(this); } } } diff --git a/SQL/TableDefinition/SQLTableFields.cs b/SQL/TableDefinition/SQLTableFields.cs index b6018fc..5bc7fc2 100644 --- a/SQL/TableDefinition/SQLTableFields.cs +++ b/SQL/TableDefinition/SQLTableFields.cs @@ -57,7 +57,7 @@ public SQLTableField Add(string strFieldName, SQL.DataType eDataType) public SQLTableField Add(string strFieldName, SQL.DataType eDataType, int intSize) { - EnsureAlterModeValid(AlterModeType.Add); + EnsureAlterModeValid(AlterModeType.Add); SQLTableField objField = new SQLTableField(); @@ -66,7 +66,7 @@ public SQLTableField Add(string strFieldName, SQL.DataType eDataType, int intSiz if (intSize > 0) objField.Size = intSize; - if (Misc.DataTypeIsCharacter(eDataType) && intSize == 0) + if (DataTypeExtensions.IsCharacter(eDataType) && intSize == 0) throw new ArgumentException("Size not specified for character based field " + strFieldName); pobjFields.Add(objField); @@ -76,7 +76,7 @@ public SQLTableField Add(string strFieldName, SQL.DataType eDataType, int intSiz public SQLTableFieldComputed AddComputed(string strFieldName, SQLExpression objComputation) { - EnsureAlterModeValid(AlterModeType.Add); + EnsureAlterModeValid(AlterModeType.Add); SQLTableFieldComputed objField = new SQLTableFieldComputed(strFieldName, objComputation); @@ -89,7 +89,7 @@ public void Add(SQLTableField objField) { if (objField == null) throw new ArgumentNullException(); - + EnsureAlterModeValid(AlterModeType.Add); pobjFields.Add(objField); @@ -99,7 +99,7 @@ public void Add(SQLTableField objField) { get { - EnsureAlterModeValid(AlterModeType.Modify); + EnsureAlterModeValid(AlterModeType.Modify); var tableField = GetTableFieldOrDefault(strFieldName); @@ -116,7 +116,7 @@ public void Add(SQLTableField objField) public void Drop(string strFieldName) { - EnsureAlterModeValid(AlterModeType.Drop); + EnsureAlterModeValid(AlterModeType.Drop); SQLTableField objField = new SQLTableField(); @@ -138,86 +138,16 @@ private bool Equals(SQLTableField tableField, string strFieldName) return tableField.Name.Equals(strFieldName, StringComparison.InvariantCultureIgnoreCase); } - /// - /// - /// - /// - /// - /// Indicates whether the ADD, MODIFY or DROP modifiers are required for each column. - /// When utilised from SQLCreateTable this will always be false. However, for SQLAlterTable this will be true. - /// - /// - internal string SQL(Database.ConnectionType eConnectionType, bool bIncludeColumnModifier) - { - const string cstrSeperator = ", "; - - string strSQL = string.Empty; - string strColumnModifier = string.Empty; - - //Include mode when altering a table, otherwise when creating a table the mode is not required. - if (bIncludeColumnModifier) - { - strColumnModifier = GetAlterModeColumnModifier(AlterMode, eConnectionType); - - //This case statement is related to the if statement below with the mode space char being added for MySQL - if (eConnectionType != Database.ConnectionType.MySQL) - strSQL = strColumnModifier + " "; - } - - foreach (SQLTableFieldBase objField in pobjFields) - { - if (bIncludeColumnModifier) - { - if (eConnectionType == Database.ConnectionType.MySQL) - strSQL += strColumnModifier + " "; - } - - strSQL += objField.SQL(eConnectionType, (AlterMode == AlterModeType.Drop)) + cstrSeperator; - } - - return strSQL.Substring(0, strSQL.Length - cstrSeperator.Length); //remove the last comma and space - } - - private static string GetAlterModeColumnModifier(AlterModeType eAlterMode, Database.ConnectionType eConnectionType) + private void EnsureAlterModeValid(SQLTableFields.AlterModeType eAlterMode) { - switch (eAlterMode) - { - case AlterModeType.Add: - return "ADD"; - case AlterModeType.Modify: - switch (eConnectionType) - { - case Database.ConnectionType.MySQL: - case Database.ConnectionType.Pervasive: - return "MODIFY COLUMN"; - case Database.ConnectionType.MicrosoftAccess: - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - case Database.ConnectionType.HyperSQL: - return "ALTER COLUMN"; - default: - throw new NotImplementedException(eConnectionType.ToString()); - break; - } - break; - case AlterModeType.Drop: - return "DROP COLUMN"; - default: - throw new NotImplementedException(); - break; - } + //if the alter mode hasn't been set then any of the modes are valid + if ((int)AlterMode == pcintAlterModeUninitialized) + AlterMode = eAlterMode; + else if (eAlterMode != AlterMode) + throw new Exceptions.DatabaseObjectsException("Cannot mix " + AlterModeDescription(AlterMode) + " fields and " + AlterModeDescription(eAlterMode) + " fields into one SQL statement"); } - private void EnsureAlterModeValid(SQLTableFields.AlterModeType eAlterMode) - { - //if the alter mode hasn't been set then any of the modes are valid - if ((int)AlterMode == pcintAlterModeUninitialized) - AlterMode = eAlterMode; - else if (eAlterMode != AlterMode) - throw new Exceptions.DatabaseObjectsException("Cannot mix " + AlterModeDescription(AlterMode) + " fields and " + AlterModeDescription(eAlterMode) + " fields into one SQL statement"); - } - - private string AlterModeDescription(SQLTableFields.AlterModeType eAlterMode) + private string AlterModeDescription(SQLTableFields.AlterModeType eAlterMode) { switch (eAlterMode) { @@ -231,7 +161,7 @@ private string AlterModeDescription(SQLTableFields.AlterModeType eAlterMode) throw new NotSupportedException(); } } - + IEnumerator IEnumerable.GetEnumerator() { return pobjFields.GetEnumerator(); @@ -245,7 +175,7 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() public abstract class SQLTableFieldBase { - protected internal abstract string SQL(Database.ConnectionType eConnectionType, bool bOnlyFieldName); + internal abstract string SQL(Serializers.Serializer serializer, SQLTableFields.AlterModeType alterMode); private SQLFieldExpression pobjNameAsExpression = new SQLFieldExpression(); @@ -265,7 +195,7 @@ public string Name } } - protected SQLExpression NameAsExpression + internal SQLExpression NameAsExpression { get { @@ -288,12 +218,17 @@ public SQLTableFieldComputed(string strFieldName, SQLExpression objComputation) pobjComputation = objComputation; } - protected internal override string SQL(Database.ConnectionType eConnectionType, bool bOnlyFieldName) - { - if (bOnlyFieldName) - throw new InvalidOperationException("Computed columns cannot be used for dropping fields"); + public SQLExpression Computation + { + get + { + return pobjComputation; + } + } - return base.NameAsExpression.SQL(eConnectionType) + " AS (" + pobjComputation.SQL(eConnectionType) + ")"; + internal override string SQL(Serializers.Serializer serializer, SQLTableFields.AlterModeType alterMode) + { + return serializer.SerializeTableFieldComputed(this, alterMode); } } @@ -325,7 +260,7 @@ public SQL.DataType DataType set { - if (pbAutoIncrements && !Misc.DataTypeIsInteger(value)) + if (pbAutoIncrements && !DataTypeExtensions.IsInteger(value)) throw new InvalidOperationException("Data type " + value.ToString() + " cannot be used as an autoincrement field, as it is not an integer field"); peType = value; @@ -352,7 +287,7 @@ public int Size { set { - Misc.DataTypeEnsureIsCharacter(peType); + DataTypeExtensions.EnsureIsCharacter(peType); if (value <= 1) throw new ArgumentException(); @@ -362,8 +297,6 @@ public int Size get { - Misc.DataTypeEnsureIsCharacter(peType); - return pintSize; } } @@ -378,14 +311,12 @@ public int ScaleLength { get { - Misc.DataTypeEnsureIsDecimal(peType); - return pintScale; } set { - Misc.DataTypeEnsureIsDecimal(peType); + DataTypeExtensions.EnsureIsDecimal(peType); if (value <= 0) throw new ArgumentException(); @@ -404,14 +335,12 @@ public int Precision { get { - Misc.DataTypeEnsureIsDecimal(peType); - return pintPrecision; } set { - Misc.DataTypeEnsureIsDecimal(peType); + DataTypeExtensions.EnsureIsDecimal(peType); if (value <= 0) throw new ArgumentException(); @@ -424,14 +353,12 @@ public bool AutoIncrements { get { - Misc.DataTypeEnsureIsInteger(peType); - return pbAutoIncrements; } set { - Misc.DataTypeEnsureIsInteger(peType); + DataTypeExtensions.EnsureIsInteger(peType); pbAutoIncrements = value; pbAcceptsNull = System.Convert.ToBoolean(!value); } @@ -466,93 +393,9 @@ public object Default } } - protected internal override string SQL(Database.ConnectionType eConnectionType, bool bOnlyFieldName) - { - if (bOnlyFieldName) - return base.NameAsExpression.SQL(eConnectionType); - else - return SQLForColumnAddOrModify(eConnectionType); - } - - private string SQLForColumnAddOrModify(Database.ConnectionType eConnectionType) - { - string strDataType = string.Empty; - string strColumnOptions; - string strSQL = string.Empty; - - //For Pervasive do not specify NULL/NOT NULL and the data type for an IDENTITY field - bool bSpecifyNullStatus = !(pbAutoIncrements && (eConnectionType == Database.ConnectionType.Pervasive)); - bool bSpecifyDataType = !(pbAutoIncrements && (eConnectionType == Database.ConnectionType.Pervasive)); - - if (bSpecifyDataType) - strDataType = Misc.SQLConvertDataTypeString(eConnectionType, peType, pintSize, pintPrecision, pintScale); - - strColumnOptions = ColumnOptions(eConnectionType, bSpecifyNullStatus); - strSQL = base.NameAsExpression.SQL(eConnectionType) + " " + strDataType + strColumnOptions; - - return strSQL; - } - - private string ColumnOptions(Database.ConnectionType eConnection, bool bSpecifyNullStatus) - { - ArrayList objOptions = new ArrayList(); - string strOptions = string.Empty; - - //In version 2.13+ the IDENTITY constraint has been reordered - //to before the contraints (i.e. DEFAULT, NULL etc.) - if (Misc.DataTypeIsInteger(peType) && pbAutoIncrements) - { - switch (eConnection) - { - case Database.ConnectionType.MicrosoftAccess: - objOptions.Add("IDENTITY"); - break; - case Database.ConnectionType.MySQL: - objOptions.Add("AUTO_INCREMENT"); - //must be set to a key - if (peKeyType == KeyType.None) - peKeyType = KeyType.Unique; - break; - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - objOptions.Add("IDENTITY"); - break; - case Database.ConnectionType.Pervasive: - objOptions.Add("IDENTITY"); - break; - case Database.ConnectionType.HyperSQL: - objOptions.Add("GENERATED BY DEFAULT AS IDENTITY(START WITH 1 INCREMENT BY 1)"); - break; - default: - throw new NotImplementedException(eConnection.ToString() + "; Auto Increment"); - break; - } - } - - if (pobjDefault != null) - objOptions.Add("DEFAULT " + Misc.SQLConvertValue(pobjDefault, eConnection)); - - //NULL status MUST be after the default value for Pervasive - //In version 2.13+ the NULL/NOT NULL constraint has been reordered - //to after the DEFAULT constraint. Hopefully, this won't cause any problems. - //According to the T-SQL docs it should not be a problem. - if (bSpecifyNullStatus) - { - if (pbAcceptsNull) - objOptions.Add("NULL"); - else - objOptions.Add("NOT NULL"); - } - - if (peKeyType == KeyType.Primary) - objOptions.Add("PRIMARY KEY"); - else if (peKeyType == KeyType.Unique) - objOptions.Add("UNIQUE"); - - foreach (object objOption in objOptions) - strOptions += " " + ((string)objOption); - - return strOptions; - } + internal override string SQL(Serializers.Serializer serializer, SQLTableFields.AlterModeType alterMode) + { + return serializer.SerializeTableField(this, alterMode); + } } } diff --git a/SQL/Transactions/SQLBeginTransaction.cs b/SQL/Transactions/SQLBeginTransaction.cs index 9ce2506..69b32d8 100644 --- a/SQL/Transactions/SQLBeginTransaction.cs +++ b/SQL/Transactions/SQLBeginTransaction.cs @@ -17,22 +17,7 @@ public override string SQL { get { - switch (base.ConnectionType) - { - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - return "BEGIN TRANSACTION"; - case Database.ConnectionType.MicrosoftAccess: - return "BEGIN TRANSACTION"; - case Database.ConnectionType.MySQL: - return "START TRANSACTION"; - case Database.ConnectionType.Pervasive: - return "START TRANSACTION"; - case Database.ConnectionType.HyperSQL: - return "START TRANSACTION"; - default: - throw new NotImplementedException(this.ConnectionType.ToString()); - } + return base.Serializer.SerializeBeingTransaction(this); } } } diff --git a/SQL/Transactions/SQLCommitTransaction.cs b/SQL/Transactions/SQLCommitTransaction.cs index 1391023..5397f22 100644 --- a/SQL/Transactions/SQLCommitTransaction.cs +++ b/SQL/Transactions/SQLCommitTransaction.cs @@ -17,22 +17,7 @@ public override string SQL { get { - switch (base.ConnectionType) - { - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - return "COMMIT TRANSACTION"; - case Database.ConnectionType.MicrosoftAccess: - return "COMMIT TRANSACTION"; - case Database.ConnectionType.MySQL: - return "COMMIT"; - case Database.ConnectionType.Pervasive: - return "COMMIT"; - case Database.ConnectionType.HyperSQL: - return "COMMIT"; - default: - throw new NotImplementedException(this.ConnectionType.ToString()); - } + return base.Serializer.SerializeCommitTransaction(this); } } } diff --git a/SQL/Transactions/SQLRollbackTransaction.cs b/SQL/Transactions/SQLRollbackTransaction.cs index f040bac..ce72bfd 100644 --- a/SQL/Transactions/SQLRollbackTransaction.cs +++ b/SQL/Transactions/SQLRollbackTransaction.cs @@ -17,22 +17,7 @@ public override string SQL { get { - switch (base.ConnectionType) - { - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.SQLServerCompactEdition: - return "ROLLBACK TRANSACTION"; - case Database.ConnectionType.MicrosoftAccess: - return "ROLLBACK TRANSACTION"; - case Database.ConnectionType.MySQL: - return "ROLLBACK"; - case Database.ConnectionType.Pervasive: - return "ROLLBACK"; - case Database.ConnectionType.HyperSQL: - return "ROLLBACK"; - default: - throw new NotImplementedException(base.ConnectionType.ToString()); - } + return base.Serializer.SerializeRollbackTransaction(this); } } } diff --git a/SQL/Transactions/SQLSetTransactionIsolationLevel.cs b/SQL/Transactions/SQLSetTransactionIsolationLevel.cs index 647e7db..c00c344 100644 --- a/SQL/Transactions/SQLSetTransactionIsolationLevel.cs +++ b/SQL/Transactions/SQLSetTransactionIsolationLevel.cs @@ -19,45 +19,20 @@ public SQLSetTransactionIsolationLevel(System.Data.IsolationLevel eIsolationLeve { peIsolationLevel = eIsolationLevel; } - - public override string SQL + + public System.Data.IsolationLevel Value { get { - switch (base.ConnectionType) - { - case Database.ConnectionType.SQLServer: - case Database.ConnectionType.MySQL: - case Database.ConnectionType.Pervasive: - case Database.ConnectionType.SQLServerCompactEdition: - case Database.ConnectionType.HyperSQL: - return "SET TRANSACTION ISOLATION LEVEL " + GetIsolationLevelString(peIsolationLevel); - default: - throw new NotImplementedException(this.ConnectionType.ToString() + "; Transaction isolation levels"); - } + return peIsolationLevel; } } - private string GetIsolationLevelString(System.Data.IsolationLevel eIsolationLevel) + public override string SQL { - switch (eIsolationLevel) + get { - case IsolationLevel.ReadCommitted: - return "READ COMMITTED"; - case IsolationLevel.ReadUncommitted: - return "READ UNCOMMITTED"; - case IsolationLevel.RepeatableRead: - return "REPEATABLE READ"; - case IsolationLevel.Serializable: - return "SERIALIZABLE"; - case IsolationLevel.Snapshot: - //Only SQL Server 2005+ supports snapshot isolation levels - if (base.ConnectionType == Database.ConnectionType.SQLServer) - return "SNAPSHOT"; - else - throw new NotSupportedException("Snapshots isolation level is not supported for " + base.ConnectionType); - default: - throw new NotImplementedException("Isolation level"); + return base.Serializer.SerializeSetTransactionIsolationLevel(this); } } } diff --git a/SQL/Views/SQLCreateView.cs b/SQL/Views/SQLCreateView.cs index 049e521..dad5065 100644 --- a/SQL/Views/SQLCreateView.cs +++ b/SQL/Views/SQLCreateView.cs @@ -62,12 +62,7 @@ public override string SQL { get { - if (string.IsNullOrEmpty(this.Name)) - throw new Exceptions.DatabaseObjectsException("View name has not been set"); - else if (pobjSelect == null) - throw new Exceptions.DatabaseObjectsException("Select statement has not been set"); - - return "CREATE VIEW " + Misc.SQLConvertIdentifierName(this.Name, this.ConnectionType) + " AS " + pobjSelect.SQL; + return base.Serializer.SerializeCreateView(this); } } } diff --git a/SQL/Views/SQLDropView.cs b/SQL/Views/SQLDropView.cs index 0108cd8..e0fe213 100644 --- a/SQL/Views/SQLDropView.cs +++ b/SQL/Views/SQLDropView.cs @@ -22,12 +22,20 @@ public SQLDropView(string strViewName) pstrName = strViewName; } + + public string ViewName + { + get + { + return pstrName; + } + } public override string SQL { get { - return "DROP VIEW " + Misc.SQLConvertIdentifierName(pstrName, this.ConnectionType); + return base.Serializer.SerializeDropView(this); } } } diff --git a/SQL/Views/SQLViewExists.cs b/SQL/Views/SQLViewExists.cs index 0e28b4f..6c1a8e7 100644 --- a/SQL/Views/SQLViewExists.cs +++ b/SQL/Views/SQLViewExists.cs @@ -29,51 +29,20 @@ public SQLViewExists(string strViewName) pstrViewName = strViewName; } - + + public string ViewName + { + get + { + return pstrViewName; + } + } + public override string SQL { get { - string strSQL = string.Empty; - SQLSelect objSelect; - - switch (this.ConnectionType) - { - case Database.ConnectionType.MicrosoftAccess: - throw new NotSupportedException(); - case Database.ConnectionType.MySQL: - objSelect = new SQLSelect(); - objSelect.ConnectionType = this.ConnectionType; - objSelect.Tables.Add("Tables").SchemaName = "INFORMATION_SCHEMA"; - objSelect.Where.Add("Table_Type", ComparisonOperator.EqualTo, "View"); - objSelect.Where.Add("TABLE_NAME", ComparisonOperator.Like, pstrViewName); - strSQL = objSelect.SQL; - break; - case Database.ConnectionType.SQLServer: - objSelect = new SQLSelect(); - objSelect.ConnectionType = this.ConnectionType; - objSelect.Tables.Add("sysobjects"); - objSelect.Where.Add("Name", ComparisonOperator.EqualTo, pstrViewName); - objSelect.Where.Add("XType", ComparisonOperator.EqualTo, "V"); //V = User defined view - strSQL = objSelect.SQL; - break; - case Database.ConnectionType.Pervasive: - throw new NotSupportedException(); - case Database.ConnectionType.HyperSQL: - objSelect = new SQLSelect(); - objSelect.ConnectionType = this.ConnectionType; - objSelect.Tables.Add("VIEWS").SchemaName = "INFORMATION_SCHEMA"; - objSelect.Where.Add("TABLE_SCHEMA", ComparisonOperator.EqualTo, "PUBLIC"); - objSelect.Where.Add("TABLE_NAME", ComparisonOperator.EqualTo, pstrViewName); - strSQL = objSelect.SQL; - break; - case Database.ConnectionType.SQLServerCompactEdition: - throw new NotSupportedException(); - default: - throw new NotImplementedException(this.ConnectionType.ToString()); - } - - return strSQL; + return base.Serializer.SerializeViewExists(this); } } }