1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
package postgresql;
import java.sql.*;
/**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A Statement object is used for executing a static SQL statement and
* obtaining the results produced by it.
*
* Only one ResultSet per Statement can be open at any point in time.
* Therefore, if the reading of one ResultSet is interleaved with the
* reading of another, each must have been generated by different
* Statements. All statement execute methods implicitly close a
* statement's current ResultSet if an open one exists.
*
* @see java.sql.Statement
* @see ResultSet
*/
public class Statement implements java.sql.Statement
{
Connection connection; // The connection who created us
ResultSet result = null; // The current results
SQLWarning warnings = null; // The warnings chain.
int maxrows = 0; // maximum no. of rows; 0 = unlimited
int timeout = 0; // The timeout for a query (not used)
boolean escapeProcessing = true;// escape processing flag
/**
* Constructor for a Statement. It simply sets the connection
* that created us.
*
* @param c the Connection instantation that creates us
*/
public Statement (Connection c)
{
connection = c;
}
/**
* Execute a SQL statement that retruns a single ResultSet
*
* @param sql typically a static SQL SELECT statement
* @return a ResulSet that contains the data produced by the query
* @exception SQLException if a database access error occurs
*/
public java.sql.ResultSet executeQuery(String sql) throws SQLException
{
this.execute(sql);
while (result != null && !result.reallyResultSet())
result = result.getNext();
if (result == null)
throw new SQLException("no results returned");
return result;
}
/**
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition
* SQL statements that return nothing such as SQL DDL statements
* can be executed
*
* @param sql a SQL statement
* @return either a row count, or 0 for SQL commands
* @exception SQLException if a database access error occurs
*/
public int executeUpdate(String sql) throws SQLException
{
this.execute(sql);
if (result.reallyResultSet())
throw new SQLException("results returned");
return this.getUpdateCount();
}
/**
* In many cases, it is desirable to immediately release a
* Statement's database and JDBC resources instead of waiting
* for this to happen when it is automatically closed. The
* close method provides this immediate release.
*
* <B>Note:</B> A Statement is automatically closed when it is
* garbage collected. When a Statement is closed, its current
* ResultSet, if one exists, is also closed.
*
* @exception SQLException if a database access error occurs (why?)
*/
public void close() throws SQLException
{
result = null;
}
/**
* The maxFieldSize limit (in bytes) is the maximum amount of
* data returned for any column value; it only applies to
* BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
* columns. If the limit is exceeded, the excess data is silently
* discarded.
*
* @return the current max column size limit; zero means unlimited
* @exception SQLException if a database access error occurs
*/
public int getMaxFieldSize() throws SQLException
{
return 8192; // We cannot change this
}
/**
* Sets the maxFieldSize - NOT! - We throw an SQLException just
* to inform them to stop doing this.
*
* @param max the new max column size limit; zero means unlimited
* @exception SQLException if a database access error occurs
*/
public void setMaxFieldSize(int max) throws SQLException
{
throw new SQLException("Attempt to setMaxFieldSize failed - compile time default");
}
/**
* The maxRows limit is set to limit the number of rows that
* any ResultSet can contain. If the limit is exceeded, the
* excess rows are silently dropped.
*
* @return the current maximum row limit; zero means unlimited
* @exception SQLException if a database access error occurs
*/
public int getMaxRows() throws SQLException
{
return maxrows;
}
/**
* Set the maximum number of rows
*
* @param max the new max rows limit; zero means unlimited
* @exception SQLException if a database access error occurs
* @see getMaxRows
*/
public void setMaxRows(int max) throws SQLException
{
maxrows = max;
}
/**
* If escape scanning is on (the default), the driver will do escape
* substitution before sending the SQL to the database.
*
* @param enable true to enable; false to disable
* @exception SQLException if a database access error occurs
*/
public void setEscapeProcessing(boolean enable) throws SQLException
{
escapeProcessing = enable;
}
/**
* The queryTimeout limit is the number of seconds the driver
* will wait for a Statement to execute. If the limit is
* exceeded, a SQLException is thrown.
*
* @return the current query timeout limit in seconds; 0 = unlimited
* @exception SQLException if a database access error occurs
*/
public int getQueryTimeout() throws SQLException
{
return timeout;
}
/**
* Sets the queryTimeout limit
*
* @param seconds - the new query timeout limit in seconds
* @exception SQLException if a database access error occurs
*/
public void setQueryTimeout(int seconds) throws SQLException
{
timeout = seconds;
}
/**
* Cancel can be used by one thread to cancel a statement that
* is being executed by another thread. However, PostgreSQL is
* a sync. sort of thing, so this really has no meaning - we
* define it as a no-op (i.e. you can't cancel, but there is no
* error if you try.)
*
* @exception SQLException only because thats the spec.
*/
public void cancel() throws SQLException
{
// No-op
}
/**
* The first warning reported by calls on this Statement is
* returned. A Statement's execute methods clear its SQLWarning
* chain. Subsequent Statement warnings will be chained to this
* SQLWarning.
*
* The Warning chain is automatically cleared each time a statement
* is (re)executed.
*
* <B>Note:</B> If you are processing a ResultSet then any warnings
* associated with ResultSet reads will be chained on the ResultSet
* object.
*
* @return the first SQLWarning on null
* @exception SQLException if a database access error occurs
*/
public SQLWarning getWarnings() throws SQLException
{
return warnings;
}
/**
* After this call, getWarnings returns null until a new warning
* is reported for this Statement.
*
* @exception SQLException if a database access error occurs (why?)
*/
public void clearWarnings() throws SQLException
{
warnings = null;
}
/**
* setCursorName defines the SQL cursor name that will be used by
* subsequent execute methods. This name can then be used in SQL
* positioned update/delete statements to identify the current row
* in the ResultSet generated by this statement. If a database
* doesn't support positioned update/delete, this method is a
* no-op.
*
* <B>Note:</B> By definition, positioned update/delete execution
* must be done by a different Statement than the one which
* generated the ResultSet being used for positioning. Also, cursor
* names must be unique within a Connection.
*
* We throw an additional constriction. There can only be one
* cursor active at any one time.
*
* @param name the new cursor name
* @exception SQLException if a database access error occurs
*/
public void setCursorName(String name) throws SQLException
{
connection.setCursorName(name);
}
/**
* Execute a SQL statement that may return multiple results. We
* don't have to worry about this since we do not support multiple
* ResultSets. You can use getResultSet or getUpdateCount to
* retrieve the result.
*
* @param sql any SQL statement
* @return true if the next result is a ResulSet, false if it is
* an update count or there are no more results
* @exception SQLException if a database access error occurs
*/
public boolean execute(String sql) throws SQLException
{
result = connection.ExecSQL(sql);
return (result != null && result.reallyResultSet());
}
/**
* getResultSet returns the current result as a ResultSet. It
* should only be called once per result.
*
* @return the current result set; null if there are no more
* @exception SQLException if a database access error occurs (why?)
*/
public java.sql.ResultSet getResultSet() throws SQLException
{
return result;
}
/**
* getUpdateCount returns the current result as an update count,
* if the result is a ResultSet or there are no more results, -1
* is returned. It should only be called once per result.
*
* @return the current result as an update count.
* @exception SQLException if a database access error occurs
*/
public int getUpdateCount() throws SQLException
{
if (result == null) return -1;
if (result.reallyResultSet()) return -1;
return result.getResultCount();
}
/**
* getMoreResults moves to a Statement's next result. If it returns
* true, this result is a ResulSet.
*
* @return true if the next ResultSet is valid
* @exception SQLException if a database access error occurs
*/
public boolean getMoreResults() throws SQLException
{
result = result.getNext();
return (result != null && result.reallyResultSet());
}
}