├── src ├── index.css ├── index.js ├── mysql_response.pegjs ├── App.js ├── components │ ├── Bar.js │ ├── ExplainTable.js │ └── ExampleQueriesBar.js ├── toolbox │ ├── theme.js │ └── theme.css └── mysql_response.js ├── .gitignore ├── package.json ├── README.md └── public └── index.html /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | 19 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render } from 'react-snapshot' 3 | import App from './App' 4 | import './index.css' 5 | 6 | const rootEl = document.getElementById('root') 7 | render(, rootEl) 8 | 9 | if (module.hot) { 10 | module.hot.accept('./App', () => { 11 | const NextApp = require('./App').default 12 | render(, rootEl) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "explain-you-mysql", 3 | "version": "0.1.0", 4 | "private": true, 5 | "homepage": "https://stereobooster.github.io/explain-you-mysql", 6 | "dependencies": { 7 | "gh-pages": "^0.12.0", 8 | "pegjs": "^0.10.0", 9 | "react": "^15.5.4", 10 | "react-snapshot": "^1.0.4", 11 | "react-toolbox": "^2.0.0-beta.8", 12 | "react-toolbox-themr": "^1.0.2" 13 | }, 14 | "devDependencies": { 15 | "react-scripts": "0.9.5" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build && react-snapshot", 20 | "test": "react-scripts test --env=jsdom", 21 | "eject": "react-scripts eject", 22 | "predeploy": "npm run build", 23 | "deploy": "gh-pages -d build", 24 | "toolbox": "react-toolbox-themr" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/mysql_response.pegjs: -------------------------------------------------------------------------------- 1 | QueryOutput 2 | = empty QueryRow* FinalRow? empty 3 | 4 | FinalRow 5 | = rows:Integer " row" [s]? " in set" ", "? warnings:Integer? " warning"? [s]? " (" [0-9.]* " sec)" nl? { return {rows: rows, warnings: warnings} } 6 | 7 | Identifier 8 | = res: [A-Za-z_0-9]* { return res.join("") } 9 | 10 | Value 11 | = res: [A-Za-z0-9_,.();<> ]* { return res.join("") } 12 | 13 | InfoRow 14 | = _* id:Identifier ":" _? val:Value? nl? {return [id, val] } 15 | 16 | InfoRows 17 | = rows:InfoRow* { var res ={}; for (var i in rows) { var row = rows[i]; res[row[0]] = row[1]; } return res } 18 | 19 | Header 20 | = "*"+ _ rowNumber:Integer ". row" _ "*"+ nl { return {number: rowNumber}; } 21 | 22 | QueryRow 23 | = header:Header rows:InfoRows { rows.number = header.number; return rows } 24 | 25 | Integer "integer" 26 | = [0-9]+ { return parseInt(text(), 10); } 27 | 28 | _ "whitespace" 29 | = [ \t] 30 | 31 | nl "newline" 32 | = _*[\n\r] 33 | 34 | empty 35 | = [ \t\n\r]* { return null } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Explain you MySQL 2 | 3 | Generate paraser: 4 | 5 | ``` 6 | yarn run pegjs src/mysql_response.pegjs 7 | ``` 8 | 9 | Deploy: 10 | 11 | ```sh 12 | yarn deploy 13 | ``` 14 | 15 | ### Explain 16 | - http://explainshell.com/ 17 | - http://tatiyants.com/postgres-query-plan-visualization/ 18 | - http://showthedocs.com/ 19 | 20 | ### Lint 21 | - http://www.shellcheck.net/ 22 | - https://github.com/yandex/gixy 23 | - http://eslint.org/ 24 | - https://github.com/bbatsov/rubocop 25 | 26 | ### Autoformat 27 | - https://github.com/prettier/prettier 28 | 29 | ### MySQL docs 30 | - https://dev.mysql.com/doc/refman/5.7/en/show-warnings.html 31 | - https://dev.mysql.com/doc/refman/5.6/en/explain-output.html#explain-output-columns 32 | - http://use-the-index-luke.com/sql/explain-plan/mysql/operations 33 | - https://www.slideshare.net/ronaldbradford/capturing-analyzing-and-optimizing-mysql 34 | - https://www.sitepoint.com/using-explain-to-write-better-mysql-queries/ 35 | 36 | ### TODO 37 | - Fix CSS 38 | - Description, title (Helmet?) 39 | - Key length note http://stackoverflow.com/questions/16568128/max-size-of-unique-index-in-mysql 40 | - visualy group subqueries by id 41 | 42 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | Explain you MySQL 17 | 18 | 19 |
20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | 3 | import ThemeProvider from 'react-toolbox/lib/ThemeProvider' 4 | import theme from './toolbox/theme.js' 5 | import './toolbox/theme.css' 6 | 7 | import Layout from 'react-toolbox/lib/layout/Layout'; 8 | import Panel from 'react-toolbox/lib/layout/Panel'; 9 | import Input from 'react-toolbox/lib/input/Input'; 10 | import Card from 'react-toolbox/lib/card/Card'; 11 | 12 | import Bar from './components/Bar' 13 | import ExplainTable from './components/ExplainTable' 14 | import ExampleQueriesBar from './components/ExampleQueriesBar' 15 | 16 | class App extends Component { 17 | state = { sql: '' }; 18 | 19 | handleChange = (value) => { 20 | this.setState({...this.state, sql: value}); 21 | }; 22 | 23 | render () { 24 | return ( 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ) 38 | } 39 | } 40 | 41 | export default App 42 | -------------------------------------------------------------------------------- /src/components/Bar.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import AppBar from 'react-toolbox/lib/app_bar/AppBar'; 3 | import Navigation from 'react-toolbox/lib/navigation/Navigation'; 4 | import Button from 'react-toolbox/lib/button/Button' 5 | 6 | const GithubIcon = () => ( 7 | 8 | 9 | 10 | ) 11 | 12 | const Bar = () => ( 13 | 14 | 15 | 18 | 19 | 20 | ) 21 | 22 | export default Bar 23 | -------------------------------------------------------------------------------- /src/toolbox/theme.js: -------------------------------------------------------------------------------- 1 | module.exports={"RTAppBar":{"appBar":"_3Py1Z","scrollHide":"PyOfn","flat":"_1J9he","fixed":"_2dwFx","inner":"lGWLJ","title":"_37vtt","leftIcon":"_30BcY","rightIcon":"_1hv3P"},"RTButton":{"button":"_2Agdx","rippleWrapper":"_3AVBi","squared":"_2GH_L","icon":"_3aBSX","solid":"_1ZxqC","raised":"_221ic _2Agdx _2GH_L _1ZxqC","flat":"_1jWAQ _2Agdx _2GH_L","floating":"_3IRMZ _2Agdx _1ZxqC","mini":"_2DCN-","toggle":"hC5Z2 _2Agdx","primary":"_3tTAW","accent":"_2wp6F","neutral":"_2CPs4","inverse":"_2SPZr"},"RTRipple":{"rippleWrapper":"_16N7o","ripple":"_3SV_u","rippleRestarting":"_2OZWa","rippleActive":"_3O2Ue"},"RTAutocomplete":{"autocomplete":"_07g5","focus":"_3qQkg","suggestions":"_3-Nb6","values":"_14fVf","value":"cBUoJ","up":"_3rmye","suggestion":"_1erPE","active":"kDY3Z","input":"_1ryxc"},"RTChip":{"chip":"_3Iv9P","avatar":"_2o8mD","deletable":"_2hlBs","delete":"_3nnfj","deleteIcon":"_2sopz","deleteX":"_10NaZ"},"RTAvatar":{"avatar":"_3OjJz","image":"_2Ueo9","letter":"_26GdB"},"RTInput":{"input":"lFVgC","withIcon":"_1nKdf","icon":"_3ga1V","inputElement":"_4bZUj","bar":"_3FySS","label":"_34120","fixed":"GRQEP","required":"_2G0aY","hint":"bMyi_","filled":"_34NWn","error":"_2k5Jz","counter":"_1oTuT","disabled":"_3ZfJq","errored":"_2s74E","hidden":"_2gAMv"},"RTCard":{"card":"_8pay8","raised":"_1AHwB","cardMedia":"_3Yc6z","wide":"_35NNe","square":"_1HBxg","content":"ewAVM","contentOverlay":"_1bBKz","cardTitle":"_1dU3o","cardActions":"ZoLIG","cardText":"K_kzH","title":"_3qCP3","subtitle":"_3p3mO","large":"_2iwOK","small":"_1RHxe"},"RTCheckbox":{"field":"_3Tq32","ripple":"_2NWrZ","text":"dXU7C","input":"_271V1","check":"_1CXAo","checked":"nSz7s","checkmark-expand":"_3GU9D","disabled":"_2jVLS"},"RTDatePicker":{"input":"_2ISvI","disabled":"Cf3yF","inputElement":"x7MhN","header":"_2vLUd","year":"_1VWY-","date":"_3K2Ws","calendarWrapper":"_1t-4v","yearsDisplay":"_2OzvT","monthsDisplay":"_2DDdC","dialog":"_3fCV6","button":"_2hL6u","calendar":"_1X9ls","prev":"Nv9Bc","next":"_3iPkS","title":"_2ESpD","years":"zEdgW","active":"_1pjXb","week":"PcByv","days":"_1qh3T","day":"_2qF_L","month":"_1hSm5","slideRightEnter":"Rk89h","slideRightLeave":"_1nam4","slideRightEnterActive":"m5B3T","slideRightLeaveActive":"_2bZap","slideLeftEnter":"bGml_","slideLeftLeave":"_2WGqM","slideLeftEnterActive":"_3Ghls","slideLeftLeaveActive":"_2WLHG"},"RTDialog":{"wrapper":"_3nrqp","dialog":"_3lw90","active":"_3ea_1","small":"_38VTT","normal":"_1K3iz","large":"_10LcP","fullscreen":"_3tLXQ","title":"_2J-aP","body":"_1Ivuq","navigation":"wgwdj","button":"_22_c6"},"RTOverlay":{"overlay":"_2LA9x","active":"_1mb5R"},"RTDrawer":{"wrapper":"_3eRY8","drawer":"_1sAOY","active":"EWFXC","right":"_2-4-H","left":"FKhpR"},"RTDropdown":{"dropdown":"ZzBNK","active":"_1DQ-E","values":"_2767w","label":"_2KjGM","value":"_6c1D5","up":"_1OA-G","disabled":"_1skVH","field":"d5bru","errored":"_3dZUG","templateValue":"_6dCtT","required":"_1j4LX","error":"fySw3","selected":"_3uiEo"},"RTLayout":{"layout":"wiKya","panel":"_3aW3s","bodyScroll":"_2uzOU","sidebarDrawer":"_2kCN0","navDrawerDrawer":"Cte92","pinned":"qf0ha","clipped":"_1y5eh","appbarInner":"_1S9wz","appbarFixed":"_2Q-xL","appbarAppBar":"F9Fy2","navDrawerPinned":"_2eOy5","appbarLeftIcon":"fZ13o","navDrawerClipped":"_2kROG","navDrawerWrapper":"_2gpOZ","sidebarPinned":"_3yo9c","sidebarClipped":"_1paQt","sidebarWrapper":"_1TUxm","sidebarWidth1":"_1EWpa","sidebarWidth2":"_37z5O","sidebarWidth3":"_24Dtc","sidebarWidth4":"_28mqi","sidebarWidth5":"K39iB","sidebarWidth6":"_2PjBX","sidebarWidth7":"_16Oxc","sidebarWidth8":"_3fr9v","sidebarWidth9":"iF_4K","sidebarWidth10":"_3mnwI","sidebarWidth11":"_2uccf","sidebarWidth12":"_1pU-9","sidebarWidth25":"_10h-v","sidebarWidth33":"BYRr2","sidebarWidth50":"_2L3ft","sidebarWidth66":"_31jol","sidebarWidth75":"_2Xvmh","sidebarWidth100":"_3T7B6"},"RTLink":{"icon":"_1-mD4","link":"_1Od3D","active":"_3blKB"},"RTList":{"list":"caNNQ","divider":"_2Jg3-","subheader":"q2l8C","inset":"_1HHo_","listItem":"ni6RH","ripple":"_2mi0Y","item":"_2GtDw","selectable":"_1OoR-","disabled":"_38DD6","checkboxItem":"OVyge","checkbox":"_3SG-0","left":"bHOJq","right":"OQ3Je","itemAction":"VB7pN","itemContentRoot":"_2FBCh","large":"EO5bo","itemText":"_12FqV","primary":"_3SxNr"},"RTMenu":{"iconMenu":"_2aMxm","icon":"_1b8Ml","menu":"_1gvr5","topLeft":"SYeW8","outline":"_2PdTB","topRight":"DFQvY","bottomLeft":"_3i7lA","bottomRight":"_3q-zB","static":"_2xf5n","menuInner":"_2t8UE","rippled":"_3o1JI","active":"_2Cekp","menuItem":"lyzBJ","disabled":"zGTpA","selected":"_2-j_P","ripple":"_2m_Cl","caption":"_3MsfE","shortcut":"_1anRY","menuDivider":"VX5Lv"},"RTNavigation":{"horizontal":"_1MJ9B","vertical":"xUlwz"},"RTProgressBar":{"linear":"_3vxHj","linear-indeterminate-bar":"_1cU21","indeterminate":"_1gPzb","value":"I0PhY","buffer":"SzbNd","circular":"_2j3vC","circular-indeterminate-bar-rotate":"zfZzh","circular-indeterminate-bar-dash":"_3DSlU","colors":"Z_PDt","circle":"DlWjM","path":"_1xZSU","multicolor":"_3XHT8"},"RTRadio":{"radio":"_1vWJb","ripple":"_78FVB","radioChecked":"_210O6 _1vWJb","field":"_36UDg","text":"_3guDD","input":"_2CPDD","disabled":"_39I6g _36UDg"},"RTSlider":{"container":"_-dLk","knob":"kq8Om","innerknob":"_8VjZ5","snaps":"_2x5j_","snap":"_12aGJ","input":"_2JHGy","progress":"_2R4jW","innerprogress":"_3p0mR","slider":"_3-BtZ","editable":"hkAL6","pinned":"_28Oo0","pressed":"_292qK","ring":"_2Oh5L"},"RTSnackbar":{"snackbar":"zDi3X","accept":"_2Y0Cy","button":"_2pCxU","warning":"_2li3o","cancel":"_3731C","active":"_38CsO","label":"_1JIbY"},"RTSwitch":{"field":"_1T2D0","text":"rxx-p","thumb":"_1pMry","ripple":"_1I9tv","on":"p92Yp","off":"_25ui_","input":"_3BTU_","switch-on":"_2Bwve","switch-off":"_1ZBFp","disabled":"_1CQ_q _1T2D0"},"RTTable":{"table":"_2xofu","head":"_1eF5Z","row":"_1qppP","selected":"_1H1dU","rowCell":"_18bqN","headCell":"gfcPv","numeric":"_3suRQ","checkboxCell":"_2yhwA","sorted":"_2r5OG","sortIcon":"_3NJs5","asc":"wZHUA"},"RTTabs":{"tabs":"_2EaQV","navigation":"_3e55Z","navigationContainer":"_3oZmF","arrow":"wPL4g","arrowContainer":"i_TGW","label":"_1yb8L","rippleWrapper":"_3c0W3","active":"_2LZ7Z","disabled":"_2gi1s","hidden":"_3kq1J","withIcon":"_1OFOx","withText":"_1Yf4A","icon":"_1LUZH","pointer":"_1xgdB","tab":"_26SP9","fixed":"_3bROj","inverse":"_33mT_"},"RTTooltip":{"tooltip":"_1v8bI","tooltipActive":"_2xWjx","tooltipTop":"_1PfOK","tooltipLeft":"_3uj3d","tooltipRight":"_3UQWj","tooltipInner":"_9q2WH"},"RTTimePicker":{"input":"_2APuy","disabled":"_2Vc_4","inputElement":"_2Z4kT","header":"_2u1sB","hours":"_3Kl2E","minutes":"_3Bp7w","separator":"_1c2VQ","ampm":"_1vAVQ","am":"_14hQA","pm":"aU9C9","dialog":"_1YlHq","button":"_1Kf0L","hoursDisplay":"_2JeOG","minutesDisplay":"_3UMNx","amFormat":"_26MJk","pmFormat":"_3H_-m","clock":"_2CwF0","placeholder":"zCpyM","clockWrapper":"_3paoD","face":"_3ui0r","number":"qr9pw","active":"_30yS_","hand":"_1rtAF","small":"_3eEHh","knob":"VqPQb","zoomInEnter":"_3DTnI","zoomInLeave":"_1tgJ3","zoomInEnterActive":"_1Fr4_","zoomInLeaveActive":"_1EUpH","zoomOutEnter":"_1Lb15","zoomOutLeave":"_3LDEu","zoomOutEnterActive":"_3y67C","zoomOutLeaveActive":"_18Ean"}} -------------------------------------------------------------------------------- /src/components/ExplainTable.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Table, TableHead, TableRow, TableCell } from 'react-toolbox/lib/table' 3 | import Tooltip from 'react-toolbox/lib/tooltip'; 4 | import { SyntaxError, parse } from '../mysql_response' 5 | import FontIcon from 'react-toolbox/lib/font_icon'; 6 | // import IconButton from 'react-toolbox/lib/button'; 7 | // 8 | 9 | const TooltipCell = Tooltip(TableCell) 10 | const TooltipIcon = Tooltip(FontIcon) 11 | 12 | const ExplainModel = { 13 | id: {type: Number}, 14 | select_type: {type: String} 15 | }; 16 | 17 | const explainSelectType = { 18 | "SIMPLE": "Simple SELECT (not using UNION or subqueries)", 19 | "PRIMARY": "Outermost SELECT", 20 | "UNION": "Second or later SELECT statement in a UNION", 21 | "DEPENDENT UNION": "Second or later SELECT statement in a UNION, dependent on outer query", 22 | "UNION RESULT": "Result of a UNION.", 23 | "SUBQUERY": "First SELECT in subquery", 24 | "DEPENDENT SUBQUERY": "First SELECT in subquery, dependent on outer query", 25 | "DERIVED": "Derived table SELECT (subquery in FROM clause)", 26 | "MATERIALIZED": "Materialized subquery", 27 | "UNCACHEABLE SUBQUERY": "A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query", 28 | "UNCACHEABLE UNION": "The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)" 29 | } 30 | 31 | const explainJoinTypes = { 32 | "system": "The table has only one row (= system table). This is a special case of the const join type.", 33 | "const": "The table has at most one matching row, which is read at the start of the query. Because there is only one row, values from the column in this row can be regarded as constants by the rest of the optimizer. const tables are very fast because they are read only once.", 34 | "eq_ref": "One row is read from this table for each combination of rows from the previous tables. Other than the system and const types, this is the best possible join type. It is used when all parts of an index are used by the join and the index is a PRIMARY KEY or UNIQUE NOT NULL index.", 35 | "ref": "All rows with matching index values are read from this table for each combination of rows from the previous tables. ref is used if the join uses only a leftmost prefix of the key or if the key is not a PRIMARY KEY or UNIQUE index (in other words, if the join cannot select a single row based on the key value). If the key that is used matches only a few rows, this is a good join type.", 36 | "fulltext": "The join is performed using a FULLTEXT index.", 37 | "ref_or_null": "This join type is like ref, but with the addition that MySQL does an extra search for rows that contain NULL values. This join type optimization is used most often in resolving subqueries.", 38 | "index_merge": "This join type indicates that the Index Merge optimization is used. In this case, the key column in the output row contains a list of indexes used, and key_len contains a list of the longest key parts for the indexes used.", 39 | "unique_subquery": "unique_subquery is just an index lookup function that replaces the subquery completely for better efficiency.", 40 | "index_subquery": "This join type is similar to unique_subquery. It replaces IN subqueries, but it works for nonunique indexes", 41 | "range": "Only rows that are in a given range are retrieved, using an index to select the rows. The key column in the output row indicates which index is used. The key_len contains the longest key part that was used. The ref column is NULL for this type.", 42 | "index": "The index join type is the same as ALL, except that the index tree is scanned.", 43 | "ALL": "A full table scan is done for each combination of rows from the previous tables. This is normally not good if the table is the first table not marked const, and usually very bad in all other cases. Normally, you can avoid ALL by adding indexes that enable row retrieval from the table based on constant values or column values from earlier tables." 44 | } 45 | 46 | const warn = 47 | 48 | const analyzeFiltered = (item) => ( 49 | item.filtered < 80 ? : null 50 | ) 51 | 52 | const analyzeKey = (item) => ( 53 | item.key == 'NULL' ? : null 54 | ) 55 | 56 | const analyzePossibleKeys = (item) => ( 57 | item.possible_keys == 'NULL' ? : null 58 | ) 59 | 60 | const analyzeJoinType = (item) => ( 61 | item.type == 'ALL' ? warn : null 62 | ) 63 | 64 | export default function ExplainTable(props) { 65 | try { 66 | if (props.sql === "") { 67 | return
Paste explain query results ("EXPLAIN your_query\G") to see table
68 | } 69 | 70 | let source = parse(props.sql).filter(x => x != null) 71 | let rows = source[0] 72 | let extra = source[1] 73 | let warnings = extra && extra.warnings 74 | 75 | return
76 | {warnings ? (
{warn} You have warnings use "SHOW WARNINGS\G" command to explore
) : null} 77 | 78 | 79 | id 80 | select_type 81 | table 82 | type 83 | possible_keys 84 | key 85 | key_len 86 | ref 87 | rows 88 | filtered 89 | Extra 90 | 91 | {rows.map((item, idx) => ( 92 | 93 | {item.id} 94 | {item.select_type} 95 | {item.table} 96 | {item.type}{analyzeJoinType(item)} 97 | {item.possible_keys}{analyzePossibleKeys(item)} 98 | {item.key}{analyzeKey(item)} 99 | {item.key_len} 100 | {item.ref} 101 | {item.rows} 102 | {item.filtered}{analyzeFiltered(item)} 103 | {item.Extra} 104 | 105 | ))} 106 |
107 |
108 | } catch (e) { 109 | // console.log(e) 110 | return
{warn} Parse error: {e.message} At {e.location.start.line}:{e.location.start.column}
111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/components/ExampleQueriesBar.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import Navigation from 'react-toolbox/lib/navigation/Navigation'; 3 | import Button from 'react-toolbox/lib/button/Button' 4 | 5 | const sql1 = `*************************** 1. row *************************** 6 | id: 1 7 | select_type: SIMPLE 8 | table: some_table 9 | partitions: NULL 10 | type: index_merge 11 | possible_keys: a,b 12 | key: a,b 13 | key_len: 60,60 14 | ref: NULL 15 | rows: 169 16 | filtered: 100.00 17 | Extra: Using sort_union(a, b); Using where 18 | 1 row in set, 1 warning (0.01 sec)` 19 | 20 | const sql2 = `********************** 1. row ********************** 21 | id: 1 22 | select_type: SIMPLE 23 | table: Country 24 | type: const 25 | possible_keys: PRIMARY 26 | key: PRIMARY 27 | key_len: 3 28 | ref: const 29 | rows: 1 30 | filtered: 100.00 31 | Extra: 32 | ********************** 2. row ********************** 33 | id: 1 34 | select_type: SIMPLE 35 | table: City 36 | type: ALL 37 | possible_keys: NULL 38 | key: NULL 39 | key_len: NULL 40 | ref: NULL 41 | rows: 4079 42 | filtered: 100.00 43 | Extra: Using where 44 | 2 rows in set, 1 warning (0.00 sec)` 45 | 46 | const sql3 = `********************** 1. row ********************** 47 | id: 1 48 | select_type: SIMPLE 49 | table: l 50 | type: ALL 51 | possible_keys: NULL 52 | key: NULL 53 | key_len: NULL 54 | ref: NULL 55 | rows: 7 56 | Extra: 57 | ********************** 2. row ********************** 58 | id: 1 59 | select_type: SIMPLE 60 | table: p 61 | type: ALL 62 | possible_keys: NULL 63 | key: NULL 64 | key_len: NULL 65 | ref: NULL 66 | rows: 110 67 | Extra: Using where; Using join buffer 68 | ********************** 3. row ********************** 69 | id: 1 70 | select_type: SIMPLE 71 | table: c 72 | type: ALL 73 | possible_keys: NULL 74 | key: NULL 75 | key_len: NULL 76 | ref: NULL 77 | rows: 122 78 | Extra: Using join buffer 79 | ********************** 4. row ********************** 80 | id: 1 81 | select_type: SIMPLE 82 | table: o 83 | type: ALL 84 | possible_keys: NULL 85 | key: NULL 86 | key_len: NULL 87 | ref: NULL 88 | rows: 326 89 | Extra: Using where; Using join buffer 90 | ********************** 5. row ********************** 91 | id: 1 92 | select_type: SIMPLE 93 | table: d 94 | type: ALL 95 | possible_keys: NULL 96 | key: NULL 97 | key_len: NULL 98 | ref: NULL 99 | rows: 2996 100 | Extra: Using where; Using join buffer 101 | 5 rows in set (0.00 sec)` 102 | 103 | const sql4 = `********************** 1. row ********************** 104 | id: 1 105 | select_type: SIMPLE 106 | table: o 107 | type: const 108 | possible_keys: PRIMARY,customerNumber 109 | key: PRIMARY 110 | key_len: 4 111 | ref: const 112 | rows: 1 113 | Extra: 114 | ********************** 2. row ********************** 115 | id: 1 116 | select_type: SIMPLE 117 | table: c 118 | type: const 119 | possible_keys: PRIMARY 120 | key: PRIMARY 121 | key_len: 4 122 | ref: const 123 | rows: 1 124 | Extra: 125 | ********************** 3. row ********************** 126 | id: 1 127 | select_type: SIMPLE 128 | table: d 129 | type: ref 130 | possible_keys: PRIMARY 131 | key: PRIMARY 132 | key_len: 4 133 | ref: const 134 | rows: 4 135 | Extra: 136 | ********************** 4. row ********************** 137 | id: 1 138 | select_type: SIMPLE 139 | table: p 140 | type: eq_ref 141 | possible_keys: PRIMARY,productLine 142 | key: PRIMARY 143 | key_len: 17 144 | ref: classicmodels.d.productCode 145 | rows: 1 146 | Extra: 147 | ********************** 5. row ********************** 148 | id: 1 149 | select_type: SIMPLE 150 | table: l 151 | type: eq_ref 152 | possible_keys: PRIMARY 153 | key: PRIMARY 154 | key_len: 52 155 | ref: classicmodels.p.productLine 156 | rows: 1 157 | Extra: 158 | 5 rows in set (0.00 sec)` 159 | 160 | const sql5 = `********************** 1. row ********************** 161 | id: 1 162 | select_type: PRIMARY 163 | table: 164 | type: ALL 165 | possible_keys: NULL 166 | key: NULL 167 | key_len: NULL 168 | ref: NULL 169 | rows: 219 170 | Extra: Using where 171 | ********************** 2. row ********************** 172 | id: 2 173 | select_type: DERIVED 174 | table: p 175 | type: ALL 176 | possible_keys: NULL 177 | key: NULL 178 | key_len: NULL 179 | ref: NULL 180 | rows: 110 181 | Extra: 182 | ********************** 3. row ********************** 183 | id: 2 184 | select_type: DERIVED 185 | table: l 186 | type: eq_ref 187 | possible_keys: PRIMARY 188 | key: PRIMARY 189 | key_len: 52 190 | ref: classicmodels.p.productLine 191 | rows: 1 192 | Extra: 193 | ********************** 4. row ********************** 194 | id: 3 195 | select_type: UNION 196 | table: v 197 | type: ALL 198 | possible_keys: NULL 199 | key: NULL 200 | key_len: NULL 201 | ref: NULL 202 | rows: 109 203 | Extra: 204 | ********************** 5. row ********************** 205 | id: 3 206 | select_type: UNION 207 | table: p 208 | type: eq_ref 209 | possible_keys: PRIMARY 210 | key: PRIMARY 211 | key_len: 17 212 | ref: classicmodels.v.productCode 213 | rows: 1 214 | Extra: 215 | ********************** 6. row ********************** 216 | id: 3 217 | select_type: UNION 218 | table: l 219 | type: eq_ref 220 | possible_keys: PRIMARY 221 | key: PRIMARY 222 | key_len: 52 223 | ref: classicmodels.p.productLine 224 | rows: 1 225 | Extra: 226 | ********************** 7. row ********************** 227 | id: NULL 228 | select_type: UNION RESULT 229 | table: 230 | type: ALL 231 | possible_keys: NULL 232 | key: NULL 233 | key_len: NULL 234 | ref: NULL 235 | rows: NULL 236 | Extra: 237 | 7 rows in set (0.01 sec)` 238 | 239 | const sql6 = `********************** 1. row ********************** 240 | id: 1 241 | select_type: PRIMARY 242 | table: 243 | type: ALL 244 | possible_keys: NULL 245 | key: NULL 246 | key_len: NULL 247 | ref: NULL 248 | rows: 12 249 | Extra: 250 | ********************** 2. row ********************** 251 | id: 2 252 | select_type: DERIVED 253 | table: p 254 | type: range 255 | possible_keys: idx_buyPrice,idx_productLine 256 | key: idx_buyPrice 257 | key_len: 8 258 | ref: NULL 259 | rows: 23 260 | Extra: Using where 261 | ********************** 3. row ********************** 262 | id: 2 263 | select_type: DERIVED 264 | table: l 265 | type: eq_ref 266 | possible_keys: PRIMARY 267 | key: PRIMARY 268 | key_len: 52 269 | ref: classicmodels.p.productLine 270 | rows: 1 271 | Extra: Using where 272 | ********************** 4. row ********************** 273 | id: 3 274 | select_type: UNION 275 | table: v 276 | type: range 277 | possible_keys: idx_buyPrice,idx_productCode 278 | key: idx_buyPrice 279 | key_len: 9 280 | ref: NULL 281 | rows: 1 282 | Extra: Using where 283 | ********************** 5. row ********************** 284 | id: 3 285 | select_type: UNION 286 | table: p 287 | type: eq_ref 288 | possible_keys: PRIMARY,idx_productLine 289 | key: PRIMARY 290 | key_len: 17 291 | ref: classicmodels.v.productCode 292 | rows: 1 293 | Extra: Using where 294 | ********************** 6. row ********************** 295 | id: 3 296 | select_type: UNION 297 | table: l 298 | type: eq_ref 299 | possible_keys: PRIMARY 300 | key: PRIMARY 301 | key_len: 52 302 | ref: classicmodels.p.productLine 303 | rows: 1 304 | Extra: Using where 305 | ********************** 7. row ********************** 306 | id: NULL 307 | select_type: UNION RESULT 308 | table: 309 | type: ALL 310 | possible_keys: NULL 311 | key: NULL 312 | key_len: NULL 313 | ref: NULL 314 | rows: NULL 315 | Extra: 316 | 7 rows in set (0.01 sec)` 317 | 318 | const ExampleQueriesBar = (props) => { 319 | let cb = props.onChange 320 | 321 | return ( 322 | Try some exmaples: 323 |