1. /**
  2. * @(#) SQLDocument.java
  3. *
  4. * The Apache Software License, Version 1.1
  5. *
  6. *
  7. * Copyright (c) 1999 The Apache Software Foundation. All rights
  8. * reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * 3. The end-user documentation included with the redistribution,
  23. * if any, must include the following acknowledgment:
  24. * "This product includes software developed by the
  25. * Apache Software Foundation (http://www.apache.org/)."
  26. * Alternately, this acknowledgment may appear in the software itself,
  27. * if and wherever such third-party acknowledgments normally appear.
  28. *
  29. * 4. The names "Xalan" and "Apache Software Foundation" must
  30. * not be used to endorse or promote products derived from this
  31. * software without prior written permission. For written
  32. * permission, please contact apache@apache.org.
  33. *
  34. * 5. Products derived from this software may not be called "Apache",
  35. * nor may "Apache" appear in their name, without prior written
  36. * permission of the Apache Software Foundation.
  37. *
  38. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  39. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  40. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  41. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  42. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  44. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  45. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  46. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  47. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  48. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  49. * SUCH DAMAGE.
  50. * ====================================================================
  51. *
  52. * This software consists of voluntary contributions made by many
  53. * individuals on behalf of the Apache Software Foundation and was
  54. * originally based on software copyright (c) 1999, Lotus
  55. * Development Corporation., http://www.lotus.com. For more
  56. * information on the Apache Software Foundation, please see
  57. * <http://www.apache.org/>.
  58. *
  59. */
  60. package org.apache.xalan.lib.sql;
  61. import org.apache.xml.dtm.DTMManager;
  62. import org.apache.xml.dtm.DTM;
  63. import java.sql.Connection;
  64. import java.sql.Statement;
  65. import java.sql.ResultSet;
  66. import java.sql.ResultSetMetaData;
  67. import java.sql.SQLException;
  68. import java.sql.*;
  69. import org.apache.xml.dtm.ref.*;
  70. /**
  71. * The SQL Document is the main controlling class the executesa SQL Query
  72. */
  73. public class SQLDocument extends DTMDocument
  74. {
  75. /**
  76. */
  77. private boolean DEBUG = false;
  78. /**
  79. */
  80. private static final String S_NAMESPACE = "http://xml.apache.org/xalan/SQLExtension";
  81. /**
  82. */
  83. private static final String S_SQL = "sql";
  84. /**
  85. */
  86. private static final String S_ROW_SET = "row-set";
  87. /**
  88. */
  89. private static final String S_METADATA = "metadata";
  90. /**
  91. */
  92. private static final String S_COLUMN_HEADER = "column-header";
  93. /**
  94. */
  95. private static final String S_ROW = "row";
  96. /**
  97. */
  98. private static final String S_COL = "col";
  99. /**
  100. */
  101. private static final String S_CATALOGUE_NAME = "catalogue-name";
  102. /**
  103. */
  104. private static final String S_DISPLAY_SIZE = "column-display-size";
  105. /**
  106. */
  107. private static final String S_COLUMN_LABEL = "column-label";
  108. /**
  109. */
  110. private static final String S_COLUMN_NAME = "column-name";
  111. /**
  112. */
  113. private static final String S_COLUMN_TYPE = "column-type";
  114. /**
  115. */
  116. private static final String S_COLUMN_TYPENAME = "column-typename";
  117. /**
  118. */
  119. private static final String S_PRECISION = "precision";
  120. /**
  121. */
  122. private static final String S_SCALE = "scale";
  123. /**
  124. */
  125. private static final String S_SCHEMA_NAME = "schema-name";
  126. /**
  127. */
  128. private static final String S_TABLE_NAME = "table-name";
  129. /**
  130. */
  131. private static final String S_CASESENSITIVE = "case-sensitive";
  132. /**
  133. */
  134. private static final String S_DEFINITLEYWRITABLE = "definitley-writable";
  135. /**
  136. */
  137. private static final String S_ISNULLABLE = "nullable";
  138. /**
  139. */
  140. private static final String S_ISSIGNED = "signed";
  141. /**
  142. */
  143. private static final String S_ISWRITEABLE = "writable";
  144. /**
  145. */
  146. private static final String S_ISSEARCHABLE = "searchable";
  147. /**
  148. */
  149. private int m_SQL_TypeID = 0;
  150. /**
  151. */
  152. private int m_MetaData_TypeID = 0;
  153. /**
  154. */
  155. private int m_ColumnHeader_TypeID = 0;
  156. /**
  157. */
  158. private int m_RowSet_TypeID = 0;
  159. /**
  160. */
  161. private int m_Row_TypeID = 0;
  162. /**
  163. */
  164. private int m_Col_TypeID = 0;
  165. /**
  166. */
  167. private int m_ColAttrib_CATALOGUE_NAME_TypeID = 0;
  168. /**
  169. */
  170. private int m_ColAttrib_DISPLAY_SIZE_TypeID = 0;
  171. /**
  172. */
  173. private int m_ColAttrib_COLUMN_LABEL_TypeID = 0;
  174. /**
  175. */
  176. private int m_ColAttrib_COLUMN_NAME_TypeID = 0;
  177. /**
  178. */
  179. private int m_ColAttrib_COLUMN_TYPE_TypeID = 0;
  180. /**
  181. */
  182. private int m_ColAttrib_COLUMN_TYPENAME_TypeID = 0;
  183. /**
  184. */
  185. private int m_ColAttrib_PRECISION_TypeID = 0;
  186. /**
  187. */
  188. private int m_ColAttrib_SCALE_TypeID = 0;
  189. /**
  190. */
  191. private int m_ColAttrib_SCHEMA_NAME_TypeID = 0;
  192. /**
  193. */
  194. private int m_ColAttrib_TABLE_NAME_TypeID = 0;
  195. /**
  196. */
  197. private int m_ColAttrib_CASESENSITIVE_TypeID = 0;
  198. /**
  199. */
  200. private int m_ColAttrib_DEFINITLEYWRITEABLE_TypeID = 0;
  201. /**
  202. */
  203. private int m_ColAttrib_ISNULLABLE_TypeID = 0;
  204. /**
  205. */
  206. private int m_ColAttrib_ISSIGNED_TypeID = 0;
  207. /**
  208. */
  209. private int m_ColAttrib_ISWRITEABLE_TypeID = 0;
  210. /**
  211. */
  212. private int m_ColAttrib_ISSEARCHABLE_TypeID = 0;
  213. /**
  214. * The DBMS Connection used to produce this SQL Document.
  215. * Will be used to clear free up the database resources on
  216. * close.
  217. */
  218. private Connection m_Connection = null;
  219. /**
  220. * The Statement used to extract the data from the Database connection.
  221. * We really don't need the connection, but it is NOT defined from
  222. * JDBC Driver to driver what happens to the ResultSet if the statment
  223. * is closed prior to reading all the data needed. So as long as we are
  224. * using the ResultSet, we will track the Statement used to produce it.
  225. */
  226. private Statement m_Statement = null;
  227. /**
  228. * The conduit to our data that will be used to fill the document.
  229. */
  230. private ResultSet m_ResultSet = null;
  231. /**
  232. * The Connection Pool that originally produced the connection.
  233. */
  234. private ConnectionPool m_ConnectionPool = null;
  235. /**
  236. * As the column header array is built, keep the node index
  237. * for each Column.
  238. * The primary use of this is to locate the first attribute for
  239. * each column in each row as we add records.
  240. */
  241. private int[] m_ColHeadersIdx;
  242. /**
  243. * An indicator on how many columns are in this query
  244. */
  245. private int m_ColCount;
  246. /**
  247. * The Index of the MetaData Node. Currently the MetaData Node contains the
  248. *
  249. */
  250. private int m_MetaDataIdx = DTM.NULL;
  251. /**
  252. * The index of the Row Set node. This is the sibling directly after
  253. * the last Column Header.
  254. */
  255. private int m_RowSetIdx = DTM.NULL;
  256. /**
  257. */
  258. private int m_SQLIdx = DTM.NULL;
  259. /**
  260. * Demark the first row element where we started adding rows into the
  261. * Document.
  262. */
  263. private int m_FirstRowIdx = DTM.NULL;
  264. /**
  265. * Keep track of the Last row inserted into the DTM from the ResultSet.
  266. * This will be used as the index of the parent Row Element when adding
  267. * a row.
  268. */
  269. private int m_LastRowIdx = DTM.NULL;
  270. /**
  271. * Streaming Mode Control, In Streaming mode we reduce the memory
  272. * footprint since we only use a single row instance.
  273. */
  274. private boolean m_StreamingMode = true;
  275. /**
  276. * @param mgr
  277. * @param ident
  278. * @param pool
  279. * @param con
  280. * @param stmt
  281. * @param data
  282. * @param streamingMode
  283. * @throws SQLException
  284. */
  285. public SQLDocument( DTMManager mgr, int ident, ConnectionPool pool, Connection con, Statement stmt, ResultSet data, boolean streamingMode )throws SQLException
  286. {
  287. super(mgr, ident);
  288. m_Connection = con;
  289. m_Statement = stmt;
  290. m_ResultSet = data;
  291. m_ConnectionPool = pool;
  292. m_StreamingMode = streamingMode;
  293. createExpandedNameTable();
  294. extractSQLMetaData(m_ResultSet.getMetaData());
  295. // Only grab the first row, subsequent rows will be
  296. // fetched on demand.
  297. // We need to do this here so at least on row is set up
  298. // to measure when we are actually reading rows.
  299. addRowToDTMFromResultSet();
  300. // We can't do this until the Document is regiostered with the Manager
  301. // Which has not happened yet
  302. // if (DEBUG) this.dumpDTM();
  303. }
  304. /**
  305. * Extract the Meta Data and build the Column Attribute List.
  306. * @param meta
  307. * @return
  308. */
  309. private void extractSQLMetaData( ResultSetMetaData meta )
  310. {
  311. // Build the Node Tree, just add the Column Header
  312. // branch now, the Row & col elements will be added
  313. // on request.
  314. // Start the document here
  315. m_DocumentIdx = addElement(0, m_Document_TypeID, DTM.NULL, DTM.NULL);
  316. // Add in the row-set Element
  317. m_SQLIdx = addElement(1, m_SQL_TypeID, m_DocumentIdx, DTM.NULL);
  318. // Add in the MetaData Element
  319. m_MetaDataIdx = addElement(1, m_MetaData_TypeID, m_SQLIdx, DTM.NULL);
  320. try
  321. {
  322. m_ColCount = meta.getColumnCount();
  323. m_ColHeadersIdx = new int[m_ColCount];
  324. }
  325. catch(Exception e)
  326. {
  327. error("ERROR Extracting Metadata");
  328. }
  329. // The ColHeaderIdx will be used to keep track of the
  330. // Element entries for the individual Column Header.
  331. int lastColHeaderIdx = DTM.NULL;
  332. // JDBC Columms Start at 1
  333. int i = 1;
  334. for (i=1; i<= m_ColCount; i++)
  335. {
  336. m_ColHeadersIdx[i-1] =
  337. addElement(2,m_ColumnHeader_TypeID, m_MetaDataIdx, lastColHeaderIdx);
  338. lastColHeaderIdx = m_ColHeadersIdx[i-1];
  339. // A bit brute force, but not sure how to clean it up
  340. try
  341. {
  342. addAttributeToNode(
  343. meta.getColumnName(i),
  344. m_ColAttrib_COLUMN_NAME_TypeID, lastColHeaderIdx);
  345. }
  346. catch(Exception e)
  347. {
  348. addAttributeToNode(
  349. S_ATTRIB_NOT_SUPPORTED,
  350. m_ColAttrib_COLUMN_NAME_TypeID, lastColHeaderIdx);
  351. }
  352. try
  353. {
  354. addAttributeToNode(
  355. meta.getColumnLabel(i),
  356. m_ColAttrib_COLUMN_LABEL_TypeID, lastColHeaderIdx);
  357. }
  358. catch(Exception e)
  359. {
  360. addAttributeToNode(
  361. S_ATTRIB_NOT_SUPPORTED,
  362. m_ColAttrib_COLUMN_LABEL_TypeID, lastColHeaderIdx);
  363. }
  364. try
  365. {
  366. addAttributeToNode(
  367. meta.getCatalogName(i),
  368. m_ColAttrib_CATALOGUE_NAME_TypeID, lastColHeaderIdx);
  369. }
  370. catch(Exception e)
  371. {
  372. addAttributeToNode(
  373. S_ATTRIB_NOT_SUPPORTED,
  374. m_ColAttrib_CATALOGUE_NAME_TypeID, lastColHeaderIdx);
  375. }
  376. try
  377. {
  378. addAttributeToNode(
  379. new Integer(meta.getColumnDisplaySize(i)),
  380. m_ColAttrib_DISPLAY_SIZE_TypeID, lastColHeaderIdx);
  381. }
  382. catch(Exception e)
  383. {
  384. addAttributeToNode(
  385. S_ATTRIB_NOT_SUPPORTED,
  386. m_ColAttrib_DISPLAY_SIZE_TypeID, lastColHeaderIdx);
  387. }
  388. try
  389. {
  390. addAttributeToNode(
  391. new Integer(meta.getColumnType(i)),
  392. m_ColAttrib_COLUMN_TYPE_TypeID, lastColHeaderIdx);
  393. }
  394. catch(Exception e)
  395. {
  396. addAttributeToNode(
  397. S_ATTRIB_NOT_SUPPORTED,
  398. m_ColAttrib_COLUMN_TYPE_TypeID, lastColHeaderIdx);
  399. }
  400. try
  401. {
  402. addAttributeToNode(
  403. meta.getColumnTypeName(i),
  404. m_ColAttrib_COLUMN_TYPENAME_TypeID, lastColHeaderIdx);
  405. }
  406. catch(Exception e)
  407. {
  408. addAttributeToNode(
  409. S_ATTRIB_NOT_SUPPORTED,
  410. m_ColAttrib_COLUMN_TYPENAME_TypeID, lastColHeaderIdx);
  411. }
  412. try
  413. {
  414. addAttributeToNode(
  415. new Integer(meta.getPrecision(i)),
  416. m_ColAttrib_PRECISION_TypeID, lastColHeaderIdx);
  417. }
  418. catch(Exception e)
  419. {
  420. addAttributeToNode(
  421. S_ATTRIB_NOT_SUPPORTED,
  422. m_ColAttrib_PRECISION_TypeID, lastColHeaderIdx);
  423. }
  424. try
  425. {
  426. addAttributeToNode(
  427. new Integer(meta.getScale(i)),
  428. m_ColAttrib_SCALE_TypeID, lastColHeaderIdx);
  429. }
  430. catch(Exception e)
  431. {
  432. addAttributeToNode(
  433. S_ATTRIB_NOT_SUPPORTED,
  434. m_ColAttrib_SCALE_TypeID, lastColHeaderIdx);
  435. }
  436. try
  437. {
  438. addAttributeToNode(
  439. meta.getSchemaName(i),
  440. m_ColAttrib_SCHEMA_NAME_TypeID, lastColHeaderIdx);
  441. }
  442. catch(Exception e)
  443. {
  444. addAttributeToNode(
  445. S_ATTRIB_NOT_SUPPORTED,
  446. m_ColAttrib_SCHEMA_NAME_TypeID, lastColHeaderIdx);
  447. }
  448. try
  449. {
  450. addAttributeToNode(
  451. meta.getTableName(i),
  452. m_ColAttrib_TABLE_NAME_TypeID, lastColHeaderIdx);
  453. }
  454. catch(Exception e)
  455. {
  456. addAttributeToNode(
  457. S_ATTRIB_NOT_SUPPORTED,
  458. m_ColAttrib_TABLE_NAME_TypeID, lastColHeaderIdx);
  459. }
  460. try
  461. {
  462. addAttributeToNode(
  463. meta.isCaseSensitive(i) ? S_ISTRUE : S_ISFALSE,
  464. m_ColAttrib_CASESENSITIVE_TypeID, lastColHeaderIdx);
  465. }
  466. catch(Exception e)
  467. {
  468. addAttributeToNode(
  469. S_ATTRIB_NOT_SUPPORTED,
  470. m_ColAttrib_CASESENSITIVE_TypeID, lastColHeaderIdx);
  471. }
  472. try
  473. {
  474. addAttributeToNode(
  475. meta.isDefinitelyWritable(i) ? S_ISTRUE : S_ISFALSE,
  476. m_ColAttrib_DEFINITLEYWRITEABLE_TypeID, lastColHeaderIdx);
  477. }
  478. catch(Exception e)
  479. {
  480. addAttributeToNode(
  481. S_ATTRIB_NOT_SUPPORTED,
  482. m_ColAttrib_DEFINITLEYWRITEABLE_TypeID, lastColHeaderIdx);
  483. }
  484. try
  485. {
  486. addAttributeToNode(
  487. meta.isNullable(i) != 0 ? S_ISTRUE : S_ISFALSE,
  488. m_ColAttrib_ISNULLABLE_TypeID, lastColHeaderIdx);
  489. }
  490. catch(Exception e)
  491. {
  492. addAttributeToNode(
  493. S_ATTRIB_NOT_SUPPORTED,
  494. m_ColAttrib_ISNULLABLE_TypeID, lastColHeaderIdx);
  495. }
  496. try
  497. {
  498. addAttributeToNode(
  499. meta.isSigned(i) ? S_ISTRUE : S_ISFALSE,
  500. m_ColAttrib_ISSIGNED_TypeID, lastColHeaderIdx);
  501. }
  502. catch(Exception e)
  503. {
  504. addAttributeToNode(
  505. S_ATTRIB_NOT_SUPPORTED,
  506. m_ColAttrib_ISSIGNED_TypeID, lastColHeaderIdx);
  507. }
  508. try
  509. {
  510. addAttributeToNode(
  511. meta.isWritable(i) == true ? S_ISTRUE : S_ISFALSE,
  512. m_ColAttrib_ISWRITEABLE_TypeID, lastColHeaderIdx);
  513. }
  514. catch(Exception e)
  515. {
  516. addAttributeToNode(
  517. S_ATTRIB_NOT_SUPPORTED,
  518. m_ColAttrib_ISWRITEABLE_TypeID, lastColHeaderIdx);
  519. }
  520. try
  521. {
  522. addAttributeToNode(
  523. meta.isSearchable(i) == true ? S_ISTRUE : S_ISFALSE,
  524. m_ColAttrib_ISSEARCHABLE_TypeID, lastColHeaderIdx);
  525. }
  526. catch(Exception e)
  527. {
  528. addAttributeToNode(
  529. S_ATTRIB_NOT_SUPPORTED,
  530. m_ColAttrib_ISSEARCHABLE_TypeID, lastColHeaderIdx);
  531. }
  532. }
  533. }
  534. /**
  535. * Populate the Expanded Name Table with the Node that we will use.
  536. * Keep a reference of each of the types for access speed.
  537. * @return
  538. */
  539. protected void createExpandedNameTable( )
  540. {
  541. super.createExpandedNameTable();
  542. m_SQL_TypeID =
  543. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_SQL, DTM.ELEMENT_NODE);
  544. m_MetaData_TypeID =
  545. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_METADATA, DTM.ELEMENT_NODE);
  546. m_ColumnHeader_TypeID =
  547. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_COLUMN_HEADER, DTM.ELEMENT_NODE);
  548. m_RowSet_TypeID =
  549. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_ROW_SET, DTM.ELEMENT_NODE);
  550. m_Row_TypeID =
  551. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_ROW, DTM.ELEMENT_NODE);
  552. m_Col_TypeID =
  553. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_COL, DTM.ELEMENT_NODE);
  554. m_ColAttrib_CATALOGUE_NAME_TypeID =
  555. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_CATALOGUE_NAME, DTM.ATTRIBUTE_NODE);
  556. m_ColAttrib_DISPLAY_SIZE_TypeID =
  557. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_DISPLAY_SIZE, DTM.ATTRIBUTE_NODE);
  558. m_ColAttrib_COLUMN_LABEL_TypeID =
  559. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_COLUMN_LABEL, DTM.ATTRIBUTE_NODE);
  560. m_ColAttrib_COLUMN_NAME_TypeID =
  561. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_COLUMN_NAME, DTM.ATTRIBUTE_NODE);
  562. m_ColAttrib_COLUMN_TYPE_TypeID =
  563. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_COLUMN_TYPE, DTM.ATTRIBUTE_NODE);
  564. m_ColAttrib_COLUMN_TYPENAME_TypeID =
  565. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_COLUMN_TYPENAME, DTM.ATTRIBUTE_NODE);
  566. m_ColAttrib_PRECISION_TypeID =
  567. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_PRECISION, DTM.ATTRIBUTE_NODE);
  568. m_ColAttrib_SCALE_TypeID =
  569. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_SCALE, DTM.ATTRIBUTE_NODE);
  570. m_ColAttrib_SCHEMA_NAME_TypeID =
  571. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_SCHEMA_NAME, DTM.ATTRIBUTE_NODE);
  572. m_ColAttrib_TABLE_NAME_TypeID =
  573. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_TABLE_NAME, DTM.ATTRIBUTE_NODE);
  574. m_ColAttrib_CASESENSITIVE_TypeID =
  575. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_CASESENSITIVE, DTM.ATTRIBUTE_NODE);
  576. m_ColAttrib_DEFINITLEYWRITEABLE_TypeID =
  577. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_DEFINITLEYWRITABLE, DTM.ATTRIBUTE_NODE);
  578. m_ColAttrib_ISNULLABLE_TypeID =
  579. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_ISNULLABLE, DTM.ATTRIBUTE_NODE);
  580. m_ColAttrib_ISSIGNED_TypeID =
  581. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_ISSIGNED, DTM.ATTRIBUTE_NODE);
  582. m_ColAttrib_ISWRITEABLE_TypeID =
  583. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_ISWRITEABLE, DTM.ATTRIBUTE_NODE);
  584. m_ColAttrib_ISSEARCHABLE_TypeID =
  585. m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_ISSEARCHABLE, DTM.ATTRIBUTE_NODE);
  586. }
  587. /**
  588. * Pull a record from the result set and map it to a DTM based ROW
  589. * If we are in Streaming mode, then only create a single row and
  590. * keep copying the data into the same row. This will keep the memory
  591. * footprint constint independant of the RecordSet Size. If we are not
  592. * in Streaming mode then create ROWS for the whole tree.
  593. * @return
  594. */
  595. private boolean addRowToDTMFromResultSet( )
  596. {
  597. try
  598. {
  599. // If we have not started the RowSet yet, then add it to the
  600. // tree.
  601. if (m_RowSetIdx == DTM.NULL)
  602. {
  603. m_RowSetIdx = addElement(1, m_RowSet_TypeID, m_SQLIdx, m_MetaDataIdx);
  604. }
  605. // Check to see if all the data has been read from the Query.
  606. // If we are at the end the signal that event
  607. if ( ! m_ResultSet.next())
  608. {
  609. // In Streaming mode, the current ROW will always point back
  610. // to itself until all the data was read. Once the Query is
  611. // empty then point the next row to DTM.NULL so that the stream
  612. // ends. Only do this if we have statted the loop to begin with.
  613. if (m_StreamingMode && (m_LastRowIdx != DTM.NULL))
  614. {
  615. // We are at the end, so let's untie the mark
  616. m_nextsib.setElementAt(DTM.NULL, m_LastRowIdx);
  617. }
  618. return false;
  619. }
  620. // If this is the first time here, start the new level
  621. if (m_FirstRowIdx == DTM.NULL)
  622. {
  623. m_FirstRowIdx =
  624. addElement(2, m_Row_TypeID, m_RowSetIdx, DTM.NULL);
  625. m_LastRowIdx = m_FirstRowIdx;
  626. if (m_StreamingMode)
  627. {
  628. // Let's tie the rows together until the end.
  629. m_nextsib.setElementAt(m_LastRowIdx, m_LastRowIdx);
  630. }
  631. }
  632. else
  633. {
  634. //
  635. // If we are in Streaming mode, then only use a single row instance
  636. if (! m_StreamingMode)
  637. {
  638. m_LastRowIdx = addElement(3, m_Row_TypeID, m_RowSetIdx, m_LastRowIdx);
  639. }
  640. }
  641. // If we are not in streaming mode, this will always be DTM.NULL
  642. // If we are in streaming mode, it will only be DTM.NULL the first time
  643. int colID = _firstch(m_LastRowIdx);
  644. // Keep Track of who our parent was when adding new col objects.
  645. int pcolID = DTM.NULL;
  646. // Columns in JDBC Start at 1 and go to the Extent
  647. for (int i=1; i<= m_ColCount; i++)
  648. {
  649. // Just grab the Column Object Type, we will convert it to a string
  650. // later.
  651. Object o = m_ResultSet.getObject(i);
  652. // Create a new column object if one does not exist.
  653. // In Streaming mode, this mechinism will reuse the column
  654. // data the second and subsequent row accesses.
  655. if (colID == DTM.NULL)
  656. {
  657. pcolID = addElementWithData(o,3,m_Col_TypeID, m_LastRowIdx, pcolID);
  658. cloneAttributeFromNode(pcolID, m_ColHeadersIdx[i-1]);
  659. }
  660. else
  661. {
  662. // We must be in streaming mode, so let's just replace the data
  663. // If the firstch was not set then we have a major error
  664. int dataIdent = _firstch(colID);
  665. if (dataIdent == DTM.NULL)
  666. {
  667. error("Streaming Mode, Data Error");
  668. }
  669. else
  670. {
  671. m_ObjectArray.setAt(dataIdent, o);
  672. }
  673. } // If
  674. // In streaming mode, this will be !DTM.NULL
  675. // So if the elements were already established then we
  676. // should be able to walk them in order.
  677. if (colID != DTM.NULL)
  678. {
  679. colID = _nextsib(colID);
  680. }
  681. } // For Col Loop
  682. }
  683. catch(Exception e)
  684. {
  685. if (DEBUG)
  686. {
  687. System.out.println(
  688. "SQL Error Fetching next row [" + e.getLocalizedMessage() + "]");
  689. }
  690. error("SQL Error Fetching next row [" + e.getLocalizedMessage() + "]");
  691. }
  692. // Only do a single row...
  693. return true;
  694. }
  695. /**
  696. * Clean up our ties to the database but this does not necessarly
  697. * clean up the document.
  698. * @return
  699. */
  700. public void close( )
  701. {
  702. if (DEBUG) System.out.println("close()");
  703. try { if (null != m_ResultSet) m_ResultSet.close(); }
  704. catch(Exception e) { }
  705. try { if (null != m_Statement) m_Statement.close(); }
  706. catch(Exception e) { }
  707. try {
  708. if (null != m_Connection)
  709. m_ConnectionPool.releaseConnection(m_Connection);
  710. } catch(Exception e) { }
  711. }
  712. /**
  713. * When an error occurs, the XConnection will call this method
  714. * do that we can deal with the Connection properly
  715. * @return
  716. */
  717. public void closeOnError( )
  718. {
  719. if (DEBUG) System.out.println("close()");
  720. try { if (null != m_ResultSet) m_ResultSet.close(); }
  721. catch(Exception e) { }
  722. try { if (null != m_Statement) m_Statement.close();
  723. } catch(Exception e) { }
  724. try {
  725. if (null != m_Connection)
  726. m_ConnectionPool.releaseConnectionOnError(m_Connection);
  727. } catch(Exception e) { }
  728. }
  729. /**
  730. * @return
  731. */
  732. protected boolean nextNode( )
  733. {
  734. if (DEBUG) System.out.println("nextNode()");
  735. try
  736. {
  737. return false;
  738. // return m_ResultSet.isAfterLast();
  739. }
  740. catch(Exception e)
  741. {
  742. return false;
  743. }
  744. }
  745. /**
  746. * @param identity
  747. * @return
  748. */
  749. protected int _nextsib( int identity )
  750. {
  751. // If we are asking for the next row and we have not
  752. // been there yet then let's see if we can get another
  753. // row from the ResultSet.
  754. //
  755. int id = _exptype(identity);
  756. if (
  757. ( id == m_Row_TypeID) &&
  758. (identity >= m_LastRowIdx))
  759. {
  760. if (DEBUG) System.out.println("reading from the ResultSet");
  761. addRowToDTMFromResultSet();
  762. }
  763. return super._nextsib(identity);
  764. }
  765. public void documentRegistration()
  766. {
  767. if (DEBUG) System.out.println("Document Registration");
  768. }
  769. public void documentRelease()
  770. {
  771. if (DEBUG) System.out.println("Document Release");
  772. }
  773. }