use of org.h2.index.IndexType in project h2database by h2database.
the class TableLink method readMetaData.
private void readMetaData() throws SQLException {
DatabaseMetaData meta = conn.getConnection().getMetaData();
storesLowerCase = meta.storesLowerCaseIdentifiers();
storesMixedCase = meta.storesMixedCaseIdentifiers();
storesMixedCaseQuoted = meta.storesMixedCaseQuotedIdentifiers();
supportsMixedCaseIdentifiers = meta.supportsMixedCaseIdentifiers();
ResultSet rs = meta.getTables(null, originalSchema, originalTable, null);
if (rs.next() && rs.next()) {
throw DbException.get(ErrorCode.SCHEMA_NAME_MUST_MATCH, originalTable);
}
rs.close();
rs = meta.getColumns(null, originalSchema, originalTable, null);
int i = 0;
ArrayList<Column> columnList = New.arrayList();
HashMap<String, Column> columnMap = new HashMap<>();
String catalog = null, schema = null;
while (rs.next()) {
String thisCatalog = rs.getString("TABLE_CAT");
if (catalog == null) {
catalog = thisCatalog;
}
String thisSchema = rs.getString("TABLE_SCHEM");
if (schema == null) {
schema = thisSchema;
}
if (!Objects.equals(catalog, thisCatalog) || !Objects.equals(schema, thisSchema)) {
// if the table exists in multiple schemas or tables,
// use the alternative solution
columnMap.clear();
columnList.clear();
break;
}
String n = rs.getString("COLUMN_NAME");
n = convertColumnName(n);
int sqlType = rs.getInt("DATA_TYPE");
String sqlTypeName = rs.getString("TYPE_NAME");
long precision = rs.getInt("COLUMN_SIZE");
precision = convertPrecision(sqlType, precision);
int scale = rs.getInt("DECIMAL_DIGITS");
scale = convertScale(sqlType, scale);
int displaySize = MathUtils.convertLongToInt(precision);
int type = DataType.convertSQLTypeToValueType(sqlType, sqlTypeName);
Column col = new Column(n, type, precision, scale, displaySize);
col.setTable(this, i++);
columnList.add(col);
columnMap.put(n, col);
}
rs.close();
if (originalTable.indexOf('.') < 0 && !StringUtils.isNullOrEmpty(schema)) {
qualifiedTableName = schema + "." + originalTable;
} else {
qualifiedTableName = originalTable;
}
try (Statement stat = conn.getConnection().createStatement()) {
rs = stat.executeQuery("SELECT * FROM " + qualifiedTableName + " T WHERE 1=0");
if (columnList.isEmpty()) {
// alternative solution
ResultSetMetaData rsMeta = rs.getMetaData();
for (i = 0; i < rsMeta.getColumnCount(); ) {
String n = rsMeta.getColumnName(i + 1);
n = convertColumnName(n);
int sqlType = rsMeta.getColumnType(i + 1);
long precision = rsMeta.getPrecision(i + 1);
precision = convertPrecision(sqlType, precision);
int scale = rsMeta.getScale(i + 1);
scale = convertScale(sqlType, scale);
int displaySize = rsMeta.getColumnDisplaySize(i + 1);
int type = DataType.getValueTypeFromResultSet(rsMeta, i + 1);
Column col = new Column(n, type, precision, scale, displaySize);
col.setTable(this, i++);
columnList.add(col);
columnMap.put(n, col);
}
}
rs.close();
} catch (Exception e) {
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e, originalTable + "(" + e.toString() + ")");
}
Column[] cols = columnList.toArray(new Column[0]);
setColumns(cols);
int id = getId();
linkedIndex = new LinkedIndex(this, id, IndexColumn.wrap(cols), IndexType.createNonUnique(false));
indexes.add(linkedIndex);
try {
rs = meta.getPrimaryKeys(null, originalSchema, originalTable);
} catch (Exception e) {
// Some ODBC bridge drivers don't support it:
// some combinations of "DataDirect SequeLink(R) for JDBC"
// http://www.datadirect.com/index.ssp
rs = null;
}
String pkName = "";
ArrayList<Column> list;
if (rs != null && rs.next()) {
// the problem is, the rows are not sorted by KEY_SEQ
list = New.arrayList();
do {
int idx = rs.getInt("KEY_SEQ");
if (pkName == null) {
pkName = rs.getString("PK_NAME");
}
while (list.size() < idx) {
list.add(null);
}
String col = rs.getString("COLUMN_NAME");
col = convertColumnName(col);
Column column = columnMap.get(col);
if (idx == 0) {
// workaround for a bug in the SQLite JDBC driver
list.add(column);
} else {
list.set(idx - 1, column);
}
} while (rs.next());
addIndex(list, IndexType.createPrimaryKey(false, false));
rs.close();
}
try {
rs = meta.getIndexInfo(null, originalSchema, originalTable, false, true);
} catch (Exception e) {
// Oracle throws an exception if the table is not found or is a
// SYNONYM
rs = null;
}
String indexName = null;
list = New.arrayList();
IndexType indexType = null;
if (rs != null) {
while (rs.next()) {
if (rs.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic) {
// ignore index statistics
continue;
}
String newIndex = rs.getString("INDEX_NAME");
if (pkName.equals(newIndex)) {
continue;
}
if (indexName != null && !indexName.equals(newIndex)) {
addIndex(list, indexType);
indexName = null;
}
if (indexName == null) {
indexName = newIndex;
list.clear();
}
boolean unique = !rs.getBoolean("NON_UNIQUE");
indexType = unique ? IndexType.createUnique(false, false) : IndexType.createNonUnique(false);
String col = rs.getString("COLUMN_NAME");
col = convertColumnName(col);
Column column = columnMap.get(col);
list.add(column);
}
rs.close();
}
if (indexName != null) {
addIndex(list, indexType);
}
}
use of org.h2.index.IndexType in project h2database by h2database.
the class RegularTable method addIndex.
@Override
public Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType, boolean create, String indexComment) {
if (indexType.isPrimaryKey()) {
for (IndexColumn c : cols) {
Column column = c.column;
if (column.isNullable()) {
throw DbException.get(ErrorCode.COLUMN_MUST_NOT_BE_NULLABLE_1, column.getName());
}
column.setPrimaryKey(true);
}
}
boolean isSessionTemporary = isTemporary() && !isGlobalTemporary();
if (!isSessionTemporary) {
database.lockMeta(session);
}
Index index;
if (isPersistIndexes() && indexType.isPersistent()) {
int mainIndexColumn;
if (database.isStarting() && database.getPageStore().getRootPageId(indexId) != 0) {
mainIndexColumn = -1;
} else if (!database.isStarting() && mainIndex.getRowCount(session) != 0) {
mainIndexColumn = -1;
} else {
mainIndexColumn = getMainIndexColumn(indexType, cols);
}
if (mainIndexColumn != -1) {
mainIndex.setMainIndexColumn(mainIndexColumn);
index = new PageDelegateIndex(this, indexId, indexName, indexType, mainIndex, create, session);
} else if (indexType.isSpatial()) {
index = new SpatialTreeIndex(this, indexId, indexName, cols, indexType, true, create, session);
} else {
index = new PageBtreeIndex(this, indexId, indexName, cols, indexType, create, session);
}
} else {
if (indexType.isHash()) {
if (cols.length != 1) {
throw DbException.getUnsupportedException("hash indexes may index only one column");
}
if (indexType.isUnique()) {
index = new HashIndex(this, indexId, indexName, cols, indexType);
} else {
index = new NonUniqueHashIndex(this, indexId, indexName, cols, indexType);
}
} else if (indexType.isSpatial()) {
index = new SpatialTreeIndex(this, indexId, indexName, cols, indexType, false, true, session);
} else {
index = new TreeIndex(this, indexId, indexName, cols, indexType);
}
}
if (database.isMultiVersion()) {
index = new MultiVersionIndex(index, this);
}
if (index.needRebuild() && rowCount > 0) {
try {
Index scan = getScanIndex(session);
long remaining = scan.getRowCount(session);
long total = remaining;
Cursor cursor = scan.find(session, null, null);
long i = 0;
int bufferSize = (int) Math.min(rowCount, database.getMaxMemoryRows());
ArrayList<Row> buffer = new ArrayList<>(bufferSize);
String n = getName() + ":" + index.getName();
int t = MathUtils.convertLongToInt(total);
while (cursor.next()) {
database.setProgress(DatabaseEventListener.STATE_CREATE_INDEX, n, MathUtils.convertLongToInt(i++), t);
Row row = cursor.get();
buffer.add(row);
if (buffer.size() >= bufferSize) {
addRowsToIndex(session, buffer, index);
}
remaining--;
}
addRowsToIndex(session, buffer, index);
if (SysProperties.CHECK && remaining != 0) {
DbException.throwInternalError("rowcount remaining=" + remaining + " " + getName());
}
} catch (DbException e) {
getSchema().freeUniqueName(indexName);
try {
index.remove(session);
} catch (DbException e2) {
// this could happen, for example on failure in the storage
// but if that is not the case it means
// there is something wrong with the database
trace.error(e2, "could not remove index");
throw e2;
}
throw e;
}
}
index.setTemporary(isTemporary());
if (index.getCreateSQL() != null) {
index.setComment(indexComment);
if (isSessionTemporary) {
session.addLocalTempTableIndex(index);
} else {
database.addSchemaObject(session, index);
}
}
indexes.add(index);
setModified();
return index;
}
use of org.h2.index.IndexType in project h2database by h2database.
the class TableLink method addIndex.
private void addIndex(List<Column> list, IndexType indexType) {
// bind the index to the leading recognized columns in the index
// (null columns might come from a function-based index)
int firstNull = list.indexOf(null);
if (firstNull == 0) {
trace.info("Omitting linked index - no recognized columns.");
return;
} else if (firstNull > 0) {
trace.info("Unrecognized columns in linked index. " + "Registering the index against the leading {0} " + "recognized columns of {1} total columns.", firstNull, list.size());
list = list.subList(0, firstNull);
}
Column[] cols = list.toArray(new Column[0]);
Index index = new LinkedIndex(this, 0, IndexColumn.wrap(cols), indexType);
indexes.add(index);
}
use of org.h2.index.IndexType in project h2database by h2database.
the class AlterTableAddConstraint method createIndex.
private Index createIndex(Table t, IndexColumn[] cols, boolean unique) {
int indexId = getObjectId();
IndexType indexType;
if (unique) {
// for unique constraints
indexType = IndexType.createUnique(t.isPersistIndexes(), false);
} else {
// constraints
indexType = IndexType.createNonUnique(t.isPersistIndexes());
}
indexType.setBelongsToConstraint(true);
String prefix = constraintName == null ? "CONSTRAINT" : constraintName;
String indexName = t.getSchema().getUniqueIndexName(session, t, prefix + "_INDEX_");
try {
Index index = t.addIndex(session, indexName, indexId, cols, indexType, true, null);
createdIndexes.add(index);
return index;
} finally {
getSchema().freeUniqueName(indexName);
}
}
use of org.h2.index.IndexType in project h2database by h2database.
the class CreateIndex method update.
@Override
public int update() {
if (!transactional) {
session.commit(true);
}
Database db = session.getDatabase();
boolean persistent = db.isPersistent();
Table table = getSchema().findTableOrView(session, tableName);
if (table == null) {
if (ifTableExists) {
return 0;
}
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
if (getSchema().findIndex(session, indexName) != null) {
if (ifNotExists) {
return 0;
}
throw DbException.get(ErrorCode.INDEX_ALREADY_EXISTS_1, indexName);
}
session.getUser().checkRight(table, Right.ALL);
table.lock(session, true, true);
if (!table.isPersistIndexes()) {
persistent = false;
}
int id = getObjectId();
if (indexName == null) {
if (primaryKey) {
indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_PRIMARY_KEY);
} else {
indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_INDEX);
}
}
IndexType indexType;
if (primaryKey) {
if (table.findPrimaryKey() != null) {
throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
}
indexType = IndexType.createPrimaryKey(persistent, hash);
} else if (unique) {
indexType = IndexType.createUnique(persistent, hash);
} else if (affinity) {
indexType = IndexType.createAffinity();
} else {
indexType = IndexType.createNonUnique(persistent, hash, spatial);
}
IndexColumn.mapColumns(indexColumns, table);
table.addIndex(session, indexName, id, indexColumns, indexType, create, comment);
return 0;
}
Aggregations