Getting table schema from a query

前端 未结 5 495

As per MSDN, SqlDataReader.GetSchemaTable returns column metadata for the query executed. I am wondering is there a similar method that will give table metadata

5条回答
  •  甜味超标
    2021-01-12 12:40

    Short answer

    This won't work. You cannot, by design, get table aliases from result schema. And you cannot rely on being able to get them from query execution plan.

    Long answer

    When you get result of a SQL query, the query has already been parsed, validated, optimized, compiled into some internal representation and executed. Aliases are part of query's "source code" and are usually lost somewhere around step 1 and 2.

    After query is executed the only things that can be seen as tables are a) real physical tables and b) returned data seen as single anonymous table. Everything between can be transformed or completely optimized out.

    If DBMSes were required to retain aliases it would be practically impossible to optimize complex queries.

    Possible solutions

    I suggest restating a problem:

    1. Are you (or your application) source of the query in question? In that case you should know the aliases.

    2. If you get queries provided by someone else... Well... That depends on why are you adding where causes.

      • In the worst case, you'll have to parse queries yourself.

      • In the best case, you could give them access to views instead of real tables and put where clauses in the views.


    Simple and ugly solution

    If I understand your requirements correctly:

    • User A enters query into your program.

    • User B can run it (but cannot edit it) and sees returned data. Additionally she can add filters based on returned columns using some kind of widget provided by you.

    • You don't want to apply filter inside application but instead add them to the query, in order to avoid fetching unnecessary data from database.

    In that case:

    • When A edits query try to run it and gather metadata for returned columns. If ColumnNames are not unique, complain to the author. Store metadata with query.

    • When B adds filter (based on query metadata), store both columns names and conditions.

    • At execution:

      • Check if filter columns are still valid (A might have changed query). If not remove invalid filters and/or inform B.

      • Execute query as something like:

         select *
         from ({query entered by A}) x
         where x.Column1 op1 Value1
             and x.Column2 op2 Value2
        

    If you want to gracefully handle database schema changes you need to add some additional checks to make sure metadata is consistent with what query really returns.

    Security note

    Your program is going to pass a query written by user A straight to database. It is crucial that you do it using database connection with permissions which do not exceed A's database permissions. Otherwise you are asking for SQL injection based exploits.

    Corollary

    If user A doesn't have direct access to the database out of security reasons, you cannot use above solution.

    In that case the only way to make it safe is to make sure your application understands 100% of the query which means parsing it in your program and allowing only operations you consider safe.

提交回复
热议问题