KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > execute > SqlXmlExecutor


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.SqlXmlExecutor
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.execute;
23
24 import org.apache.derby.iapi.error.StandardException;
25 import org.apache.derby.iapi.reference.SQLState;
26 import org.apache.derby.iapi.sql.Activation;
27
28 import org.apache.derby.iapi.types.BooleanDataValue;
29 import org.apache.derby.iapi.types.StringDataValue;
30 import org.apache.derby.iapi.types.XML;
31 import org.apache.derby.iapi.types.XMLDataValue;
32 import org.apache.derby.iapi.types.SqlXmlUtil;
33
34 /**
35  * This class is really just an execution time "utility" that
36  * makes calls to methods on the XMLDataValue interface. Instances
37  * of this class are generated at execution time by the various
38  * Derby XML operators--one instance for each row in the target
39  * result set--and then the appropriate operator call is made on
40  * that instance (see, for example, the generateExpression() methods
41  * in UnaryOperatorNode and BinaryOperatorNode). When an instance
42  * of this class is instantiated, one of the arguments that can be
43  * provided is an id that is used to retrieve an already-constructed
44  * (from compilation time) instance of SqlXmlUtil from the current
45  * Activation. When it comes time to execute the operator, this class
46  * just makes the appropriate call on the received XMLDataValue object
47  * and passes in the SqlXmlUtil, from which the XMLDataValue can
48  * retrieve compile-time objects. The XMLDataValue can also make
49  * calls to various XML-specific utilities on the SqlXmlUtil
50  * object.
51  *
52  * Let's take an example. Assume the statement that the user
53  * wants to execute is:
54  *
55  * select id from xtable
56  * where XMLEXISTS('/simple' PASSING BY REF xcol)
57  *
58  * At compilation time we will compile the expression "/simple"
59  * and store the compiled version of the query into an instance
60  * of SqlXmlUtil. Then we will save that instance of SqlXmlUtil
61  * as an object in the statement activation, from which we will
62  * receive an id that can be used later to retrieve the object
63  * (i.e. to retrieve the SqlXmlUtil). Then, for *each* row
64  * in xtable, we'll generate the following:
65  *
66  * boolean result =
67  * (new SqlXmlExecutor(activation, compileTimeObjectId)).
68  * XMLExists("/simple", xcol);
69  *
70  * In other words, for each row we create a new instance of
71  * this class and call "XMLExists" on that instance. Then,
72  * as seen below, we retrieve the SqlXmlUtil from the activation
73  * and pass that into a call to "XMLExists" on the XML value
74  * itself (i.e. xcol). XMLDataValue.XMLExists() then uses the
75  * methods and objects (which include the compiled query
76  * expression for "/simple") defined on SqlXmlUtil to complete
77  * the operation.
78  *
79  * Okay, so why do we use this execution-time SqlXmlExecutor class
80  * instead of just generating a call to XMLDataValue.XMLExists()
81  * directly? The reason is that we only want to compile the XML
82  * query expression once per statement--and where possible we'd
83  * also like to only generate re-usable XML-specific objects
84  * once per statement, as well. If instead we generated a call to
85  * XMLDataValue.XMLExists() directly for each row, then we would
86  * have to either pass in the expression string and have XMLDataValue
87  * compile it, or we would have to compile the expression string
88  * and then pass the compiled object into XMLDataValue--in either
89  * case, we'd end up compiling the XML query expression (and creating
90  * the corresponding XML-specific objects) once for each row in
91  * the target result set. By using the "saveObject" functionality
92  * in Activation along with this SqlXmlExecutor class, we make
93  * it so that we only have to compile the XML query expression and
94  * create XML-specific objects once (at compile time), and then
95  * we can re-use those objects for every row in the target
96  * result set. Yes, we're still creating an instance of this
97  * class (SqlXmlExecutor) once per row, and yes we have to fetch
98  * the appropriate SqlXmlUtil object once per row, but this is
99  * still going to be cheaper than having to re-compile the query
100  * expression and re-create XML objects for every row.
101  *
102  * So in short, this class allows us to improve the execution-time
103  * performance of XML operators by allowing us to create XML-
104  * specific objects and compile XML query expressions once per
105  * statement, instead of once per row.
106  *
107  * One final note: the reason this class is in this package
108  * instead of the types package is that, in order to retrieve
109  * the compile-time objects, we have to use the "getSavedObject()"
110  * method on the Activation. But the Activation class is part
111  * of the SQL layer (org.apache.derby.iapi.sql.Activation) and
112  * we want to keep the types layer independent of the SQL layer
113  * because the types can be used during recovery before the SQL
114  * system has booted. So the next logical choices were the compile
115  * package (impl.sql.compile) or the execution package; of those,
116  * the execution package seems more appropriate since this
117  * class is only instantiated and used during execution, not
118  * during compilation.
119  */

120
121 public class SqlXmlExecutor {
122
123     // The activation from which we load the compile-time XML
124
// objects (including the compiled XML query expression in
125
// case of XMLEXISTS and XMLQUERY).
126
private Activation activation;
127     private int sqlXUtilId;
128
129     // Target type and target width that were specified
130
// for an XMLSERIALIZE operator.
131
private int targetTypeId;
132     private int targetMaxWidth;
133
134     // Whether or not to preserve whitespace for XMLPARSE
135
// operator.
136
private boolean preserveWS;
137
138     /**
139      * Constructor 1: Used for XMLPARSE op.
140      * @param activation Activation from which to retrieve saved objects
141      * @param utilId Id by which we find saved objects in activation
142      * @param preserveWS Whether or not to preserve whitespace
143      */

144     public SqlXmlExecutor(Activation activation, int utilId,
145         boolean preserveWS)
146     {
147         this.activation = activation;
148         this.sqlXUtilId = utilId;
149         this.preserveWS = preserveWS;
150     }
151
152     /**
153      * Constructor 2: Used for XMLSERIALIZE op.
154      * @param targetTypeId The string type to which we want to serialize.
155      * @param targetMaxWidth The max width of the target type.
156      */

157     public SqlXmlExecutor(int targetTypeId, int targetMaxWidth)
158     {
159         this.targetTypeId = targetTypeId;
160         this.targetMaxWidth = targetMaxWidth;
161     }
162
163     /**
164      * Constructor 3: Used for XMLEXISTS/XMLQUERY ops.
165      * @param activation Activation from which to retrieve saved objects
166      * @param utilId Id by which we find saved objects in activation
167      */

168     public SqlXmlExecutor(Activation activation, int utilId)
169     {
170         this.activation = activation;
171         this.sqlXUtilId = utilId;
172     }
173
174     /**
175      * Make the call to perform an XMLPARSE operation on the
176      * received XML string and store the result in the received
177      * XMLDataValue (or if it's null, create a new one).
178      *
179      * @param xmlText String to parse
180      * @param result XMLDataValue in which to store the result
181      * @return The received XMLDataValue with its content set to
182      * correspond to the received xmlText, if the text constitutes
183      * a valid XML document. If the received XMLDataValue is
184      * null, then create a new one and set its content to
185      * correspond to the received xmlText.
186      */

187     public XMLDataValue XMLParse(StringDataValue xmlText, XMLDataValue result)
188         throws StandardException
189     {
190         if (result == null)
191             result = new XML();
192
193         if (xmlText.isNull())
194         {
195             result.setToNull();
196             return result;
197         }
198
199         return result.XMLParse(
200             xmlText.getString(), preserveWS, getSqlXmlUtil());
201     }
202
203     /**
204      * Make the call to perform an XMLSERIALIZE operation on the
205      * received XML data value and store the result in the received
206      * StringDataValue (or if it's null, create a new one).
207      *
208      * @param xmlVal XML value to serialize
209      * @param result StringDataValue in which to store the result
210      * @return A serialized (to string) version of this XML object,
211      * in the form of a StringDataValue object.
212      */

213     public StringDataValue XMLSerialize(XMLDataValue xmlVal,
214         StringDataValue result) throws StandardException
215     {
216         return xmlVal.XMLSerialize(result, targetTypeId, targetMaxWidth);
217     }
218
219     /**
220      * Make the call to perform an XMLEXISTS operation on the
221      * received XML data value.
222      *
223      * @param xExpr Query expression to be evaluated
224      * @param xmlContext Context node against which to evaluate
225      * the expression.
226      * @return True if evaluation of the query expression
227      * against xmlContext returns at least one item; unknown if
228      * either the xml value is NULL; false otherwise.
229      */

230     public BooleanDataValue XMLExists(StringDataValue xExpr,
231         XMLDataValue xmlContext) throws StandardException
232     {
233         return xmlContext.XMLExists(getSqlXmlUtil());
234     }
235
236     /**
237      * Make the call to perform an XMLQUERY operation on the
238      * received XML data value and store the result in the
239      * received result holder (or, if it's null, create a
240      * new one).
241      *
242      * @param xExpr Query expression to be evaluated
243      * @param xmlContext Context node against which to evaluate
244      * the expression.
245      * @param result XMLDataValue in which to store the result
246      * @return The received XMLDataValue with its content set to
247      * result of evaulating the query expression against xmlContext.
248      * If the received XMLDataValue is null, then create a new one
249      * and set its content to correspond to the received xmlText.
250      */

251     public XMLDataValue XMLQuery(StringDataValue xExpr,
252         XMLDataValue xmlContext, XMLDataValue result)
253         throws StandardException
254     {
255         return xmlContext.XMLQuery(result, getSqlXmlUtil());
256     }
257
258     /**
259      * Return the saved object in this.activation that corresponds to
260      * this.sqlxUtilId. Assumption is that those fields have been
261      * set by the time we get here.
262      */

263     private SqlXmlUtil getSqlXmlUtil()
264         throws StandardException
265     {
266         return (SqlXmlUtil)
267             activation.getPreparedStatement().getSavedObject(sqlXUtilId);
268     }
269
270 }
271
Popular Tags