use of java.sql.SQLFeatureNotSupportedException in project jena by apache.
the class SelectResultsMetadata method makeColumns.
/**
* 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;
}
use of java.sql.SQLFeatureNotSupportedException in project jena by apache.
the class TripleResultsMetadata method makeColumns.
/**
* Gets the columns for CONSTRUCT/DESCRIBE results
*
* @param results
* Results
* @param ts
* Underlying triples
* @param subjLabel
* Label for subject column, use {@code null} to omit the subject
* column
* @param predLabel
* Label for predicate column, use {@code null} to omit the
* predicate column
* @param objLabel
* Label for object column, use {@code null} to omit the object
* column
*
* @return Column Information
* @throws SQLException
*/
private static ColumnInfo[] makeColumns(JenaResultSet results, PeekIterator<Triple> ts, String subjLabel, String predLabel, String objLabel) throws SQLException {
int numColumns = 0;
if (subjLabel != null)
numColumns++;
if (predLabel != null)
numColumns++;
if (objLabel != null)
numColumns++;
ColumnInfo[] columns = new ColumnInfo[numColumns];
// Figure out column names
String[] names = new String[numColumns];
names[0] = subjLabel != null ? subjLabel : (predLabel != null ? predLabel : objLabel);
if (numColumns > 1) {
names[1] = subjLabel != null && predLabel != null ? predLabel : objLabel;
}
if (numColumns == 3) {
names[2] = objLabel;
}
int level = JdbcCompatibility.normalizeLevel(results.getJdbcCompatibilityLevel());
boolean columnsAsStrings = JdbcCompatibility.shouldTypeColumnsAsString(level);
boolean columnsDetected = JdbcCompatibility.shouldDetectColumnTypes(level);
Triple t = null;
Node[] values = new Node[numColumns];
if (columnsDetected) {
if (ts.hasNext()) {
// Need to peek the first Triple and grab appropriate nodes
t = ts.peek();
if (numColumns == NUM_COLUMNS) {
values[0] = t.getSubject();
values[1] = t.getPredicate();
values[2] = t.getObject();
} else {
values[0] = subjLabel != null ? t.getSubject() : (predLabel != null ? t.getPredicate() : t.getObject());
if (numColumns > 1) {
values[1] = subjLabel != null && predLabel != null ? t.getPredicate() : t.getObject();
}
}
} 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(names[i], Types.JAVA_OBJECT, columnNoNulls);
LOGGER.info("Low JDBC compatibility, column " + names[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(names[i], columnNoNulls);
LOGGER.info("Medium JDBC compatibility, column " + names[i] + " is being typed as String");
} else if (columnsDetected) {
// High compatibility, detect columns types based on first row
// of results
columns[i] = JdbcCompatibility.detectColumnType(names[i], values[i], false);
LOGGER.info("High compatibility, column " + names[i] + " was detected as being of type " + columns[i].getClassName());
} else {
throw new SQLFeatureNotSupportedException("Unknown JDBC compatibility level was set");
}
}
return columns;
}
use of java.sql.SQLFeatureNotSupportedException in project phoenix by apache.
the class PhoenixRuntimeTest method testGetTenantIdExpression.
@Test
public void testGetTenantIdExpression() throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
Expression e1 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SYSTEM_STATS_NAME);
assertNull(e1);
Expression e2 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME);
assertNotNull(e2);
Expression e3 = PhoenixRuntime.getTenantIdExpression(conn, PhoenixDatabaseMetaData.SYSTEM_SEQUENCE_NAME);
assertNotNull(e3);
conn.createStatement().execute("CREATE TABLE FOO (k VARCHAR PRIMARY KEY)");
Expression e4 = PhoenixRuntime.getTenantIdExpression(conn, "FOO");
assertNull(e4);
conn.createStatement().execute("CREATE TABLE A.BAR (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true");
Expression e5 = PhoenixRuntime.getTenantIdExpression(conn, "A.BAR");
assertNotNull(e5);
conn.createStatement().execute("CREATE INDEX I1 ON A.BAR (K2)");
Expression e5A = PhoenixRuntime.getTenantIdExpression(conn, "A.I1");
assertNotNull(e5A);
conn.createStatement().execute("CREATE TABLE BAS (k1 VARCHAR NOT NULL, k2 VARCHAR, CONSTRAINT PK PRIMARY KEY(K1,K2)) MULTI_TENANT=true, SALT_BUCKETS=3");
Expression e6 = PhoenixRuntime.getTenantIdExpression(conn, "BAS");
assertNotNull(e6);
conn.createStatement().execute("CREATE INDEX I2 ON BAS (K2)");
Expression e6A = PhoenixRuntime.getTenantIdExpression(conn, "I2");
assertNotNull(e6A);
try {
PhoenixRuntime.getTenantIdExpression(conn, "NOT.ATABLE");
fail();
} catch (TableNotFoundException e) {
// Expected
}
Properties props = PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES);
props.setProperty(PhoenixRuntime.TENANT_ID_ATTRIB, "t1");
Connection tsconn = DriverManager.getConnection(getUrl(), props);
tsconn.createStatement().execute("CREATE VIEW V(V1 VARCHAR) AS SELECT * FROM BAS");
Expression e7 = PhoenixRuntime.getTenantIdExpression(tsconn, "V");
assertNotNull(e7);
tsconn.createStatement().execute("CREATE LOCAL INDEX I3 ON V (V1)");
try {
PhoenixRuntime.getTenantIdExpression(tsconn, "I3");
fail();
} catch (SQLFeatureNotSupportedException e) {
// Expected
}
}
use of java.sql.SQLFeatureNotSupportedException in project phoenix by apache.
the class MetaDataClient method createIndex.
/**
* Create an index table by morphing the CreateIndexStatement into a CreateTableStatement and calling
* MetaDataClient.createTable. In doing so, we perform the following translations:
* 1) Change the type of any columns being indexed to types that support null if the column is nullable.
* For example, a BIGINT type would be coerced to a DECIMAL type, since a DECIMAL type supports null
* when it's in the row key while a BIGINT does not.
* 2) Append any row key column from the data table that is not in the indexed column list. Our indexes
* rely on having a 1:1 correspondence between the index and data rows.
* 3) Change the name of the columns to include the column family. For example, if you have a column
* named "B" in a column family named "A", the indexed column name will be "A:B". This makes it easy
* to translate the column references in a query to the correct column references in an index table
* regardless of whether the column reference is prefixed with the column family name or not. It also
* has the side benefit of allowing the same named column in different column families to both be
* listed as an index column.
* @param statement
* @param splits
* @return MutationState from population of index table from data table
* @throws SQLException
*/
public MutationState createIndex(CreateIndexStatement statement, byte[][] splits) throws SQLException {
IndexKeyConstraint ik = statement.getIndexConstraint();
TableName indexTableName = statement.getIndexTableName();
Map<String, Object> tableProps = Maps.newHashMapWithExpectedSize(statement.getProps().size());
Map<String, Object> commonFamilyProps = Maps.newHashMapWithExpectedSize(statement.getProps().size() + 1);
populatePropertyMaps(statement.getProps(), tableProps, commonFamilyProps);
List<Pair<ParseNode, SortOrder>> indexParseNodeAndSortOrderList = ik.getParseNodeAndSortOrderList();
List<ColumnName> includedColumns = statement.getIncludeColumns();
TableRef tableRef = null;
PTable table = null;
int numRetries = 0;
boolean allocateIndexId = false;
boolean isLocalIndex = statement.getIndexType() == IndexType.LOCAL;
int hbaseVersion = connection.getQueryServices().getLowestClusterHBaseVersion();
if (isLocalIndex) {
if (!connection.getQueryServices().getProps().getBoolean(QueryServices.ALLOW_LOCAL_INDEX_ATTRIB, QueryServicesOptions.DEFAULT_ALLOW_LOCAL_INDEX)) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.UNALLOWED_LOCAL_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
}
if (!connection.getQueryServices().supportsFeature(Feature.LOCAL_INDEX)) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_LOCAL_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
}
}
while (true) {
try {
ColumnResolver resolver = FromCompiler.getResolver(statement, connection, statement.getUdfParseNodes());
tableRef = resolver.getTables().get(0);
Date asyncCreatedDate = null;
if (statement.isAsync()) {
asyncCreatedDate = new Date(tableRef.getTimeStamp());
}
PTable dataTable = tableRef.getTable();
boolean isTenantConnection = connection.getTenantId() != null;
if (isTenantConnection) {
if (dataTable.getType() != PTableType.VIEW) {
throw new SQLFeatureNotSupportedException("An index may only be created for a VIEW through a tenant-specific connection");
}
}
if (!dataTable.isImmutableRows()) {
if (hbaseVersion < PhoenixDatabaseMetaData.MUTABLE_SI_VERSION_THRESHOLD) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.NO_MUTABLE_INDEXES).setTableName(indexTableName.getTableName()).build().buildException();
}
if (!connection.getQueryServices().hasIndexWALCodec() && !dataTable.isTransactional()) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_MUTABLE_INDEX_CONFIG).setTableName(indexTableName.getTableName()).build().buildException();
}
}
int posOffset = 0;
List<PColumn> pkColumns = dataTable.getPKColumns();
Set<RowKeyColumnExpression> unusedPkColumns;
if (dataTable.getBucketNum() != null) {
// Ignore SALT column
unusedPkColumns = Sets.newLinkedHashSetWithExpectedSize(pkColumns.size() - 1);
posOffset++;
} else {
unusedPkColumns = Sets.newLinkedHashSetWithExpectedSize(pkColumns.size());
}
for (int i = posOffset; i < pkColumns.size(); i++) {
PColumn column = pkColumns.get(i);
unusedPkColumns.add(new RowKeyColumnExpression(column, new RowKeyValueAccessor(pkColumns, i), "\"" + column.getName().getString() + "\""));
}
List<ColumnDefInPkConstraint> allPkColumns = Lists.newArrayListWithExpectedSize(unusedPkColumns.size());
List<ColumnDef> columnDefs = Lists.newArrayListWithExpectedSize(includedColumns.size() + indexParseNodeAndSortOrderList.size());
/*
* Allocate an index ID in two circumstances:
* 1) for a local index, as all local indexes will reside in the same HBase table
* 2) for a view on an index.
*/
if (isLocalIndex || (dataTable.getType() == PTableType.VIEW && dataTable.getViewType() != ViewType.MAPPED)) {
allocateIndexId = true;
PDataType dataType = MetaDataUtil.getViewIndexIdDataType();
ColumnName colName = ColumnName.caseSensitiveColumnName(MetaDataUtil.getViewIndexIdColumnName());
allPkColumns.add(new ColumnDefInPkConstraint(colName, SortOrder.getDefault(), false));
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), false, null, null, false, SortOrder.getDefault(), null, false));
}
if (dataTable.isMultiTenant()) {
PColumn col = dataTable.getPKColumns().get(posOffset);
RowKeyColumnExpression columnExpression = new RowKeyColumnExpression(col, new RowKeyValueAccessor(pkColumns, posOffset), col.getName().getString());
unusedPkColumns.remove(columnExpression);
PDataType dataType = IndexUtil.getIndexColumnDataType(col);
ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
allPkColumns.add(new ColumnDefInPkConstraint(colName, col.getSortOrder(), false));
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, SortOrder.getDefault(), col.getName().getString(), col.isRowTimestamp()));
}
PhoenixStatement phoenixStatment = new PhoenixStatement(connection);
StatementContext context = new StatementContext(phoenixStatment, resolver);
IndexExpressionCompiler expressionIndexCompiler = new IndexExpressionCompiler(context);
Set<ColumnName> indexedColumnNames = Sets.newHashSetWithExpectedSize(indexParseNodeAndSortOrderList.size());
for (Pair<ParseNode, SortOrder> pair : indexParseNodeAndSortOrderList) {
ParseNode parseNode = pair.getFirst();
// normalize the parse node
parseNode = StatementNormalizer.normalize(parseNode, resolver);
// compile the parseNode to get an expression
expressionIndexCompiler.reset();
Expression expression = parseNode.accept(expressionIndexCompiler);
if (expressionIndexCompiler.isAggregate()) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.AGGREGATE_EXPRESSION_NOT_ALLOWED_IN_INDEX).build().buildException();
}
if (expression.getDeterminism() != Determinism.ALWAYS) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.NON_DETERMINISTIC_EXPRESSION_NOT_ALLOWED_IN_INDEX).build().buildException();
}
if (expression.isStateless()) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.STATELESS_EXPRESSION_NOT_ALLOWED_IN_INDEX).build().buildException();
}
unusedPkColumns.remove(expression);
// Go through parse node to get string as otherwise we
// can lose information during compilation
StringBuilder buf = new StringBuilder();
parseNode.toSQL(resolver, buf);
// need to escape backslash as this expression will be re-parsed later
String expressionStr = StringUtil.escapeBackslash(buf.toString());
ColumnName colName = null;
ColumnRef colRef = expressionIndexCompiler.getColumnRef();
boolean isRowTimestamp = false;
if (colRef != null) {
// if this is a regular column
PColumn column = colRef.getColumn();
String columnFamilyName = column.getFamilyName() != null ? column.getFamilyName().getString() : null;
colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(columnFamilyName, column.getName().getString()));
isRowTimestamp = column.isRowTimestamp();
if (colRef.getColumn().getExpressionStr() != null) {
expressionStr = colRef.getColumn().getExpressionStr();
}
} else {
// if this is an expression
// TODO column names cannot have double quotes, remove this once this PHOENIX-1621 is fixed
String name = expressionStr.replaceAll("\"", "'");
colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(null, name));
}
indexedColumnNames.add(colName);
PDataType dataType = IndexUtil.getIndexColumnDataType(expression.isNullable(), expression.getDataType());
allPkColumns.add(new ColumnDefInPkConstraint(colName, pair.getSecond(), isRowTimestamp));
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), expression.isNullable(), expression.getMaxLength(), expression.getScale(), false, pair.getSecond(), expressionStr, isRowTimestamp));
}
// Next all the PK columns from the data table that aren't indexed
if (!unusedPkColumns.isEmpty()) {
for (RowKeyColumnExpression colExpression : unusedPkColumns) {
PColumn col = dataTable.getPKColumns().get(colExpression.getPosition());
// we don't need these in the index
if (col.getViewConstant() == null) {
ColumnName colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
allPkColumns.add(new ColumnDefInPkConstraint(colName, colExpression.getSortOrder(), col.isRowTimestamp()));
PDataType dataType = IndexUtil.getIndexColumnDataType(colExpression.isNullable(), colExpression.getDataType());
columnDefs.add(FACTORY.columnDef(colName, dataType.getSqlTypeName(), colExpression.isNullable(), colExpression.getMaxLength(), colExpression.getScale(), false, colExpression.getSortOrder(), colExpression.toString(), col.isRowTimestamp()));
}
}
}
// Last all the included columns (minus any PK columns)
for (ColumnName colName : includedColumns) {
PColumn col = resolver.resolveColumn(null, colName.getFamilyName(), colName.getColumnName()).getColumn();
colName = ColumnName.caseSensitiveColumnName(IndexUtil.getIndexColumnName(col));
// Check for duplicates between indexed and included columns
if (indexedColumnNames.contains(colName)) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.COLUMN_EXIST_IN_DEF).build().buildException();
}
if (!SchemaUtil.isPKColumn(col) && col.getViewConstant() == null) {
// Need to re-create ColumnName, since the above one won't have the column family name
colName = ColumnName.caseSensitiveColumnName(isLocalIndex ? IndexUtil.getLocalIndexColumnFamily(col.getFamilyName().getString()) : col.getFamilyName().getString(), IndexUtil.getIndexColumnName(col));
columnDefs.add(FACTORY.columnDef(colName, col.getDataType().getSqlTypeName(), col.isNullable(), col.getMaxLength(), col.getScale(), false, col.getSortOrder(), col.getExpressionStr(), col.isRowTimestamp()));
}
}
// We need this in the props so that the correct column family is created
if (dataTable.getDefaultFamilyName() != null && dataTable.getType() != PTableType.VIEW && !allocateIndexId) {
statement.getProps().put("", new Pair<String, Object>(DEFAULT_COLUMN_FAMILY_NAME, dataTable.getDefaultFamilyName().getString()));
}
PrimaryKeyConstraint pk = FACTORY.primaryKey(null, allPkColumns);
tableProps.put(MetaDataUtil.DATA_TABLE_NAME_PROP_NAME, dataTable.getName().getString());
CreateTableStatement tableStatement = FACTORY.createTable(indexTableName, statement.getProps(), columnDefs, pk, statement.getSplitNodes(), PTableType.INDEX, statement.ifNotExists(), null, null, statement.getBindCount(), null);
table = createTableInternal(tableStatement, splits, dataTable, null, null, null, null, allocateIndexId, statement.getIndexType(), asyncCreatedDate, tableProps, commonFamilyProps);
break;
} catch (ConcurrentTableMutationException e) {
// Can happen if parent data table changes while above is in progress
if (numRetries < 5) {
numRetries++;
continue;
}
throw e;
}
}
if (table == null) {
return new MutationState(0, 0, connection);
}
if (logger.isInfoEnabled())
logger.info("Created index " + table.getName().getString() + " at " + table.getTimeStamp());
boolean asyncIndexBuildEnabled = connection.getQueryServices().getProps().getBoolean(QueryServices.INDEX_ASYNC_BUILD_ENABLED, QueryServicesOptions.DEFAULT_INDEX_ASYNC_BUILD_ENABLED);
// In async process, we return immediately as the MR job needs to be triggered .
if (statement.isAsync() && asyncIndexBuildEnabled) {
return new MutationState(0, 0, connection);
}
// connection so that our new index table is visible.
if (connection.getSCN() != null) {
return buildIndexAtTimeStamp(table, statement.getTable());
}
return buildIndex(table, tableRef);
}
use of java.sql.SQLFeatureNotSupportedException in project phoenix by apache.
the class SQLParser method nextStatement.
/**
* Parses the input as a series of semicolon-terminated SQL statements.
* @throws SQLException
*/
public BindableStatement nextStatement(ParseNodeFactory factory) throws SQLException {
try {
parser.resetBindCount();
parser.setParseNodeFactory(factory);
BindableStatement statement = parser.nextStatement();
return statement;
} catch (RecognitionException e) {
throw PhoenixParserException.newException(e, parser.getTokenNames());
} catch (UnsupportedOperationException e) {
throw new SQLFeatureNotSupportedException(e);
} catch (RuntimeException e) {
if (e.getCause() instanceof SQLException) {
throw (SQLException) e.getCause();
}
throw PhoenixParserException.newException(e, parser.getTokenNames());
}
}
Aggregations