public boolean isPartOfPrimaryKey(Column column) { KeyRecord pk = ((Table) column.getParent()).getPrimaryKey(); if (pk != null) { for (Column col : pk.getColumns()) { if (col.getName().equals(column.getName())) { return true; } } } return false; }
@Test public void testOptionsKey() throws Exception { String ddl = "CREATE FOREIGN TABLE G1( e1 integer, e2 varchar, e3 date, UNIQUE (e1) OPTIONS (CUSTOM_PROP 'VALUE'))"; Schema s = helpParse(ddl, "model").getSchema(); Map<String, Table> tableMap = s.getTables(); assertTrue("Table not found", tableMap.containsKey("G1")); Table table = tableMap.get("G1"); KeyRecord record = table.getAllKeys().iterator().next(); assertEquals("VALUE", record.getProperty("CUSTOM_PROP", false)); }
private boolean keyMatches(List<String> names, KeyRecord record) { if (names.size() != record.getColumns().size()) { return false; } Set<String> keyNames = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); for (Column c : record.getColumns()) { keyNames.add(c.getName()); } for (int i = 0; i < names.size(); i++) { if (!keyNames.contains(names.get(i))) { return false; } } return true; }
private void addConstraint( String defaultName, String type, KeyRecord constraint, boolean addOptions) { append(COMMA).append(NEWLINE).append(TAB); boolean nameMatches = defaultName.equals(constraint.getName()); if (!nameMatches) { append(CONSTRAINT) .append(SPACE) .append(SQLStringVisitor.escapeSinglePart(constraint.getName())) .append(SPACE); } append(type); addColumns(constraint.getColumns(), false); if (addOptions) { appendOptions(constraint); } }
private void validateConstraintNames( MetadataValidator metadataValidator, ValidatorReport report, ModelMetaData model, Collection<KeyRecord> keys, Set<String> names) { for (KeyRecord record : keys) { if (record.getName() == null) { continue; } if (!names.add(record.getName())) { metadataValidator.log( report, model, Messages.gs(Messages.TEIID.TEIID31152, record.getFullName())); } } }
static boolean sameColumnSet(KeyRecord recordOne, KeyRecord recordTwo) { if (recordOne == null || recordTwo == null) { return false; } List<Column> setOne = recordOne.getColumns(); List<Column> setTwo = recordTwo.getColumns(); if (setOne.size() != setTwo.size()) { return false; } for (int i = 0; i < setOne.size(); i++) { Column one = setOne.get(i); Column two = setTwo.get(i); if (!one.getName().equals(two.getName())) { return false; } } return true; }
private static void buildEntityTypes( MetadataStore metadataStore, List<EdmSchema.Builder> edmSchemas) { for (Schema schema : metadataStore.getSchemaList()) { List<EdmEntitySet.Builder> entitySets = new ArrayList<EdmEntitySet.Builder>(); List<EdmEntityType.Builder> entityTypes = new ArrayList<EdmEntityType.Builder>(); for (Table table : schema.getTables().values()) { KeyRecord primaryKey = table.getPrimaryKey(); List<KeyRecord> uniques = table.getUniqueKeys(); if (primaryKey == null && uniques.isEmpty()) { LogManager.logDetail( LogConstants.CTX_ODATA, ODataPlugin.Util.gs(ODataPlugin.Event.TEIID16002, table.getFullName())); continue; } EdmEntityType.Builder entityType = EdmEntityType.newBuilder().setName(table.getName()).setNamespace(schema.getName()); // adding key if (primaryKey != null) { for (Column c : primaryKey.getColumns()) { entityType.addKeys(c.getName()); } } else { for (Column c : uniques.get(0).getColumns()) { entityType.addKeys(c.getName()); } } // adding properties for (Column c : table.getColumns()) { EdmProperty.Builder property = EdmProperty.newBuilder(c.getName()) .setType(ODataTypeManager.odataType(c.getDatatype().getRuntimeTypeName())) .setNullable(c.getNullType() == NullType.Nullable); if (c.getDatatype() .getRuntimeTypeName() .equals(DataTypeManager.DefaultDataTypes.STRING)) { property.setFixedLength(c.isFixedLength()).setMaxLength(c.getLength()).setUnicode(true); } entityType.addProperties(property); } // entity set one for one entity type EdmEntitySet.Builder entitySet = EdmEntitySet.newBuilder().setName(table.getName()).setEntityType(entityType); entityType.setNamespace(schema.getName()); entitySets.add(entitySet); // add enitity types for entity schema entityTypes.add(entityType); } // entity container is holder entity sets, association sets, function imports EdmEntityContainer.Builder entityContainer = EdmEntityContainer.newBuilder() .setName(schema.getName()) .setIsDefault(false) .addEntitySets(entitySets); // build entity schema EdmSchema.Builder modelSchema = EdmSchema.newBuilder() .setNamespace(schema.getName()) .addEntityTypes(entityTypes) .addEntityContainers(entityContainer); edmSchemas.add(modelSchema); } }
@Override public void execute( VDBMetaData vdb, MetadataStore store, ValidatorReport report, MetadataValidator metadataValidator) { for (Schema schema : store.getSchemaList()) { if (vdb.getImportedModels().contains(schema.getName())) { continue; } ModelMetaData model = vdb.getModel(schema.getName()); for (Table t : schema.getTables().values()) { if (t.isVirtual()) { if (t.isMaterialized() && t.getMaterializedTable() != null) { String matTableName = t.getMaterializedTable().getFullName(); int index = matTableName.indexOf(Table.NAME_DELIM_CHAR); if (index == -1) { metadataValidator.log( report, model, Messages.gs(Messages.TEIID.TEIID31088, matTableName, t.getFullName())); } else { String schemaName = matTableName.substring(0, index); Schema matSchema = store.getSchema(schemaName); if (matSchema == null) { metadataValidator.log( report, model, Messages.gs( Messages.TEIID.TEIID31089, schemaName, matTableName, t.getFullName())); } else { Table matTable = matSchema.getTable(matTableName.substring(index + 1)); if (matTable == null) { metadataValidator.log( report, model, Messages.gs( Messages.TEIID.TEIID31090, matTableName.substring(index + 1), schemaName, t.getFullName())); } else { t.setMaterializedTable(matTable); } } } } } for (KeyRecord record : t.getAllKeys()) { if (record.getColumns() == null || record.getColumns().isEmpty()) { metadataValidator.log( report, model, Messages.gs(Messages.TEIID.TEIID31149, t.getFullName(), record.getName())); } } List<ForeignKey> fks = t.getForeignKeys(); if (fks == null || fks.isEmpty()) { continue; } for (ForeignKey fk : fks) { // Only applicable to older teiid releases than 8.9 if (fk.getReferenceKey() != null && !metadataValidator.isTeiidOrGreater(Version.TEIID_8_9)) { // ensure derived fields are set fk.setReferenceKey(fk.getReferenceKey()); continue; } String referenceTableName = fk.getReferenceTableName(); Table referenceTable = null; if (fk.getReferenceKey() == null) { if (referenceTableName == null) { metadataValidator.log( report, model, Messages.gs(Messages.TEIID.TEIID31091, t.getFullName())); continue; } // TODO there is an ambiguity here because we don't properly track the name parts // so we have to first check for a table name that may contain . referenceTable = schema.getTable(referenceTableName); } else { referenceTableName = fk.getReferenceKey().getParent().getFullName(); } String referenceSchemaName = schema.getName(); int index = referenceTableName.indexOf(Table.NAME_DELIM_CHAR); if (referenceTable == null) { if (index != -1) { referenceSchemaName = referenceTableName.substring(0, index); Schema referenceSchema = store.getSchema(referenceSchemaName); if (referenceSchema == null) { metadataValidator.log( report, model, Messages.gs(Messages.TEIID.TEIID31093, referenceSchemaName, t.getFullName())); continue; } referenceTable = referenceSchema.getTable(referenceTableName.substring(index + 1)); } if (referenceTable == null) { metadataValidator.log( report, model, Messages.gs( Messages.TEIID.TEIID31092, t.getFullName(), referenceTableName.substring(index + 1), referenceSchemaName)); continue; } } KeyRecord uniqueKey = null; List<String> referenceColumns = fk.getReferenceColumns(); if (fk.getReferenceKey() != null) { // index metadata logic sets the key prior to having the column names List<Column> cols = fk.getReferenceKey().getColumns(); referenceColumns = new ArrayList<String>(); for (Column col : cols) { referenceColumns.add(col.getName()); } } if (referenceColumns == null || referenceColumns.isEmpty()) { if (referenceTable.getPrimaryKey() == null) { metadataValidator.log( report, model, Messages.gs( Messages.TEIID.TEIID31094, t.getFullName(), referenceTableName.substring(index + 1), referenceSchemaName)); } else { uniqueKey = referenceTable.getPrimaryKey(); } } else { for (KeyRecord record : referenceTable.getUniqueKeys()) { if (keyMatches(fk.getReferenceColumns(), record)) { uniqueKey = record; break; } } if (uniqueKey == null && referenceTable.getPrimaryKey() != null && keyMatches(fk.getReferenceColumns(), referenceTable.getPrimaryKey())) { uniqueKey = referenceTable.getPrimaryKey(); } } if (uniqueKey == null) { metadataValidator.log( report, model, Messages.gs( Messages.TEIID.TEIID31095, t.getFullName(), referenceTableName.substring(index + 1), referenceSchemaName, fk.getReferenceColumns())); } else { fk.setReferenceKey(uniqueKey); } } } } }
private void validate( VDBMetaData vdb, ModelMetaData model, AbstractMetadataRecord record, ValidatorReport report, IQueryMetadataInterface metadata, MetadataFactory mf) { ValidatorReport resolverReport = null; try { if (record instanceof Procedure) { Procedure p = (Procedure) record; Command command = queryParser.parseProcedure(p.getQueryPlan(), false); GroupSymbol gs = createASTNode(ASTNodes.GROUP_SYMBOL); gs.setName(p.getFullName()); QueryResolver resolver = new QueryResolver(queryParser); resolver.resolveCommand(command, gs, ICommand.TYPE_STORED_PROCEDURE, metadata, false); Validator validator = new Validator(); resolverReport = validator.validate(command, metadata); determineDependencies(p, command); } else if (record instanceof Table) { Table t = (Table) record; GroupSymbol symbol = createASTNode(ASTNodes.GROUP_SYMBOL); symbol.setName(t.getFullName()); ResolverUtil.resolveGroup(symbol, metadata); String selectTransformation = t.getSelectTransformation(); boolean columnsIsEmpty = t.getColumns() == null || t.getColumns().isEmpty(); // Consider columns if teid 8.11 or lower boolean considerColumns_811 = isTeiidOrGreater(Version.TEIID_8_12_4) ? true : columnsIsEmpty; // Consider columns if teiid 8.12.4+ boolean considerColumns_8124 = isTeiidOrGreater(Version.TEIID_8_12_4) ? columnsIsEmpty : true; if (t.isVirtual() && considerColumns_811) { QueryCommand command = (QueryCommand) queryParser.parseCommand(selectTransformation); QueryResolver resolver = new QueryResolver(queryParser); resolver.resolveCommand(command, metadata); Validator validator = new Validator(); resolverReport = validator.validate(command, metadata); if (!resolverReport.hasItems() && considerColumns_8124) { List<Expression> symbols = command.getProjectedSymbols(); for (Expression column : symbols) { try { addColumn(Symbol.getShortName(column), column.getType(), t, mf); } catch (Exception e) { log(report, model, e.getMessage()); } } } if (considerColumns_8124) { determineDependencies(t, command); if (t.getInsertPlan() != null && t.isInsertPlanEnabled()) { validateUpdatePlan( model, report, metadata, t, t.getInsertPlan(), Command.TYPE_INSERT); } if (t.getUpdatePlan() != null && t.isUpdatePlanEnabled()) { validateUpdatePlan( model, report, metadata, t, t.getUpdatePlan(), Command.TYPE_UPDATE); } if (t.getDeletePlan() != null && t.isDeletePlanEnabled()) { validateUpdatePlan( model, report, metadata, t, t.getDeletePlan(), Command.TYPE_DELETE); } } } boolean addCacheHint = false; if (t.isMaterialized() && t.getMaterializedTable() == null) { List<KeyRecord> fbis = t.getFunctionBasedIndexes(); List<GroupSymbol> groups = Arrays.asList(symbol); if (fbis != null && !fbis.isEmpty()) { for (KeyRecord fbi : fbis) { for (int j = 0; j < fbi.getColumns().size(); j++) { Column c = fbi.getColumns().get(j); if (c.getParent() != fbi) { continue; } String exprString = c.getNameInSource(); try { Expression ex = queryParser.parseExpression(exprString); ResolverVisitor resolverVisitor = new ResolverVisitor(teiidVersion); resolverVisitor.resolveLanguageObject(ex, groups, metadata); if (!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(ex) .isEmpty()) { log( report, model, Messages.gs(Messages.TEIID.TEIID31114, exprString, fbi.getFullName())); } EvaluatableVisitor ev = new EvaluatableVisitor(teiidVersion); PreOrPostOrderNavigator.doVisit(ex, ev, PostOrderNavigator.PRE_ORDER); if (ev.getDeterminismLevel().compareTo(Determinism.VDB_DETERMINISTIC) < 0) { log( report, model, Messages.gs(Messages.TEIID.TEIID31115, exprString, fbi.getFullName())); } } catch (QueryResolverException e) { log( report, model, Messages.gs( Messages.TEIID.TEIID31116, exprString, fbi.getFullName(), e.getMessage())); } } } } } else { addCacheHint = true; } // this seems to parse, resolve and validate. QueryResolver resolver = new QueryResolver(queryParser); QueryNode node = resolver.resolveView( symbol, new QueryNode(t.getSelectTransformation()), SQLConstants.Reserved.SELECT, metadata); CacheHint cacheHint = node.getCommand().getCacheHint(); Long ttl = -1L; if (cacheHint != null && cacheHint.getTtl() != null && addCacheHint && t.getProperty(MATVIEW_TTL, false) == null) { ttl = cacheHint.getTtl(); t.setProperty(MATVIEW_TTL, String.valueOf(ttl)); } } if (resolverReport != null && resolverReport.hasItems()) { for (ValidatorFailure v : resolverReport.getItems()) { log( report, model, v.getStatus() == IValidatorFailure.VFStatus.ERROR ? Severity.ERROR : Severity.WARNING, v.getMessage()); } } processReport(model, record, report, resolverReport); } catch (Exception e) { log( report, model, Messages.gs(Messages.TEIID.TEIID31080, record.getFullName(), e.getMessage())); } }