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 %}