Source code: nl/aidministrator/rdf/ral/rdbms/SQLStatementIterator.java
1 /* Sesame - Storage and Querying architecture for RDF and RDF Schema
2 * Copyright (C) 2002 Aidministrator Nederland b.v.
3 *
4 * Contact:
5 * Aidministrator Nederland b.v.
6 * Julianaplein 14b
7 * 3817 CS Amersfoort
8 * The Netherlands
9 * tel. +31(0)33 4659987
10 * fax. +31(0)33 4659987
11 * sesame@aidministrator.nl
12 *
13 * http://www.aidministrator.nl/
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30 package nl.aidministrator.rdf.ral.rdbms;
31
32 import nl.aidministrator.rdf.ral.StatementIterator;
33 import nl.aidministrator.rdf.sail.model.*;
34 import java.util.NoSuchElementException;
35 import java.sql.*;
36
37 /**
38 * A StatementIterator that executes an SQL query. The ResultSet should
39 * contain 6 columns: namespace(String) and localname(String) of subject,
40 * namespace(String) and localname(String) of predicate and namespace(String),
41 * localname(String) if object is instance of rdfs:Resource or language(String)
42 * and value(String) if object is instance of rdfs:Literal.
43 * With getObject() a StatementIterator returns the object of the statement it
44 * is pointing at. An object can be of type rdfs:Resource or rdfs:Literal,
45 * therefore it should know whether to construct a Resource or a Literal out of
46 * the ResultSet. A way to establish this is to execute 2 queries, one where
47 * object of table triples is joined with id of table resources and one where it is joined
48 * with id of table literals. Boolean _literalsHasBeenQueried identifies which query is
49 * executed, so whether to construct a Resource or a Literal out of the
50 * ResultSet.
51 *
52 * @author Peter van 't Hof
53 * @version 1.4, 12/17/01
54 */
55 public class SQLStatementIterator implements StatementIterator {
56
57 /*----------+
58 | Variables |
59 +----------*/
60 /**
61 * ResultSet for the query. */
62 protected ResultSet _resultSet;
63
64 /**
65 * SQL statement that was used to generate the ResultSet. It cannot be closed
66 * until all results have been read from the ResultSet.
67 */
68 protected java.sql.Statement _statement;
69 /**
70 * Connection to the database. */
71 protected Connection _databaseCon;
72 /**
73 * The query to execute. */
74 protected String _queryResources;
75 /**
76 * The query to execute. */
77 protected String _queryLiterals;
78 /**
79 * Flag indicating whether there are any more results. */
80 protected boolean _hasNext;
81 /**
82 * Subject of statement iterator is currently pointing at. */
83 protected Resource _nextSubject;
84 /**
85 * Predicate of statement iterator is currently pointing at. */
86 protected Resource _nextPredicate;
87 /**
88 * Object of statement iterator is currently pointing at. */
89 protected Value _nextObject;
90 /**
91 * Is subject fixed. */
92 protected boolean _subjectFixed;
93 /**
94 * Is predicate fixed. */
95 protected boolean _predicateFixed;
96 /**
97 * Is object fixed. */
98 protected boolean _objectFixed;
99 /**
100 * Indicates which query is executed. */
101 protected boolean _literalsHasBeenQueried;
102
103 /*-------------+
104 | Constructors |
105 +-------------*/
106
107 /**
108 * Constructor.
109 *
110 * @param databaseCon connection to the repository
111 * @param queryResources query specified for the resources table
112 * @param queryLiterals query specified for the literals table
113 * @param subject subject of pattern
114 * @param predicate predicate of pattern
115 * @param object object of pattern
116 */
117 public SQLStatementIterator(Connection databaseCon, String queryResources, String queryLiterals, Resource subject, Resource predicate, Value object) {
118 _databaseCon = databaseCon;
119 _queryResources = queryResources;
120 _queryLiterals = queryLiterals;
121
122 _literalsHasBeenQueried = false;
123
124 if (subject == null) {
125 _subjectFixed = false;
126 }
127 else {
128 _subjectFixed = true;
129 _nextSubject = subject;
130 }
131 if (predicate == null) {
132 _predicateFixed = false;
133 }
134 else {
135 _predicateFixed = true;
136 _nextPredicate = predicate;
137 }
138 if (object == null) {
139 _objectFixed = false;
140 }
141 else {
142 _objectFixed = true;
143 _nextObject = object;
144 }
145 _execQuery(_queryResources);
146 _proceed();
147 }
148
149 /*--------+
150 | Methods |
151 +--------*/
152
153 private void _proceed() {
154 if (!hasNext()) { // No more results for this query.
155 if (!_literalsHasBeenQueried) { // Are both queries executed?
156 _literalsHasBeenQueried = true;
157 _execQuery(_queryLiterals);
158
159 _proceed();
160 }
161 else {
162 close();
163 }
164 }
165 }
166
167 private void _execQuery(String query) {
168 try {
169 _statement = _databaseCon.createStatement();
170 _resultSet = _statement.executeQuery(query);
171
172 _hasNext = _resultSet.next(); // Check if the new ResultSet contains any values.
173 }
174 catch (SQLException e) {
175 // FIXME: should throw a RalException
176
177 System.err.println("SQLException in _execQuery()..." + e.getMessage());
178 close();
179 }
180 }
181
182 public boolean hasNext() {
183 return _hasNext;
184 }
185
186 public void next() {
187 if (_hasNext) {
188 try {
189 if (!_subjectFixed) {
190 _nextSubject = new Resource(_resultSet.getString(1), _resultSet.getString(2));
191 }
192 if (!_predicateFixed) {
193 _nextPredicate = new Resource(_resultSet.getString(3), _resultSet.getString(4));
194 }
195 if (!_objectFixed) {
196 if (!_literalsHasBeenQueried) {
197 _nextObject = new Resource(_resultSet.getString(5), _resultSet.getString(6));
198 }
199 else {
200 _nextObject = new Literal(_resultSet.getString(6), _resultSet.getString(5));
201
202 }
203 }
204 _hasNext = _resultSet.next();
205 _proceed();
206 }
207 catch (SQLException e) {
208 // FIXME: should throw a RalException
209
210 System.err.println("SQLException in next()...");
211 close();
212 }
213 }
214 else {
215 throw new NoSuchElementException("No more statements...");
216 }
217 }
218
219 public Resource getSubject() {
220 return _nextSubject;
221 }
222
223 public Resource getPredicate() {
224 return _nextPredicate;
225 }
226
227 public Value getObject() {
228 return _nextObject;
229 }
230
231 public void close() {
232 try {
233 if (_resultSet != null) {
234 _resultSet.close();
235 }
236 if (_statement != null) {
237 _statement.close();
238 }
239 _databaseCon.close();
240 }
241 catch (SQLException e) {
242 // FIXME: should throw a RalException
243
244 System.err.println("SQLException in close()...");
245 }
246 _hasNext = false; // No more results are returned.
247 }
248
249 /**
250 * Called by the garbage collector on SQLValueIterator when garbage
251 * collection determines that there are no more references to the
252 * SQLValueIterator.
253 */
254 protected void finalize() {
255 close();
256 }
257 }