/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.jdbc.results.metadata;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Types;
import java.util.List;
import org.apache.jena.jdbc.JdbcCompatibility;
import org.apache.jena.jdbc.results.JenaResultSet;
import org.apache.jena.jdbc.results.SelectResults;
import org.apache.jena.jdbc.results.metadata.columns.ColumnInfo;
import org.apache.jena.jdbc.results.metadata.columns.SparqlColumnInfo;
import org.apache.jena.jdbc.results.metadata.columns.StringColumn;
import org.apache.jena.query.ResultSet ;
import org.apache.jena.query.ResultSetFactory ;
import org.apache.jena.sparql.core.Var ;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.resultset.ResultSetPeekable ;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Result Set Metadata for {@link SelectResults} instances
*
*/
public class SelectResultsMetadata extends JenaResultsMetadata {
private static final Logger LOGGER = LoggerFactory.getLogger(SelectResultsMetadata.class);
private ResultSetPeekable innerResults;
/**
* Creates new SELECT results metadata
*
* @param results
* JDBC result set
* @param rset
* Underlying SPARQL results
* @throws SQLException
*/
public SelectResultsMetadata(JenaResultSet results, ResultSetPeekable rset) throws SQLException {
super(results, makeColumns(results, rset));
this.innerResults = rset;
}
/**
* Creates new SELECT results metadata
*
* @param results
* JDBC result set
* @param rset
* Underlying SPARQL results
* @throws SQLException
*/
public SelectResultsMetadata(JenaResultSet results, ResultSet rset) throws SQLException {
this(results, ResultSetFactory.makePeekable(rset));
}
/**
* Creates new SELECT results metadata
*
* @param metadata Original metadata
* @param columns
* Column metadata
* @throws SQLException
*/
public SelectResultsMetadata(SelectResultsMetadata metadata, ColumnInfo[] columns) throws SQLException {
super(metadata.getJenaResultSet(), columns);
this.innerResults = metadata.innerResults;
}
/**
* Makes column information for SELECT results
*
* @param results
* Result Set
* @param rset
* Underlying SPARQL results
* @return Column information
* @throws SQLException
* Thrown if the column information cannot be created
*/
private static ColumnInfo[] makeColumns(JenaResultSet results, ResultSetPeekable rset) throws SQLException {
List<String> vars = rset.getResultVars();
ColumnInfo[] columns = new ColumnInfo[vars.size()];
int level = JdbcCompatibility.normalizeLevel(results.getJdbcCompatibilityLevel());
boolean columnsAsStrings = JdbcCompatibility.shouldTypeColumnsAsString(level);
boolean columnsDetected = JdbcCompatibility.shouldDetectColumnTypes(level);
Binding b = null;
if (columnsDetected) {
if (rset.hasNext()) {
b = rset.peekBinding();
} else {
// If we were supposed to detect columns but there is no data
// available then we will just fallback to typing everything as
// strings
columnsAsStrings = true;
columnsDetected = false;
}
}
for (int i = 0; i < columns.length; i++) {
if (!columnsAsStrings && !columnsDetected) {
// Low compatibility, report columns as being typed as
// JAVA_OBJECT with ARQ Node as the column class
columns[i] = new SparqlColumnInfo(vars.get(i), Types.JAVA_OBJECT, columnNullable);
LOGGER.info("Low JDBC compatibility, column " + vars.get(i) + " is being typed as Node");
} else if (columnsAsStrings) {
// Medium compatibility, report columns as being typed as
// NVARCHAR with String as the column class
columns[i] = new StringColumn(vars.get(i), columnNullable);
LOGGER.info("Medium JDBC compatibility, column " + vars.get(i) + " is being typed as String");
} else if (columnsDetected) {
// High compatibility, detect columns types based on first row
// of results
columns[i] = JdbcCompatibility.detectColumnType(vars.get(i), b.get(Var.alloc(vars.get(i))), true);
LOGGER.info("High compatibility, column " + vars.get(i) + " was detected as being of type "
+ columns[i].getClassName());
} else {
throw new SQLFeatureNotSupportedException("Unknown JDBC compatibility level was set");
}
}
return columns;
}
}