private TupleSource loadGlobalTable( final CommandContext context, final GroupSymbol group, final String tableName, final GlobalTableStore globalStore) throws TeiidComponentException, TeiidProcessingException { LogManager.logInfo( LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30013, tableName)); final QueryMetadataInterface metadata = context.getMetadata(); final List<ElementSymbol> allColumns = ResolverUtil.resolveElementsInGroup(group, metadata); final TempTable table = globalStore.createMatTable(tableName, group); table.setUpdatable(false); return new ProxyTupleSource() { TupleSource insertTupleSource; boolean success; QueryProcessor qp; boolean closed; boolean errored; @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { int rowCount = -1; try { if (insertTupleSource == null) { String fullName = metadata.getFullName(group.getMetadataID()); String transformation = metadata.getVirtualPlan(group.getMetadataID()).getQuery(); qp = context .getQueryProcessorFactory() .createQueryProcessor(transformation, fullName, context); insertTupleSource = new BatchCollector.BatchProducerTupleSource(qp); } table.insert(insertTupleSource, allColumns, false, null); table.getTree().compact(); rowCount = table.getRowCount(); Determinism determinism = qp.getContext().getDeterminismLevel(); context.setDeterminismLevel(determinism); // TODO: could pre-process indexes to remove overlap for (Object index : metadata.getIndexesInGroup(group.getMetadataID())) { List<ElementSymbol> columns = GlobalTableStoreImpl.resolveIndex(metadata, allColumns, index); table.addIndex(columns, false); } for (Object key : metadata.getUniqueKeysInGroup(group.getMetadataID())) { List<ElementSymbol> columns = GlobalTableStoreImpl.resolveIndex(metadata, allColumns, key); table.addIndex(columns, true); } CacheHint hint = table.getCacheHint(); if (hint != null && table.getPkLength() > 0) { table.setUpdatable(hint.isUpdatable(false)); } if (determinism.compareTo(Determinism.VDB_DETERMINISTIC) < 0 && (hint == null || hint.getScope() == null || Scope.VDB.compareTo(hint.getScope()) <= 0)) { LogManager.logInfo( LogConstants.CTX_DQP, QueryPlugin.Util.gs( QueryPlugin.Event.TEIID31143, determinism, tableName)); // $NON-NLS-1$ } globalStore.loaded(tableName, table); success = true; LogManager.logInfo( LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30014, tableName, rowCount)); return CollectionTupleSource.createUpdateCountTupleSource(rowCount); } catch (BlockedException e) { throw e; } catch (Exception e) { errored = true; LogManager.logError( LogConstants.CTX_MATVIEWS, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30015, tableName)); closeSource(); rethrow(e); throw new AssertionError(); } } @Override public void closeSource() { if (closed) { return; } if (!errored) { LogManager.logInfo( LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31153, tableName)); } closed = true; if (!success) { globalStore.failedLoad(tableName); table.remove(); } if (qp != null) { qp.closeProcessing(); } super.closeSource(); } }; }
TupleSource registerRequest(final CommandContext context, String modelName, final Command command) throws TeiidComponentException, TeiidProcessingException { final TempTableStore contextStore = context.getTempTableStore(); if (command instanceof Query) { Query query = (Query) command; if (modelName != null && !modelName.equals(TempMetadataAdapter.TEMP_MODEL.getID())) { return null; } return registerQuery(context, contextStore, query); } if (command instanceof ProcedureContainer) { if (command instanceof StoredProcedure) { StoredProcedure proc = (StoredProcedure) command; if (CoreConstants.SYSTEM_ADMIN_MODEL.equals(modelName)) { TupleSource result = handleSystemProcedures(context, proc); if (result != null) { return result; } } else if (proc.getGroup().isGlobalTable()) { return handleCachedProcedure(context, proc); } return null; // it's not a stored procedure we want to handle } final GroupSymbol group = ((ProcedureContainer) command).getGroup(); if (!modelName.equals(TempMetadataAdapter.TEMP_MODEL.getID()) || !group.isTempGroupSymbol()) { return null; } return new ProxyTupleSource() { @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { final String groupKey = group.getNonCorrelationName(); final TempTable table = contextStore.getOrCreateTempTable( groupKey, command, bufferManager, true, true, context, group); if (command instanceof Insert) { Insert insert = (Insert) command; TupleSource ts = insert.getTupleSource(); if (ts == null) { Evaluator eval = new Evaluator(Collections.emptyMap(), TempTableDataManager.this, context); List<Object> values = new ArrayList<Object>(insert.getValues().size()); for (Expression expr : (List<Expression>) insert.getValues()) { values.add(eval.evaluate(expr, null)); } ts = new CollectionTupleSource(Arrays.asList(values).iterator()); } return table.insert(ts, insert.getVariables(), true, context); } if (command instanceof Update) { final Update update = (Update) command; final Criteria crit = update.getCriteria(); return table.update(crit, update.getChangeList()); } if (command instanceof Delete) { final Delete delete = (Delete) command; final Criteria crit = delete.getCriteria(); if (crit == null) { // TODO: we'll add a real truncate later int rows = table.truncate(false); return CollectionTupleSource.createUpdateCountTupleSource(rows); } return table.delete(crit); } throw new AssertionError("unknown command " + command); // $NON-NLS-1$ } }; } if (command instanceof Create) { Create create = (Create) command; String tempTableName = create.getTable().getName(); if (contextStore.hasTempTable(tempTableName)) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30229, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30229, tempTableName)); } if (create.getTableMetadata() != null) { contextStore.addForeignTempTable(tempTableName, create); } else { contextStore.addTempTable(tempTableName, create, bufferManager, true, context); } return CollectionTupleSource.createUpdateCountTupleSource(0); } if (command instanceof Drop) { String tempTableName = ((Drop) command).getTable().getName(); contextStore.removeTempTableByName(tempTableName, context); return CollectionTupleSource.createUpdateCountTupleSource(0); } if (command instanceof AlterTempTable) { AlterTempTable att = (AlterTempTable) command; TempTable tt = contextStore.getTempTable(att.getTempTable()); Assertion.isNotNull(tt, "Table doesn't exist"); // $NON-NLS-1$ tt.setUpdatable(false); if (att.getIndexColumns() != null && tt.getRowCount() > 2 * tt.getTree().getPageSize(true)) { for (List<ElementSymbol> cols : att.getIndexColumns()) { tt.addIndex(cols, false); } } return CollectionTupleSource.createUpdateCountTupleSource(0); } return null; }
private TupleSource handleSystemProcedures(final CommandContext context, StoredProcedure proc) throws TeiidComponentException, QueryMetadataException, QueryProcessingException, QueryResolverException, QueryValidatorException, TeiidProcessingException, ExpressionEvaluationException { final QueryMetadataInterface metadata = context.getMetadata(); if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEW)) { Object groupID = validateMatView( metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue()); TempMetadataID matTableId = context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); String matViewName = metadata.getFullName(groupID); String matTableName = metadata.getFullName(matTableId); LogManager.logDetail( LogConstants.CTX_MATVIEWS, "processing refreshmatview for", matViewName); // $NON-NLS-1$ boolean invalidate = Boolean.TRUE.equals(((Constant) proc.getParameter(3).getExpression()).getValue()); boolean needsLoading = globalStore.needsLoading(matTableName, globalStore.getAddress(), true, true, invalidate); if (!needsLoading) { return CollectionTupleSource.createUpdateCountTupleSource(-1); } GroupSymbol matTable = new GroupSymbol(matTableName); matTable.setMetadataID(matTableId); return loadGlobalTable(context, matTable, matTableName, globalStore); } else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROW)) { final Object groupID = validateMatView( metadata, (String) ((Constant) proc.getParameter(2).getExpression()).getValue()); TempMetadataID matTableId = context.getGlobalTableStore().getGlobalTempTableMetadataId(groupID); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); Object pk = metadata.getPrimaryKey(groupID); String matViewName = metadata.getFullName(groupID); if (pk == null) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30230, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30230, matViewName)); } List<?> ids = metadata.getElementIDsInKey(pk); Constant key = (Constant) proc.getParameter(3).getExpression(); Object initialValue = key.getValue(); SPParameter keyOther = proc.getParameter(4); Object[] otherCols = null; int length = 1; if (keyOther != null) { otherCols = ((ArrayImpl) ((Constant) keyOther.getExpression()).getValue()).getValues(); if (otherCols != null) { length += otherCols.length; } } if (ids.size() != length) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30231, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30231, matViewName, ids.size(), length)); } final String matTableName = RelationalPlanner.MAT_PREFIX + matViewName.toUpperCase(); MatTableInfo info = globalStore.getMatTableInfo(matTableName); if (!info.isValid()) { return CollectionTupleSource.createUpdateCountTupleSource(-1); } TempTable tempTable = globalStore.getTempTable(matTableName); if (!tempTable.isUpdatable()) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30232, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30232, matViewName)); } Iterator<?> iter = ids.iterator(); final Object[] params = new Object[length]; StringBuilder criteria = new StringBuilder(); for (int i = 0; i < length; i++) { Object id = iter.next(); String targetTypeName = metadata.getElementType(id); Object value = i == 0 ? initialValue : otherCols[i - 1]; value = DataTypeManager.transformValue(value, DataTypeManager.getDataTypeClass(targetTypeName)); params[i] = value; if (i != 0) { criteria.append(" AND "); // $NON-NLS-1$ } criteria.append(metadata.getFullName(id)).append(" = ?"); // $NON-NLS-1$ } LogManager.logInfo( LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30012, matViewName, Arrays.toString(params))); String queryString = Reserved.SELECT + " * " + Reserved.FROM + ' ' + matViewName + ' ' + Reserved.WHERE + ' ' + //$NON-NLS-1$ criteria.toString() + ' ' + Reserved.OPTION + ' ' + Reserved.NOCACHE; final QueryProcessor qp = context .getQueryProcessorFactory() .createQueryProcessor(queryString, matViewName.toUpperCase(), context, params); final TupleSource ts = new BatchCollector.BatchProducerTupleSource(qp); return new ProxyTupleSource() { @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { List<?> tuple = ts.nextTuple(); boolean delete = false; if (tuple == null) { delete = true; tuple = Arrays.asList(params); } else { tuple = new ArrayList<Object>(tuple); // ensure the list is serializable } List<?> result = globalStore.updateMatViewRow(matTableName, tuple, delete); if (eventDistributor != null) { eventDistributor.updateMatViewRow( context.getVdbName(), context.getVdbVersion(), metadata.getName(metadata.getModelID(groupID)), metadata.getName(groupID), tuple, delete); } return CollectionTupleSource.createUpdateCountTupleSource(result != null ? 1 : 0); } @Override public void closeSource() { super.closeSource(); qp.closeProcessing(); } }; } return null; }
private TupleSource updateMatviewRows( final CommandContext context, final QueryMetadataInterface metadata, final Object groupID, final GlobalTableStore globalStore, final String matViewName, List<?> ids, Object[][] params) throws QueryProcessingException, TeiidComponentException, QueryMetadataException, TransformationException { final String matTableName = RelationalPlanner.MAT_PREFIX + matViewName.toUpperCase(); MatTableInfo info = globalStore.getMatTableInfo(matTableName); if (!info.isValid()) { return CollectionTupleSource.createUpdateCountTupleSource(-1); } TempTable tempTable = globalStore.getTempTable(matTableName); if (!tempTable.isUpdatable()) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30232, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30232, matViewName)); } List<Object[]> converted = new ArrayList<Object[]>(); for (Object[] param : params) { if (param == null || ids.size() != param.length) { throw new QueryProcessingException( QueryPlugin.Event.TEIID30231, QueryPlugin.Util.gs( QueryPlugin.Event.TEIID30231, matViewName, ids.size(), param == null ? 0 : param.length)); } final Object[] vals = new Object[param.length]; for (int i = 0; i < ids.size(); i++) { Object value = param[i]; String targetTypeName = metadata.getElementType(ids.get(i)); value = DataTypeManager.transformValue(value, DataTypeManager.getDataTypeClass(targetTypeName)); vals[i] = value; } converted.add(vals); } final Iterator<Object[]> paramIter = converted.iterator(); Iterator<?> iter = ids.iterator(); StringBuilder criteria = new StringBuilder(); for (int i = 0; i < ids.size(); i++) { Object id = iter.next(); String targetTypeName = metadata.getElementType(id); if (i != 0) { criteria.append(" AND "); // $NON-NLS-1$ } criteria.append(metadata.getFullName(id)).append(" = ?"); // $NON-NLS-1$ } final String queryString = Reserved.SELECT + " * " + Reserved.FROM + ' ' + matViewName + ' ' + Reserved.WHERE + ' ' + //$NON-NLS-1$ criteria.toString() + ' ' + Reserved.OPTION + ' ' + Reserved.NOCACHE; return new ProxyTupleSource() { private QueryProcessor qp; private TupleSource ts; private Object[] params; private int count; @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { while (true) { if (qp == null) { params = paramIter.next(); LogManager.logInfo( LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs( QueryPlugin.Event.TEIID30012, matViewName, Arrays.toString(params))); qp = context .getQueryProcessorFactory() .createQueryProcessor(queryString, matViewName.toUpperCase(), context, params); ts = new BatchCollector.BatchProducerTupleSource(qp); } List<?> tuple = ts.nextTuple(); boolean delete = false; if (tuple == null) { delete = true; tuple = Arrays.asList(params); } else { tuple = new ArrayList<Object>(tuple); // ensure the list is serializable } List<?> result = globalStore.updateMatViewRow(matTableName, tuple, delete); if (result != null) { count++; } if (eventDistributor != null) { eventDistributor.updateMatViewRow( context.getVdbName(), context.getVdbVersion(), metadata.getName(metadata.getModelID(groupID)), metadata.getName(groupID), tuple, delete); } qp.closeProcessing(); qp = null; ts = null; if (!paramIter.hasNext()) { break; } } return CollectionTupleSource.createUpdateCountTupleSource(count); } @Override public void closeSource() { super.closeSource(); if (qp != null) { qp.closeProcessing(); } } }; }