|
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #ifndef __SQLSRVSTATEMENT_H__ |
|
17 #define __SQLSRVSTATEMENT_H__ |
|
18 |
|
19 #include <e32base.h> |
|
20 #include <s32mem.h> //TBufBuf |
|
21 #include "SqlUtil.h" //Sql2OsErrCode() |
|
22 #include "SqlBufFlat.h" //RSqlBufFlat |
|
23 #include "SqlSrvStatementUtil.h" //Global SQL statement related functions |
|
24 |
|
25 //Forward declarations |
|
26 struct sqlite3; |
|
27 struct sqlite3_stmt; |
|
28 class RWriteStream; |
|
29 class CSqlSrvStatement; |
|
30 |
|
31 ///////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
32 ////////////////////// HSqlSrvStmtParamBuf ////////////////////////////////// |
|
33 ///////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
34 |
|
35 /** |
|
36 Buffer for storing binary/text parameter values (an input from client side write stream objects or bound text/binary parameters). |
|
37 Every CSqlSrvStatement object maintains a collection of HSqlSrvStmtParamBuf objects. |
|
38 |
|
39 Please, note that: |
|
40 |
|
41 - The life-time of the HSqlSrvStmtParamBuf objects is controlled by a set of flags: |
|
42 = iStatementFinalized - False by default, set to true if the bound statement has been finalized. |
|
43 When DoRelease() is called, the method checks this poreperty and if the statement has been finalized, |
|
44 then obviously no more parameter binding operations can be performed and it is safe to destroy the |
|
45 current HSqlSrvStmtParamBuf object. Otherwise the HSqlSrvStmtParamBuf object won't be destroyed, |
|
46 it will be marked as "dead" - see the "iAlive" property; |
|
47 = iAlive - True by default, set to false by the DoRelease() call, if the object cannot be destroyed because |
|
48 the bound statement is not finalized yet; |
|
49 = iBufType - EBufIpcStream if the current HSqlSrvStmtParamBuf object is an IPC stream buffer, EBufSimpleBind |
|
50 if the object holds a parameter value, that has been bound not using an IPC stream. This property |
|
51 is checked when the bound statement gets finalized - inside the NotifyStatementFinalized() function. |
|
52 If the current object is not an IPC stream buffer, then it is safe to destroy the object because |
|
53 the bound statement is finalized; |
|
54 |
|
55 All these checks allow keeping the buffer object alive when it is needed and code like the code bellow should work without problems: |
|
56 @code |
|
57 RSqlStatement stmt; //Prepare a statement with a binary/text parameter |
|
58 .... |
|
59 RSqlParamWriteStream strm; |
|
60 strm.BindBinary(stmt,...); //Use a stream object to bind the parameter value |
|
61 strm.WriteL(...); |
|
62 strm.CommitL(); //The stream commit call will bind the streamed parameter value to the statement |
|
63 strm.Close(); //The stream close operation should not destroy the HSqlSrvStmtParamBuf object, because the parameter |
|
64 //value is kept in the buffer, and when that value was bound to the statement, the |
|
65 //SQLITE_STATIC constant was used, which means - SQLite won't make a copy of the parameter value, |
|
66 //SQLite will keep a pointer to the parameter value and use it for the Exec() operation. |
|
67 stmt.Exec(); //At this point the SQLite library should be able to get the parameter data and use it. |
|
68 @endcode |
|
69 |
|
70 - Another reason for keeping the HSqlSrvStmtParamBuf object alive during the life-time of the CSqlSrvStatement object is that |
|
71 the RSqlStatement::Reset() call should not destroy the buffer. The client should be able to resuse |
|
72 the buffered parameter data for the next RSqlStatement::Exec() call. For example: |
|
73 @code |
|
74 RSqlStatement stmt; //Prepare a statement with two binary parameters |
|
75 .... |
|
76 RSqlParamWriteStream strm1, strm2; |
|
77 |
|
78 strm1.BindBinary(stmt,...); //Use a stream object to bind the 1st parameter value |
|
79 strm1.WriteL(...); |
|
80 strm1.CommitL(); |
|
81 strm1.Close(); |
|
82 |
|
83 strm2.BindBinary(stmt,...); //Use a stream object to bind the 2nd parameter value |
|
84 strm2.WriteL(...); |
|
85 strm2.CommitL(); |
|
86 strm2.Close(); |
|
87 |
|
88 stmt.Exec(); //Do the operation using the bound parameter values |
|
89 stmt.Reset(); //This call should not destroy the HSqlSrvStmtParamBuf objects that keep the parameter values |
|
90 |
|
91 strm2.BindBinary(stmt,...); //Use a stream object to bind the 2nd parameter value |
|
92 strm2.WriteL(...); |
|
93 strm2.CommitL(); |
|
94 strm2.Close(); |
|
95 |
|
96 stmt.Exec(); //Do the operation using the bound parameter values. |
|
97 //The operation should be able to use the old 1st parameter value without any problems, |
|
98 //and also the new 2nd parameter value. |
|
99 @endcode |
|
100 |
|
101 - The HSqlSrvStmtParamBuf object can be synch-ed just once. The reason for that is to prevent the double commit-s, |
|
102 that will occur as a result of MStreamBuf::Close() calls on the client side, where the Close() method will try to sync the buffer. |
|
103 The single sync will prevent the SQL server from crashing, if the order of the RSqlStatement::Close() and |
|
104 RSqlParamWriteStream::Close() calls is reversed, e.g.: |
|
105 @code |
|
106 RSqlStatement stmt; |
|
107 .... |
|
108 RSqlParamWriteStream strm; |
|
109 strm.BindBinary(stmt,...); |
|
110 strm.WriteL(...); |
|
111 strm.CommitL(); |
|
112 stmt.Exec(); |
|
113 stmt.Close(); |
|
114 strm.Close(); |
|
115 @endcode |
|
116 |
|
117 - For BC reasons, even though the HSqlSrvStmtParamBuf object can be synch-ed just once (the operation is controlled by the iSynchDone |
|
118 flag), the client side still will be able to update the buffer content, because the related HIpcStream stream object keeps a copy |
|
119 of the buffer's base address. Since the parameter is bound using the SQLITE_STATIC constant (SQLite won't make a copy of the |
|
120 parameter value), at the moment of the Exec() call, SQLite will use the give pointer to the parameter value and will pick up |
|
121 the updated buffer even without a commit call; |
|
122 |
|
123 @endcode |
|
124 |
|
125 - The iSynchDone flag controls the number of buffer commit operations. It is false by default, |
|
126 set to true by the DoSynchL() call. The HSqlSrvStmtParamBuf object can be synch-ed just once, because DoSynchL() |
|
127 calls sqlite3_bind_text/binary() and the expectation is that the whole buffer with the parameter data is ready for binding; |
|
128 If the buffer is not commited by calling DoSynchL(), the buffer still will be commited by the DoSynchL() call performed from |
|
129 MStreamBuf::Close(). But in a case of a sync failure, no error will be reported to the client side; |
|
130 |
|
131 @see HIpcStream |
|
132 @see CSqlSrvStatement |
|
133 |
|
134 @internalComponent |
|
135 */ |
|
136 NONSHARABLE_CLASS(HSqlSrvStmtParamBuf) : public TBufBuf |
|
137 { |
|
138 public: |
|
139 enum TDataType {EBinary, EText16}; |
|
140 enum TBufType {EBufSimpleBind, EBufIpcStream}; |
|
141 |
|
142 static inline HSqlSrvStmtParamBuf* NewL(CSqlSrvStatement& aStatement, TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType, |
|
143 HSqlSrvStmtParamBuf::TBufType aBufType); |
|
144 inline void Reset(HSqlSrvStmtParamBuf::TDataType aDataType, HSqlSrvStmtParamBuf::TBufType aBufType); |
|
145 |
|
146 inline const TPtrC8 SetDataL(const TDesC8& aData); |
|
147 inline const TPtrC8 Data() const; |
|
148 inline HSqlSrvStmtParamBuf::TDataType DataType() const; |
|
149 |
|
150 void NotifyStatementFinalized(); |
|
151 inline TInt ParamIndex() const; |
|
152 |
|
153 private: |
|
154 inline HSqlSrvStmtParamBuf(CSqlSrvStatement& aStatement, TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType, |
|
155 HSqlSrvStmtParamBuf::TBufType aBufType); |
|
156 virtual ~HSqlSrvStmtParamBuf(); |
|
157 inline void ConstructL(); |
|
158 virtual void DoSynchL(); |
|
159 virtual void DoRelease(); |
|
160 |
|
161 private: |
|
162 enum {EExpandSize = 512}; |
|
163 |
|
164 CSqlSrvStatement& iStatement; //The bound CSqlSrvStatement object |
|
165 CBufFlat* iBuf; //Parameter buffer - not owned by HSqlSrvStmtParamBuf |
|
166 TInt iParamIndex; //The parameter index |
|
167 TBool iStatementFinalized;//True if the bound statement object has been finalized |
|
168 TBool iAlive; //True if DoRelease() has not been called yet |
|
169 HSqlSrvStmtParamBuf::TDataType iDataType;//The parameter type |
|
170 HSqlSrvStmtParamBuf::TBufType iBufType; //IPC stream buf or a simple "bind param" buf |
|
171 TBool iSynchDone; //True if the buffer data has been bound to the statement |
|
172 }; |
|
173 |
|
174 ///////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
175 ////////////////// CSqlSrvStatement ////////////////////////////////// |
|
176 ///////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
177 |
|
178 /** |
|
179 SQL statement handle. |
|
180 |
|
181 CSqlSrvStatement is a server side class which processes the client side requests for: |
|
182 - preparing 16-bit and 8-bit SQL statements; |
|
183 - executing prepared SQL statement; |
|
184 - retrieving parameter names and column names; |
|
185 - binding SQL parameters; |
|
186 - retrieving column values; |
|
187 - reseting the prepared SQL statement; |
|
188 - moving the cursor to the next record; |
|
189 |
|
190 @see CSqlSrvStatement::NewLC() |
|
191 @see CSqlSrvStatement::NewLC() |
|
192 @see CSqlSrvStatement::BindL() |
|
193 @see CSqlSrvStatement::Next() |
|
194 @see CSqlSrvStatement::Reset() |
|
195 @see CSqlSrvStatement::Exec() |
|
196 @see CSqlSrvStatement::ColumnNamesL() |
|
197 @see CSqlSrvStatement::ParamNamesL() |
|
198 @see CSqlSrvStatement::ColumnValuesL() |
|
199 @see CSqlSrvStatement::ColumnSource() |
|
200 |
|
201 @see HSqlSrvStmtParamBuf |
|
202 |
|
203 @internalComponent |
|
204 */ |
|
205 NONSHARABLE_CLASS(CSqlSrvStatement) : public CBase |
|
206 { |
|
207 public: |
|
208 static CSqlSrvStatement* NewLC(sqlite3* aDbHandle, const TDesC16& aSqlStmt, TInt& aColumnCount, TInt& aParamCount); |
|
209 static CSqlSrvStatement* NewLC(sqlite3* aDbHandle, const TDesC8& aSqlStmt, TInt& aColumnCount, TInt& aParamCount); |
|
210 virtual ~CSqlSrvStatement(); |
|
211 |
|
212 void BindL(const RSqlBufFlat& aParamBuf); |
|
213 inline TInt Next(); |
|
214 inline TInt Reset(); |
|
215 inline TInt Exec(); |
|
216 |
|
217 inline const RSqlBufFlat& BufFlatL(TSqlBufFlatType aWhat) const; |
|
218 const RSqlBufFlat& ColumnNamesL(); |
|
219 const RSqlBufFlat& ParamNamesL(); |
|
220 const RSqlBufFlat& ColumnValuesL(); |
|
221 TInt ColumnSource(TInt aColumnIndex, TPtrC8& aColumnSource) const; |
|
222 |
|
223 TInt ColumnInt(TInt aColIdx) const; |
|
224 TInt64 ColumnInt64(TInt aColIdx) const; |
|
225 TReal ColumnReal(TInt aColIdx) const; |
|
226 TPtrC ColumnText(TInt aColIdx) const; |
|
227 TPtrC8 ColumnBinary(TInt aColIdx) const; |
|
228 |
|
229 HBufC* GetDeclColumnTypesL(); |
|
230 |
|
231 HSqlSrvStmtParamBuf* GetParamBufL(TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType, HSqlSrvStmtParamBuf::TBufType aBufType); |
|
232 void BindParamBufL(TInt aParamIndex); |
|
233 |
|
234 private: |
|
235 inline CSqlSrvStatement(); |
|
236 inline void ConstructL(sqlite3* aDbHandle, const TDesC16& aSqlStmt); |
|
237 inline void ConstructL(sqlite3* aDbHandle, const TDesC8& aSqlStmt); |
|
238 void DoCommonConstructL(); |
|
239 void DestroyParamBufArray(); |
|
240 void ExtendParamBufArrayL(TInt aParamIndex); |
|
241 TPtrC8 CopyAndStoreParamL(TInt aParamIndex, HSqlSrvStmtParamBuf::TDataType aDataType, const TDesC8& aParamValue); |
|
242 |
|
243 private: |
|
244 sqlite3_stmt* iStmtHandle; //SQL statement handle |
|
245 TInt iColumnCount; |
|
246 TInt iParamCount; |
|
247 TSqlBufFlatType iBufFlatType; //What is in iFlatBuf data member |
|
248 RSqlBufFlat iBufFlat; //Flat buffer used for: column names, parameter names, column values |
|
249 RArray<HSqlSrvStmtParamBuf*> iParamBufArray;//An array with pointers to HSqlSrvStmtParamBuf buffers for the text/binary parameters |
|
250 |
|
251 }; |
|
252 |
|
253 #include "SqlSrvStatement.inl" |
|
254 |
|
255 #endif//__SQLSRVSTATEMENT_H__ |