/[eiffelstudio]/trunk/Src/framework/sqlite3/sqlite_statement_iteration_cursor.e
ViewVC logotype

Contents of /trunk/Src/framework/sqlite3/sqlite_statement_iteration_cursor.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 85923 - (show annotations)
Fri Mar 18 15:53:01 2011 UTC (8 years, 8 months ago) by jfiat
File size: 8277 byte(s)
Fixed void-safety issue with sqlite3 library
1 note
2 description: "[
3 Cursor to iterate over SQLITE_STATEMENT execution result
4 ]"
5 legal: "See notice at end of class."
6 status: "See notice at end of class."
7 date: "$Date$"
8 revision: "$Revision$"
9
10 class
11 SQLITE_STATEMENT_ITERATION_CURSOR
12
13 inherit
14 ITERATION_CURSOR [SQLITE_RESULT_ROW]
15 rename
16 make as iteration_make,
17 cursor_index as index
18 redefine
19 start, forth, after
20 end
21
22 SQLITE_SHARED_API
23 export
24 {NONE} all
25 end
26
27 SQLITE_INTERNALS
28 export
29 {NONE} all
30 end
31
32 SQLITE_DATABASE_EXTERNALS
33 export
34 {NONE} all
35 end
36
37 SQLITE_STATEMENT_EXTERNALS
38 export
39 {NONE} all
40 end
41
42 SQLITE_BIND_ARG_MARSHALLER
43 export
44 {NONE} all
45 end
46
47 create
48 make,
49 make_with_bindings
50
51 feature {NONE} -- Initalization
52
53 make (a_statement: SQLITE_STATEMENT)
54 -- Initialize the cursor for `a_statement'.
55 require
56 a_statement_attached: attached a_statement
57 a_statement_is_accessible: a_statement.is_accessible
58 a_statement_is_connected: a_statement.is_connected
59 do
60 statement := a_statement
61 --| Create a dummy attached `target' to satisfy void-safety
62 --| This dummy value will be overwritten by `iteration_make'
63 target := dummy_target
64 iteration_make (Current)
65 last_result := {SQLITE_RESULT_CODE}.ok
66 ensure
67 statement_statement: statement = a_statement
68 last_result_is_ok: last_result = {SQLITE_RESULT_CODE}.ok
69 end
70
71 make_with_bindings (a_statement: SQLITE_STATEMENT; a_bindings: ARRAY [SQLITE_BIND_ARG [ANY]])
72 -- Initialize the cursor for `a_statement' using `a_binding'.
73 require
74 a_statement_attached: attached a_statement
75 a_statement_is_accessible: a_statement.is_accessible
76 a_statement_is_connected: a_statement.is_connected
77 a_bindings_attached: attached a_bindings
78 not_a_bindings_is_empty: not a_bindings.is_empty
79 do
80 make (a_statement)
81 bindings := a_bindings
82 ensure
83 statement_statement: statement = a_statement
84 bindings_set: bindings = a_bindings
85 last_result_is_ok: last_result = {SQLITE_RESULT_CODE}.ok
86 end
87
88 feature -- Access
89
90 statement: SQLITE_STATEMENT
91 -- SQLite statement being iterated over.
92
93 bindings: detachable ARRAY [SQLITE_BIND_ARG [ANY]]
94 -- Binding arguments to execute the statement with.
95
96 item: SQLITE_RESULT_ROW
97 -- <Precursor>
98 local
99 l_result: like internal_item
100 do
101 l_result := internal_item
102 check l_result_attached: attached l_result end
103 Result := l_result
104 end
105
106 feature {NONE} -- Access
107
108 last_result: INTEGER
109 -- Last result code set by `start'/`forth'.
110
111 feature -- Status report
112
113 after: BOOLEAN
114 -- <Precursor>
115 do
116 Result := not sqlite_success (last_result) or else last_result = {SQLITE_RESULT_CODE}.done
117 --has_started and then not attached internal_item
118 end
119
120 feature {NONE} -- Status report
121
122 has_started: BOOLEAN
123 -- Indicates if the cursor has been started yet.
124
125 feature -- Cursor movement
126
127 start
128 -- <Precursor>
129 local
130 l_api: like sqlite_api
131 l_stmt: POINTER
132 l_result: INTEGER
133 i_upper, i: INTEGER
134 l_arg_variable: IMMUTABLE_STRING_8
135 l_arg_id: C_STRING
136 l_arg_index: INTEGER
137 do
138 Precursor
139 -- Reset the iternal item
140 internal_item := Void
141
142 l_api := sqlite_api
143 l_stmt := statement.internal_stmt
144
145 -- Reset statement, for reuse.
146 l_result := sqlite3_reset (l_api, l_stmt)
147 check success: sqlite_success (l_result) end
148
149 -- Perform bindings
150 if attached bindings as l_bindings then
151 -- `sqlite3_reset' does not reset the bindings! We have to do it as a second stage.
152 -- In a future release, when we might allow bindings to be set arbitrarily we might
153 -- not want to reset them. There is a performance gain for clients, because there is
154 -- not object marshalling required for arguments that do not change. Currently we have
155 -- to pass all arguments again when executing, and they are rebound (involving copy
156 -- operations etc.)
157 l_result := sqlite3_clear_bindings (l_api, l_stmt)
158 check success: sqlite_success (l_result) end
159
160 from
161 i := l_bindings.lower
162 i_upper := l_bindings.upper
163 until
164 i > i_upper
165 loop
166 if attached l_bindings[i] as l_arg then
167 l_arg_variable := l_arg.variable
168 create l_arg_id.make (l_arg_variable)
169 l_arg_index := sqlite3_bind_parameter_index (l_api, l_stmt, l_arg_id.item)
170 if l_arg_index = 0 and then l_arg_variable[1] = '?' then
171 l_arg_variable := l_arg_variable.substring (2, l_arg_variable.count)
172 if l_arg_variable.is_integer_32 then
173 l_arg_index := l_arg_variable.to_integer_32
174 else
175 -- Contracts in SQLITE_BIND_ARG should make this impossible.
176 check should_never_happen: False end
177 end
178 end
179
180 if l_arg_index > 0 then
181 l_arg.bind_to_statement (statement, l_arg_index)
182 else
183 -- Silently ignore unknown variables.
184 end
185 end
186 i := i + 1
187 end
188 end
189
190 last_result := l_result
191
192 -- Reset index, because `forth' will increase it.
193 index := 0
194
195 -- Raise an exception, if there was an exception case.
196 sqlite_raise_on_failure (l_result)
197
198 if not after then
199 -- Notify the statement that execution has begun.
200 statement.on_before_execute
201
202 -- Go to first element.
203 forth
204 else
205 index := 1
206 end
207 end
208
209 forth
210 -- <Precursor>
211 local
212 l_api: like sqlite_api
213 l_stmt: POINTER
214 l_db: detachable SQLITE_DATABASE
215 l_exception: detachable SQLITE_EXCEPTION
216 l_result: INTEGER
217 l_done: BOOLEAN
218 l_locked: BOOLEAN
219 do
220 Precursor
221
222 l_api := sqlite_api
223 l_stmt := statement.internal_stmt
224 l_db := statement.database
225
226 -- Note the locking sequencing, to ensure access to the error messages
227 -- are not affected by other threads.
228 l_db.lock -- (+1) 1
229 l_locked := True
230
231 l_result := sqlite3_step (l_api, l_stmt)
232 l_done := l_result = {SQLITE_RESULT_CODE}.done
233 if sqlite_success (l_result) then
234 create internal_item.make (statement)
235 else
236 internal_item := Void
237 l_exception := l_db.last_exception
238 end
239
240 -- Unlock before any callback because it may need access to the DB using another thread.
241 l_locked := False
242 l_db.unlock -- (-1) 0
243
244 -- Set last result
245 last_result := l_result
246
247 if after then
248 -- Notify the statement that execution has completed.
249 statement.on_after_executed
250 end
251
252 -- Raise an exception, if there was an exception case.
253 if attached l_exception then
254 l_exception.raise
255 else
256 sqlite_raise_on_failure (l_result)
257 end
258 rescue
259 if l_locked and attached l_db then
260 l_locked := False
261 l_db.unlock
262 end
263 end
264
265 feature {NONE} -- Implementation: Internal cache
266
267 internal_item: detachable like item
268 -- Cached version of `item'.
269 -- Note: Do not use directly!
270
271 feature {NONE} -- Implementation: void-safety helper
272
273 dummy_target: ITERABLE [SQLITE_RESULT_ROW]
274 -- Dummy object used to initialize `target' with attached value
275 once
276 create {SPECIAL [SQLITE_RESULT_ROW]} Result .make_empty (0)
277 end
278
279 ;note
280 copyright: "Copyright (c) 1984-2011, Eiffel Software"
281 license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
282 licensing_options: "http://www.eiffel.com/licensing"
283 copying: "[
284 This file is part of Eiffel Software's Eiffel Development Environment.
285
286 Eiffel Software's Eiffel Development Environment is free
287 software; you can redistribute it and/or modify it under
288 the terms of the GNU General Public License as published
289 by the Free Software Foundation, version 2 of the License
290 (available at the URL listed under "license" above).
291
292 Eiffel Software's Eiffel Development Environment is
293 distributed in the hope that it will be useful, but
294 WITHOUT ANY WARRANTY; without even the implied warranty
295 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
296 See the GNU General Public License for more details.
297
298 You should have received a copy of the GNU General Public
299 License along with Eiffel Software's Eiffel Development
300 Environment; if not, write to the Free Software Foundation,
301 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
302 ]"
303 source: "[
304 Eiffel Software
305 5949 Hollister Ave., Goleta, CA 93117 USA
306 Telephone 805-685-1006, Fax 805-685-6869
307 Website http://www.eiffel.com
308 Customer support http://support.eiffel.com
309 ]"
310
311 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date ID Revision

  ViewVC Help
Powered by ViewVC 1.1.23