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(); } }; }
private TupleSource registerQuery( final CommandContext context, final TempTableStore contextStore, final Query query) { final GroupSymbol group = query.getFrom().getGroups().get(0); if (!group.isTempGroupSymbol()) { return null; } final String tableName = group.getNonCorrelationName(); if (group.isGlobalTable()) { TempMetadataID matTableId = (TempMetadataID) group.getMetadataID(); final GlobalTableStore globalStore = getGlobalStore(context, matTableId); final MatTableInfo info = globalStore.getMatTableInfo(tableName); return new ProxyTupleSource() { Future<Void> moreWork = null; TupleSource loadingTupleSource; DQPWorkContext newWorkContext; @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { if (loadingTupleSource != null) { load(); } else { boolean load = false; if (!info.isUpToDate()) { boolean invalidate = true; VDBMetaData vdb = context.getVdb(); if (vdb != null) { String val = vdb.getPropertyValue("lazy-invalidate"); // $NON-NLS-1$ if (val != null) { invalidate = !Boolean.valueOf(val); } } load = globalStore.needsLoading( tableName, globalStore.getAddress(), true, false, invalidate); if (load) { load = globalStore.needsLoading( tableName, globalStore.getAddress(), false, false, invalidate); } if (!load) { synchronized (info) { if (!info.isUpToDate()) { RequestWorkItem workItem = context.getWorkItem(); info.addWaiter(workItem); if (moreWork != null) { moreWork.cancel(false); } moreWork = workItem.scheduleWork(10000); // fail-safe - attempt again in 10 seconds throw BlockedException.block( "Blocking on mat view load", tableName); // $NON-NLS-1$ } } } else { if (!info.isValid() || executor == null) { // blocking load // TODO: we should probably do all loads using a temp session if (info.getVdbMetaData() != null && context.getDQPWorkContext() != null && !info.getVdbMetaData() .getFullName() .equals(context.getDQPWorkContext().getVDB().getFullName())) { assert executor != null; // load with by pretending we're in the imported vdb newWorkContext = createWorkContext(context, info.getVdbMetaData()); CommandContext newContext = context.clone(); newContext.setNewVDBState(newWorkContext); loadingTupleSource = loadGlobalTable( newContext, group, tableName, newContext.getGlobalTableStore()); } else { loadingTupleSource = loadGlobalTable(context, group, tableName, globalStore); } load(); } else { loadViaRefresh(context, tableName, context.getDQPWorkContext().getVDB(), info); } } } } TempTable table = globalStore.getTempTable(tableName); context.accessedDataObject(group.getMetadataID()); TupleSource result = table.createTupleSource( query.getProjectedSymbols(), query.getCriteria(), query.getOrderBy()); cancelMoreWork(); return result; } private void load() throws TeiidComponentException, TeiidProcessingException { if (newWorkContext != null) { try { newWorkContext.runInContext( new Callable<Void>() { @Override public Void call() throws Exception { loadingTupleSource.nextTuple(); return null; } }); } catch (Throwable e) { rethrow(e); } } else { loadingTupleSource.nextTuple(); } } private void cancelMoreWork() { if (moreWork != null) { moreWork.cancel(false); moreWork = null; } } @Override public void closeSource() { if (loadingTupleSource != null) { loadingTupleSource.closeSource(); } super.closeSource(); cancelMoreWork(); } }; } // it's not expected for a blocked exception to bubble up from here, so return a tuplesource to // perform getOrCreateTempTable return new ProxyTupleSource() { @Override protected TupleSource createTupleSource() throws TeiidComponentException, TeiidProcessingException { TempTableStore tts = contextStore; TempTable tt = tts.getOrCreateTempTable(tableName, query, bufferManager, true, false, context, group); if (context.getDataObjects() != null) { Object id = RelationalPlanner.getTrackableGroup(group, context.getMetadata()); if (id != null) { context.accessedDataObject(id); } } return tt.createTupleSource( query.getProjectedSymbols(), query.getCriteria(), query.getOrderBy()); } }; }
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(); } } }; }
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 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(), REFRESHMATVIEWROWS)) { 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); Object[][] params = (Object[][]) ((ArrayImpl) ((Constant) proc.getParameter(3).getExpression()).getValue()) .getValues(); return updateMatviewRows(context, metadata, groupID, globalStore, matViewName, ids, params); } 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); final 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[] param = null; if (keyOther != null) { Object[] otherCols = ((ArrayImpl) ((Constant) keyOther.getExpression()).getValue()).getValues(); if (otherCols != null) { param = new Object[1 + otherCols.length]; param[0] = initialValue; for (int i = 0; i < otherCols.length; i++) { param[i + 1] = otherCols[i]; } } } if (param == null) { param = new Object[] {initialValue}; } Object[][] params = new Object[][] {param}; return updateMatviewRows(context, metadata, groupID, globalStore, matViewName, ids, params); } return null; }