2017-09-11 38 views
0

TSql120ParserMicrosoft.SqlServer.TransactSql.ScriptDom)を使用してSQLクエリパーサーを構築していて、メカニックスはかなりシンプルなので、クエリをバッチに分割して適切なステートメントから情報を取得します。TSQL120Parserを使用してどのテーブルに属しているかについての情報を得る

SELECT 
    capture_instance as TableName 
    , supports_net_changes as SupportNetChanges 
    , index_name as PrimaryKeyName 
FROM 
    cdc.change_tables as ChangeTables 

私は次のように文にクエリを壊しています:

public void Parse(string query) 
    { 
     ColumnListInfo = new ColumnInfoList(); 

     IList<ParseError> parseErrors; 
     TSqlFragment result = _sqlParser.Parse(new StringReader(query), out parseErrors); 

     if (parseErrors.Any()) 
     { 
      throw new AggregateException(string.Join(Environment.NewLine, parseErrors.SelectMany(error => $"Error: {error.Message}").ToArray())); 
     } 

     var sqlScript = (TSqlScript)result; 
     foreach (TSqlStatement sqlStatement in sqlScript.Batches.SelectMany(sqlBatch => sqlBatch.Statements)) 
     { 
      if (sqlStatement.GetType() == typeof(SelectStatement)) 
      { 
       ProcessSqlSelectStatement(sqlStatement); 
      } 
      else 
      { 
       throw new ArgumentException($"Query type not supported: {sqlStatement.GetType()}"); 
      } 
     } 
    } 

次のI

私は、単純なクエリを使用することができますselect文のテーブルにselect文の列に参加するにはどのように問題を抱えていますselect文程度と文から情報を取得しています:

private void GenerateSelectInfo(QuerySpecification querySpecification) 
    { 
     int selectElementId = 0; 

     foreach (SelectElement selectElement in querySpecification.SelectElements) 
     { 
      if (selectElement.GetType() != typeof (SelectScalarExpression)) continue; 

      SelectScalarExpression selectScalarExpression = (SelectScalarExpression)selectElement; 
      IdentifierOrValueExpression identifierOrValueExpression = selectScalarExpression.ColumnName; 
      var identityString = string.Empty; 

      if (identifierOrValueExpression != null) 
      { 
       if (identifierOrValueExpression.ValueExpression == null) 
       { 
        identityString = identifierOrValueExpression.Identifier.Value; 
       } 
       ColumnListInfo.AddIfNeeded(selectElementId, identityString); 

       ScalarExpression scalarExpression = selectScalarExpression.Expression; 
       GenerateSelectScalarExperssionRecurse(selectElementId, scalarExpression); 
      } 
      else 
      { 
       throw new Exception("Error, something else than SelectScalarExpression found"); 
      } 

      selectElementId++; 
     } 
    } 
    private void GenerateReferenceRecurse(TableReference tableReference) 
    { 
     if (tableReference.GetType() == typeof(NamedTableReference)) 
     { 
      var namedTableReference = (NamedTableReference)tableReference; 
      Identifier aliasIdentifier = namedTableReference.Alias; 
      SchemaObjectName schemaObjectName = namedTableReference.SchemaObject; 
      ColumnListInfo.AddTableReference(schemaObjectName, aliasIdentifier); 
     } 
     else if (tableReference.GetType() == typeof(SchemaObjectFunctionTableReference)) 
     { 
      var namedTableReference = (SchemaObjectFunctionTableReference)tableReference; 
      Identifier aliasIdentifier = namedTableReference.Alias; 
      SchemaObjectName schemaObjectName = namedTableReference.SchemaObject; 
      ColumnListInfo.AddTableReference(schemaObjectName, aliasIdentifier); 
     } 
     else if (tableReference.GetType() == typeof(QualifiedJoin)) 
     { 
      QualifiedJoin qualifiedJoin = (QualifiedJoin)tableReference; 
      GenerateReferenceRecurse(qualifiedJoin.FirstTableReference); 
      GenerateReferenceRecurse(qualifiedJoin.SecondTableReference); 
     } 
     else if (tableReference.GetType() == typeof(JoinTableReference)) 
     { 
      JoinTableReference joinTableReference = (JoinTableReference)tableReference; 
      GenerateReferenceRecurse(joinTableReference.FirstTableReference); 
      GenerateReferenceRecurse(joinTableReference.SecondTableReference); 

     } 
     else 
     { 
      throw new ArgumentException($"Not supported table reference : {tableReference.GetType()}"); 
     } 
    } 

    private void GenerateSelectScalarExperssionRecurse(int selectElementId, ScalarExpression scalarExpression) 
    { 
     if (scalarExpression.GetType() == typeof(ColumnReferenceExpression)) 
     { 
      ColumnReferenceExpression columnReferenceExpression = (ColumnReferenceExpression)scalarExpression; 
      MultiPartIdentifier multiPartIdentifier = columnReferenceExpression.MultiPartIdentifier; 
      ColumnListInfo.AddRefereceIdentifier(selectElementId, multiPartIdentifier); 
     } 
     else if (scalarExpression.GetType() == typeof(ConvertCall)) 
     { 
      ConvertCall convertCall = (ConvertCall)scalarExpression; 
      ScalarExpression scalarExpressionParameter = convertCall.Parameter; 
      GenerateSelectScalarExperssionRecurse(selectElementId, scalarExpressionParameter); 
     } 
     else if (scalarExpression.GetType() == typeof(FunctionCall)) 
     { 
      FunctionCall functionCall = (FunctionCall)scalarExpression; 
      Identifier functionIdentifier = functionCall.FunctionName; 
      ColumnListInfo.AddFunctionIdentifier(selectElementId, functionIdentifier); 
     } 
     else 
     { 
      throw new ArgumentException($"Not supported Expression: {scalarExpression.GetType()}"); 
     } 
    } 

私はいずれかの私は、テーブル情報

を得ることができ、そこから合流しかし、今、私はテーブルがどの列になっているの情報を組み合わせることが熱いかわからない、私が試したがあるかのように再帰的な方法を使用して:

 public void AddTableReference(SchemaObjectName schemaObjectName, Identifier aliasIdentifier) 
     { 
      if (ColumnList.Count <= 0) return; 

      foreach (ColumnInfo columnInfo in ColumnList) 
      { 
       if (aliasIdentifier != null && 
        string.Equals(columnInfo.TableAlias, aliasIdentifier.Value, StringComparison.CurrentCultureIgnoreCase)) 
       { 
        if (schemaObjectName.SchemaIdentifier != null) columnInfo.TableSchema = schemaObjectName.SchemaIdentifier.Value; 
        if (schemaObjectName.BaseIdentifier != null) columnInfo.TableName = schemaObjectName.BaseIdentifier.Value; 
       } 
       else if (aliasIdentifier == null && schemaObjectName.BaseIdentifier != null && 
         string.Equals(schemaObjectName.BaseIdentifier.Value, columnInfo.TableAlias, StringComparison.CurrentCultureIgnoreCase)) 
       { 
        if (schemaObjectName.SchemaIdentifier != null) columnInfo.TableSchema = schemaObjectName.SchemaIdentifier.Value; 
        if (schemaObjectName.BaseIdentifier != null) columnInfo.TableName = schemaObjectName.BaseIdentifier.Value; 
       } 
      } 
     } 

は、しかし、これはジョイン列でのみ機能し、方法はありますか?

+1

列名テーブル名やエイリアスの接頭辞が付いていない場合、あなた(そして実際にはSQL Server)はこの情報を純粋に*解析することはできません。データベースメタデータをクエリして、クエリ内のスコープ内のどのテーブルに指定された名前の列が含まれているかを確認する必要があります(複数のテーブルに同じ名前の列が含まれている場合にエラーが発生します) –

+0

**複数のタイプミス**:それは**政治家ではなく、**列**(「柱」ではなく「1」は十分です)であり、「魔女」は古い醜い女性ですほうき - あなたがしたいものは**です** ** –

+0

そして愚かな自動正しいプラグイン –

答えて

0

Damien_The_Unbelieverが述べたように:

をBLOCKQUOTE カラム名はテーブル名または別名、あなた(そして実際にSQL Serverなど)が付けされていない場合は、構文解析から、純粋にこの情報を判断することはできません。データベースメタデータを照会して、照会内のどの表の中に指定された名前の列が含まれているかを判別する必要があります(複数の表に同じ名前の列が含まれている場合はエラーを発生させる必要があります)

関連する問題