View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.jdbc;
25  
26  import java.sql.Connection;
27  import java.sql.DatabaseMetaData;
28  import java.sql.ResultSet;
29  import java.sql.RowIdLifetime;
30  import java.sql.SQLException;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collections;
34  import java.util.Comparator;
35  import java.util.Iterator;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.logging.Level;
39  import javax.jcr.Repository;
40  import javax.jcr.RepositoryException;
41  import javax.jcr.nodetype.NodeType;
42  import javax.jcr.nodetype.PropertyDefinition;
43  import javax.jcr.query.QueryResult;
44  import org.modeshape.jdbc.metadata.JDBCColumnNames;
45  import org.modeshape.jdbc.metadata.JDBCColumnPositions;
46  import org.modeshape.jdbc.metadata.MetaDataQueryResult;
47  import org.modeshape.jdbc.metadata.MetadataProvider;
48  import org.modeshape.jdbc.metadata.ResultSetMetaDataImpl;
49  import org.modeshape.jdbc.metadata.ResultsMetadataConstants;
50  
51  /**
52   * This driver's implementation of JDBC {@link DatabaseMetaData}.
53   */
54  public class JcrMetaData implements DatabaseMetaData {
55  
56      /** CONSTANTS */
57      protected static final String WILDCARD = "%"; //$NON-NLS-1$
58      protected static final Integer DEFAULT_ZERO = new Integer(0);
59      protected static final int NO_LIMIT = 0;
60  
61      private JcrConnection connection;
62      private String catalogName;
63  
64      public JcrMetaData( JcrConnection connection ) {
65          this.connection = connection;
66          assert this.connection != null;
67          catalogName = connection.getCatalog();
68          assert catalogName != null;
69      }
70  
71      /**
72       * {@inheritDoc}
73       * 
74       * @see java.sql.DatabaseMetaData#getDriverMajorVersion()
75       */
76      @Override
77      public int getDriverMajorVersion() {
78          return JcrDriver.getDriverMetadata().getMajorVersion();
79      }
80  
81      /**
82       * {@inheritDoc}
83       * 
84       * @see java.sql.DatabaseMetaData#getDriverMinorVersion()
85       */
86      @Override
87      public int getDriverMinorVersion() {
88          return JcrDriver.getDriverMetadata().getMinorVersion();
89      }
90  
91      /**
92       * {@inheritDoc}
93       * 
94       * @see java.sql.DatabaseMetaData#getDriverName()
95       */
96      @Override
97      public String getDriverName() {
98          return JcrDriver.getDriverMetadata().getName();
99      }
100 
101     /**
102      * {@inheritDoc}
103      * 
104      * @see java.sql.DatabaseMetaData#getDriverVersion()
105      */
106     @Override
107     public String getDriverVersion() {
108         return JcrDriver.getDriverMetadata().getVersion();
109     }
110 
111     /**
112      * {@inheritDoc}
113      * 
114      * @see java.sql.DatabaseMetaData#getDatabaseMajorVersion()
115      */
116     @Override
117     public int getDatabaseMajorVersion() {
118         return Integer.parseInt(getDatabaseProductVersion().split("[.-]")[0]);
119     }
120 
121     /**
122      * {@inheritDoc}
123      * 
124      * @see java.sql.DatabaseMetaData#getDatabaseMinorVersion()
125      */
126     @Override
127     public int getDatabaseMinorVersion() {
128         return Integer.parseInt(getDatabaseProductVersion().split("[.-]")[1]);
129     }
130 
131     /**
132      * {@inheritDoc}
133      * 
134      * @see java.sql.DatabaseMetaData#getDatabaseProductName()
135      */
136     @Override
137     public String getDatabaseProductName() {
138         return this.connection.getRepositoryDelegate().getDescriptor(Repository.REP_NAME_DESC);
139     }
140 
141     public String getDatabaseProductUrl() {
142         return this.connection.getRepositoryDelegate().getDescriptor(Repository.REP_VENDOR_URL_DESC);
143     }
144 
145     /**
146      * {@inheritDoc}
147      * 
148      * @see java.sql.DatabaseMetaData#getDatabaseProductVersion()
149      */
150     @Override
151     public String getDatabaseProductVersion() {
152         return this.connection.getRepositoryDelegate().getDescriptor(Repository.REP_VERSION_DESC);
153     }
154 
155     /**
156      * {@inheritDoc}
157      * 
158      * @see java.sql.DatabaseMetaData#getJDBCMajorVersion()
159      */
160     @Override
161     public int getJDBCMajorVersion() {
162         return 2;
163     }
164 
165     /**
166      * {@inheritDoc}
167      * 
168      * @see java.sql.DatabaseMetaData#getJDBCMinorVersion()
169      */
170     @Override
171     public int getJDBCMinorVersion() {
172         return 0;
173     }
174 
175     /**
176      * {@inheritDoc}
177      * 
178      * @see java.sql.DatabaseMetaData#getConnection()
179      */
180     @Override
181     public Connection getConnection() {
182         return connection;
183     }
184 
185     /**
186      * {@inheritDoc}
187      * 
188      * @see java.sql.DatabaseMetaData#isReadOnly()
189      */
190     @Override
191     public boolean isReadOnly() {
192         return true;
193     }
194 
195     /**
196      * {@inheritDoc}
197      * 
198      * @see java.sql.DatabaseMetaData#allProceduresAreCallable()
199      */
200     @Override
201     public boolean allProceduresAreCallable() throws SQLException {
202         return false;
203     }
204 
205     /**
206      * {@inheritDoc}
207      * 
208      * @see java.sql.DatabaseMetaData#allTablesAreSelectable()
209      */
210     @Override
211     public boolean allTablesAreSelectable() throws SQLException {
212         return false;
213     }
214 
215     /**
216      * {@inheritDoc}
217      * 
218      * @see java.sql.DatabaseMetaData#autoCommitFailureClosesAllResultSets()
219      */
220     @Override
221     public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
222         return false;
223     }
224 
225     /**
226      * {@inheritDoc}
227      * 
228      * @see java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()
229      */
230     @Override
231     public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
232         return false;
233     }
234 
235     /**
236      * {@inheritDoc}
237      * 
238      * @see java.sql.DatabaseMetaData#dataDefinitionIgnoredInTransactions()
239      */
240     @Override
241     public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
242         return false;
243     }
244 
245     /**
246      * {@inheritDoc}
247      * 
248      * @see java.sql.DatabaseMetaData#deletesAreDetected(int)
249      */
250     @Override
251     public boolean deletesAreDetected( int type ) throws SQLException {
252         return false;
253     }
254 
255     /**
256      * {@inheritDoc}
257      * 
258      * @see java.sql.DatabaseMetaData#doesMaxRowSizeIncludeBlobs()
259      */
260     @Override
261     public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
262         return false;
263     }
264 
265     /**
266      * {@inheritDoc}
267      * 
268      * @see java.sql.DatabaseMetaData#getAttributes(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
269      */
270     @Override
271     public ResultSet getAttributes( String catalog,
272                                     String schemaPattern,
273                                     String typeNamePattern,
274                                     String attributeNamePattern ) throws SQLException {
275         return null;
276     }
277 
278     /**
279      * {@inheritDoc}
280      * 
281      * @see java.sql.DatabaseMetaData#getBestRowIdentifier(java.lang.String, java.lang.String, java.lang.String, int, boolean)
282      */
283     @Override
284     public ResultSet getBestRowIdentifier( String catalog,
285                                            String schema,
286                                            String table,
287                                            int scope,
288                                            boolean nullable ) throws SQLException {
289         return null;
290     }
291 
292     /**
293      * {@inheritDoc}
294      * 
295      * @see java.sql.DatabaseMetaData#getCatalogSeparator()
296      */
297     @Override
298     public String getCatalogSeparator() throws SQLException {
299         return null;
300     }
301 
302     /**
303      * {@inheritDoc}
304      * <p>
305      * This driver maps the repository name as the JDBC catalog name. Therefore, this method returns 'Repository' for the catalog
306      * term.
307      * </p>
308      * 
309      * @see java.sql.DatabaseMetaData#getCatalogTerm()
310      */
311     @Override
312     public String getCatalogTerm() {
313         return "Repository";
314     }
315 
316     /**
317      * {@inheritDoc}
318      * <p>
319      * This driver maps the repository name as the JDBC catalog name. Therefore, this method returns a result set containing only
320      * the repository's name.
321      * </p>
322      * 
323      * @see java.sql.DatabaseMetaData#getCatalogs()
324      */
325     @Override
326     public ResultSet getCatalogs() throws SQLException {
327         List<List<?>> records = new ArrayList<List<?>>(1);
328 
329         List<String> row = Arrays.asList(catalogName);
330         records.add(row);
331 
332         /***********************************************************************
333          * Hardcoding JDBC column names for the columns returned in results object
334          ***********************************************************************/
335 
336         Map<?, Object>[] metadataList = new Map[1];
337 
338         metadataList[0] = MetadataProvider.getColumnMetadata(catalogName,
339                                                              null,
340                                                              JDBCColumnNames.CATALOGS.TABLE_CAT,
341                                                              JcrType.DefaultDataTypes.STRING,
342                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
343                                                              this.connection);
344 
345         MetadataProvider provider = new MetadataProvider(metadataList);
346 
347         ResultSetMetaDataImpl resultSetMetaData = new ResultSetMetaDataImpl(provider);
348 
349         JcrStatement stmt = new JcrStatement(this.connection);
350         QueryResult queryresult = MetaDataQueryResult.createResultSet(records, resultSetMetaData);
351         ResultSet rs = new JcrResultSet(stmt, queryresult, resultSetMetaData);
352 
353         return rs;
354     }
355 
356     /**
357      * {@inheritDoc}
358      * 
359      * @see java.sql.DatabaseMetaData#getClientInfoProperties()
360      */
361     @Override
362     public ResultSet getClientInfoProperties() throws SQLException {
363         return null;
364     }
365 
366     /**
367      * {@inheritDoc}
368      * 
369      * @see java.sql.DatabaseMetaData#getColumnPrivileges(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
370      */
371     @Override
372     public ResultSet getColumnPrivileges( String catalog,
373                                           String schema,
374                                           String table,
375                                           String columnNamePattern ) throws SQLException {
376         return null;
377     }
378 
379     /**
380      * {@inheritDoc}
381      * 
382      * @see java.sql.DatabaseMetaData#getColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
383      */
384     @SuppressWarnings( "unchecked" )
385     @Override
386     public ResultSet getColumns( String catalog,
387                                  String schemaPattern,
388                                  String tableNamePattern,
389                                  String columnNamePattern ) throws SQLException {
390         JcrDriver.logger.log(Level.FINE, "getcolumns: " + catalog + ":" + schemaPattern + ":" + tableNamePattern + ":"
391                                          + columnNamePattern);
392 
393         // Get all tables if tableNamePattern is null
394         if (tableNamePattern == null) {
395             tableNamePattern = WILDCARD;
396         }
397 
398         Map<?, Object>[] metadataList = new Map[JDBCColumnPositions.COLUMNS.MAX_COLUMNS];
399 
400         metadataList[0] = MetadataProvider.getColumnMetadata(catalogName,
401                                                              null,
402                                                              JDBCColumnNames.COLUMNS.TABLE_CAT,
403                                                              JcrType.DefaultDataTypes.STRING,
404                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
405                                                              this.connection);
406         metadataList[1] = MetadataProvider.getColumnMetadata(catalogName,
407                                                              null,
408                                                              JDBCColumnNames.COLUMNS.TABLE_SCHEM,
409                                                              JcrType.DefaultDataTypes.STRING,
410                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
411                                                              this.connection);
412         metadataList[2] = MetadataProvider.getColumnMetadata(catalogName,
413                                                              null,
414                                                              JDBCColumnNames.COLUMNS.TABLE_NAME,
415                                                              JcrType.DefaultDataTypes.STRING,
416                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
417                                                              this.connection);
418         metadataList[3] = MetadataProvider.getColumnMetadata(catalogName,
419                                                              null,
420                                                              JDBCColumnNames.COLUMNS.COLUMN_NAME,
421                                                              JcrType.DefaultDataTypes.STRING,
422                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
423                                                              this.connection);
424         metadataList[4] = MetadataProvider.getColumnMetadata(catalogName,
425                                                              null,
426                                                              JDBCColumnNames.COLUMNS.DATA_TYPE,
427                                                              JcrType.DefaultDataTypes.LONG,
428                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
429                                                              this.connection);
430         metadataList[5] = MetadataProvider.getColumnMetadata(catalogName,
431                                                              null,
432                                                              JDBCColumnNames.COLUMNS.TYPE_NAME,
433                                                              JcrType.DefaultDataTypes.STRING,
434                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
435                                                              this.connection);
436         metadataList[6] = MetadataProvider.getColumnMetadata(catalogName,
437                                                              null,
438                                                              JDBCColumnNames.COLUMNS.COLUMN_SIZE,
439                                                              JcrType.DefaultDataTypes.LONG,
440                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
441                                                              this.connection);
442         metadataList[7] = MetadataProvider.getColumnMetadata(catalogName,
443                                                              null,
444                                                              JDBCColumnNames.COLUMNS.BUFFER_LENGTH,
445                                                              JcrType.DefaultDataTypes.LONG,
446                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
447                                                              this.connection);
448         metadataList[8] = MetadataProvider.getColumnMetadata(catalogName,
449                                                              null,
450                                                              JDBCColumnNames.COLUMNS.DECIMAL_DIGITS,
451                                                              JcrType.DefaultDataTypes.LONG,
452                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
453                                                              this.connection);
454         metadataList[9] = MetadataProvider.getColumnMetadata(catalogName,
455                                                              null,
456                                                              JDBCColumnNames.COLUMNS.NUM_PREC_RADIX,
457                                                              JcrType.DefaultDataTypes.LONG,
458                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
459                                                              this.connection);
460 
461         metadataList[10] = MetadataProvider.getColumnMetadata(catalogName,
462                                                               null,
463                                                               JDBCColumnNames.COLUMNS.NULLABLE,
464                                                               JcrType.DefaultDataTypes.LONG,
465                                                               ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
466                                                               this.connection);
467         metadataList[11] = MetadataProvider.getColumnMetadata(catalogName,
468                                                               null,
469                                                               JDBCColumnNames.COLUMNS.REMARKS,
470                                                               JcrType.DefaultDataTypes.STRING,
471                                                               ResultsMetadataConstants.NULL_TYPES.NULLABLE,
472                                                               this.connection);
473         metadataList[12] = MetadataProvider.getColumnMetadata(catalogName,
474                                                               null,
475                                                               JDBCColumnNames.COLUMNS.COLUMN_DEF,
476                                                               JcrType.DefaultDataTypes.STRING,
477                                                               ResultsMetadataConstants.NULL_TYPES.NULLABLE,
478                                                               this.connection);
479         metadataList[13] = MetadataProvider.getColumnMetadata(catalogName,
480                                                               null,
481                                                               JDBCColumnNames.COLUMNS.SQL_DATA_TYPE,
482                                                               JcrType.DefaultDataTypes.LONG,
483                                                               ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
484                                                               this.connection);
485         metadataList[14] = MetadataProvider.getColumnMetadata(catalogName,
486                                                               null,
487                                                               JDBCColumnNames.COLUMNS.SQL_DATETIME_SUB,
488                                                               JcrType.DefaultDataTypes.LONG,
489                                                               ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
490                                                               this.connection);
491         metadataList[15] = MetadataProvider.getColumnMetadata(catalogName,
492                                                               null,
493                                                               JDBCColumnNames.COLUMNS.CHAR_OCTET_LENGTH,
494                                                               JcrType.DefaultDataTypes.LONG,
495                                                               ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
496                                                               this.connection);
497         metadataList[16] = MetadataProvider.getColumnMetadata(catalogName,
498                                                               null,
499                                                               JDBCColumnNames.COLUMNS.ORDINAL_POSITION,
500                                                               JcrType.DefaultDataTypes.LONG,
501                                                               ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
502                                                               this.connection);
503         metadataList[17] = MetadataProvider.getColumnMetadata(catalogName,
504                                                               null,
505                                                               JDBCColumnNames.COLUMNS.IS_NULLABLE,
506                                                               JcrType.DefaultDataTypes.STRING,
507                                                               ResultsMetadataConstants.NULL_TYPES.NULLABLE,
508                                                               this.connection);
509         metadataList[18] = MetadataProvider.getColumnMetadata(catalogName,
510                                                               null,
511                                                               JDBCColumnNames.COLUMNS.SCOPE_CATLOG,
512                                                               JcrType.DefaultDataTypes.STRING,
513                                                               ResultsMetadataConstants.NULL_TYPES.NULLABLE,
514                                                               this.connection);
515         metadataList[19] = MetadataProvider.getColumnMetadata(catalogName,
516                                                               null,
517                                                               JDBCColumnNames.COLUMNS.SCOPE_SCHEMA,
518                                                               JcrType.DefaultDataTypes.STRING,
519                                                               ResultsMetadataConstants.NULL_TYPES.NULLABLE,
520                                                               this.connection);
521 
522         metadataList[20] = MetadataProvider.getColumnMetadata(catalogName,
523                                                               null,
524                                                               JDBCColumnNames.COLUMNS.SCOPE_TABLE,
525                                                               JcrType.DefaultDataTypes.STRING,
526                                                               ResultsMetadataConstants.NULL_TYPES.NULLABLE,
527                                                               this.connection);
528         metadataList[21] = MetadataProvider.getColumnMetadata(catalogName,
529                                                               null,
530                                                               JDBCColumnNames.COLUMNS.SOURCE_DATA_TYPE,
531                                                               JcrType.DefaultDataTypes.LONG,
532                                                               ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
533                                                               this.connection);
534 
535         MetadataProvider provider = new MetadataProvider(metadataList);
536 
537         ResultSetMetaDataImpl resultSetMetaData = new ResultSetMetaDataImpl(provider);
538 
539         List<List<?>> records = new ArrayList<List<?>>();
540 
541         try {
542 
543             List<NodeType> nodetypes = filterNodeTypes(tableNamePattern);
544 
545             Iterator<NodeType> nodeIt = nodetypes.iterator();
546             // process each node
547             while (nodeIt.hasNext()) {
548 
549                 NodeType type = nodeIt.next();
550 
551                 if (type.getPropertyDefinitions() == null) {
552                     throw new SQLException("Program Error:  missing propertydefintions for " + type.getName());
553                 }
554 
555                 List<PropertyDefinition> defns = filterPropertyDefnitions(columnNamePattern, type.getPropertyDefinitions());
556 
557                 int ordinal = 0;
558                 Iterator<PropertyDefinition> defnsIt = defns.iterator();
559                 // build the list of records.
560                 while (defnsIt.hasNext()) {
561 
562                     PropertyDefinition propDefn = defnsIt.next();
563 
564                     // list represents a record on the Results object.
565                     List<Object> currentRow = new ArrayList<Object>(JDBCColumnPositions.COLUMNS.MAX_COLUMNS);
566 
567                     JcrType jcrtype = JcrType.typeInfo(propDefn.getRequiredType());
568 
569                     currentRow.add(catalogName); // TABLE_CAT
570                     currentRow.add("NULL"); // TABLE_SCHEM
571                     currentRow.add(type.getName()); // TABLE_NAME
572                     currentRow.add(propDefn.getName()); // COLUMN_NAME
573                     currentRow.add(jcrtype.getJdbcType()); // DATA_TYPE
574                     currentRow.add(jcrtype.getJcrName()); // TYPE_NAME
575                     currentRow.add(jcrtype.getNominalDisplaySize()); // COLUMN_SIZE
576                     currentRow.add("NULL"); // BUFFER_LENGTH
577                     currentRow.add(JcrMetaData.DEFAULT_ZERO); // DECIMAL_DIGITS
578                     currentRow.add(JcrMetaData.DEFAULT_ZERO); // NUM_PREC_RADIX
579 
580                     currentRow.add((propDefn.isMandatory() ? ResultsMetadataConstants.NULL_TYPES.NOT_NULL : ResultsMetadataConstants.NULL_TYPES.NULLABLE)); // NULLABLE
581                     currentRow.add(""); // REMARKS
582                     currentRow.add("NULL"); // COLUMN_DEF
583                     currentRow.add(JcrMetaData.DEFAULT_ZERO); // COLUMN_DEF
584                     currentRow.add(JcrMetaData.DEFAULT_ZERO); // SQL_DATETIME_SUB
585 
586                     currentRow.add(JcrMetaData.DEFAULT_ZERO); // CHAR_OCTET_LENGTH
587                     currentRow.add(new Integer(ordinal + 1)); // ORDINAL_POSITION
588                     currentRow.add(propDefn.isMandatory() ? "NO" : "YES"); // IS_NULLABLE
589                     currentRow.add("NULL"); // SCOPE_CATLOG
590                     currentRow.add("NULL"); // SCOPE_SCHEMA
591 
592                     currentRow.add("NULL"); // SCOPE_TABLE
593                     currentRow.add(JcrMetaData.DEFAULT_ZERO); // SOURCE_DATA_TYPE
594 
595                     // add the current row to the list of records.
596                     records.add(currentRow);
597 
598                     ++ordinal;
599                 }
600 
601             }// end of while
602 
603             JcrStatement jcrstmt = new JcrStatement(this.connection);
604             QueryResult queryresult = MetaDataQueryResult.createResultSet(records, resultSetMetaData);
605             return new JcrResultSet(jcrstmt, queryresult, resultSetMetaData);
606 
607         } catch (RepositoryException e) {
608             throw new SQLException(e.getLocalizedMessage());
609         }
610 
611     }
612 
613     /**
614      * {@inheritDoc}
615      * 
616      * @see java.sql.DatabaseMetaData#getCrossReference(java.lang.String, java.lang.String, java.lang.String, java.lang.String,
617      *      java.lang.String, java.lang.String)
618      */
619     @Override
620     public ResultSet getCrossReference( String parentCatalog,
621                                         String parentSchema,
622                                         String parentTable,
623                                         String foreignCatalog,
624                                         String foreignSchema,
625                                         String foreignTable ) throws SQLException {
626         return null;
627     }
628 
629     /**
630      * {@inheritDoc}
631      * 
632      * @see java.sql.DatabaseMetaData#getDefaultTransactionIsolation()
633      */
634     @Override
635     public int getDefaultTransactionIsolation() throws SQLException {
636         return Connection.TRANSACTION_NONE;
637     }
638 
639     /**
640      * {@inheritDoc}
641      * <p>
642      * This driver maps REFERENCE properties as keys, and therefore it represents as imported keys those REFERENCE properties on
643      * the type identified by the table name.
644      * </p>
645      * 
646      * @see java.sql.DatabaseMetaData#getExportedKeys(java.lang.String, java.lang.String, java.lang.String)
647      */
648     @Override
649     public ResultSet getExportedKeys( String catalog,
650                                       String schema,
651                                       String table ) throws SQLException {
652         return null;
653     }
654 
655     /**
656      * {@inheritDoc}
657      * 
658      * @see java.sql.DatabaseMetaData#getExtraNameCharacters()
659      */
660     @Override
661     public String getExtraNameCharacters() throws SQLException {
662         return null;
663     }
664 
665     /**
666      * {@inheritDoc}
667      * 
668      * @see java.sql.DatabaseMetaData#getFunctionColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
669      */
670     @Override
671     public ResultSet getFunctionColumns( String catalog,
672                                          String schemaPattern,
673                                          String functionNamePattern,
674                                          String columnNamePattern ) throws SQLException {
675         return null;
676     }
677 
678     /**
679      * {@inheritDoc}
680      * 
681      * @see java.sql.DatabaseMetaData#getFunctions(java.lang.String, java.lang.String, java.lang.String)
682      */
683     @Override
684     public ResultSet getFunctions( String catalog,
685                                    String schemaPattern,
686                                    String functionNamePattern ) throws SQLException {
687         return null;
688     }
689 
690     /**
691      * {@inheritDoc}
692      * <p>
693      * JCR-SQL2 allows identifiers to be surrounded by matching single quotes, double quotes, or opening and closing square
694      * brackets. Therefore, this method returns a single-quote character as the quote string.
695      * </p>
696      * 
697      * @see java.sql.DatabaseMetaData#getIdentifierQuoteString()
698      */
699     @Override
700     public String getIdentifierQuoteString() {
701         return "'";
702     }
703 
704     /**
705      * {@inheritDoc}
706      * <p>
707      * This driver maps REFERENCE properties as keys, and therefore it represents as imported keys those properties on other types
708      * referencing the type identified by the table name.
709      * </p>
710      * 
711      * @see java.sql.DatabaseMetaData#getImportedKeys(java.lang.String, java.lang.String, java.lang.String)
712      */
713     @Override
714     public ResultSet getImportedKeys( String catalog,
715                                       String schema,
716                                       String table ) throws SQLException {
717         return null;
718     }
719 
720     /**
721      * {@inheritDoc}
722      * 
723      * @see java.sql.DatabaseMetaData#getIndexInfo(java.lang.String, java.lang.String, java.lang.String, boolean, boolean)
724      */
725     @Override
726     public ResultSet getIndexInfo( String catalog,
727                                    String schema,
728                                    String table,
729                                    boolean unique,
730                                    boolean approximate ) throws SQLException {
731         return null;
732     }
733 
734     /**
735      * {@inheritDoc}
736      * <p>
737      * There is no maximum length of binary literals (or if there is a limit it is not known), so this method returns 0.
738      * </p>
739      * 
740      * @see java.sql.DatabaseMetaData#getMaxBinaryLiteralLength()
741      */
742     @Override
743     public int getMaxBinaryLiteralLength() {
744         return JcrMetaData.NO_LIMIT; // no limit
745     }
746 
747     /**
748      * {@inheritDoc}
749      * <p>
750      * There is no maximum length of the catalog (repository) names - or the limit is not known.
751      * </p>
752      * 
753      * @see java.sql.DatabaseMetaData#getMaxCatalogNameLength()
754      */
755     @Override
756     public int getMaxCatalogNameLength() {
757         return JcrMetaData.NO_LIMIT; // none
758     }
759 
760     /**
761      * {@inheritDoc}
762      * <p>
763      * There is no maximum length of character literals (or if there is a limit it is not known), so this method returns 0.
764      * </p>
765      * 
766      * @see java.sql.DatabaseMetaData#getMaxCharLiteralLength()
767      */
768     @Override
769     public int getMaxCharLiteralLength() {
770         return JcrMetaData.NO_LIMIT;
771     }
772 
773     /**
774      * {@inheritDoc}
775      * <p>
776      * There is no maximum length of column names (or if there is a limit it is not known), so this method returns 0.
777      * </p>
778      * 
779      * @see java.sql.DatabaseMetaData#getMaxColumnNameLength()
780      */
781     @Override
782     public int getMaxColumnNameLength() {
783         return JcrMetaData.NO_LIMIT; // no limit
784     }
785 
786     /**
787      * {@inheritDoc}
788      * <p>
789      * JCR-SQL2 does not support GROUP BY, so this method returns 0.
790      * </p>
791      * 
792      * @see java.sql.DatabaseMetaData#getMaxColumnsInGroupBy()
793      */
794     @Override
795     public int getMaxColumnsInGroupBy() {
796         return 0;
797     }
798 
799     /**
800      * {@inheritDoc}
801      * <p>
802      * There is no limit to the number of columns in an index (or if there is a limit it is not known), so this method returns 0.
803      * </p>
804      * 
805      * @see java.sql.DatabaseMetaData#getMaxColumnsInIndex()
806      */
807     @Override
808     public int getMaxColumnsInIndex() {
809         return JcrMetaData.NO_LIMIT; // no limit
810     }
811 
812     /**
813      * {@inheritDoc}
814      * <p>
815      * There is no limit to the number of columns in an ORDER BY statement (or if there is a limit it is not known), so this
816      * method returns 0.
817      * </p>
818      * 
819      * @see java.sql.DatabaseMetaData#getMaxColumnsInOrderBy()
820      */
821     @Override
822     public int getMaxColumnsInOrderBy() {
823         return JcrMetaData.NO_LIMIT; // not known (technically there is no limit, but there would be a practical limit)
824     }
825 
826     /**
827      * {@inheritDoc}
828      * <p>
829      * There is no limit to the number of columns in a select statement (or if there is a limit it is not known), so this method
830      * returns 0.
831      * </p>
832      * 
833      * @see java.sql.DatabaseMetaData#getMaxColumnsInSelect()
834      */
835     @Override
836     public int getMaxColumnsInSelect() {
837         return JcrMetaData.NO_LIMIT; // no limit
838     }
839 
840     /**
841      * {@inheritDoc}
842      * <p>
843      * There is no limit to the number of columns in a table (or if there is a limit it is not known), so this method returns 0.
844      * </p>
845      * 
846      * @see java.sql.DatabaseMetaData#getMaxColumnsInTable()
847      */
848     @Override
849     public int getMaxColumnsInTable() {
850         return JcrMetaData.NO_LIMIT; // no limit
851     }
852 
853     /**
854      * {@inheritDoc}
855      * <p>
856      * There is no limit to the number of connections (or if there is a limit it is not known), so this method returns 0.
857      * </p>
858      * 
859      * @see java.sql.DatabaseMetaData#getMaxConnections()
860      */
861     @Override
862     public int getMaxConnections() {
863         return JcrMetaData.NO_LIMIT; // no limit
864     }
865 
866     /**
867      * {@inheritDoc}
868      * <p>
869      * There are no cursors (or there is no limit), so this method returns 0.
870      * </p>
871      * 
872      * @see java.sql.DatabaseMetaData#getMaxCursorNameLength()
873      */
874     @Override
875     public int getMaxCursorNameLength() {
876         return 0;
877     }
878 
879     /**
880      * {@inheritDoc}
881      * <p>
882      * There are no indexes (or there is no limit), so this method returns 0.
883      * </p>
884      * 
885      * @see java.sql.DatabaseMetaData#getMaxIndexLength()
886      */
887     @Override
888     public int getMaxIndexLength() {
889         return 0; // no limit
890     }
891 
892     /**
893      * {@inheritDoc}
894      * <p>
895      * There are no procedures, so this method returns 0.
896      * </p>
897      * 
898      * @see java.sql.DatabaseMetaData#getMaxProcedureNameLength()
899      */
900     @Override
901     public int getMaxProcedureNameLength() {
902         return 0; // no limit
903     }
904 
905     /**
906      * {@inheritDoc}
907      * <p>
908      * There is no maximum row size.
909      * </p>
910      * 
911      * @see java.sql.DatabaseMetaData#getMaxRowSize()
912      */
913     @Override
914     public int getMaxRowSize() {
915         return JcrMetaData.NO_LIMIT; // no limit
916     }
917 
918     /**
919      * {@inheritDoc}
920      * <p>
921      * There is no maximum length of the schema (workspace) names - or the limit is not known.
922      * </p>
923      * 
924      * @see java.sql.DatabaseMetaData#getMaxSchemaNameLength()
925      */
926     @Override
927     public int getMaxSchemaNameLength() {
928         return JcrMetaData.NO_LIMIT; // none
929     }
930 
931     /**
932      * {@inheritDoc}
933      * 
934      * @see java.sql.DatabaseMetaData#getMaxStatementLength()
935      */
936     @Override
937     public int getMaxStatementLength() {
938         return 0; // no limit
939     }
940 
941     /**
942      * {@inheritDoc}
943      * 
944      * @see java.sql.DatabaseMetaData#getMaxStatements()
945      */
946     @Override
947     public int getMaxStatements() {
948         return 0; // no limit
949     }
950 
951     /**
952      * {@inheritDoc}
953      * 
954      * @see java.sql.DatabaseMetaData#getMaxTableNameLength()
955      */
956     @Override
957     public int getMaxTableNameLength() {
958         return 0; // no limit
959     }
960 
961     /**
962      * {@inheritDoc}
963      * 
964      * @see java.sql.DatabaseMetaData#getMaxTablesInSelect()
965      */
966     @Override
967     public int getMaxTablesInSelect() {
968         return 0; // not known (technically there is no limit, but there would be a practical limit)
969     }
970 
971     /**
972      * {@inheritDoc}
973      * 
974      * @see java.sql.DatabaseMetaData#getMaxUserNameLength()
975      */
976     @Override
977     public int getMaxUserNameLength() {
978         return 0; // no limit
979     }
980 
981     /**
982      * {@inheritDoc}
983      * 
984      * @see java.sql.DatabaseMetaData#getNumericFunctions()
985      */
986     @Override
987     public String getNumericFunctions() throws SQLException {
988         return null;
989     }
990 
991     /**
992      * {@inheritDoc}
993      * 
994      * @see java.sql.DatabaseMetaData#getPrimaryKeys(java.lang.String, java.lang.String, java.lang.String)
995      */
996     @Override
997     public ResultSet getPrimaryKeys( String catalog,
998                                      String schema,
999                                      String table ) throws SQLException {
1000         return null;
1001     }
1002 
1003     /**
1004      * {@inheritDoc}
1005      * 
1006      * @see java.sql.DatabaseMetaData#getProcedureColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
1007      */
1008     @Override
1009     public ResultSet getProcedureColumns( String catalog,
1010                                           String schemaPattern,
1011                                           String procedureNamePattern,
1012                                           String columnNamePattern ) throws SQLException {
1013         return null;
1014     }
1015 
1016     /**
1017      * {@inheritDoc}
1018      * 
1019      * @see java.sql.DatabaseMetaData#getProcedureTerm()
1020      */
1021     @Override
1022     public String getProcedureTerm() throws SQLException {
1023         return null;
1024     }
1025 
1026     /**
1027      * {@inheritDoc}
1028      * 
1029      * @see java.sql.DatabaseMetaData#getProcedures(java.lang.String, java.lang.String, java.lang.String)
1030      */
1031     @Override
1032     public ResultSet getProcedures( String catalog,
1033                                     String schemaPattern,
1034                                     String procedureNamePattern ) throws SQLException {
1035         return null;
1036     }
1037 
1038     /**
1039      * {@inheritDoc}
1040      * 
1041      * @see java.sql.DatabaseMetaData#getResultSetHoldability()
1042      */
1043     @Override
1044     public int getResultSetHoldability() throws SQLException {
1045         return 0;
1046     }
1047 
1048     /**
1049      * {@inheritDoc}
1050      * 
1051      * @see java.sql.DatabaseMetaData#getRowIdLifetime()
1052      */
1053     @Override
1054     public RowIdLifetime getRowIdLifetime() {
1055         return RowIdLifetime.ROWID_UNSUPPORTED;
1056     }
1057 
1058     /**
1059      * {@inheritDoc}
1060      * 
1061      * @see java.sql.DatabaseMetaData#getSQLKeywords()
1062      */
1063     @Override
1064     public String getSQLKeywords() throws SQLException {
1065         return null;
1066     }
1067 
1068     /**
1069      * {@inheritDoc}
1070      * 
1071      * @see java.sql.DatabaseMetaData#getSQLStateType()
1072      */
1073     @Override
1074     public int getSQLStateType() throws SQLException {
1075         return 0;
1076     }
1077 
1078     /**
1079      * {@inheritDoc}
1080      * 
1081      * @see java.sql.DatabaseMetaData#getSchemaTerm()
1082      */
1083     @Override
1084     public String getSchemaTerm() throws SQLException {
1085         return " ";
1086     }
1087 
1088     /**
1089      * {@inheritDoc}
1090      * 
1091      * @see java.sql.DatabaseMetaData#getSchemas()
1092      */
1093     @Override
1094     public ResultSet getSchemas() throws SQLException {
1095         List<List<?>> records = new ArrayList<List<?>>(1);
1096 
1097         /***********************************************************************
1098          * Hardcoding JDBC column names for the columns returned in results object
1099          ***********************************************************************/
1100 
1101         Map<?, Object>[] metadataList = new Map[1];
1102 
1103         metadataList[0] = MetadataProvider.getColumnMetadata(catalogName,
1104                                                              null,
1105                                                              JDBCColumnNames.COLUMNS.TABLE_SCHEM,
1106                                                              JcrType.DefaultDataTypes.STRING,
1107                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1108                                                              this.connection);
1109 
1110         MetadataProvider provider = new MetadataProvider(metadataList);
1111 
1112         ResultSetMetaDataImpl resultSetMetaData = new ResultSetMetaDataImpl(provider);
1113 
1114         JcrStatement stmt = new JcrStatement(this.connection);
1115         QueryResult queryresult = MetaDataQueryResult.createResultSet(records, resultSetMetaData);
1116         ResultSet rs = new JcrResultSet(stmt, queryresult, resultSetMetaData);
1117 
1118         return rs;
1119     }
1120 
1121     /**
1122      * {@inheritDoc}
1123      * 
1124      * @see java.sql.DatabaseMetaData#getSchemas(java.lang.String, java.lang.String)
1125      */
1126     @Override
1127     public ResultSet getSchemas( String catalog,
1128                                  String schemaPattern ) throws SQLException {
1129         return getSchemas();
1130     }
1131 
1132     /**
1133      * {@inheritDoc}
1134      * 
1135      * @see java.sql.DatabaseMetaData#getSearchStringEscape()
1136      */
1137     @Override
1138     public String getSearchStringEscape() throws SQLException {
1139         return null;
1140     }
1141 
1142     /**
1143      * {@inheritDoc}
1144      * 
1145      * @see java.sql.DatabaseMetaData#getStringFunctions()
1146      */
1147     @Override
1148     public String getStringFunctions() throws SQLException {
1149         return null;
1150     }
1151 
1152     /**
1153      * {@inheritDoc}
1154      * 
1155      * @see java.sql.DatabaseMetaData#getSuperTables(java.lang.String, java.lang.String, java.lang.String)
1156      */
1157     @Override
1158     public ResultSet getSuperTables( String catalog,
1159                                      String schemaPattern,
1160                                      String tableNamePattern ) throws SQLException {
1161         return null;
1162     }
1163 
1164     /**
1165      * {@inheritDoc}
1166      * 
1167      * @see java.sql.DatabaseMetaData#getSuperTypes(java.lang.String, java.lang.String, java.lang.String)
1168      */
1169     @Override
1170     public ResultSet getSuperTypes( String catalog,
1171                                     String schemaPattern,
1172                                     String typeNamePattern ) throws SQLException {
1173         return null;
1174     }
1175 
1176     /**
1177      * {@inheritDoc}
1178      * 
1179      * @see java.sql.DatabaseMetaData#getSystemFunctions()
1180      */
1181     @Override
1182     public String getSystemFunctions() throws SQLException {
1183         return null;
1184     }
1185 
1186     /**
1187      * {@inheritDoc}
1188      * 
1189      * @see java.sql.DatabaseMetaData#getTablePrivileges(java.lang.String, java.lang.String, java.lang.String)
1190      */
1191     @Override
1192     public ResultSet getTablePrivileges( String catalog,
1193                                          String schemaPattern,
1194                                          String tableNamePattern ) throws SQLException {
1195         return null;
1196     }
1197 
1198     /**
1199      * {@inheritDoc}
1200      * 
1201      * @see java.sql.DatabaseMetaData#getTableTypes()
1202      */
1203     @SuppressWarnings( "unchecked" )
1204     @Override
1205     public ResultSet getTableTypes() throws SQLException {
1206 
1207         List<List<?>> records = new ArrayList<List<?>>(1);
1208         List<String> row = Arrays.asList(new String[] {ResultsMetadataConstants.TABLE_TYPES.VIEW});
1209         records.add(row);
1210 
1211         /***********************************************************************
1212          * Hardcoding JDBC column names for the columns returned in results object
1213          ***********************************************************************/
1214 
1215         Map<?, Object>[] metadataList = new Map[1];
1216 
1217         metadataList[0] = MetadataProvider.getColumnMetadata(catalogName,
1218                                                              null,
1219                                                              JDBCColumnNames.TABLE_TYPES.TABLE_TYPE,
1220                                                              JcrType.DefaultDataTypes.STRING,
1221                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1222                                                              this.connection);
1223 
1224         MetadataProvider provider = new MetadataProvider(metadataList);
1225 
1226         ResultSetMetaDataImpl resultSetMetaData = new ResultSetMetaDataImpl(provider);
1227 
1228         JcrStatement stmt = new JcrStatement(this.connection);
1229         QueryResult queryresult = MetaDataQueryResult.createResultSet(records, resultSetMetaData);
1230         ResultSet rs = new JcrResultSet(stmt, queryresult, resultSetMetaData);
1231         return rs;
1232     }
1233 
1234     /**
1235      * {@inheritDoc}
1236      * 
1237      * @see java.sql.DatabaseMetaData#getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
1238      */
1239     @Override
1240     public ResultSet getTables( String catalog,
1241                                 String schemaPattern,
1242                                 String tableNamePattern,
1243                                 String[] types ) throws SQLException {
1244 
1245         JcrDriver.logger.log(Level.FINE, "getTables: " + catalog + ":" + schemaPattern + ":" + tableNamePattern + ":" + types);
1246 
1247         // Get all tables if tableNamePattern is null
1248         if (tableNamePattern == null) {
1249             tableNamePattern = WILDCARD;
1250         }
1251 
1252         Map<?, Object>[] metadataList = new Map[JDBCColumnPositions.TABLES.MAX_COLUMNS];
1253 
1254         metadataList[0] = MetadataProvider.getColumnMetadata(catalogName,
1255                                                              null,
1256                                                              JDBCColumnNames.TABLES.TABLE_CAT,
1257                                                              JcrType.DefaultDataTypes.STRING,
1258                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1259                                                              this.connection);
1260         metadataList[1] = MetadataProvider.getColumnMetadata(catalogName,
1261                                                              null,
1262                                                              JDBCColumnNames.TABLES.TABLE_SCHEM,
1263                                                              JcrType.DefaultDataTypes.STRING,
1264                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1265                                                              this.connection);
1266         metadataList[2] = MetadataProvider.getColumnMetadata(catalogName,
1267                                                              null,
1268                                                              JDBCColumnNames.TABLES.TABLE_NAME,
1269                                                              JcrType.DefaultDataTypes.STRING,
1270                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
1271                                                              this.connection);
1272         metadataList[3] = MetadataProvider.getColumnMetadata(catalogName,
1273                                                              null,
1274                                                              JDBCColumnNames.TABLES.TABLE_TYPE,
1275                                                              JcrType.DefaultDataTypes.STRING,
1276                                                              ResultsMetadataConstants.NULL_TYPES.NOT_NULL,
1277                                                              this.connection);
1278         metadataList[4] = MetadataProvider.getColumnMetadata(catalogName,
1279                                                              null,
1280                                                              JDBCColumnNames.TABLES.REMARKS,
1281                                                              JcrType.DefaultDataTypes.STRING,
1282                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1283                                                              this.connection);
1284         metadataList[5] = MetadataProvider.getColumnMetadata(catalogName,
1285                                                              null,
1286                                                              JDBCColumnNames.TABLES.TYPE_CAT,
1287                                                              JcrType.DefaultDataTypes.STRING,
1288                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1289                                                              this.connection);
1290         metadataList[6] = MetadataProvider.getColumnMetadata(catalogName,
1291                                                              null,
1292                                                              JDBCColumnNames.TABLES.TYPE_SCHEM,
1293                                                              JcrType.DefaultDataTypes.STRING,
1294                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1295                                                              this.connection);
1296         metadataList[7] = MetadataProvider.getColumnMetadata(catalogName,
1297                                                              null,
1298                                                              JDBCColumnNames.TABLES.TYPE_NAME,
1299                                                              JcrType.DefaultDataTypes.STRING,
1300                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1301                                                              this.connection);
1302         metadataList[8] = MetadataProvider.getColumnMetadata(catalogName,
1303                                                              null,
1304                                                              JDBCColumnNames.TABLES.SELF_REFERENCING_COL_NAME,
1305                                                              JcrType.DefaultDataTypes.STRING,
1306                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1307                                                              this.connection);
1308         metadataList[9] = MetadataProvider.getColumnMetadata(catalogName,
1309                                                              null,
1310                                                              JDBCColumnNames.TABLES.REF_GENERATION,
1311                                                              JcrType.DefaultDataTypes.STRING,
1312                                                              ResultsMetadataConstants.NULL_TYPES.NULLABLE,
1313                                                              this.connection);
1314 
1315         MetadataProvider provider = new MetadataProvider(metadataList);
1316 
1317         ResultSetMetaDataImpl resultSetMetaData = new ResultSetMetaDataImpl(provider);
1318 
1319         List<List<?>> records = new ArrayList<List<?>>();
1320 
1321         try {
1322             List<NodeType> nodetypes = filterNodeTypes(tableNamePattern);
1323 
1324             Iterator<NodeType> nodeIt = nodetypes.iterator();
1325             // build the list of records from the nodetypes.
1326             while (nodeIt.hasNext()) {
1327 
1328                 NodeType type = nodeIt.next();
1329                 if (!type.isQueryable()) continue;
1330 
1331                 // list represents a record on the Results object.
1332                 List<Object> currentRow = new ArrayList<Object>(JDBCColumnPositions.TABLES.MAX_COLUMNS);
1333                 // add values in the current record on the Results object to the list
1334                 // number of values to be fetched from each row is MAX_COLUMNS.
1335 
1336                 currentRow.add(catalogName); // TABLE_CAT
1337                 currentRow.add("NULL"); // TABLE_SCHEM
1338                 currentRow.add(type.getName()); // TABLE_NAME
1339                 currentRow.add(ResultsMetadataConstants.TABLE_TYPES.VIEW); // TABLE_TYPE
1340                 currentRow.add("Is Mixin: " + type.isMixin()); // REMARKS
1341                 currentRow.add("NULL"); // TYPE_CAT
1342                 currentRow.add("NULL"); // TYPE_SCHEM
1343                 currentRow.add("NULL"); // TYPE_NAME
1344                 currentRow.add(type.getPrimaryItemName()); // SELF_REF
1345                 currentRow.add("DERIVED"); // REF_GEN
1346 
1347                 // add the current row to the list of records.
1348                 records.add(currentRow);
1349             }// end of while
1350 
1351             JcrStatement jcrstmt = new JcrStatement(this.connection);
1352             QueryResult queryresult = MetaDataQueryResult.createResultSet(records, resultSetMetaData);
1353 
1354             return new JcrResultSet(jcrstmt, queryresult, resultSetMetaData);
1355 
1356         } catch (RepositoryException e) {
1357             throw new SQLException(e.getLocalizedMessage());
1358         }
1359     }
1360 
1361     /**
1362      * {@inheritDoc}
1363      * 
1364      * @see java.sql.DatabaseMetaData#getTimeDateFunctions()
1365      */
1366     @Override
1367     public String getTimeDateFunctions() throws SQLException {
1368         return null;
1369     }
1370 
1371     /**
1372      * {@inheritDoc}
1373      * 
1374      * @see java.sql.DatabaseMetaData#getTypeInfo()
1375      */
1376     @Override
1377     public ResultSet getTypeInfo() throws SQLException {
1378         return null;
1379     }
1380 
1381     /**
1382      * {@inheritDoc}
1383      * 
1384      * @see java.sql.DatabaseMetaData#getUDTs(java.lang.String, java.lang.String, java.lang.String, int[])
1385      */
1386     @Override
1387     public ResultSet getUDTs( String catalog,
1388                               String schemaPattern,
1389                               String typeNamePattern,
1390                               int[] types ) throws SQLException {
1391         return null;
1392     }
1393 
1394     /**
1395      * {@inheritDoc}
1396      * <p>
1397      * This method returns the effective URL of the connection, which includes all connection properties (even if those properties
1398      * were passed in via the Properties argument). Note that each character in the password is replaced with a '*' character.
1399      * </p>
1400      * 
1401      * @see java.sql.DatabaseMetaData#getURL()
1402      */
1403     @Override
1404     public String getURL() {
1405         return connection.info().getEffectiveUrl();
1406     }
1407 
1408     /**
1409      * {@inheritDoc}
1410      * 
1411      * @see java.sql.DatabaseMetaData#getUserName()
1412      */
1413     @Override
1414     public String getUserName() {
1415         return connection.info().getUsername();
1416     }
1417 
1418     /**
1419      * {@inheritDoc}
1420      * 
1421      * @see java.sql.DatabaseMetaData#getVersionColumns(java.lang.String, java.lang.String, java.lang.String)
1422      */
1423     @Override
1424     public ResultSet getVersionColumns( String catalog,
1425                                         String schema,
1426                                         String table ) throws SQLException {
1427         return null;
1428     }
1429 
1430     /**
1431      * {@inheritDoc}
1432      * 
1433      * @see java.sql.DatabaseMetaData#insertsAreDetected(int)
1434      */
1435     @Override
1436     public boolean insertsAreDetected( int type ) {
1437         return false; // read-only
1438     }
1439 
1440     /**
1441      * {@inheritDoc}
1442      * 
1443      * @see java.sql.DatabaseMetaData#isCatalogAtStart()
1444      */
1445     @Override
1446     public boolean isCatalogAtStart() throws SQLException {
1447         return true;
1448     }
1449 
1450     /**
1451      * {@inheritDoc}
1452      * 
1453      * @see java.sql.DatabaseMetaData#locatorsUpdateCopy()
1454      */
1455     @Override
1456     public boolean locatorsUpdateCopy() {
1457         return false; // read-only
1458     }
1459 
1460     /**
1461      * {@inheritDoc}
1462      * 
1463      * @see java.sql.DatabaseMetaData#nullPlusNonNullIsNull()
1464      */
1465     @Override
1466     public boolean nullPlusNonNullIsNull() {
1467         return false;
1468     }
1469 
1470     /**
1471      * {@inheritDoc}
1472      * <p>
1473      * Assumed to be false for JCR implementations (meaning that sort order IS used), though section 6.7.37 of JCR 2.0
1474      * specification says ordering of null values is implementation-determined.
1475      * </p>
1476      * 
1477      * @see java.sql.DatabaseMetaData#nullsAreSortedAtEnd()
1478      */
1479     @Override
1480     public boolean nullsAreSortedAtEnd() {
1481         return false;
1482     }
1483 
1484     /**
1485      * {@inheritDoc}
1486      * <p>
1487      * Assumed to be false for JCR implementations (meaning that sort order IS used), though section 6.7.37 of JCR 2.0
1488      * specification says ordering of null values is implementation-determined.
1489      * </p>
1490      * 
1491      * @see java.sql.DatabaseMetaData#nullsAreSortedAtStart()
1492      */
1493     @Override
1494     public boolean nullsAreSortedAtStart() {
1495         return false;
1496     }
1497 
1498     /**
1499      * {@inheritDoc}
1500      * <p>
1501      * Assumed to be false for JCR implementations, though section 6.7.37 of JCR 2.0 specification says ordering of null values is
1502      * implementation-determined.
1503      * </p>
1504      * 
1505      * @see java.sql.DatabaseMetaData#nullsAreSortedHigh()
1506      */
1507     @Override
1508     public boolean nullsAreSortedHigh() {
1509         return false;
1510     }
1511 
1512     /**
1513      * {@inheritDoc}
1514      * <p>
1515      * Assumed to be true for JCR implementations, though section 6.7.37 of JCR 2.0 specification says ordering of null values is
1516      * implementation-determined.
1517      * </p>
1518      * 
1519      * @see java.sql.DatabaseMetaData#nullsAreSortedLow()
1520      */
1521     @Override
1522     public boolean nullsAreSortedLow() {
1523         return true;
1524     }
1525 
1526     /**
1527      * {@inheritDoc}
1528      * 
1529      * @see java.sql.DatabaseMetaData#othersDeletesAreVisible(int)
1530      */
1531     @Override
1532     public boolean othersDeletesAreVisible( int type ) {
1533         return false; // read-only
1534     }
1535 
1536     /**
1537      * {@inheritDoc}
1538      * 
1539      * @see java.sql.DatabaseMetaData#othersInsertsAreVisible(int)
1540      */
1541     @Override
1542     public boolean othersInsertsAreVisible( int type ) {
1543         return false; // read-only
1544     }
1545 
1546     /**
1547      * {@inheritDoc}
1548      * 
1549      * @see java.sql.DatabaseMetaData#othersUpdatesAreVisible(int)
1550      */
1551     @Override
1552     public boolean othersUpdatesAreVisible( int type ) {
1553         return false; // read-only
1554     }
1555 
1556     /**
1557      * {@inheritDoc}
1558      * 
1559      * @see java.sql.DatabaseMetaData#ownDeletesAreVisible(int)
1560      */
1561     @Override
1562     public boolean ownDeletesAreVisible( int type ) {
1563         return false; // read-only
1564     }
1565 
1566     /**
1567      * {@inheritDoc}
1568      * 
1569      * @see java.sql.DatabaseMetaData#ownInsertsAreVisible(int)
1570      */
1571     @Override
1572     public boolean ownInsertsAreVisible( int type ) {
1573         return false; // read-only
1574     }
1575 
1576     /**
1577      * {@inheritDoc}
1578      * 
1579      * @see java.sql.DatabaseMetaData#ownUpdatesAreVisible(int)
1580      */
1581     @Override
1582     public boolean ownUpdatesAreVisible( int type ) {
1583         return false; // read-only
1584     }
1585 
1586     /**
1587      * {@inheritDoc}
1588      * 
1589      * @see java.sql.DatabaseMetaData#storesLowerCaseIdentifiers()
1590      */
1591     @Override
1592     public boolean storesLowerCaseIdentifiers() {
1593         return false; // JCR node types are case-sensitive
1594     }
1595 
1596     /**
1597      * {@inheritDoc}
1598      * 
1599      * @see java.sql.DatabaseMetaData#storesLowerCaseQuotedIdentifiers()
1600      */
1601     @Override
1602     public boolean storesLowerCaseQuotedIdentifiers() {
1603         return false; // JCR node types are case-sensitive
1604     }
1605 
1606     /**
1607      * {@inheritDoc}
1608      * 
1609      * @see java.sql.DatabaseMetaData#storesMixedCaseIdentifiers()
1610      */
1611     @Override
1612     public boolean storesMixedCaseIdentifiers() {
1613         return false; // JCR node types are case-sensitive
1614     }
1615 
1616     /**
1617      * {@inheritDoc}
1618      * 
1619      * @see java.sql.DatabaseMetaData#storesMixedCaseQuotedIdentifiers()
1620      */
1621     @Override
1622     public boolean storesMixedCaseQuotedIdentifiers() {
1623         return false; // JCR node types are case-sensitive
1624     }
1625 
1626     /**
1627      * {@inheritDoc}
1628      * 
1629      * @see java.sql.DatabaseMetaData#storesUpperCaseIdentifiers()
1630      */
1631     @Override
1632     public boolean storesUpperCaseIdentifiers() {
1633         return false; // JCR node types are case-sensitive
1634     }
1635 
1636     /**
1637      * {@inheritDoc}
1638      * 
1639      * @see java.sql.DatabaseMetaData#storesUpperCaseQuotedIdentifiers()
1640      */
1641     @Override
1642     public boolean storesUpperCaseQuotedIdentifiers() {
1643         return false; // JCR node types are case-sensitive
1644     }
1645 
1646     /**
1647      * {@inheritDoc}
1648      * 
1649      * @see java.sql.DatabaseMetaData#supportsANSI92EntryLevelSQL()
1650      */
1651     @Override
1652     public boolean supportsANSI92EntryLevelSQL() {
1653         return false; // JCR-SQL2 is not entry-level ANSI92 SQL
1654     }
1655 
1656     /**
1657      * {@inheritDoc}
1658      * 
1659      * @see java.sql.DatabaseMetaData#supportsANSI92FullSQL()
1660      */
1661     @Override
1662     public boolean supportsANSI92FullSQL() {
1663         return false; // JCR-SQL2 is not full ANSI92 SQL
1664     }
1665 
1666     /**
1667      * {@inheritDoc}
1668      * 
1669      * @see java.sql.DatabaseMetaData#supportsANSI92IntermediateSQL()
1670      */
1671     @Override
1672     public boolean supportsANSI92IntermediateSQL() {
1673         return false; // JCR-SQL2 is not intermediate ANSI92 SQL
1674     }
1675 
1676     /**
1677      * {@inheritDoc}
1678      * 
1679      * @see java.sql.DatabaseMetaData#supportsAlterTableWithAddColumn()
1680      */
1681     @Override
1682     public boolean supportsAlterTableWithAddColumn() {
1683         // Not in JCR-SQL2
1684         return false;
1685     }
1686 
1687     /**
1688      * {@inheritDoc}
1689      * 
1690      * @see java.sql.DatabaseMetaData#supportsAlterTableWithDropColumn()
1691      */
1692     @Override
1693     public boolean supportsAlterTableWithDropColumn() {
1694         // Not in JCR-SQL2
1695         return false;
1696     }
1697 
1698     /**
1699      * {@inheritDoc}
1700      * 
1701      * @see java.sql.DatabaseMetaData#supportsBatchUpdates()
1702      */
1703     @Override
1704     public boolean supportsBatchUpdates() {
1705         // Not in JCR-SQL2
1706         return false;
1707     }
1708 
1709     /**
1710      * {@inheritDoc}
1711      * 
1712      * @see java.sql.DatabaseMetaData#supportsCatalogsInDataManipulation()
1713      */
1714     @Override
1715     public boolean supportsCatalogsInDataManipulation() {
1716         // Not in JCR-SQL2
1717         return false;
1718     }
1719 
1720     /**
1721      * {@inheritDoc}
1722      * 
1723      * @see java.sql.DatabaseMetaData#supportsCatalogsInIndexDefinitions()
1724      */
1725     @Override
1726     public boolean supportsCatalogsInIndexDefinitions() {
1727         // No such thing in JCR-SQL2
1728         return false;
1729     }
1730 
1731     /**
1732      * {@inheritDoc}
1733      * 
1734      * @see java.sql.DatabaseMetaData#supportsCatalogsInPrivilegeDefinitions()
1735      */
1736     @Override
1737     public boolean supportsCatalogsInPrivilegeDefinitions() {
1738         // No defining privileges in JCR 1.0 or 2.0 or JCR-SQL2
1739         return false;
1740     }
1741 
1742     /**
1743      * {@inheritDoc}
1744      * 
1745      * @see java.sql.DatabaseMetaData#supportsCatalogsInProcedureCalls()
1746      */
1747     @Override
1748     public boolean supportsCatalogsInProcedureCalls() {
1749         // No such thing in JCR-SQL2
1750         return false;
1751     }
1752 
1753     /**
1754      * {@inheritDoc}
1755      * 
1756      * @see java.sql.DatabaseMetaData#supportsCatalogsInTableDefinitions()
1757      */
1758     @Override
1759     public boolean supportsCatalogsInTableDefinitions() {
1760         // No defining tables in JCR 1.0 or 2.0 or JCR-SQL2
1761         return false;
1762     }
1763 
1764     /**
1765      * {@inheritDoc}
1766      * 
1767      * @see java.sql.DatabaseMetaData#supportsColumnAliasing()
1768      */
1769     @Override
1770     public boolean supportsColumnAliasing() {
1771         // JCR-SQL2 does support aliases on column names (section 6.7.39)
1772         return false;
1773     }
1774 
1775     /**
1776      * {@inheritDoc}
1777      * 
1778      * @see java.sql.DatabaseMetaData#supportsConvert()
1779      */
1780     @Override
1781     public boolean supportsConvert() throws SQLException {
1782         return false;
1783     }
1784 
1785     /**
1786      * {@inheritDoc}
1787      * 
1788      * @see java.sql.DatabaseMetaData#supportsConvert(int, int)
1789      */
1790     @Override
1791     public boolean supportsConvert( int fromType,
1792                                     int toType ) throws SQLException {
1793         return false;
1794     }
1795 
1796     /**
1797      * {@inheritDoc}
1798      * 
1799      * @see java.sql.DatabaseMetaData#supportsCoreSQLGrammar()
1800      */
1801     @Override
1802     public boolean supportsCoreSQLGrammar() throws SQLException {
1803         return false;
1804     }
1805 
1806     /**
1807      * {@inheritDoc}
1808      * 
1809      * @see java.sql.DatabaseMetaData#supportsCorrelatedSubqueries()
1810      */
1811     @Override
1812     public boolean supportsCorrelatedSubqueries() throws SQLException {
1813         return false;
1814     }
1815 
1816     /**
1817      * {@inheritDoc}
1818      * 
1819      * @see java.sql.DatabaseMetaData#supportsDataDefinitionAndDataManipulationTransactions()
1820      */
1821     @Override
1822     public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
1823         return false;
1824     }
1825 
1826     /**
1827      * {@inheritDoc}
1828      * 
1829      * @see java.sql.DatabaseMetaData#supportsDataManipulationTransactionsOnly()
1830      */
1831     @Override
1832     public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
1833         return false;
1834     }
1835 
1836     /**
1837      * {@inheritDoc}
1838      * 
1839      * @see java.sql.DatabaseMetaData#supportsDifferentTableCorrelationNames()
1840      */
1841     @Override
1842     public boolean supportsDifferentTableCorrelationNames() throws SQLException {
1843         return false;
1844     }
1845 
1846     /**
1847      * {@inheritDoc}
1848      * 
1849      * @see java.sql.DatabaseMetaData#supportsExpressionsInOrderBy()
1850      */
1851     @Override
1852     public boolean supportsExpressionsInOrderBy() throws SQLException {
1853         return false;
1854     }
1855 
1856     /**
1857      * {@inheritDoc}
1858      * 
1859      * @see java.sql.DatabaseMetaData#supportsExtendedSQLGrammar()
1860      */
1861     @Override
1862     public boolean supportsExtendedSQLGrammar() throws SQLException {
1863         return false;
1864     }
1865 
1866     /**
1867      * {@inheritDoc}
1868      * 
1869      * @see java.sql.DatabaseMetaData#supportsFullOuterJoins()
1870      */
1871     @Override
1872     public boolean supportsFullOuterJoins() {
1873         // JCR-SQL2 does not support FULL OUTER JOIN ...
1874         return false;
1875     }
1876 
1877     /**
1878      * {@inheritDoc}
1879      * 
1880      * @see java.sql.DatabaseMetaData#supportsGetGeneratedKeys()
1881      */
1882     @Override
1883     public boolean supportsGetGeneratedKeys() throws SQLException {
1884         return false;
1885     }
1886 
1887     /**
1888      * {@inheritDoc}
1889      * 
1890      * @see java.sql.DatabaseMetaData#supportsGroupBy()
1891      */
1892     @Override
1893     public boolean supportsGroupBy() throws SQLException {
1894         return false; // not in JCR-SQL2;
1895     }
1896 
1897     /**
1898      * {@inheritDoc}
1899      * 
1900      * @see java.sql.DatabaseMetaData#supportsGroupByBeyondSelect()
1901      */
1902     @Override
1903     public boolean supportsGroupByBeyondSelect() throws SQLException {
1904         return false; // not in JCR-SQL2;
1905     }
1906 
1907     /**
1908      * {@inheritDoc}
1909      * 
1910      * @see java.sql.DatabaseMetaData#supportsGroupByUnrelated()
1911      */
1912     @Override
1913     public boolean supportsGroupByUnrelated() throws SQLException {
1914         return false; // not in JCR-SQL2;
1915     }
1916 
1917     /**
1918      * {@inheritDoc}
1919      * 
1920      * @see java.sql.DatabaseMetaData#supportsIntegrityEnhancementFacility()
1921      */
1922     @Override
1923     public boolean supportsIntegrityEnhancementFacility() throws SQLException {
1924         return false;
1925     }
1926 
1927     /**
1928      * {@inheritDoc}
1929      * 
1930      * @see java.sql.DatabaseMetaData#supportsLikeEscapeClause()
1931      */
1932     @Override
1933     public boolean supportsLikeEscapeClause() throws SQLException {
1934         return false;
1935     }
1936 
1937     /**
1938      * {@inheritDoc}
1939      * 
1940      * @see java.sql.DatabaseMetaData#supportsLimitedOuterJoins()
1941      */
1942     @Override
1943     public boolean supportsLimitedOuterJoins() throws SQLException {
1944         return false;
1945     }
1946 
1947     /**
1948      * {@inheritDoc}
1949      * 
1950      * @see java.sql.DatabaseMetaData#supportsMinimumSQLGrammar()
1951      */
1952     @Override
1953     public boolean supportsMinimumSQLGrammar() throws SQLException {
1954         return false;
1955     }
1956 
1957     /**
1958      * {@inheritDoc}
1959      * 
1960      * @see java.sql.DatabaseMetaData#supportsMixedCaseIdentifiers()
1961      */
1962     @Override
1963     public boolean supportsMixedCaseIdentifiers() throws SQLException {
1964         return false;
1965     }
1966 
1967     /**
1968      * {@inheritDoc}
1969      * 
1970      * @see java.sql.DatabaseMetaData#supportsMixedCaseQuotedIdentifiers()
1971      */
1972     @Override
1973     public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
1974         return false;
1975     }
1976 
1977     /**
1978      * {@inheritDoc}
1979      * 
1980      * @see java.sql.DatabaseMetaData#supportsMultipleOpenResults()
1981      */
1982     @Override
1983     public boolean supportsMultipleOpenResults() throws SQLException {
1984         return false;
1985     }
1986 
1987     /**
1988      * {@inheritDoc}
1989      * 
1990      * @see java.sql.DatabaseMetaData#supportsMultipleResultSets()
1991      */
1992     @Override
1993     public boolean supportsMultipleResultSets() throws SQLException {
1994         return false;
1995     }
1996 
1997     /**
1998      * {@inheritDoc}
1999      * 
2000      * @see java.sql.DatabaseMetaData#supportsMultipleTransactions()
2001      */
2002     @Override
2003     public boolean supportsMultipleTransactions() throws SQLException {
2004         return false;
2005     }
2006 
2007     /**
2008      * {@inheritDoc}
2009      * 
2010      * @see java.sql.DatabaseMetaData#supportsNamedParameters()
2011      */
2012     @Override
2013     public boolean supportsNamedParameters() throws SQLException {
2014         return false;
2015     }
2016 
2017     /**
2018      * {@inheritDoc}
2019      * 
2020      * @see java.sql.DatabaseMetaData#supportsNonNullableColumns()
2021      */
2022     @Override
2023     public boolean supportsNonNullableColumns() throws SQLException {
2024         return false;
2025     }
2026 
2027     /**
2028      * {@inheritDoc}
2029      * 
2030      * @see java.sql.DatabaseMetaData#supportsOpenCursorsAcrossCommit()
2031      */
2032     @Override
2033     public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
2034         return false;
2035     }
2036 
2037     /**
2038      * {@inheritDoc}
2039      * 
2040      * @see java.sql.DatabaseMetaData#supportsOpenCursorsAcrossRollback()
2041      */
2042     @Override
2043     public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
2044         return false;
2045     }
2046 
2047     /**
2048      * {@inheritDoc}
2049      * 
2050      * @see java.sql.DatabaseMetaData#supportsOpenStatementsAcrossCommit()
2051      */
2052     @Override
2053     public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
2054         return false;
2055     }
2056 
2057     /**
2058      * {@inheritDoc}
2059      * 
2060      * @see java.sql.DatabaseMetaData#supportsOpenStatementsAcrossRollback()
2061      */
2062     @Override
2063     public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
2064         return false;
2065     }
2066 
2067     /**
2068      * {@inheritDoc}
2069      * 
2070      * @see java.sql.DatabaseMetaData#supportsOrderByUnrelated()
2071      */
2072     @Override
2073     public boolean supportsOrderByUnrelated() throws SQLException {
2074         return false;
2075     }
2076 
2077     /**
2078      * {@inheritDoc}
2079      * 
2080      * @see java.sql.DatabaseMetaData#supportsOuterJoins()
2081      */
2082     @Override
2083     public boolean supportsOuterJoins() {
2084         return true; // JCR-SQL2
2085     }
2086 
2087     /**
2088      * {@inheritDoc}
2089      * 
2090      * @see java.sql.DatabaseMetaData#supportsPositionedDelete()
2091      */
2092     @Override
2093     public boolean supportsPositionedDelete() {
2094         return false; // read-only
2095     }
2096 
2097     /**
2098      * {@inheritDoc}
2099      * 
2100      * @see java.sql.DatabaseMetaData#supportsPositionedUpdate()
2101      */
2102     @Override
2103     public boolean supportsPositionedUpdate() {
2104         return false; // read-only
2105     }
2106 
2107     /**
2108      * {@inheritDoc}
2109      * 
2110      * @see java.sql.DatabaseMetaData#supportsResultSetConcurrency(int, int)
2111      */
2112     @Override
2113     public boolean supportsResultSetConcurrency( int type,
2114                                                  int concurrency ) throws SQLException {
2115         return false;
2116     }
2117 
2118     /**
2119      * {@inheritDoc}
2120      * 
2121      * @see java.sql.DatabaseMetaData#supportsResultSetHoldability(int)
2122      */
2123     @Override
2124     public boolean supportsResultSetHoldability( int holdability ) throws SQLException {
2125         return false;
2126     }
2127 
2128     /**
2129      * {@inheritDoc}
2130      * 
2131      * @see java.sql.DatabaseMetaData#supportsResultSetType(int)
2132      */
2133     @Override
2134     public boolean supportsResultSetType( int type ) throws SQLException {
2135         return false;
2136     }
2137 
2138     /**
2139      * {@inheritDoc}
2140      * 
2141      * @see java.sql.DatabaseMetaData#supportsSavepoints()
2142      */
2143     @Override
2144     public boolean supportsSavepoints() {
2145         return false; // nope
2146     }
2147 
2148     /**
2149      * {@inheritDoc}
2150      * 
2151      * @see java.sql.DatabaseMetaData#supportsSchemasInDataManipulation()
2152      */
2153     @Override
2154     public boolean supportsSchemasInDataManipulation() {
2155         return false; // nope
2156     }
2157 
2158     /**
2159      * {@inheritDoc}
2160      * 
2161      * @see java.sql.DatabaseMetaData#supportsSchemasInIndexDefinitions()
2162      */
2163     @Override
2164     public boolean supportsSchemasInIndexDefinitions() {
2165         return false; // nope
2166     }
2167 
2168     /**
2169      * {@inheritDoc}
2170      * 
2171      * @see java.sql.DatabaseMetaData#supportsSchemasInPrivilegeDefinitions()
2172      */
2173     @Override
2174     public boolean supportsSchemasInPrivilegeDefinitions() {
2175         return false; // nope
2176     }
2177 
2178     /**
2179      * {@inheritDoc}
2180      * 
2181      * @see java.sql.DatabaseMetaData#supportsSchemasInProcedureCalls()
2182      */
2183     @Override
2184     public boolean supportsSchemasInProcedureCalls() {
2185         return false; // nope
2186     }
2187 
2188     /**
2189      * {@inheritDoc}
2190      * 
2191      * @see java.sql.DatabaseMetaData#supportsSchemasInTableDefinitions()
2192      */
2193     @Override
2194     public boolean supportsSchemasInTableDefinitions() {
2195         return false; // nope
2196     }
2197 
2198     /**
2199      * {@inheritDoc}
2200      * 
2201      * @see java.sql.DatabaseMetaData#supportsSelectForUpdate()
2202      */
2203     @Override
2204     public boolean supportsSelectForUpdate() {
2205         return false; // read-only
2206     }
2207 
2208     /**
2209      * {@inheritDoc}
2210      * 
2211      * @see java.sql.DatabaseMetaData#supportsStatementPooling()
2212      */
2213     @Override
2214     public boolean supportsStatementPooling() {
2215         return false; // nope
2216     }
2217 
2218     /**
2219      * {@inheritDoc}
2220      * 
2221      * @see java.sql.DatabaseMetaData#supportsStoredFunctionsUsingCallSyntax()
2222      */
2223     @Override
2224     public boolean supportsStoredFunctionsUsingCallSyntax() {
2225         return false; // nope
2226     }
2227 
2228     /**
2229      * {@inheritDoc}
2230      * 
2231      * @see java.sql.DatabaseMetaData#supportsStoredProcedures()
2232      */
2233     @Override
2234     public boolean supportsStoredProcedures() {
2235         return false; // nope
2236     }
2237 
2238     /**
2239      * {@inheritDoc}
2240      * 
2241      * @see java.sql.DatabaseMetaData#supportsSubqueriesInComparisons()
2242      */
2243     @Override
2244     public boolean supportsSubqueriesInComparisons() {
2245         return false; // no subqueries in JCR-SQL2
2246     }
2247 
2248     /**
2249      * {@inheritDoc}
2250      * 
2251      * @see java.sql.DatabaseMetaData#supportsSubqueriesInExists()
2252      */
2253     @Override
2254     public boolean supportsSubqueriesInExists() {
2255         return false; // no subqueries in JCR-SQL2
2256     }
2257 
2258     /**
2259      * {@inheritDoc}
2260      * 
2261      * @see java.sql.DatabaseMetaData#supportsSubqueriesInIns()
2262      */
2263     @Override
2264     public boolean supportsSubqueriesInIns() {
2265         return false; // no subqueries in JCR-SQL2
2266     }
2267 
2268     /**
2269      * {@inheritDoc}
2270      * 
2271      * @see java.sql.DatabaseMetaData#supportsSubqueriesInQuantifieds()
2272      */
2273     @Override
2274     public boolean supportsSubqueriesInQuantifieds() {
2275         return false; // no subqueries in JCR-SQL2
2276     }
2277 
2278     /**
2279      * {@inheritDoc}
2280      * 
2281      * @see java.sql.DatabaseMetaData#supportsTableCorrelationNames()
2282      */
2283     @Override
2284     public boolean supportsTableCorrelationNames() {
2285         // JCR-SQL2 does support table aliases that can be used as prefixes for column names
2286         return true;
2287     }
2288 
2289     /**
2290      * {@inheritDoc}
2291      * 
2292      * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel(int)
2293      */
2294     @Override
2295     public boolean supportsTransactionIsolationLevel( int level ) {
2296         return level == Connection.TRANSACTION_READ_COMMITTED;
2297     }
2298 
2299     /**
2300      * {@inheritDoc}
2301      * 
2302      * @see java.sql.DatabaseMetaData#supportsTransactions()
2303      */
2304     @Override
2305     public boolean supportsTransactions() {
2306         // Generally, JCR does support transactions ...
2307         return false;
2308     }
2309 
2310     /**
2311      * {@inheritDoc}
2312      * 
2313      * @see java.sql.DatabaseMetaData#supportsUnion()
2314      */
2315     @Override
2316     public boolean supportsUnion() {
2317         // JCR-SQL2 does not support UNION ...
2318         return false;
2319     }
2320 
2321     /**
2322      * {@inheritDoc}
2323      * 
2324      * @see java.sql.DatabaseMetaData#supportsUnionAll()
2325      */
2326     @Override
2327     public boolean supportsUnionAll() {
2328         // JCR-SQL2 does not support UNION ALL ...
2329         return false;
2330     }
2331 
2332     /**
2333      * {@inheritDoc}
2334      * 
2335      * @see java.sql.DatabaseMetaData#updatesAreDetected(int)
2336      */
2337     @Override
2338     public boolean updatesAreDetected( int type ) {
2339         return false;
2340     }
2341 
2342     /**
2343      * {@inheritDoc}
2344      * 
2345      * @see java.sql.DatabaseMetaData#usesLocalFilePerTable()
2346      */
2347     @Override
2348     public boolean usesLocalFilePerTable() {
2349         return false;
2350     }
2351 
2352     /**
2353      * {@inheritDoc}
2354      * 
2355      * @see java.sql.DatabaseMetaData#usesLocalFiles()
2356      */
2357     @Override
2358     public boolean usesLocalFiles() {
2359         return false;
2360     }
2361 
2362     /**
2363      * {@inheritDoc}
2364      * 
2365      * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
2366      */
2367     @Override
2368     public boolean isWrapperFor( Class<?> iface ) {
2369         return iface.isInstance(this);
2370     }
2371 
2372     /**
2373      * {@inheritDoc}
2374      * 
2375      * @see java.sql.Wrapper#unwrap(java.lang.Class)
2376      */
2377     @Override
2378     public <T> T unwrap( Class<T> iface ) throws SQLException {
2379         if (!isWrapperFor(iface)) {
2380             throw new SQLException(JdbcI18n.classDoesNotImplementInterface.text(DatabaseMetaData.class.getSimpleName(),
2381                                                                                 iface.getName()));
2382         }
2383 
2384         return iface.cast(this);
2385     }
2386 
2387     private List<NodeType> filterNodeTypes( String tableNamePattern ) throws RepositoryException {
2388         List<NodeType> nodetypes = null;
2389 
2390         if (tableNamePattern.trim().equals(WILDCARD)) {
2391             nodetypes = this.connection.getRepositoryDelegate().nodeTypes();
2392         } else if (tableNamePattern.contains(WILDCARD)) {
2393             nodetypes = new ArrayList<NodeType>();
2394             String partName = null;
2395             boolean isLeading = false;
2396             boolean isTrailing = false;
2397             partName = tableNamePattern;
2398 
2399             if (partName.startsWith(WILDCARD)) {
2400                 partName = partName.substring(1);
2401                 isLeading = true;
2402             }
2403             if (partName.endsWith(WILDCARD) && partName.length() > 1) {
2404                 partName = partName.substring(0, partName.length() - 1);
2405                 isTrailing = true;
2406             }
2407 
2408             List<NodeType> nts = this.connection.getRepositoryDelegate().nodeTypes();
2409             Iterator<NodeType> nodeIt = nts.iterator();
2410             // build the list of records from server's Results object.
2411             while (nodeIt.hasNext()) {
2412 
2413                 NodeType type = nodeIt.next();
2414 
2415                 if (isLeading) {
2416                     if (isTrailing) {
2417                         if (type.getName().indexOf(partName, 1) > -1) {
2418                             nodetypes.add(type);
2419                         }
2420                     } else if (type.getName().endsWith(partName)) {
2421                         nodetypes.add(type);
2422                     }
2423 
2424                 } else if (isTrailing) {
2425                     if (type.getName().startsWith(partName)) {
2426                         nodetypes.add(type);
2427                     }
2428                 }
2429             }
2430 
2431         } else {
2432             NodeType nt = this.connection.getRepositoryDelegate().nodeType(tableNamePattern);
2433             if (nt != null) {
2434                 nodetypes = new ArrayList<NodeType>(1);
2435                 nodetypes.add(nt);
2436             }
2437         }
2438 
2439         if (nodetypes.size() > 1) {
2440             final Comparator<NodeType> name_order = new Comparator<NodeType>() {
2441                 public int compare( NodeType e1,
2442                                     NodeType e2 ) {
2443                     return e1.getName().compareTo(e2.getName());
2444                 }
2445             };
2446             Collections.sort(nodetypes, name_order);
2447         }
2448 
2449         return nodetypes;
2450     }
2451 
2452     private List<PropertyDefinition> filterPropertyDefnitions( String columnNamePattern,
2453                                                                PropertyDefinition[] defns ) {
2454         List<PropertyDefinition> resultDefns = new ArrayList<PropertyDefinition>(defns.length);
2455 
2456         if (columnNamePattern.trim().equals(WILDCARD)) {
2457             resultDefns = Arrays.asList(defns);
2458         } else if (columnNamePattern.contains(WILDCARD)) {
2459             String partName = null;
2460             boolean isLeading = false;
2461             boolean isTrailing = false;
2462             partName = columnNamePattern;
2463 
2464             if (partName.startsWith(WILDCARD)) {
2465                 partName = partName.substring(1);
2466                 isLeading = true;
2467             }
2468             if (partName.endsWith(WILDCARD) && partName.length() > 1) {
2469                 partName = partName.substring(0, partName.length() - 1);
2470                 isTrailing = true;
2471             }
2472 
2473             for (int i = 0; i < defns.length; i++) {
2474 
2475                 PropertyDefinition defn = defns[i];
2476 
2477                 if (isLeading) {
2478                     if (isTrailing) {
2479                         if (defn.getName().indexOf(partName, 1) > -1) {
2480                             resultDefns.add(defn);
2481                         }
2482                     } else if (defn.getName().endsWith(partName)) {
2483                         resultDefns.add(defn);
2484                     }
2485 
2486                 } else if (isTrailing) {
2487                     if (defn.getName().startsWith(partName)) {
2488                         resultDefns.add(defn);
2489                     }
2490                 }
2491             }
2492 
2493         } else {
2494             for (int i = 0; i < defns.length; i++) {
2495                 PropertyDefinition defn = defns[i];
2496                 if (defn.getName().equals(columnNamePattern)) {
2497                     resultDefns.add(defn);
2498                 }
2499             }
2500 
2501         }
2502 
2503         if (resultDefns.size() > 1) {
2504             final Comparator<PropertyDefinition> name_order = new Comparator<PropertyDefinition>() {
2505                 public int compare( PropertyDefinition e1,
2506                                     PropertyDefinition e2 ) {
2507                     return e1.getName().compareTo(e2.getName());
2508                 }
2509             };
2510             Collections.sort(resultDefns, name_order);
2511         }
2512 
2513         return resultDefns;
2514     }
2515 
2516 }