comparison Source/Data/Sql/SqlProvider/FirebirdSqlProvider.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f990fcb411a9
1 using System;
2 using System.Data;
3 using System.Text;
4
5 #region ReSharper disable
6 // ReSharper disable SuggestUseVarKeywordEverywhere
7 // ReSharper disable SuggestUseVarKeywordEvident
8 #endregion
9
10 namespace BLToolkit.Data.Sql.SqlProvider
11 {
12 using DataProvider;
13 using Mapping;
14 using Reflection;
15
16 using Linq;
17
18 public class FirebirdSqlProvider : BasicSqlProvider, IMappingSchemaProvider
19 {
20 public FirebirdSqlProvider()
21 {
22 }
23
24 // public override int CommandCount(SqlQuery sqlQuery)
25 // {
26 // return sqlQuery.IsInsert && sqlQuery.Set.WithIdentity ? 2 : 1;
27 // }
28
29 // protected override void BuildCommand(int commandNumber, StringBuilder sb)
30 // {
31 // SequenceNameAttribute attr = GetSequenceNameAttribute(true);
32 //
33 // AppendIndent(sb)
34 // .Append("SELECT gen_id(")
35 // .Append(attr.SequenceName)
36 // .AppendLine(", 0) FROM rdb$database");
37 // }
38
39 protected override ISqlProvider CreateSqlProvider()
40 {
41 return new FirebirdSqlProvider();
42 }
43
44 protected override void BuildSelectClause(StringBuilder sb)
45 {
46 if (SqlQuery.From.Tables.Count == 0)
47 {
48 AppendIndent(sb);
49 sb.Append("SELECT").AppendLine();
50 BuildColumns(sb);
51 AppendIndent(sb);
52 sb.Append("FROM rdb$database").AppendLine();
53 }
54 else
55 base.BuildSelectClause(sb);
56 }
57
58 protected override bool SkipFirst { get { return false; } }
59 protected override string SkipFormat { get { return "SKIP {0}"; } }
60 protected override string FirstFormat { get { return "FIRST {0}"; } }
61
62 public override bool IsIdentityParameterRequired { get { return true; } }
63
64 protected override void BuildGetIdentity(StringBuilder sb)
65 {
66 var identityField = SqlQuery.Insert.Into.GetIdentityField();
67
68 if (identityField == null)
69 throw new SqlException("Identity field must be defined for '{0}'.", SqlQuery.Insert.Into.Name);
70
71 AppendIndent(sb).AppendLine("RETURNING");
72 AppendIndent(sb).Append("\t");
73 BuildExpression(sb, identityField, false, true);
74 }
75
76 public override ISqlExpression GetIdentityExpression(SqlTable table, SqlField identityField, bool forReturning)
77 {
78 if (table.SequenceAttributes != null)
79 return new SqlExpression("GEN_ID(" + table.SequenceAttributes[0].SequenceName + ", 1)", Precedence.Primary);
80
81 return base.GetIdentityExpression(table, identityField, forReturning);
82 }
83
84 public override ISqlExpression ConvertExpression(ISqlExpression expr)
85 {
86 expr = base.ConvertExpression(expr);
87
88 if (expr is SqlBinaryExpression)
89 {
90 SqlBinaryExpression be = (SqlBinaryExpression)expr;
91
92 switch (be.Operation)
93 {
94 case "%": return new SqlFunction(be.SystemType, "Mod", be.Expr1, be.Expr2);
95 case "&": return new SqlFunction(be.SystemType, "Bin_And", be.Expr1, be.Expr2);
96 case "|": return new SqlFunction(be.SystemType, "Bin_Or", be.Expr1, be.Expr2);
97 case "^": return new SqlFunction(be.SystemType, "Bin_Xor", be.Expr1, be.Expr2);
98 case "+": return be.SystemType == typeof(string)? new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence): expr;
99 }
100 }
101 else if (expr is SqlFunction)
102 {
103 SqlFunction func = (SqlFunction)expr;
104
105 switch (func.Name)
106 {
107 case "Convert" :
108 if (TypeHelper.GetUnderlyingType(func.SystemType) == typeof(bool))
109 {
110 ISqlExpression ex = AlternativeConvertToBoolean(func, 1);
111 if (ex != null)
112 return ex;
113 }
114
115 return new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, FloorBeforeConvert(func), func.Parameters[0]);
116
117 case "DateAdd" :
118 switch ((Sql.DateParts)((SqlValue)func.Parameters[0]).Value)
119 {
120 case Sql.DateParts.Quarter :
121 return new SqlFunction(func.SystemType, func.Name, new SqlValue(Sql.DateParts.Month), Mul(func.Parameters[1], 3), func.Parameters[2]);
122 case Sql.DateParts.DayOfYear:
123 case Sql.DateParts.WeekDay:
124 return new SqlFunction(func.SystemType, func.Name, new SqlValue(Sql.DateParts.Day), func.Parameters[1], func.Parameters[2]);
125 case Sql.DateParts.Week :
126 return new SqlFunction(func.SystemType, func.Name, new SqlValue(Sql.DateParts.Day), Mul(func.Parameters[1], 7), func.Parameters[2]);
127 }
128
129 break;
130 }
131 }
132 else if (expr is SqlExpression)
133 {
134 SqlExpression e = (SqlExpression)expr;
135
136 if (e.Expr.StartsWith("Extract(Quarter"))
137 return Inc(Div(Dec(new SqlExpression(e.SystemType, "Extract(Month from {0})", e.Parameters)), 3));
138
139 if (e.Expr.StartsWith("Extract(YearDay"))
140 return Inc(new SqlExpression(e.SystemType, e.Expr.Replace("Extract(YearDay", "Extract(yearDay"), e.Parameters));
141
142 if (e.Expr.StartsWith("Extract(WeekDay"))
143 return Inc(new SqlExpression(e.SystemType, e.Expr.Replace("Extract(WeekDay", "Extract(weekDay"), e.Parameters));
144 }
145
146 return expr;
147 }
148
149 protected override void BuildFunction(StringBuilder sb, SqlFunction func)
150 {
151 func = ConvertFunctionParameters(func);
152 base.BuildFunction(sb, func);
153 }
154
155 protected override void BuildDataType(StringBuilder sb, SqlDataType type)
156 {
157 switch (type.SqlDbType)
158 {
159 case SqlDbType.Decimal :
160 base.BuildDataType(sb, type.Precision > 18 ? new SqlDataType(type.SqlDbType, type.Type, 18, type.Scale) : type);
161 break;
162 case SqlDbType.TinyInt : sb.Append("SmallInt"); break;
163 case SqlDbType.Money : sb.Append("Decimal(18,4)"); break;
164 case SqlDbType.SmallMoney : sb.Append("Decimal(10,4)"); break;
165 #if !MONO
166 case SqlDbType.DateTime2 :
167 #endif
168 case SqlDbType.SmallDateTime :
169 case SqlDbType.DateTime : sb.Append("TimeStamp"); break;
170 case SqlDbType.NVarChar :
171 sb.Append("VarChar");
172 if (type.Length > 0)
173 sb.Append('(').Append(type.Length).Append(')');
174 break;
175 default : base.BuildDataType(sb, type); break;
176 }
177 }
178
179 static void SetNonQueryParameter(IQueryElement element)
180 {
181 if (element.ElementType == QueryElementType.SqlParameter)
182 ((SqlParameter)element).IsQueryParameter = false;
183 }
184
185 public override SqlQuery Finalize(SqlQuery sqlQuery)
186 {
187 CheckAliases(sqlQuery, int.MaxValue);
188
189 new QueryVisitor().Visit(sqlQuery.Select, SetNonQueryParameter);
190
191 if (sqlQuery.QueryType == QueryType.InsertOrUpdate)
192 {
193 foreach (var key in sqlQuery.Insert.Items)
194 new QueryVisitor().Visit(key.Expression, SetNonQueryParameter);
195
196 foreach (var key in sqlQuery.Update.Items)
197 new QueryVisitor().Visit(key.Expression, SetNonQueryParameter);
198
199 foreach (var key in sqlQuery.Update.Keys)
200 new QueryVisitor().Visit(key.Expression, SetNonQueryParameter);
201 }
202
203 new QueryVisitor().Visit(sqlQuery, element =>
204 {
205 if (element.ElementType == QueryElementType.InSubQueryPredicate)
206 new QueryVisitor().Visit(((SqlQuery.Predicate.InSubQuery)element).Expr1, SetNonQueryParameter);
207 });
208
209 sqlQuery = base.Finalize(sqlQuery);
210
211 switch (sqlQuery.QueryType)
212 {
213 case QueryType.Delete : return GetAlternativeDelete(sqlQuery);
214 case QueryType.Update : return GetAlternativeUpdate(sqlQuery);
215 default : return sqlQuery;
216 }
217 }
218
219 protected override void BuildFromClause(StringBuilder sb)
220 {
221 if (!SqlQuery.IsUpdate)
222 base.BuildFromClause(sb);
223 }
224
225 protected override void BuildColumnExpression(StringBuilder sb, ISqlExpression expr, string alias, ref bool addAlias)
226 {
227 var wrap = false;
228
229 if (expr.SystemType == typeof(bool))
230 {
231 if (expr is SqlQuery.SearchCondition)
232 wrap = true;
233 else
234 {
235 var ex = expr as SqlExpression;
236 wrap = ex != null && ex.Expr == "{0}" && ex.Parameters.Length == 1 && ex.Parameters[0] is SqlQuery.SearchCondition;
237 }
238 }
239
240 if (wrap) sb.Append("CASE WHEN ");
241 base.BuildColumnExpression(sb, expr, alias, ref addAlias);
242 if (wrap) sb.Append(" THEN 1 ELSE 0 END");
243 }
244
245 public static bool QuoteIdentifiers = false;
246
247 public override object Convert(object value, ConvertType convertType)
248 {
249 switch (convertType)
250 {
251 case ConvertType.NameToQueryField:
252 case ConvertType.NameToQueryTable:
253 if (QuoteIdentifiers)
254 {
255 string name = value.ToString();
256
257 if (name.Length > 0 && name[0] == '"')
258 return value;
259
260 return '"' + name + '"';
261 }
262
263 break;
264
265 case ConvertType.NameToQueryParameter:
266 case ConvertType.NameToCommandParameter:
267 case ConvertType.NameToSprocParameter:
268 return "@" + value;
269
270 case ConvertType.SprocParameterToName:
271 if (value != null)
272 {
273 string str = value.ToString();
274 return str.Length > 0 && str[0] == '@' ? str.Substring(1) : str;
275 }
276
277 break;
278 }
279
280 return value;
281 }
282
283 protected override void BuildInsertOrUpdateQuery(StringBuilder sb)
284 {
285 BuildInsertOrUpdateQueryAsMerge(sb, "FROM rdb$database");
286 }
287
288 #region IMappingSchemaProvider Members
289
290 readonly FirebirdMappingSchema _mappingSchema = new FirebirdMappingSchema();
291
292 MappingSchema IMappingSchemaProvider.MappingSchema
293 {
294 get { return _mappingSchema; }
295 }
296
297 #endregion
298 }
299 }