Mercurial > pub > bltoolkit
comparison Source/Data/Sql/SqlProvider/MySqlSqlProvider.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.Collections.Generic; | |
3 using System.Data; | |
4 using System.Text; | |
5 | |
6 namespace BLToolkit.Data.Sql.SqlProvider | |
7 { | |
8 using DataProvider; | |
9 using Reflection; | |
10 | |
11 public class MySqlSqlProvider : BasicSqlProvider | |
12 { | |
13 public override int CommandCount(SqlQuery sqlQuery) | |
14 { | |
15 return sqlQuery.IsInsert && sqlQuery.Insert.WithIdentity ? 2 : 1; | |
16 } | |
17 | |
18 protected override void BuildCommand(int commandNumber, StringBuilder sb) | |
19 { | |
20 sb.AppendLine("SELECT LAST_INSERT_ID()"); | |
21 } | |
22 | |
23 protected override ISqlProvider CreateSqlProvider() | |
24 { | |
25 return new MySqlSqlProvider(); | |
26 } | |
27 | |
28 protected override string LimitFormat { get { return "LIMIT {0}"; } } | |
29 | |
30 public override bool IsNestedJoinParenthesisRequired { get { return true; } } | |
31 | |
32 protected override void BuildOffsetLimit(StringBuilder sb) | |
33 { | |
34 if (SqlQuery.Select.SkipValue == null) | |
35 base.BuildOffsetLimit(sb); | |
36 else | |
37 { | |
38 AppendIndent(sb) | |
39 .AppendFormat( | |
40 "LIMIT {0},{1}", | |
41 BuildExpression(new StringBuilder(), SqlQuery.Select.SkipValue), | |
42 SqlQuery.Select.TakeValue == null ? | |
43 long.MaxValue.ToString() : | |
44 BuildExpression(new StringBuilder(), SqlQuery.Select.TakeValue).ToString()) | |
45 .AppendLine(); | |
46 } | |
47 } | |
48 | |
49 public override ISqlExpression ConvertExpression(ISqlExpression expr) | |
50 { | |
51 expr = base.ConvertExpression(expr); | |
52 | |
53 if (expr is SqlBinaryExpression) | |
54 { | |
55 var be = (SqlBinaryExpression)expr; | |
56 | |
57 switch (be.Operation) | |
58 { | |
59 case "+": | |
60 if (be.SystemType == typeof(string)) | |
61 { | |
62 if (be.Expr1 is SqlFunction) | |
63 { | |
64 var func = (SqlFunction)be.Expr1; | |
65 | |
66 if (func.Name == "Concat") | |
67 { | |
68 var list = new List<ISqlExpression>(func.Parameters) { be.Expr2 }; | |
69 return new SqlFunction(be.SystemType, "Concat", list.ToArray()); | |
70 } | |
71 } | |
72 | |
73 return new SqlFunction(be.SystemType, "Concat", be.Expr1, be.Expr2); | |
74 } | |
75 | |
76 break; | |
77 } | |
78 } | |
79 else if (expr is SqlFunction) | |
80 { | |
81 var func = (SqlFunction) expr; | |
82 | |
83 switch (func.Name) | |
84 { | |
85 case "Convert" : | |
86 var ftype = TypeHelper.GetUnderlyingType(func.SystemType); | |
87 | |
88 if (ftype == typeof(bool)) | |
89 { | |
90 var ex = AlternativeConvertToBoolean(func, 1); | |
91 if (ex != null) | |
92 return ex; | |
93 } | |
94 | |
95 if ((ftype == typeof(double) || ftype == typeof(float)) && TypeHelper.GetUnderlyingType(func.Parameters[1].SystemType) == typeof(decimal)) | |
96 return func.Parameters[1]; | |
97 | |
98 return new SqlExpression(func.SystemType, "Cast({0} as {1})", Precedence.Primary, FloorBeforeConvert(func), func.Parameters[0]); | |
99 } | |
100 } | |
101 else if (expr is SqlExpression) | |
102 { | |
103 var e = (SqlExpression)expr; | |
104 | |
105 if (e.Expr.StartsWith("Extract(DayOfYear")) | |
106 return new SqlFunction(e.SystemType, "DayOfYear", e.Parameters); | |
107 | |
108 if (e.Expr.StartsWith("Extract(WeekDay")) | |
109 return Inc( | |
110 new SqlFunction(e.SystemType, | |
111 "WeekDay", | |
112 new SqlFunction( | |
113 null, | |
114 "Date_Add", | |
115 e.Parameters[0], | |
116 new SqlExpression(null, "interval 1 day")))); | |
117 } | |
118 | |
119 return expr; | |
120 } | |
121 | |
122 protected override void BuildDataType(StringBuilder sb, SqlDataType type) | |
123 { | |
124 switch (type.SqlDbType) | |
125 { | |
126 case SqlDbType.Int : | |
127 case SqlDbType.SmallInt : sb.Append("Signed"); break; | |
128 case SqlDbType.TinyInt : sb.Append("Unsigned"); break; | |
129 case SqlDbType.Money : sb.Append("Decimal(19,4)"); break; | |
130 case SqlDbType.SmallMoney : sb.Append("Decimal(10,4)"); break; | |
131 #if !MONO | |
132 case SqlDbType.DateTime2 : | |
133 #endif | |
134 case SqlDbType.SmallDateTime : sb.Append("DateTime"); break; | |
135 case SqlDbType.Bit : sb.Append("Boolean"); break; | |
136 case SqlDbType.Float : | |
137 case SqlDbType.Real : base.BuildDataType(sb, SqlDataType.Decimal); break; | |
138 case SqlDbType.VarChar : | |
139 case SqlDbType.NVarChar : | |
140 sb.Append("Char"); | |
141 if (type.Length > 0) | |
142 sb.Append('(').Append(type.Length).Append(')'); | |
143 break; | |
144 default: base.BuildDataType(sb, type); break; | |
145 } | |
146 } | |
147 | |
148 protected override void BuildDeleteClause(StringBuilder sb) | |
149 { | |
150 var table = SqlQuery.Delete.Table != null ? | |
151 (SqlQuery.From.FindTableSource(SqlQuery.Delete.Table) ?? SqlQuery.Delete.Table) : | |
152 SqlQuery.From.Tables[0]; | |
153 | |
154 AppendIndent(sb) | |
155 .Append("DELETE ") | |
156 .Append(Convert(GetTableAlias(table), ConvertType.NameToQueryTableAlias)) | |
157 .AppendLine(); | |
158 } | |
159 | |
160 protected override void BuildUpdateClause(StringBuilder sb) | |
161 { | |
162 base.BuildFromClause(sb); | |
163 sb.Remove(0, 4).Insert(0, "UPDATE"); | |
164 base.BuildUpdateSet(sb); | |
165 } | |
166 | |
167 protected override void BuildFromClause(StringBuilder sb) | |
168 { | |
169 if (!SqlQuery.IsUpdate) | |
170 base.BuildFromClause(sb); | |
171 } | |
172 | |
173 public static char ParameterSymbol { get; set; } | |
174 public static bool TryConvertParameterSymbol { get; set; } | |
175 | |
176 private static string _commandParameterPrefix = ""; | |
177 public static string CommandParameterPrefix | |
178 { | |
179 get { return _commandParameterPrefix; } | |
180 set { _commandParameterPrefix = string.IsNullOrEmpty(value) ? string.Empty : value; } | |
181 } | |
182 | |
183 private static string _sprocParameterPrefix = ""; | |
184 public static string SprocParameterPrefix | |
185 { | |
186 get { return _sprocParameterPrefix; } | |
187 set { _sprocParameterPrefix = string.IsNullOrEmpty(value) ? string.Empty : value; } | |
188 } | |
189 | |
190 private static List<char> _convertParameterSymbols; | |
191 public static List<char> ConvertParameterSymbols | |
192 { | |
193 get { return _convertParameterSymbols; } | |
194 set { _convertParameterSymbols = value ?? new List<char>(); } | |
195 } | |
196 | |
197 public override object Convert(object value, ConvertType convertType) | |
198 { | |
199 if (value == null) | |
200 throw new ArgumentNullException("value"); | |
201 | |
202 switch (convertType) | |
203 { | |
204 case ConvertType.NameToQueryParameter: | |
205 return ParameterSymbol + value.ToString(); | |
206 | |
207 case ConvertType.NameToCommandParameter: | |
208 return ParameterSymbol + CommandParameterPrefix + value; | |
209 | |
210 case ConvertType.NameToSprocParameter: | |
211 { | |
212 var valueStr = value.ToString(); | |
213 | |
214 if(string.IsNullOrEmpty(valueStr)) | |
215 throw new ArgumentException("Argument 'value' must represent parameter name."); | |
216 | |
217 if (valueStr[0] == ParameterSymbol) | |
218 valueStr = valueStr.Substring(1); | |
219 | |
220 if (valueStr.StartsWith(SprocParameterPrefix, StringComparison.Ordinal)) | |
221 valueStr = valueStr.Substring(SprocParameterPrefix.Length); | |
222 | |
223 return ParameterSymbol + SprocParameterPrefix + valueStr; | |
224 } | |
225 | |
226 case ConvertType.SprocParameterToName: | |
227 { | |
228 var str = value.ToString(); | |
229 str = (str.Length > 0 && (str[0] == ParameterSymbol || (TryConvertParameterSymbol && ConvertParameterSymbols.Contains(str[0])))) ? str.Substring(1) : str; | |
230 | |
231 if (!string.IsNullOrEmpty(SprocParameterPrefix) && str.StartsWith(SprocParameterPrefix)) | |
232 str = str.Substring(SprocParameterPrefix.Length); | |
233 | |
234 return str; | |
235 } | |
236 case ConvertType.NameToQueryField: | |
237 case ConvertType.NameToQueryFieldAlias: | |
238 case ConvertType.NameToQueryTableAlias: | |
239 { | |
240 var name = value.ToString(); | |
241 if (name.Length > 0 && name[0] == '`') | |
242 return value; | |
243 } | |
244 return "`" + value + "`"; | |
245 case ConvertType.NameToDatabase: | |
246 case ConvertType.NameToOwner: | |
247 case ConvertType.NameToQueryTable: | |
248 { | |
249 var name = value.ToString(); | |
250 if (name.Length > 0 && name[0] == '`') | |
251 return value; | |
252 | |
253 if (name.IndexOf('.') > 0) | |
254 value = string.Join("`.`", name.Split('.')); | |
255 } | |
256 return "`" + value + "`"; | |
257 | |
258 } | |
259 | |
260 return value; | |
261 } | |
262 | |
263 protected override StringBuilder BuildExpression(StringBuilder sb, ISqlExpression expr, bool buildTableName, bool checkParentheses, string alias, ref bool addAlias) | |
264 { | |
265 return base.BuildExpression( | |
266 sb, | |
267 expr, | |
268 buildTableName && SqlQuery.QueryType != QueryType.InsertOrUpdate, | |
269 checkParentheses, | |
270 alias, | |
271 ref addAlias); | |
272 } | |
273 | |
274 protected override void BuildInsertOrUpdateQuery(StringBuilder sb) | |
275 { | |
276 BuildInsertQuery(sb); | |
277 AppendIndent(sb).AppendLine("ON DUPLICATE KEY UPDATE"); | |
278 | |
279 Indent++; | |
280 | |
281 var first = true; | |
282 | |
283 foreach (var expr in SqlQuery.Update.Items) | |
284 { | |
285 if (!first) | |
286 sb.Append(',').AppendLine(); | |
287 first = false; | |
288 | |
289 AppendIndent(sb); | |
290 BuildExpression(sb, expr.Column, false, true); | |
291 sb.Append(" = "); | |
292 BuildExpression(sb, expr.Expression, false, true); | |
293 } | |
294 | |
295 Indent--; | |
296 | |
297 sb.AppendLine(); | |
298 } | |
299 | |
300 protected override void BuildEmptyInsert(StringBuilder sb) | |
301 { | |
302 sb.AppendLine("() VALUES ()"); | |
303 } | |
304 | |
305 public static bool GenerateOldGuid = false; | |
306 | |
307 public override void BuildValue(StringBuilder sb, object value) | |
308 { | |
309 if (GenerateOldGuid && value is Guid) | |
310 { | |
311 var bytes = ((Guid)value).ToByteArray(); | |
312 | |
313 sb.Append("X'").Append(ByteArrayToHex(bytes)).Append('\''); | |
314 } | |
315 else | |
316 base.BuildValue(sb, value); | |
317 } | |
318 | |
319 static string ByteArrayToHex(byte[] barray) | |
320 { | |
321 var c = new char[barray.Length * 2]; | |
322 | |
323 for (var i = 0; i < barray.Length; ++i) | |
324 { | |
325 var b = ((byte)(barray[i] >> 4)); | |
326 | |
327 c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30); | |
328 b = ((byte)(barray[i] & 0xF)); | |
329 c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30); | |
330 } | |
331 | |
332 return new string(c); | |
333 } | |
334 | |
335 protected override void BuildString(StringBuilder sb, string value) | |
336 { | |
337 base.BuildString(sb, value.Replace("\\", "\\\\")); | |
338 } | |
339 | |
340 protected override void BuildChar(StringBuilder sb, char value) | |
341 { | |
342 if (value == '\\') | |
343 sb.Append("\\\\"); | |
344 else | |
345 base.BuildChar(sb, value); | |
346 } | |
347 } | |
348 } |