2002-10-16 Daniel Morgan <danmorg@sc.rr.com>
[mono.git] / mcs / class / Mono.Data.PostgreSqlClient / Mono.Data.PostgreSqlClient / ParmUtil.cs
1 //\r
2 // ParmUtil.cs - utility to bind variables in a SQL statement to parameters in C# code\r
3 //               This is in the PostgreSQL .NET Data provider in Mono\r
4 //\r
5 // Author: \r
6 //    Daniel Morgan <danmorg@sc.rr.com>\r
7 //\r
8 // (c)copyright 2002 Daniel Morgan\r
9 //\r
10 \r
11 // comment DEBUG_ParmUtil for production, for debug messages, uncomment\r
12 //#define DEBUG_ParmUtil\r
13 \r
14 using System;\r
15 using System.Data;\r
16 using System.Text;\r
17 \r
18 namespace Mono.Data.PostgreSqlClient {\r
19 \r
20         enum PostgresBindVariableCharacter {\r
21                 Semicolon,\r
22                 At,\r
23                 QuestionMark\r
24         }\r
25 \r
26         public class ParmUtil {\r
27 \r
28                 private string sql = "";\r
29                 private string resultSql = "";\r
30                 private PgSqlParameterCollection parmsCollection = null;\r
31                 \r
32                 static private PostgresBindVariableCharacter PgbindChar = PostgresBindVariableCharacter.Semicolon;\r
33                 static char bindChar;\r
34 \r
35                 // static constructor\r
36                 static ParmUtil() {\r
37                         switch(PgbindChar) {\r
38                         case PostgresBindVariableCharacter.Semicolon:\r
39                                 bindChar = ':';\r
40                                 break;\r
41                         case PostgresBindVariableCharacter.At:\r
42                                 bindChar = '@';\r
43                                 break;\r
44                         case PostgresBindVariableCharacter.QuestionMark:\r
45                                 // this doesn't have named parameters,\r
46                                 // they must be in order\r
47                                 bindChar = '?';\r
48                                 break;\r
49                         }\r
50                 }\r
51                                 \r
52                 public ParmUtil(string query, PgSqlParameterCollection parms) {\r
53                         sql = query;\r
54                         parmsCollection = parms;\r
55                 }\r
56                 \r
57                 public string ResultSql {\r
58                         get {\r
59                                 return resultSql;\r
60                         }\r
61                 }\r
62 \r
63                 // TODO: currently only works for input variables,\r
64                 //       need to do input/output, output, and return\r
65                 public string ReplaceWithParms() {\r
66 \r
67                         StringBuilder result = new StringBuilder();\r
68                         char[] chars = sql.ToCharArray();\r
69                         bool bStringConstFound = false;\r
70 \r
71                         for(int i = 0; i < chars.Length; i++) {\r
72                                 if(chars[i] == '\'') {\r
73                                         if(bStringConstFound == true)\r
74                                                 bStringConstFound = false;\r
75                                         else\r
76                                                 bStringConstFound = true;\r
77 \r
78                                         result.Append(chars[i]);\r
79                                 }\r
80                                 else if(chars[i] == bindChar && \r
81                                         bStringConstFound == false) {\r
82 #if DEBUG_ParmUtil\r
83                                         Console.WriteLine("Bind Variable character found...");\r
84 #endif                                  \r
85                                         StringBuilder parm = new StringBuilder();\r
86                                         i++;\r
87                                         while(i <= chars.Length) {\r
88                                                 char ch;\r
89                                                 if(i == chars.Length)\r
90                                                         ch = ' '; // a space\r
91                                                 else\r
92                                                         ch = chars[i];\r
93 \r
94 #if DEBUG_ParmUtil                                              \r
95                                                 Console.WriteLine("Is char Letter or digit?");\r
96 #endif                                          \r
97                                                 if(Char.IsLetterOrDigit(ch)) {\r
98 #if DEBUG_ParmUtil\r
99                                                         Console.WriteLine("Char IS letter or digit. " + \r
100                                                                 "Now, append char to parm StringBuilder");\r
101 #endif\r
102                                                         parm.Append(ch);\r
103                                                 }\r
104                                                 else {\r
105 #if DEBUG_ParmUtil\r
106                                                         Console.WriteLine("Char is NOT letter or char. " + \r
107                                                                 "thus we got rest of bind variable name. ");\r
108                                                                 \r
109                                                         // replace bind variable placeholder \r
110                                                         // with data value constant\r
111                                                         Console.WriteLine("parm StringBuilder to string p...");\r
112 #endif\r
113                                                         string p = parm.ToString();\r
114 #if DEBUG_ParmUtil\r
115                                                         Console.WriteLine("calling BindReplace...");\r
116 #endif                                                  \r
117                                                         bool found = BindReplace(result, p);\r
118 #if DEBUG_ParmUtil\r
119                                                         Console.WriteLine("    Found = " + found);\r
120 #endif\r
121                                                         if(found == true)\r
122                                                                 break;\r
123                                                         else {                                          \r
124                                                                 // *** Error Handling\r
125                                                                 Console.WriteLine("Error: parameter not found: " + p);\r
126                                                                 return "";\r
127                                                         }\r
128                                                 }\r
129                                                 i++;\r
130                                         }\r
131                                         i--;\r
132                                 }\r
133                                 else \r
134                                         result.Append(chars[i]);\r
135                         }\r
136                         \r
137                         resultSql = result.ToString();\r
138                         return resultSql;\r
139                 }\r
140 \r
141                 public bool BindReplace (StringBuilder result, string p) {\r
142                         // bind variable\r
143                         bool found = false;\r
144 \r
145 #if DEBUG_ParmUtil\r
146                         Console.WriteLine("Does the parmsCollection contain the parameter???: " + p);\r
147 #endif\r
148                         if(parmsCollection.Contains(p) == true) {\r
149                                 // parameter found\r
150 #if DEBUG_ParmUtil\r
151                                 Console.WriteLine("Parameter Found: " + p);\r
152 #endif\r
153                                 PgSqlParameter prm = parmsCollection[p];\r
154 \r
155 #if DEBUG_ParmUtil                                                                                                                                      \r
156                                 // DEBUG \r
157                                 Console.WriteLine("          Value: " + prm.Value);\r
158                                 Console.WriteLine("      Direction: " + prm.Direction);\r
159 #endif\r
160                                 // convert object to string and place\r
161                                 // into SQL\r
162                                 if(prm.Direction == ParameterDirection.Input) {\r
163                                         string strObj = PostgresHelper.\r
164                                                 ObjectToString(prm.DbType, \r
165                                                                 prm.Value);\r
166                                         result.Append(strObj);\r
167                                 }\r
168                                 else\r
169                                         result.Append(bindChar + p);\r
170 \r
171                                 found = true;\r
172                         }\r
173                         return found;\r
174                 }\r
175         }\r
176 }\r