github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/views/vdatabase/Detail.html (about) 1 <!-- Content managed by Project Forge, see [projectforge.md] for details. --> 2 {% import ( 3 "github.com/kyleu/dbaudit/app" 4 "github.com/kyleu/dbaudit/app/controller/cutil" 5 "github.com/kyleu/dbaudit/app/lib/database" 6 "github.com/kyleu/dbaudit/app/util" 7 "github.com/kyleu/dbaudit/views/components" 8 "github.com/kyleu/dbaudit/views/layout" 9 ) %} 10 11 {% code type Detail struct { 12 layout.Basic 13 Mode string 14 Svc *database.Service 15 Recent database.DebugStatements 16 Sizes database.TableSizes 17 SQL string 18 Columns []string 19 Results [][]any 20 Timing int 21 Commit bool 22 } %} 23 24 {% func (p *Detail) Body(as *app.State, ps *cutil.PageState) %} 25 <div class="card"> 26 <h3>{%= components.SVGRefIcon(`database`, ps) %}{%s p.Svc.Key %}</h3> 27 <div class="mt"> 28 {%- if p.Svc.Tracing() == "" -%} 29 <em>tracing is disabled</em> 30 {%- else -%} 31 <em>tracing is enabled in [{%s p.Svc.Tracing() %}] mode</em> 32 {%- endif -%} 33 </div> 34 <div class="mt"> 35 <a href="#modal-settings"><button>Tracing Settings</button></a> 36 {%= settingsModal(p.Svc) %} 37 {%- if p.Svc.Tracing() != "" -%} 38 <a href="/admin/database/{%s p.Svc.Key %}/recent"><button>Recent Activity</button></a> 39 {%- endif -%} 40 <a href="/admin/database/{%s p.Svc.Key %}/tables"><button>Tables</button></a> 41 <a href="/admin/database/{%s p.Svc.Key %}/analyze"><button>Analyze</button></a> 42 <a href="/admin/database/{%s p.Svc.Key %}/sql"><button>SQL</button></a> 43 </div> 44 </div> 45 {%- switch p.Mode -%} 46 {%- case "recent" -%} 47 {%= recentStatements(p.Recent, p.Svc, as, ps) %} 48 {%- case "tables" -%} 49 {%= tableSizes(p.Svc.Key, p.Sizes, as, ps) %} 50 {%- case "sql" -%} 51 {%= sqlEditor(p.SQL, p.Svc, p.Commit, p.Columns, p.Results, p.Timing, as, ps) %} 52 {%- endswitch -%} 53 {% endfunc %} 54 55 {% func recentStatements(recent database.DebugStatements, svc *database.Service, as *app.State, ps *cutil.PageState) %} 56 <div class="card"> 57 <h3>Recent Activity</h3> 58 {%- if len(recent) == 0 -%} 59 {%- if svc.Tracing() == "" -%} 60 <em>Tracing is not enabled for this database</em> 61 {%- else -%} 62 <em>No recent statements</em> 63 {%- endif -%} 64 {%- else -%} 65 <div class="overflow full-width"> 66 <table> 67 <thead> 68 <tr> 69 <th>SQL</th> 70 <th>Values</th> 71 <th>Count</th> 72 <th>Status</th> 73 <th>Message</th> 74 <th>Duration</th> 75 </tr> 76 </thead> 77 <tbody> 78 {%- for _, s := range recent -%} 79 <tr> 80 <td> 81 <a href="?idx={%d s.Index %}">{%s s.SQLTrimmed(100) %}</a> 82 </td> 83 <td>{%d len(s.Values) %}</td> 84 <td>{%d s.Count %}</td> 85 <td> 86 {%- if s.Error == "" -%} 87 OK 88 {%- else -%} 89 <span class="error">[error]: {%s s.ErrorTrimmed(100) %}</span> 90 {%- endif -%} 91 </td> 92 <td>{%s s.Message %}</td> 93 <td>{%s util.MicrosToMillis(s.Timing) %}</td> 94 </tr> 95 {%- endfor -%} 96 </tbody> 97 </table> 98 </div> 99 {%- endif -%} 100 </div> 101 {% endfunc %} 102 103 {% func tableSizes(key string, sizes database.TableSizes, as *app.State, ps *cutil.PageState) %} 104 <div class="card"> 105 <h3>Table Sizes</h3> 106 <div class="overflow full-width"> 107 <table> 108 <thead> 109 <tr> 110 <th>Name</th> 111 <th title="(estimated)">Rows*</th> 112 </tr> 113 </thead> 114 <tbody> 115 {%- for _, size := range sizes -%} 116 <tr> 117 <td><a href="/admin/database/{%s key %}/tables/{%s size.Schema %}/{%s size.Name %}">{%s size.Name %}</a></td> 118 <td>{%s size.Rows %}</td> 119 </tr> 120 {%- endfor -%} 121 </tbody> 122 </table> 123 </div> 124 </div> 125 {% endfunc %} 126 127 {% func sqlEditor(sql string, svc *database.Service, commit bool, columns []string, results [][]any, timing int, as *app.State, ps *cutil.PageState) %} 128 <div class="card"> 129 <h3>SQL Editor</h3> 130 <form method="post" action="/admin/database/{%s svc.Key %}/sql"> 131 <div class="mt expanded"> 132 <textarea name="sql" rows="12" placeholder="SQL statement">{%s sql %}</textarea> 133 </div> 134 {%- if svc.ReadOnly -%} 135 <input type="hidden" name="commit" value="false" /> 136 {%- else -%} 137 <div class="mt"> 138 <label><input type="checkbox" name="commit" value="true" {% if commit %}checked="checked"{% endif %}/> Commit Changes</label> 139 </div> 140 {%- endif -%} 141 <div class="mt"> 142 <button type="submit" name="action" value="run">Run</button> 143 <button type="submit" name="action" value="analyze">Analyze</button> 144 </div> 145 </form> 146 </div> 147 {%- if results != nil -%} 148 <div class="card"> 149 <div class="right">{%s util.MicrosToMillis(timing) %}</div> 150 <h3>Results</h3> 151 {%- if len(results) == 0 -%} 152 <em>No rows returned</em> 153 {%- else -%} 154 <div class="overflow full-width"> 155 <table class="mt expanded"> 156 <thead> 157 <tr> 158 {%- for _, c := range columns -%} 159 <th>{%s c %}</th> 160 {%- endfor -%} 161 </tr> 162 </thead> 163 <tbody> 164 {%- for _, row := range results -%} 165 <tr> 166 {%- for _, x := range row -%} 167 <td>{%v x %}</td> 168 {%- endfor -%} 169 </tr> 170 {%- endfor -%} 171 </tbody> 172 </table> 173 </div> 174 {%- endif -%} 175 </div> 176 {%- endif -%} 177 {% endfunc %} 178 179 {% func settingsModal(svc *database.Service) %} 180 <div id="modal-settings" class="modal" style="display: none;"> 181 <a class="backdrop" href="#"></a> 182 <div class="modal-content"> 183 <div class="modal-header"> 184 <a href="#" class="modal-close">×</a> 185 <h2>Tracing Settings</h2> 186 </div> 187 <div class="modal-body"> 188 <form action="/admin/database/{%s svc.Key %}/enable"> 189 <div class="overflow full-width"> 190 <table> 191 <tbody> 192 {%- code trc := svc.Tracing() %} 193 <tr> 194 <td><label><input type="radio" name="tracing" value=""{% if trc == `` %} checked="checked"{% endif %}> No Tracing</label></td> 195 <td><em>Fastest configuration, no tracing overhead</em></td> 196 </tr> 197 <tr> 198 <td><label><input type="radio" name="tracing" value="statement"{% if trc == `statement` %} checked="checked"{% endif %}> Save Queries</label></td> 199 <td><em>Save most recent 100 SQL statements with timing information</em></td> 200 </tr> 201 <tr> 202 <td><label><input type="radio" name="tracing" value="values"{% if trc == `values` %} checked="checked"{% endif %}> Save Results</label></td> 203 <td><em>Saves SQL, timing, and the results of the query</em></td> 204 </tr> 205 <tr> 206 <td><label><input type="radio" name="tracing" value="analyze"{% if trc == `analyze` %} checked="checked"{% endif %}> Analyze Queries</label></td> 207 <td><em>In addition to the above, runs an explain plan on each query</em></td> 208 </tr> 209 <tr> 210 <td colspan="2"><button>Submit</button></td> 211 </tr> 212 </tbody> 213 </table> 214 </div> 215 </form> 216 </div> 217 </div> 218 </div> 219 {% endfunc %}