comparison Source/Data/Sql/SqlProvider/DB2SqlProvider.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.Text;
3
4 using BLToolkit.Reflection;
5
6 namespace BLToolkit.Data.Sql.SqlProvider
7 {
8 using DataProvider;
9
10 public class DB2SqlProvider : BasicSqlProvider
11 {
12 public override bool TakeAcceptsParameter { get { return SqlQuery.Select.SkipValue != null; } }
13
14 SqlField _identityField;
15
16 public override int CommandCount(SqlQuery sqlQuery)
17 {
18 if (sqlQuery.IsInsert && sqlQuery.Insert.WithIdentity)
19 {
20 _identityField = sqlQuery.Insert.Into.GetIdentityField();
21
22 if (_identityField == null)
23 return 2;
24 }
25
26 return 1;
27 }
28
29 public override int BuildSql(int commandNumber, SqlQuery sqlQuery, StringBuilder sb, int indent, int nesting, bool skipAlias)
30 {
31 if (_identityField != null)
32 {
33 indent += 2;
34
35 AppendIndent(sb).AppendLine("SELECT");
36 AppendIndent(sb).Append("\t");
37 BuildExpression(sb, _identityField, false, true);
38 sb.AppendLine();
39 AppendIndent(sb).AppendLine("FROM");
40 AppendIndent(sb).AppendLine("\tNEW TABLE");
41 AppendIndent(sb).AppendLine("\t(");
42 }
43
44 var ret = base.BuildSql(commandNumber, sqlQuery, sb, indent, nesting, skipAlias);
45
46 if (_identityField != null)
47 sb.AppendLine("\t)");
48
49 return ret;
50 }
51
52 protected override void BuildCommand(int commandNumber, StringBuilder sb)
53 {
54 sb.AppendLine("SELECT identity_val_local() FROM SYSIBM.SYSDUMMY1");
55 }
56
57 protected override ISqlProvider CreateSqlProvider()
58 {
59 return new DB2SqlProvider();
60 }
61
62 protected override void BuildSql(StringBuilder sb)
63 {
64 AlternativeBuildSql(sb, false, base.BuildSql);
65 }
66
67 protected override void BuildSelectClause(StringBuilder sb)
68 {
69 if (SqlQuery.From.Tables.Count == 0)
70 {
71 AppendIndent(sb).AppendLine("SELECT");
72 BuildColumns(sb);
73 AppendIndent(sb).AppendLine("FROM SYSIBM.SYSDUMMY1 FETCH FIRST 1 ROW ONLY");
74 }
75 else
76 base.BuildSelectClause(sb);
77 }
78
79 protected override string LimitFormat
80 {
81 get { return SqlQuery.Select.SkipValue == null ? "FETCH FIRST {0} ROWS ONLY" : null; }
82 }
83
84 public override ISqlExpression ConvertExpression(ISqlExpression expr)
85 {
86 expr = base.ConvertExpression(expr);
87
88 if (expr is SqlBinaryExpression)
89 {
90 var be = (SqlBinaryExpression)expr;
91
92 switch (be.Operation)
93 {
94 case "%":
95 {
96 var expr1 = !TypeHelper.IsIntegerType(be.Expr1.SystemType) ? new SqlFunction(typeof(int), "Int", be.Expr1) : be.Expr1;
97 return new SqlFunction(be.SystemType, "Mod", expr1, be.Expr2);
98 }
99 case "&": return new SqlFunction(be.SystemType, "BitAnd", be.Expr1, be.Expr2);
100 case "|": return new SqlFunction(be.SystemType, "BitOr", be.Expr1, be.Expr2);
101 case "^": return new SqlFunction(be.SystemType, "BitXor", be.Expr1, be.Expr2);
102 case "+": return be.SystemType == typeof(string)? new SqlBinaryExpression(be.SystemType, be.Expr1, "||", be.Expr2, be.Precedence): expr;
103 }
104 }
105 else if (expr is SqlFunction)
106 {
107 var func = (SqlFunction) expr;
108
109 switch (func.Name)
110 {
111 case "Convert" :
112 if (TypeHelper.GetUnderlyingType(func.SystemType) == typeof(bool))
113 {
114 var ex = AlternativeConvertToBoolean(func, 1);
115 if (ex != null)
116 return ex;
117 }
118
119 if (func.Parameters[0] is SqlDataType)
120 {
121 var type = (SqlDataType)func.Parameters[0];
122
123 if (type.Type == typeof(string) && func.Parameters[1].SystemType != typeof(string))
124 return new SqlFunction(func.SystemType, "RTrim", new SqlFunction(typeof(string), "Char", func.Parameters[1]));
125
126 if (type.Length > 0)
127 return new SqlFunction(func.SystemType, type.SqlDbType.ToString(), func.Parameters[1], new SqlValue(type.Length));
128
129 if (type.Precision > 0)
130 return new SqlFunction(func.SystemType, type.SqlDbType.ToString(), func.Parameters[1], new SqlValue(type.Precision), new SqlValue(type.Scale));
131
132 return new SqlFunction(func.SystemType, type.SqlDbType.ToString(), func.Parameters[1]);
133 }
134
135 if (func.Parameters[0] is SqlFunction)
136 {
137 var f = (SqlFunction)func.Parameters[0];
138
139 return
140 f.Name == "Char" ?
141 new SqlFunction(func.SystemType, f.Name, func.Parameters[1]) :
142 f.Parameters.Length == 1 ?
143 new SqlFunction(func.SystemType, f.Name, func.Parameters[1], f.Parameters[0]) :
144 new SqlFunction(func.SystemType, f.Name, func.Parameters[1], f.Parameters[0], f.Parameters[1]);
145 }
146
147 {
148 var e = (SqlExpression)func.Parameters[0];
149 return new SqlFunction(func.SystemType, e.Expr, func.Parameters[1]);
150 }
151
152 case "Millisecond" : return Div(new SqlFunction(func.SystemType, "Microsecond", func.Parameters), 1000);
153 case "SmallDateTime" :
154 case "DateTime" :
155 case "DateTime2" : return new SqlFunction(func.SystemType, "TimeStamp", func.Parameters);
156 case "TinyInt" : return new SqlFunction(func.SystemType, "SmallInt", func.Parameters);
157 case "Money" : return new SqlFunction(func.SystemType, "Decimal", func.Parameters[0], new SqlValue(19), new SqlValue(4));
158 case "SmallMoney" : return new SqlFunction(func.SystemType, "Decimal", func.Parameters[0], new SqlValue(10), new SqlValue(4));
159 case "VarChar" :
160 if (TypeHelper.GetUnderlyingType(func.Parameters[0].SystemType) == typeof(decimal))
161 return new SqlFunction(func.SystemType, "Char", func.Parameters[0]);
162 break;
163 case "NChar" :
164 case "NVarChar" : return new SqlFunction(func.SystemType, "Char", func.Parameters);
165 case "DateDiff" :
166 {
167 switch ((Linq.Sql.DateParts)((SqlValue)func.Parameters[0]).Value)
168 {
169 case Linq.Sql.DateParts.Day : return new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 86400", Precedence.Multiplicative, func.Parameters[2], func.Parameters[1]);
170 case Linq.Sql.DateParts.Hour : return new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 3600", Precedence.Multiplicative, func.Parameters[2], func.Parameters[1]);
171 case Linq.Sql.DateParts.Minute : return new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) / 60", Precedence.Multiplicative, func.Parameters[2], func.Parameters[1]);
172 case Linq.Sql.DateParts.Second : return new SqlExpression(typeof(int), "(Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))", Precedence.Additive, func.Parameters[2], func.Parameters[1]);
173 case Linq.Sql.DateParts.Millisecond : return new SqlExpression(typeof(int), "((Days({0}) - Days({1})) * 86400 + (MIDNIGHT_SECONDS({0}) - MIDNIGHT_SECONDS({1}))) * 1000 + (MICROSECOND({0}) - MICROSECOND({1})) / 1000", Precedence.Additive, func.Parameters[2], func.Parameters[1]);
174 }
175 }
176
177 break;
178 }
179 }
180
181 return expr;
182 }
183
184 protected override void BuildFunction(StringBuilder sb, SqlFunction func)
185 {
186 func = ConvertFunctionParameters(func);
187 base.BuildFunction(sb, func);
188 }
189
190 static void SetQueryParameter(IQueryElement element)
191 {
192 if (element.ElementType == QueryElementType.SqlParameter)
193 ((SqlParameter)element).IsQueryParameter = false;
194 }
195
196 public override SqlQuery Finalize(SqlQuery sqlQuery)
197 {
198 new QueryVisitor().Visit(sqlQuery.Select, SetQueryParameter);
199
200 //if (sqlQuery.QueryType == QueryType.InsertOrUpdate)
201 // foreach (var key in sqlQuery.Insert.Items)
202 // if (((SqlField)key.Column).IsPrimaryKey)
203 // new QueryVisitor().Visit(key.Expression, SetQueryParameter);
204
205 sqlQuery = base.Finalize(sqlQuery);
206
207 switch (sqlQuery.QueryType)
208 {
209 case QueryType.Delete : return GetAlternativeDelete(sqlQuery);
210 case QueryType.Update : return GetAlternativeUpdate(sqlQuery);
211 default : return sqlQuery;
212 }
213 }
214
215 protected override void BuildFromClause(StringBuilder sb)
216 {
217 if (!SqlQuery.IsUpdate)
218 base.BuildFromClause(sb);
219 }
220
221 public override void BuildValue(StringBuilder sb, object value)
222 {
223 if (value is Guid)
224 {
225 var s = ((Guid)value).ToString("N");
226
227 sb
228 .Append("Cast(x'")
229 .Append(s.Substring( 6, 2))
230 .Append(s.Substring( 4, 2))
231 .Append(s.Substring( 2, 2))
232 .Append(s.Substring( 0, 2))
233 .Append(s.Substring(10, 2))
234 .Append(s.Substring( 8, 2))
235 .Append(s.Substring(14, 2))
236 .Append(s.Substring(12, 2))
237 .Append(s.Substring(16, 16))
238 .Append("' as char(16) for bit data)");
239 }
240 else
241 base.BuildValue(sb, value);
242 }
243
244 protected override void BuildColumnExpression(StringBuilder sb, ISqlExpression expr, string alias, ref bool addAlias)
245 {
246 var wrap = false;
247
248 if (expr.SystemType == typeof(bool))
249 {
250 if (expr is SqlQuery.SearchCondition)
251 wrap = true;
252 else
253 {
254 var ex = expr as SqlExpression;
255 wrap = ex != null && ex.Expr == "{0}" && ex.Parameters.Length == 1 && ex.Parameters[0] is SqlQuery.SearchCondition;
256 }
257 }
258
259 if (wrap) sb.Append("CASE WHEN ");
260 base.BuildColumnExpression(sb, expr, alias, ref addAlias);
261 if (wrap) sb.Append(" THEN 1 ELSE 0 END");
262 }
263
264 public static bool QuoteIdentifiers = true;
265
266 public override object Convert(object value, ConvertType convertType)
267 {
268 switch (convertType)
269 {
270 case ConvertType.NameToQueryParameter:
271 return "@" + value;
272
273 case ConvertType.NameToCommandParameter:
274 case ConvertType.NameToSprocParameter:
275 return ":" + value;
276
277 case ConvertType.SprocParameterToName:
278 if (value != null)
279 {
280 var str = value.ToString();
281 return str.Length > 0 && str[0] == ':'? str.Substring(1): str;
282 }
283
284 break;
285
286 case ConvertType.NameToQueryField:
287 case ConvertType.NameToQueryFieldAlias:
288 case ConvertType.NameToQueryTable:
289 case ConvertType.NameToQueryTableAlias:
290 if (QuoteIdentifiers)
291 {
292 var name = value.ToString();
293
294 if (name.Length > 0 && name[0] == '"')
295 return value;
296
297 return '"' + name + '"';
298 }
299
300 break;
301 }
302
303 return value;
304 }
305
306 protected override void BuildInsertOrUpdateQuery(StringBuilder sb)
307 {
308 BuildInsertOrUpdateQueryAsMerge(sb, "FROM SYSIBM.SYSDUMMY1 FETCH FIRST 1 ROW ONLY");
309 }
310
311 protected override void BuildEmptyInsert(StringBuilder sb)
312 {
313 sb.Append("VALUES ");
314
315 foreach (var col in SqlQuery.Insert.Into.Fields)
316 sb.Append("(DEFAULT)");
317
318 sb.AppendLine();
319 }
320 }
321 }