OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / user / gnugk / gksql_odbc.cxx
1 /*
2  * gksql_odbc.cxx
3  *
4  * ODBC driver module for GnuGk
5  *
6  * Copyright (c) 2006, Simon Horne
7  *
8  * This work is published under the GNU Public License (GPL)
9  * see file COPYING for details.
10  * We also explicitely grant the right to link this code
11  * with the OpenH323 library.
12  *
13  */
14
15 #ifdef P_ODBC
16
17 #include <ptlib.h>
18 #include <ptlib/podbc.h>
19
20
21 /** Class that encapsulates SQL query result for odbc backend.
22         It does not provide any multithread safety, so should be accessed
23         from a single thread at time.
24 */
25 class GkodbcResult : public GkSQLResult
26 {
27 public:
28         /// Build the result from SELECT type query
29         GkodbcResult(
30                 /// SELECT type query result
31                 PGresult* selectResult
32                 );
33
34         /// Build the result from INSERT, DELETE or UPDATE query
35         GkodbcResult(
36                 /// number of rows affected by the query
37                 long numRowsAffected
38                 );
39
40         /// Build the empty     result and store query execution error information
41         GkodbcResult(
42                 /// odbc specific error code
43                 unsigned int errorCode,
44                 /// odbc specific error message text
45                 const char* errorMsg
46                 );
47         
48         virtual ~GkodbcResult();
49         
50         /** @return
51             Backend specific error message, if the query failed.
52         */      
53         virtual PString GetErrorMessage();
54         
55         /** @return
56             Backend specific error code, if the query failed.
57         */      
58         virtual long GetErrorCode();
59         
60         /** @return
61             True if rows can be fetched in random access order, false if
62             rows have to be fethed sequentially and can be retrieved only once.
63         */
64         virtual bool HasRandomAccess();
65
66         /** Fetch a single row from the result set. After each row is fetched,
67             cursor position is moved to a next row.
68                 
69             @return
70             True if the row has been fetched, false if no more rows are available.
71         */
72         virtual bool FetchRow(
73                 /// array to be filled with string representations of the row fields
74                 PStringArray& result
75                 );
76         virtual bool FetchRow(
77                 /// array to be filled with string representations of the row fields
78                 ResultRow& result
79                 );
80
81         /** @return
82             True if the column at the index #fieldOffset# is NULL in the row 
83             fetched most recently.
84         */
85         virtual bool IsNullField(
86                 /// index of the column to check
87                 long fieldOffset
88                 );
89                         
90         /** Fetch a single row from the result set. This function requires
91                 that the backend supports random row access.
92                 
93             @return
94             True if the row has been fetched, false if a row at the given offset
95                 does not exists or SQL backend does not support random row access.
96         */
97         virtual bool FetchRow(
98                 /// array to be filled with string representations of the row fields
99                 PStringArray& result,
100                 /// index (0 based) of the row to fetch
101                 long rowOffset
102                 );
103         virtual bool FetchRow(
104                 /// array to be filled with string representations of the row fields
105                 ResultRow& result,
106                 /// index (0 based) of the row to fetch
107                 long rowOffset
108                 );
109                 
110         /** @return
111             True if the column at the index #fieldOffset# is NULL in the row 
112             at the specified index.
113         */
114         virtual bool IsNullField(
115                 /// index of the column to check
116                 long fieldOffset,
117                 /// index (0 based) of the row to check
118                 long rowOffset
119                 );
120
121 private:
122         GkodbcResult();
123         GkodbcResult(const GkodbcResult&);
124         GkodbcResult& operator=(const GkodbcResult&);
125         
126 protected:
127         /// query result for SELECT type queries, NULL otherwise
128         PGresult* m_sqlResult;
129         /// the most recent row returned by fetch operation
130         int m_sqlRow;
131         /// PgSQL specific error code (if the query failed)
132         unsigned int m_errorCode;
133         /// PgSQL specific error message text (if the query failed)
134         PString m_errorMessage;
135 };
136
137 /// odbc backend connection implementation.
138 class GkodbcConnection : public GkSQLConnection
139 {
140 public:
141         /// Build a new PgSQL connection object
142         GkodbcConnection(
143                 /// name to use in the log
144                 const char* name = "odbc"
145                 );
146         
147         virtual ~GkodbcConnection();
148
149 protected:
150         class odbcConnWrapper : public GkSQLConnection::SQLConnWrapper
151         {
152         public:
153                 odbcConnWrapper(
154                         /// unique identifier for this connection
155                         int id,
156                         /// host:port this connection is made to
157                         const PString& host,
158                         /// odbc connection object
159                         PODBC * conn
160                         ) : SQLConnWrapper(id, host), m_conn(conn) {}
161
162                 virtual ~odbcConnWrapper();
163
164         private:
165                 odbcConnWrapper();
166                 odbcConnWrapper(const odbcConnWrapper&);
167                 odbcConnWrapper& operator=(const odbcConnWrapper&);
168
169         public:
170                 PODBC* m_conn;
171         };
172
173         /** Create a new SQL connection using parameters stored in this object.
174             When the connection is to be closed, the object is simply deleted
175             using delete operator.
176             
177             @return
178             NULL if database connection could not be established 
179             or an object of odbcConnWrapper class.
180         */
181         virtual SQLConnPtr CreateNewConnection(
182                 /// unique identifier for this connection
183                 int id
184                 );
185         
186         /** Execute the query using specified SQL connection.
187
188                 @return
189                 Query execution result.
190         */
191         virtual GkSQLResult* ExecuteQuery(
192                 /// SQL connection to use for query execution
193                 SQLConnPtr conn,
194                 /// query string
195                 const char* queryStr,
196                 /// maximum time (ms) for the query execution, -1 means infinite
197                 long timeout = -1
198                 );
199                 
200         /** Escape any special characters in the string, so it can be used in a SQL query.
201
202                 @return
203                 Escaped string.
204         */
205         virtual PString EscapeString(
206                 /// SQL connection to get escaping parameters from
207                 SQLConnPtr conn,
208                 /// string to be escaped
209                 const char* str
210                 );
211
212 private:
213         GkodbcConnection(const GkodbcConnection&);
214         GkodbcConnection& operator=(const GkodbcConnection&);
215 };
216
217
218 GkodbcResult::GkodbcResult(
219         /// SELECT type query result
220         PGresult* selectResult
221         ) 
222         : GkSQLResult(false), m_sqlResult(selectResult), m_sqlRow(-1),
223         m_errorCode(0)
224 {
225         if (m_sqlResult) {
226                 m_numRows = PQntuples(m_sqlResult);
227                 m_numFields = PQnfields(m_sqlResult);
228         } else
229                 m_queryError = true;
230                 
231         m_selectType = true;
232 }
233
234 GkodbcResult::GkodbcResult(
235         /// number of rows affected by the query
236         long numRowsAffected
237         ) 
238         : GkSQLResult(false), m_sqlResult(NULL), m_sqlRow(-1), 
239         m_errorCode(0)
240 {
241         m_numRows = numRowsAffected;
242         m_selectType = false;
243 }
244         
245 GkodbcResult::GkodbcResult(
246         /// odbc specific error code
247         unsigned int errorCode,
248         /// odbc specific error message text
249         const char* errorMsg
250         ) 
251         : GkSQLResult(true), m_sqlResult(NULL), m_sqlRow(-1),
252         m_errorCode(errorCode), m_errorMessage(errorMsg)
253 {
254 }
255
256 GkodbcResult::~GkodbcResult()
257 {
258 }
259
260 bool GkodbcResult::HasRandomAccess()
261 {
262         return true;
263 }
264
265 PString GkodbcResult::GetErrorMessage()
266 {
267         return m_errorMessage;
268 }
269         
270 long GkodbcResult::GetErrorCode()
271 {
272         return m_errorCode;
273 }
274
275 bool GkodbcResult::FetchRow(
276         /// array to be filled with string representations of the row fields
277         PStringArray& result
278         )
279 {
280        return false;
281 }
282
283 bool GkodbcResult::FetchRow(
284         /// array to be filled with string representations of the row fields
285         ResultRow& result
286         )
287 {
288         return false;
289 }
290
291 bool GkodbcResult::IsNullField(
292         /// index of the column to check
293         long fieldOffset
294         )
295 {
296         return false;
297 }
298
299 bool GkodbcResult::FetchRow(
300         /// array to be filled with string representations of the row fields
301         PStringArray& result,
302         /// index (0 based) of the row to fetch
303         long rowOffset
304         )
305 {
306         return false;
307 }
308
309 bool GkodbcResult::FetchRow(
310         /// array to be filled with string representations of the row fields
311         ResultRow& result,
312         /// index (0 based) of the row to fetch
313         long rowOffset
314         )
315 {
316         return false;
317 }
318
319 bool GkodbcResult::IsNullField(
320         /// index of the column to check
321         long fieldOffset,
322         /// index (0 based) of the row to check
323         long rowOffset
324         )
325 {
326         return false;
327 }
328
329
330 GkodbcConnection::GkodbcConnection(
331         /// name to use in the log
332         const char* name
333         ) : GkSQLConnection(name)
334 {
335 }
336         
337 GkodbcConnection::~GkodbcConnection()
338 {
339 }
340
341 GkodbcConnection::odbcConnWrapper::~odbcConnWrapper()
342 {
343 }
344
345 GkSQLConnection::SQLConnPtr GkodbcConnection::CreateNewConnection(
346         /// unique identifier for this connection
347         int id
348         )
349 {
350         return NULL;
351 }
352         
353 GkSQLResult* GkodbcConnection::ExecuteQuery(
354         /// SQL connection to use for query execution
355         GkSQLConnection::SQLConnPtr conn,
356         /// query string
357         const char* queryStr,
358         /// maximum time (ms) for the query execution, -1 means infinite
359         long /*timeout*/
360         )
361 {
362
363         return new GkodbcResult(resultInfo, PQresultErrorMessage(result));
364         
365 }
366
367 PString GkodbcConnection::EscapeString(
368         /// SQL connection to get escaping parameters from
369         SQLConnPtr conn,
370         /// string to be escaped
371         const char* str
372         )
373 {
374         PString escapedStr;
375
376         return escapedStr;
377 }
378
379 namespace {
380         GkSQLCreator<GkodbcConnection> PgSQLCreator("odbc");
381 }
382
383 #endif /* HAS_PGSQL */