</tr>
</%def>
-<%def name="result_table(rows=[], status=[])" filter="trim">
- ## Passing the result rows and processing them here avoids duplicating
- ## the results in RAM.
- <table>
- ${caller.body()}
- <tbody>
- % for row in rows:
- ${self.render_row(row.data)}
- % endfor
- </tbody>
- </table>
- <p>
- % for status_row in status:
- % if not loop.first:
- <br>
- % endif
- ${status_row.data}
- % endfor
- </p>
-</%def>
-
<%def name="sql_error()">
<p>${caller.body()}</p>
</%def>
command_result = []
status_result = []
%>
- <hr>
% for result_row in result_rows:
- <% type = result_row.type %>
- % if type == 'data':
- <% command_result.append(result_row) %>
- % elif type == 'status':
- <% status_result.append(result_row) %>
- % else:
- % if new_result:
- <%self:result_table
- rows="${command_result}" status="${status_result}">
- ${self.render_heading(new_result.data)}
- </%self:result_table>
- <hr>
- <%
- command_result = []
- status_result = []
- %>
- % endif
- % if type == 'new_result':
- <% new_result = result_row %>
- % elif type == 'error':
- <%self:sql_error>
- ${result_row.data}
- </%self:sql_error>
- % endif
+ <hr>
+ % if result_row.statusmessage is not None:
+ <p>${result_row.statusmessage.data.split(' ')[0]}</p>
% endif
- % endfor
- <%self:result_table
- rows="${command_result}" status="${status_result}">
- ${self.render_heading(new_result.data)}
- </%self:result_table>
+ % if result_row.rows:
+ <table>
+ % if result_row.heading is not None:
+ ${self.render_heading(result_row.heading.data)}
+ % endif
+ <tbody>
+ % for row in result_row.rows:
+ ${self.render_row(row.data)}
+ % endfor
+ </tbody>
+ </table>
+ % endif
+
+ <p>${result_row.rowcount.data}</p>
+ % endfor
<hr>
</%def>
@attrs.define()
class SQLResult():
+ rows = attrs.field(factory=list)
+ statusmessage = attrs.field(default=None)
+ rowcount = attrs.field(default=None)
+ heading = attrs.field(default=None)
+
+
+@attrs.define()
+class ResultRow():
data = attrs.field(default=None)
- type = attrs.field(default=None)
- def build_new_result_row(self, cur, have_rows):
- self.type = 'new_result'
- if have_rows:
- # The data contains the column headings
- self.data = [col.name for col in cur.description]
+ def build_heading_row(self, cur):
+ self.data = [col.name for col in cur.description]
return self
def build_statusmessage_row(self, cur):
- self.type = 'status'
self.data = cur.statusmessage
return self
def build_rowcount_row(self, cur):
- self.type = 'status'
self.data = f'{cur.rowcount} rows affected'
return self
def build_data_row(self, data):
- self.type = 'data'
self.data = data
return self
descr=err.diag.message_primary,
detail=self.format_detail(err, stmt_text))
- def get_result_rows(self, cur, sql_results):
- first = True
+ def get_result_rows(self, cur):
+ rows = []
while (row := cur.fetchone()) is not None:
- if first:
- sql_results.append(SQLResult().build_new_result_row(cur, True))
- first = False
- sql_results.append(SQLResult().build_data_row(row))
+ rows.append(ResultRow().build_data_row(row))
+ return rows
def cleanup(self):
'''
sql_results = self.sql_results
nextset = True
while nextset is True:
- have_rows = cur.rownumber is not None
- if have_rows:
- self.get_result_rows(cur, sql_results)
- else:
- sql_results.append(SQLResult().build_new_result_row(
- cur, have_rows))
- sql_results.append(SQLResult().build_statusmessage_row(cur))
- sql_results.append(SQLResult().build_rowcount_row(cur))
+ sql_result = SQLResult()
+ if cur.rownumber is not None:
+ sql_result.heading = ResultRow().build_heading_row(cur)
+ sql_result.rows = self.get_result_rows(cur)
+ sql_result.statusmessage = ResultRow().build_statusmessage_row(cur)
+ sql_result.rowcount = ResultRow().build_rowcount_row(cur)
+ sql_results.append(sql_result)
nextset = cur.nextset()
def factory(self, ue):