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;
 }
示例#2
0
 private void addColumns(List<Column> columns, boolean includeType) {
   append(LPAREN);
   boolean first = true;
   for (Column c : columns) {
     if (first) {
       first = false;
     } else {
       append(COMMA).append(SPACE);
     }
     if (includeType) {
       appendColumn(c, true, includeType);
       appendColumnOptions(c);
     } else if (c.getParent() instanceof KeyRecord) {
       // function based column
       append(c.getNameInSource());
     } else {
       append(SQLStringVisitor.escapeSinglePart(c.getName()));
     }
   }
   append(RPAREN);
 }
示例#3
0
  private void buildColumnOptions(BaseColumn baseColumn, StringBuilder options) {
    if (baseColumn instanceof Column) {
      Column column = (Column) baseColumn;
      if (!column.isSelectable()) {
        addOption(options, SELECTABLE, column.isSelectable());
      }

      // if table is already updatable, then columns are implicitly updatable.
      if (!column.isUpdatable()
          && column.getParent() instanceof Table
          && ((Table) column.getParent()).supportsUpdate()) {
        addOption(options, UPDATABLE, column.isUpdatable());
      }

      if (column.isCurrency()) {
        addOption(options, CURRENCY, column.isCurrency());
      }

      // only record if not default
      if (!column.isCaseSensitive() && column.getDatatype().isCaseSensitive()) {
        addOption(options, CASE_SENSITIVE, column.isCaseSensitive());
      }

      if (!column.isSigned() && column.getDatatype().isSigned()) {
        addOption(options, SIGNED, column.isSigned());
      }
      if (column.isFixedLength()) {
        addOption(options, FIXED_LENGTH, column.isFixedLength());
      }
      // length and octet length should be same. so this should be never be true.
      // TODO - this is not quite valid since we are dealing with length representing chars in
      // UTF-16, then there should be twice the bytes
      if (column.getCharOctetLength() != 0 && column.getLength() != column.getCharOctetLength()) {
        addOption(options, CHAR_OCTET_LENGTH, column.getCharOctetLength());
      }

      // by default the search type is default data type search, so avoid it.
      if (column.getSearchType() != null
          && (!column.getSearchType().equals(column.getDatatype().getSearchType())
              || column.isSearchTypeSet())) {
        addOption(options, SEARCHABLE, column.getSearchType().name());
      }

      if (column.getMinimumValue() != null) {
        addOption(options, MIN_VALUE, column.getMinimumValue());
      }

      if (column.getMaximumValue() != null) {
        addOption(options, MAX_VALUE, column.getMaximumValue());
      }

      if (column.getNullValues() != -1) {
        addOption(options, NULL_VALUE_COUNT, column.getNullValues());
      }

      if (column.getDistinctValues() != -1) {
        addOption(options, DISTINCT_VALUES, column.getDistinctValues());
      }
    }

    if (baseColumn.getNativeType() != null) {
      addOption(options, NATIVE_TYPE, baseColumn.getNativeType());
    }

    buildOptions(baseColumn, options);
  }
  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()));
    }
  }