Skip to content

Add JSON output mode#66

Open
nikezono wants to merge 1 commit into
jarulraj:masterfrom
nikezono:json-output
Open

Add JSON output mode#66
nikezono wants to merge 1 commit into
jarulraj:masterfrom
nikezono:json-output

Conversation

@nikezono

Copy link
Copy Markdown

Summary

  • Add --json / -j output mode for machine-readable sqlcheck results
  • Emit JSON with issues and summary, plus file_name for file-based input
  • Support --json -v to include detailed anti-pattern messages

Related Issue

Testing

  • cmake --build /path/to/sqlcheck/build
  • ctest --test-dir /path/to/sqlcheck/build --output-on-failure
  • echo "select * from bugs;" | /path/to/sqlcheck/build/bin/sqlcheck --json
$ /path/to/sqlcheck/build/bin/sqlcheck -f examples/top_mutexes.sql --json -v

{
  "file_name": "examples/top_mutexes.sql",
  "issues": [
    {
      "line": 1,
      "statement": "with top_mutexes as (\r\n select--+ leading(t1 s1 v1 v2 t2 s2) use_hash(s1) use_nl(v1) use_hash(s2) materialize\r\n t1.hsecs\r\n ,s1.*\r\n ,s2.sleeps as end_sleeps\r\n ,s2.wait_time as end_wait_time\r\n ,s2.sleeps-s1.sleeps as delta_sleeps\r\n ,t2.hsecs - t1.hsecs as delta_hsecs\r\n --,s2.* \r\n from v$timer t1\r\n ,v$mutex_sleep s1\r\n ,(select/*+ no_merge */ sum(level) a from dual connect by level<=1e6) v1\r\n ,v$timer t2\r\n ,v$mutex_sleep s2\r\n where s1.mutex_type=s2.mutex_type\r\n and s1.location=s2.location\r\n)\r\nselect *\r\nfrom top_mutexes\r\norder by delta_sleeps desc",
      "risk": "HIGH RISK",
      "type": "QUERY ANTI-PATTERN",
      "title": "SELECT *",
      "message": "● Inefficiency in moving data to the consumer:  When you SELECT *, you're often retrieving more columns from the database than your application really needs to function. This causes more data to move from the database server to the client, slowing access and increasing load on your machines, as well as taking more time to travel across the network. This is especially true when someone adds new columns to underlying tables that didn't exist and weren't needed when the original consumers coded their data access.\n● Indexing issues:  Consider a scenario where you want to tune a query to a high level of performance. If you were to use *, and it returned more columns than you actually needed, the server would often have to perform more expensive methods to retrieve your data than it otherwise might. For example, you wouldn't be able to create an index which simply covered the columns in your SELECT list, and even if you did (including all columns [shudder]), the next guy who came around and added a column to the underlying table would cause the optimizer to ignore your optimized covering index, and you'd likely find that the performance of your query would drop substantially for no readily apparent reason.\n● Binding Problems:  When you SELECT *, it's possible to retrieve two columns of the same name from two different tables. This can often crash your data consumer. Imagine a query that joins two tables, both of which contain a column called \"ID\". How would a consumer know which was which? SELECT * can also confuse views (at least in some versions SQL Server) when underlying table structures change -- the view is not rebuilt, and the data which comes back can be nonsense. And the worst part of it is that you can take care to name your columns whatever you want, but the next guy who comes along might have no way of knowing that he has to worry about adding a column which will collide with your already-developed names."
    },
    {
      "line": 1,
      "statement": "with top_mutexes as (\r\n select--+ leading(t1 s1 v1 v2 t2 s2) use_hash(s1) use_nl(v1) use_hash(s2) materialize\r\n t1.hsecs\r\n ,s1.*\r\n ,s2.sleeps as end_sleeps\r\n ,s2.wait_time as end_wait_time\r\n ,s2.sleeps-s1.sleeps as delta_sleeps\r\n ,t2.hsecs - t1.hsecs as delta_hsecs\r\n --,s2.* \r\n from v$timer t1\r\n ,v$mutex_sleep s1\r\n ,(select/*+ no_merge */ sum(level) a from dual connect by level<=1e6) v1\r\n ,v$timer t2\r\n ,v$mutex_sleep s2\r\n where s1.mutex_type=s2.mutex_type\r\n and s1.location=s2.location\r\n)\r\nselect *\r\nfrom top_mutexes\r\norder by delta_sleeps desc",
      "risk": "LOW RISK",
      "type": "QUERY ANTI-PATTERN",
      "title": "Spaghetti Query Alert",
      "message": "● Split up a complex spaghetti query into several simpler queries:  SQL is a very expressive language—you can accomplish a lot in a single query or statement. But that doesn't mean it's mandatory or even a good idea to approach every task with the assumption it has to be done in one line of code. One common unintended consequence of producing all your results in one query is a Cartesian product. This happens when two of the tables in the query have no condition restricting their relationship. Without such a restriction, the join of two tables pairs each row in the first table to every row in the other table. Each such pairing becomes a row of the result set, and you end up with many more rows than you expect. It's important to consider that these queries are simply hard to write, hard to modify, and hard to debug. You should expect to get regular requests for incremental enhancements to your database applications. Managers want more complex reports and more fields in a user interface. If you design intricate, monolithic SQL queries, it's more costly and time-consuming to make enhancements to them. Your time is worth something, both to you and to your project. Split up a complex spaghetti query into several simpler queries. When you split up a complex SQL query, the result may be many similar queries, perhaps varying slightly depending on data values. Writing these queries is a chore, so it's a good application of SQL code generation. Although SQL makes it seem possible to solve a complex problem in a single line of code, don't be tempted to build a house of cards."
    }
  ],
  "summary": {
    "all": 2,
    "high": 1,
    "medium": 0,
    "low": 1,
    "hints": 0
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant