Update website

This commit is contained in:
Guilhem Lavaux 2025-03-24 09:27:39 +01:00
parent a0b0d3dae7
commit ae7ef6ad45
3151 changed files with 566766 additions and 48 deletions

View file

@ -0,0 +1,12 @@
<td{{ nowrap ? ' class="nowrap"' }}>
{{ is_selected ? '<strong>' }}
<a class="foreign_value" data-key="{{ keyname }}" href="#" title="
{%- trans 'Use this value' %}{{ title is not empty ? ': ' ~ title }}">
{% if nowrap %}
{{ keyname }}
{% else %}
{{ description }}
{% endif %}
</a>
{{ is_selected ? '</strong>' }}
</td>

View file

@ -0,0 +1,5 @@
{% if foreign_data.disp_row is iterable and
(show_all and foreign_data.the_total > max_rows) %}
<input class="btn btn-secondary" type="submit" id="foreign_showAll" name="foreign_showAll" value="
{%- trans 'Show all' %}">
{% endif %}

View file

@ -0,0 +1,156 @@
{# Display Chart options #}
<div id="div_view_options">
<form method="post" id="tblchartform" action="{{ url('/table/chart') }}" class="ajax">
{{ get_hidden_inputs(url_params) }}
<fieldset>
<legend>
{% trans 'Display chart' %}
</legend>
<div class="chartOption">
<div class="formelement">
<input type="radio" name="chartType" value="bar" id="radio_bar">
<label for ="radio_bar">{% trans %}Bar{% context %}Chart type{% endtrans %}</label>
</div>
<div class="formelement">
<input type="radio" name="chartType" value="column" id="radio_column">
<label for ="radio_column">{% trans %}Column{% context %}Chart type{% endtrans %}</label>
</div>
<div class="formelement">
<input type="radio" name="chartType" value="line" id="radio_line" checked="checked">
<label for ="radio_line">{% trans %}Line{% context %}Chart type{% endtrans %}</label>
</div>
<div class="formelement">
<input type="radio" name="chartType" value="spline" id="radio_spline">
<label for ="radio_spline">{% trans %}Spline{% context %}Chart type{% endtrans %}</label>
</div>
<div class="formelement">
<input type="radio" name="chartType" value="area" id="radio_area">
<label for ="radio_area">{% trans %}Area{% context %}Chart type{% endtrans %}</label>
</div>
<span class="span_pie hide">
<input type="radio" name="chartType" value="pie" id="radio_pie">
<label for ="radio_pie">{% trans %}Pie{% context %}Chart type{% endtrans %}</label>
</span>
<span class="span_timeline hide">
<input type="radio" name="chartType" value="timeline" id="radio_timeline">
<label for ="radio_timeline">{% trans %}Timeline{% context %}Chart type{% endtrans %}</label>
</span>
<span class="span_scatter hide">
<input type="radio" name="chartType" value="scatter" id="radio_scatter">
<label for ="radio_scatter">{% trans %}Scatter{% context %}Chart type{% endtrans %}</label>
</span>
<br><br>
<span class="barStacked hide">
<input type="checkbox" name="barStacked" value="1" id="checkbox_barStacked">
<label for ="checkbox_barStacked">{% trans 'Stacked' %}</label>
</span>
<br><br>
<label for ="chartTitle">{% trans 'Chart title:' %}</label>
<input type="text" name="chartTitle" id="chartTitle">
</div>
{% set xaxis = null %}
<div class="chartOption">
<label for="select_chartXAxis">{% trans 'X-Axis:' %}</label>
<select name="chartXAxis" id="select_chartXAxis">
{% for idx, key in keys %}
{% if xaxis is same as(null) %}
{% set xaxis = idx %}
{% endif %}
{% if xaxis is same as(idx) %}
<option value="{{ idx }}" selected="selected">{{ key }}</option>
{% else %}
<option value="{{ idx }}">{{ key }}</option>
{% endif %}
{% endfor %}
</select>
<br>
<label for="select_chartSeries">
{% trans 'Series:' %}
</label>
<select name="chartSeries" id="select_chartSeries" multiple="multiple">
{% for idx, key in keys %}
{% if fields_meta[idx].type in numeric_types %}
{% if idx == xaxis and numeric_column_count > 1 %}
<option value="{{ idx }}">{{ key }}</option>
{% else %}
<option value="{{ idx }}" selected="selected">{{ key }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
<input type="hidden" name="dateTimeCols" value="
{% set date_time_types = ['date', 'datetime', 'timestamp'] %}
{% for idx, key in keys %}
{% if fields_meta[idx].type in date_time_types %}
{{ idx ~ ' ' }}
{% endif %}
{% endfor %}">
<input type="hidden" name="numericCols" value="
{% for idx, key in keys %}
{% if fields_meta[idx].type in numeric_types %}
{{ idx ~ ' ' }}
{% endif %}
{% endfor %}">
</div>
<div class="chartOption">
<label for="xaxis_panel">
{% trans 'X-Axis label:' %}
</label>
<input style="margin-top:0;" type="text" name="xaxis_label" id="xaxis_label" value="{{ xaxis == -1 ? 'X Values'|trans : keys[xaxis] }}">
<br>
<label for="yaxis_label">
{% trans 'Y-Axis label:' %}
</label>
<input type="text" name="yaxis_label" id="yaxis_label" value="{% trans 'Y Values' %}">
<br>
</div>
<div class="clearfloat"></div>
<div>
<input type="checkbox" id="chkAlternative" name="chkAlternative" value="alternativeFormat">
<label for="chkAlternative">{% trans 'Series names are in a column' %}</label>
<br>
<label for="select_seriesColumn">
{% trans 'Series column:' %}
</label>
<select name="chartSeriesColumn" id="select_seriesColumn" disabled>
{% for idx, key in keys %}
<option value="{{ idx }}"
{% if idx == 1 %}
selected="selected"
{% endif %}>
{{ key }}
</option>
{% set series_column = idx %}
{% endfor %}
</select>
<label for="select_valueColumn">
{% trans 'Value Column:' %}
</label>
<select name="chartValueColumn" id="select_valueColumn" disabled>
{% set selected = false %}
{% for idx, key in keys %}
{% if fields_meta[idx].type in numeric_types %}
{% if not selected and idx != xaxis and idx != series_column %}
<option value="{{ idx }}" selected="selected">{{ key }}</option>
{% set selected = true %}
{% else %}
<option value="{{ idx }}">{{ key }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
</div>
{{ get_start_and_number_of_rows_panel(sql_query) }}
<div class="clearfloat"></div>
<div id="resizer" style="width:600px; height:400px;">
<div style="position: absolute; right: 10px; top: 10px; cursor: pointer; z-index: 1000;">
<a class="disableAjax" id="saveChart" href="#" download="chart.png">
{{ get_image('b_saveimage', 'Save chart as image'|trans) }}
</a>
</div>
<div id="querychart" dir="ltr">
</div>
</div>
</fieldset>
</form>
</div>

View file

@ -0,0 +1,32 @@
<form action="{{ url('/table/delete/rows') }}" method="post">
{{ get_hidden_inputs({
'db': db,
'table': table,
'selected': selected,
'original_sql_query': sql_query,
'fk_checks': '0'
}) }}
<fieldset class="confirmation">
<legend>
{% trans 'Do you really want to execute the following query?' %}
</legend>
<ul>
{% for row in selected %}
<li><code>DELETE FROM {{ backquote(table) }} WHERE {{ row }};</code></li>
{% endfor %}
</ul>
</fieldset>
<fieldset class="tblFooters">
<div id="foreignkeychk" class="floatleft">
<input type="checkbox" name="fk_checks" id="fk_checks" value="1"{{ is_foreign_key_check ? ' checked' }}>
<label for="fk_checks">{% trans 'Enable foreign key checks' %}</label>
</div>
<div class="floatright">
<input id="buttonYes" class="btn btn-secondary" type="submit" name="mult_btn" value="{% trans 'Yes' %}">
<input id="buttonNo" class="btn btn-secondary" type="submit" name="mult_btn" value="{% trans 'No' %}">
</div>
</fieldset>
</form>

View file

@ -0,0 +1,16 @@
{% extends 'export.twig' %}
{% block message %}{{ message|raw }}{% endblock %}
{% block title %}
{% if export_type == 'raw' %}
{% trans %}Exporting a raw query{% notes %}A query that the user has written freely{% endtrans %}
{% else %}
{{ 'Exporting rows from "%s" table'|trans|format(table) }}
{% endif %}
{% endblock %}
{% set filename_hint %}
{% trans '@SERVER@ will become the server name, @DATABASE@ will become the database name and @TABLE@ will become the table name.' %}
{% endset %}

View file

@ -0,0 +1,62 @@
<ul class="nav nav-pills m-2">
<li class="nav-item">
<a class="nav-link" href="{{ url('/table/search', {'db': db, 'table': table, 'pos': 0}) }}">
{{ get_icon('b_search', 'Table search'|trans, false, false, 'TabsMode') }}
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url('/table/zoom-search', {'db': db, 'table': table}) }}">
{{ get_icon('b_select', 'Zoom search'|trans, false, false, 'TabsMode') }}
</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="{{ url('/table/find-replace', {'db': db, 'table': table}) }}">
{{ get_icon('b_find_replace', 'Find and replace'|trans, false, false, 'TabsMode') }}
</a>
</li>
</ul>
<form method="post" action="{{ url('/table/find-replace') }}" name="insertForm" id="find_replace_form" class="ajax lock-page">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="goto" value="{{ goto }}">
<input type="hidden" name="back" value="{{ url('/table/find-replace') }}">
<fieldset id="fieldset_find_replace">
<fieldset id="fieldset_find">
<legend>
{% trans 'Find and replace' %}
</legend>
<label for="findInput">{% trans 'Find:' %}</label>
<input type="text" value="" name="find" id="findInput" required>
<label for="replaceWithInput">{% trans 'Replace with:' %}</label>
<input type="text" value="" name="replaceWith" id="replaceWithInput">
<label for="columnIndexSelect">{% trans 'Column:' %}</label>
<select name="columnIndex" id="columnIndexSelect">
{% for i in 0..column_names|length - 1 %}
{% set type = types[column_names[i]] %}
{% if sql_types.getTypeClass(type) == 'CHAR' %}
<option value="{{ i }}">
{{- column_names[i] -}}
</option>
{% endif %}
{% endfor %}
</select>
<input type="checkbox" name="useRegex" id="useRegex">
<label for="useRegex">
{% trans 'Use regular expression' %}
</label>
</fieldset>
</fieldset>
<fieldset class="tblFooters">
<input class="btn btn-primary" type="submit" name="submit" value="{% trans 'Go' %}">
</fieldset>
</form>
<div id="sqlqueryresultsouter"></div>

View file

@ -0,0 +1,39 @@
<form method="post"
action="{{ url('/table/find-replace') }}"
name="previewForm"
id="previewForm">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="replace" value="true">
<input type="hidden" name="columnIndex" value="{{ column_index }}">
<input type="hidden" name="findString" value="{{ find }}">
<input type="hidden" name="replaceWith" value="{{ replace_with }}">
<input type="hidden" name="useRegex" value="{{ use_regex }}">
<fieldset id="fieldset_find_replace_preview">
<legend>{% trans 'Find and replace - preview' %}</legend>
<table class="pma-table" id="previewTable">
<thead>
<tr>
<th>{% trans 'Count' %}</th>
<th>{% trans 'Original string' %}</th>
<th>{% trans 'Replaced string' %}</th>
</tr>
</thead>
<tbody>
{% if result is iterable %}
{% for row in result %}
<tr>
<td class="right">{{ row[2] }}</td>{# count #}
<td>{{ row[0] }}</td>{# original #}
<td>{{ row[1] }}</td>{# replaced #}
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</fieldset>
<fieldset class="tblFooters">
<input class="btn btn-secondary" type="submit" name="replace" value="{% trans 'Replace' %}">
</fieldset>
</form>

View file

@ -0,0 +1,80 @@
<div id="div_view_options">
<fieldset>
<legend>{% trans 'Display GIS Visualization' %}</legend>
<div id="gis_div" style="position:relative;">
<form method="post" action="{{ url('/table/gis-visualization') }}">
{{ get_hidden_inputs(url_params) }}
<label for="labelColumn">
{% trans "Label column" %}
</label>
<select name="visualizationSettings[labelColumn]" id="labelColumn" class="autosubmit">
<option value="">{% trans "-- None --" %}</option>
{% for value in label_candidates %}
<option value="{{ value }}"{{ value == visualization_settings['labelColumn'] ? ' selected="selected"' }}>
{{ value }}
</option>
{% endfor %}
</select>
<label for="spatialColumn">
{% trans "Spatial column" %}
</label>
<select name="visualizationSettings[spatialColumn]" id="spatialColumn" class="autosubmit">
{% for value in spatial_candidates %}
<option value="{{ value }}"{{ value == visualization_settings['spatialColumn'] ? ' selected="selected"' }}>
{{ value }}
</option>
{% endfor %}
</select>
<input type="hidden" name="displayVisualization" value="redraw">
<tr>
<td class="choice" colspan="2">
<input type="checkbox"
name="visualizationSettings[choice]"
id="choice" value="useBaseLayer"
{% if visualization_settings['choice'] is defined %}
checked="checked"
{% endif %}>
<label for="choice" id="labelChoice">
{% trans "Use OpenStreetMaps as Base Layer" %}
</label>
</td>
</tr>
{{ get_start_and_number_of_rows_panel(sql_query) }}
</form>
<div class="pma_quick_warp" style="width: 50px; position: absolute; right: 0; top: 0; cursor: pointer;">
<div class="drop_list">
<span class="drop_button" style="padding: 0; border: 0;">
{{ get_image('b_saveimage', 'Save'|trans) }}
</span>
<ul>
<li class="warp_link">
<a href="{{ download_url|raw }}&fileFormat=png" class="disableAjax">PNG</a>
</li>
<li class="warp_link">
<a href="{{ download_url|raw }}&fileFormat=pdf" class="disableAjax">PDF</a>
</li>
<li class="warp_link">
<a href="{{ download_url|raw }}&fileFormat=svg" class="disableAjax">SVG</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearfloat"></div>
<div id="placeholder"
style="width:{{ visualization_settings['width'] }}px;height:{{ visualization_settings['height'] }}px;">
{{ visualization|raw }}
</div>
<div id="openlayersmap"></div>
<input type="hidden" id="themeImagePath" value="{{ theme_image_path }}">
<script language="javascript" type="text/javascript">
function drawOpenLayers()
{
{{ draw_ol|raw }}
}
</script>
</fieldset>
</div>

View file

@ -0,0 +1,3 @@
{% extends 'import.twig' %}
{% block title %}{{ 'Importing into the table "%s"'|trans|format(table) }}{% endblock %}

View file

@ -0,0 +1,235 @@
<form action="{{ url('/table/indexes') }}"
method="post"
name="index_frm"
id="index_frm"
class="ajax">
{{ get_hidden_inputs(form_params) }}
<fieldset id="index_edit_fields">
<div class="index_info">
<div>
<div class="label">
<strong>
<label for="input_index_name">
{% trans 'Index name:' %}
{{ show_hint('"PRIMARY" <b>must</b> be the name of and <b>only of</b> a primary key!'|trans) }}
</label>
</strong>
</div>
<input type="text"
name="index[Key_name]"
id="input_index_name"
size="25"
maxlength="64"
value="{{ index.getName() }}"
onfocus="this.select()">
</div>
<div>
<div class="label">
<strong>
<label for="select_index_choice">
{% trans 'Index choice:' %}
{{ show_mysql_docu('ALTER_TABLE') }}
</label>
</strong>
</div>
<select name="index[Index_choice]" id="select_index_choice"{{ create_edit_table ? ' disabled' }}>
{% if index.getChoice() == 'PRIMARY' or not index.hasPrimary() %}
<option value="PRIMARY"{{ index.getChoice() == 'PRIMARY' ? ' selected' }}>PRIMARY</option>
{% endif %}
<option value="INDEX"{{ index.getChoice() == 'INDEX' ? ' selected' }}>INDEX</option>
<option value="UNIQUE"{{ index.getChoice() == 'UNIQUE' ? ' selected' }}>UNIQUE</option>
<option value="SPATIAL"{{ index.getChoice() == 'SPATIAL' ? ' selected' }}>SPATIAL</option>
<option value="FULLTEXT"{{ index.getChoice() == 'FULLTEXT' ? ' selected' }}>FULLTEXT</option>
</select>
</div>
<div id="indexoptions"{% if default_sliders_state != 'disabled' -%}
{{- default_sliders_state == 'closed' ? ' style="display: none; overflow:auto;"' }} class="pma_auto_slider" title="{% trans 'Advanced options' %}"
{%- endif %}>
<div>
<div class="label">
<strong>
<label for="input_key_block_size">
{% trans 'Key block size:' %}
</label>
</strong>
</div>
<input type="text"
name="index[Key_block_size]"
id="input_key_block_size"
size="30"
value="{{ index.getKeyBlockSize() }}">
</div>
<div>
<div class="label">
<strong>
<label for="select_index_type">
{% trans 'Index type:' %}
{{ show_mysql_docu('ALTER_TABLE') }}
</label>
</strong>
</div>
<select name="index[Index_type]" id="select_index_type">
{% for index_type in ['', 'BTREE', 'HASH'] %}
<option value="{{ index_type }}"{{ index.getType() == index_type ? ' selected' }}>{{ index_type }}</option>
{% endfor %}
</select>
</div>
<div>
<div class="label">
<strong>
<label for="input_parser">
{% trans 'Parser:' %}
</label>
</strong>
</div>
<input type="text"
name="index[Parser]"
id="input_parse"
size="30"
value="{{ index.getParser() }}">
</div>
<div>
<div class="label">
<strong>
<label for="input_index_comment">
{% trans 'Comment:' %}
</label>
</strong>
</div>
<input type="text"
name="index[Index_comment]"
id="input_index_comment"
size="30"
maxlength="1024"
value="{{ index.getComment() }}">
</div>
</div>
<!-- end of indexoptions div -->
<div class="clearfloat"></div>
<table class="pma-table" id="index_columns">
<thead>
<tr>
<th></th>
<th>
{% trans 'Column' %}
</th>
<th>
{% trans 'Size' %}
</th>
</tr>
</thead>
{% set spatial_types = [
'geometry',
'point',
'linestring',
'polygon',
'multipoint',
'multilinestring',
'multipolygon',
'geomtrycollection'
] %}
<tbody>
{% for column in index.getColumns() %}
<tr class="noclick">
<td>
<span class="drag_icon" title="{% trans 'Drag to reorder' %}"></span>
</td>
<td>
<select name="index[columns][names][]">
<option value="">
-- {% trans 'Ignore' %} --
</option>
{% for field_name, field_type in fields %}
{% if (index.getChoice() != 'FULLTEXT'
or field_type matches '/(char|text)/i')
and (index.getChoice() != 'SPATIAL'
or field_type in spatial_types) %}
<option value="{{ field_name }}"
{%- if field_name == column.getName() %}
selected="selected"
{%- endif %}>
{{ field_name }} [{{ field_type }}]
</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
<input type="text"
size="5"
onfocus="this.select()"
name="index[columns][sub_parts][]"
value="{{ index.getChoice() != 'SPATIAL' ?
column.getSubPart() }}">
</td>
</tr>
{% endfor %}
{% if add_fields > 0 %}
{% for i in range(1, add_fields) %}
<tr class="noclick">
<td>
<span class="drag_icon" title="{% trans 'Drag to reorder' %}"></span>
</td>
<td>
<select name="index[columns][names][]">
<option value="">-- {% trans 'Ignore' %} --</option>
{% set j = 0 %}
{% for field_name, field_type in fields %}
{% if create_edit_table %}
{% set col_index = field_type[1] %}
{% set field_type = field_type[0] %}
{% endif %}
{% set j = j + 1 %}
<option value="{{ col_index is defined ?
col_index : field_name }}"
{{- j == i ? ' selected="selected"' }}>
{{ field_name }} [{{ field_type }}]
</option>
{% endfor %}
</select>
</td>
<td>
<input type="text"
size="5"
onfocus="this.select()"
name="index[columns][sub_parts][]"
value="">
</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
<div class="add_more">
<div class="slider"></div>
<div class="add_fields hide">
<input class="btn btn-secondary" type="submit"
id="add_fields"
value="{{ 'Add %s column(s) to index'|trans|format(1) }}">
</div>
</div>
</div>
</fieldset>
<fieldset class="tblFooters">
<button class="btn btn-secondary" type="submit" id="preview_index_frm">{% trans 'Preview SQL' %}</button>
</fieldset>
</form>

View file

@ -0,0 +1,30 @@
<form action="{{ url('/table/indexes/rename') }}" method="post" name="index_frm" id="index_frm" class="ajax">
{{ get_hidden_inputs(form_params) }}
<fieldset id="index_edit_fields">
<div class="index_info">
<div>
<div class="label">
<strong>
<label for="input_index_name">
{% trans 'Index name:' %}
{{ show_hint('"PRIMARY" <b>must</b> be the name of and <b>only of</b> a primary key!'|trans) }}
</label>
</strong>
</div>
<input type="text"
name="index[Key_name]"
id="input_index_name"
size="25"
maxlength="64"
value="{{ index.getName() }}"
onfocus="this.select()">
</div>
</div>
</fieldset>
<fieldset class="tblFooters">
<button class="btn btn-secondary" type="submit" id="preview_index_frm">{% trans 'Preview SQL' %}</button>
</fieldset>
</form>

View file

@ -0,0 +1,19 @@
<form id="continueForm" method="post" action="{{ url('/table/replace') }}" name="continueForm">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="goto" value="{{ goto }}">
<input type="hidden" name="err_url" value="{{ err_url }}">
<input type="hidden" name="sql_query" value="{{ sql_query }}">
{% if has_where_clause %}
{% for key_id, where_clause in where_clause_array %}
<input type="hidden" name="where_clause[{{ key_id }}]" value="
{{- where_clause|trim }}">
{% endfor %}
{% endif %}
{% set insert_rows %}
<input type="number" name="insert_rows" id="insert_rows" value="
{{- insert_rows_default }}" min="1">
{% endset %}
{{ 'Continue insertion with %s rows'|trans|format(insert_rows)|raw }}
</form>

View file

@ -0,0 +1,39 @@
<div class="container-fluid">
<h2>
{% trans 'Analyze table' %}
{{ show_mysql_docu('ANALYZE_TABLE') }}
</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }}</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'analyze' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>

View file

@ -0,0 +1,41 @@
<div class="container-fluid">
<h2>
{% trans 'Check table' %}
{{ show_mysql_docu('CHECK_TABLE') }}
</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }}</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'check' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
{{ indexes_problems|raw }}
</div>

View file

@ -0,0 +1,37 @@
<div class="container-fluid">
<h2>
{% trans 'Checksum table' %}
{{ show_mysql_docu('CHECKSUM_TABLE') }}
</h2>
{{ message|raw }}
<table class="pma-table my-3">
<thead>
<tr>
<th>{% trans 'Table' %}</th>
<th>{% trans 'Checksum' %}</th>
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
<td>{{ row.Table }}</td>
<td class="text-right">
{% if row.Checksum is not null %}
{{ row.Checksum }}
{% else %}
<em class="text-muted">NULL</em>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% for warning in warnings %}
{% apply notice %}
{{ warning.Level }}: #{{ warning.Code }} {{ warning.Message }}
{% endapply %}
{% endfor %}
</div>

View file

@ -0,0 +1,39 @@
<div class="container-fluid">
<h2>
{% trans 'Optimize table' %}
{{ show_mysql_docu('OPTIMIZE_TABLE') }}
</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }}</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'optimize' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>

View file

@ -0,0 +1,39 @@
<div class="container-fluid">
<h2>
{% trans 'Repair table' %}
{{ show_mysql_docu('REPAIR_TABLE') }}
</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }}</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'repair' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>

View file

@ -0,0 +1,482 @@
<div class="container-fluid">
{% if not hide_order_table %}
<form method="post" id="alterTableOrderby" action="{{ url('/table/operations') }}">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="submitorderby" value="1">
<div class="card mb-2">
<div class="card-header">{% trans 'Alter table order by' %}</div>
<div class="card-body">
<div class="form-row">
<div class="col-auto">
<label class="sr-only" for="tableOrderFieldSelect">{% trans 'Column' %}</label>
<select id="tableOrderFieldSelect" class="form-control" name="order_field" aria-describedby="tableOrderFieldSelectHelp">
{% for column in columns %}
<option value="{{ column.Field }}">{{ column.Field }}</option>
{% endfor %}
</select>
<small id="tableOrderFieldSelectHelp" class="form-text text-muted">
{% trans %}(singly){% context %}Alter table order by a single field.{% endtrans %}
</small>
</div>
<div class="col-auto">
<div class="form-check">
<input class="form-check-input" id="tableOrderAscRadio" name="order_order" type="radio" value="asc" checked>
<label class="form-check-label" for="tableOrderAscRadio">{% trans 'Ascending' %}</label>
</div>
<div class="form-check">
<input class="form-check-input" id="tableOrderDescRadio" name="order_order" type="radio" value="desc">
<label class="form-check-label" for="tableOrderDescRadio">{% trans 'Descending' %}</label>
</div>
</div>
</div>
</div>
<div class="card-footer text-right">
<input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
</div>
</div>
</form>
{% endif %}
<form method="post" action="{{ url('/table/operations') }}" id="moveTableForm" class="ajax" onsubmit="return Functions.emptyCheckTheField(this, 'new_name')">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="reload" value="1">
<input type="hidden" name="what" value="data">
<div class="card mb-2">
<div class="card-header">{% trans 'Move table to (database.table)' %}</div>
<div class="card-body">
<div class="form-group form-row">
<div class="col-auto">
<div class="input-group">
{% if database_list is not empty %}
<select id="moveTableDatabaseInput" class="form-control" name="target_db" aria-label="{% trans 'Database' %}">
{% for each_db in database_list %}
<option value="{{ each_db.name }}"{{ each_db.is_selected ? ' selected' }}>{{ each_db.name }}</option>
{% endfor %}
</select>
{% else %}
<input id="moveTableDatabaseInput" class="form-control" type="text" maxlength="100" name="target_db" value="{{ db }}" aria-label="{% trans 'Database' %}">
{% endif %}
<div class="input-group-prepend input-group-append">
<span class="input-group-text">.</span>
</div>
<input class="form-control" type="text" required="required" name="new_name" maxlength="64" value="{{ table }}" aria-label="{% trans 'Table' %}">
</div>
</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="sql_auto_increment" value="1" id="checkbox_auto_increment_mv">
<label class="form-check-label" for="checkbox_auto_increment_mv">{% trans 'Add AUTO_INCREMENT value' %}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="adjust_privileges" value="1" id="checkbox_privileges_tables_move"
{%- if has_privileges %} checked{% else %} title="
{%- trans 'You don\'t have sufficient privileges to perform this operation; Please refer to the documentation for more details.' %}" disabled{% endif %}>
<label class="form-check-label" for="checkbox_privileges_tables_move">
{% trans 'Adjust privileges' %}
{{ show_docu('faq', 'faq6-39') }}
</label>
</div>
</div>
<div class="card-footer text-right">
<input class="btn btn-primary" type="submit" name="submit_move" value="{% trans 'Go' %}">
</div>
</div>
</form>
<form method="post" action="{{ url('/table/operations') }}" id="tableOptionsForm" class="ajax">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="reload" value="1">
<input type="hidden" name="submitoptions" value="1">
<input type="hidden" name="prev_comment" value="{{ table_comment }}">
{% if has_auto_increment %}
<input type="hidden" name="hidden_auto_increment" value="{{ auto_increment }}">
{% endif %}
<div class="card mb-2">
<div class="card-header">{% trans 'Table options' %}</div>
<div class="card-body">
<div class="form-group form-inline">
<div class="form-group">
<label for="renameTableInput">{% trans 'Rename table to' %}</label>
<input class="form-control mx-2" id="renameTableInput" type="text" name="new_name" maxlength="64" value="{{ table }}" required>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="adjust_privileges" value="1" id="checkbox_privileges_table_options"
{%- if has_privileges %} checked{% else %} title="
{%- trans 'You don\'t have sufficient privileges to perform this operation; Please refer to the documentation for more details.' %}" disabled{% endif %}>
<label class="form-check-label" for="checkbox_privileges_table_options">
{% trans 'Adjust privileges' %}
{{ show_docu('faq', 'faq6-39') }}
</label>
</div>
</div>
<div class="form-group form-inline">
<label for="tableCommentsInput">{% trans 'Table comments' %}</label>
<input class="form-control ml-2" id="tableCommentsInput" type="text" name="comment" maxlength="2048" value="{{ table_comment }}">
</div>
<div class="form-group form-inline">
<label class="text-nowrap" for="newTableStorageEngineSelect">
{% trans 'Storage engine' %}
{{ show_mysql_docu('Storage_engines') }}
</label>
<select class="form-control ml-2" name="new_tbl_storage_engine" id="newTableStorageEngineSelect">
{% for engine in storage_engines %}
<option value="{{ engine.name }}"{% if engine.comment is not empty %} title="{{ engine.comment }}"{% endif %}
{{- engine.name|lower == storage_engine|lower or (storage_engine is empty and engine.is_default) ? ' selected' }}>
{{- engine.name -}}
</option>
{% endfor %}
</select>
</div>
<div class="form-group form-inline">
<label for="collationSelect">{% trans 'Collation' %}</label>
<select class="form-control mx-2" id="collationSelect" lang="en" dir="ltr" name="tbl_collation">
<option value=""></option>
{% for charset in charsets %}
<optgroup label="{{ charset.getName() }}" title="{{ charset.getDescription() }}">
{% for collation in collations[charset.getName()] %}
<option value="{{ collation.getName() }}" title="{{ collation.getDescription() }}"{{ tbl_collation == collation.getName() ? ' selected' }}>
{{ collation.getName() }}
</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="change_all_collations" value="1" id="checkbox_change_all_collations">
<label class="form-check-label" for="checkbox_change_all_collations">{% trans 'Change all column collations' %}</label>
</div>
</div>
{% if has_pack_keys %}
<div class="form-group form-inline">
<label for="new_pack_keys">PACK_KEYS</label>
<select class="form-control ml-2" name="new_pack_keys" id="new_pack_keys">
<option value="DEFAULT"{{ pack_keys == 'DEFAULT' ? ' selected' }}>DEFAULT</option>
<option value="0"{{ pack_keys == '0' ? ' selected' }}>0</option>
<option value="1"{{ pack_keys == '1' ? ' selected' }}>1</option>
</select>
</div>
{% endif %}
{% if has_checksum_and_delay_key_write %}
<div class="form-group form-check">
<input class="form-check-input" type="checkbox" name="new_checksum" id="new_checksum" value="1"{{ checksum == '1' ? ' checked' }}>
<label class="form-check-label" for="new_checksum">CHECKSUM</label>
</div>
<div class="form-group form-check">
<input class="form-check-input" type="checkbox" name="new_delay_key_write" id="new_delay_key_write" value="1"{{ delay_key_write == '1' ? ' checked' }}>
<label class="form-check-label" for="new_delay_key_write">DELAY_KEY_WRITE</label>
</div>
{% endif %}
{% if has_transactional_and_page_checksum %}
<div class="form-group form-check">
<input class="form-check-input" type="checkbox" name="new_transactional" id="new_transactional" value="1"{{ transactional == '1' ? ' checked' }}>
<label class="form-check-label" for="new_transactional">TRANSACTIONAL</label>
</div>
<div class="form-group form-check">
<input class="form-check-input" type="checkbox" name="new_page_checksum" id="new_page_checksum" value="1"{{ page_checksum == '1' ? ' checked' }}>
<label class="form-check-label" for="new_page_checksum">PAGE_CHECKSUM</label>
</div>
{% endif %}
{% if has_auto_increment %}
<div class="form-group form-inline">
<label for="auto_increment_opt">AUTO_INCREMENT</label>
<input class="form-control ml-2" id="auto_increment_opt" type="number" name="new_auto_increment" value="{{ auto_increment }}">
</div>
{% endif %}
{% if row_formats is not empty %}
<div class="form-group form-inline">
<label for="new_row_format">ROW_FORMAT</label>
<select class="form-control ml-2" id="new_row_format" name="new_row_format">
{% for row_format in row_formats %}
<option value="{{ row_format }}"{{ row_format == row_format_current|upper ? ' selected' }}>{{ row_format }}</option>
{% endfor %}
</select>
</div>
{% endif %}
</div>
<div class="card-footer text-right">
<input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
</div>
</div>
</form>
<form method="post" action="{{ url('/table/operations') }}" name="copyTable" id="copyTable" class="ajax" onsubmit="return Functions.emptyCheckTheField(this, 'new_name')">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="reload" value="1">
<div class="card mb-2">
<div class="card-header">{% trans 'Copy table to (database.table)' %}</div>
<div class="card-body">
<div class="form-group form-row">
<div class="col-auto">
<div class="input-group">
{% if database_list is not empty %}
<select class="form-control" name="target_db" aria-label="{% trans 'Database' %}">
{% for each_db in database_list %}
<option value="{{ each_db.name }}"{{ each_db.is_selected ? ' selected' }}>{{ each_db.name }}</option>
{% endfor %}
</select>
{% else %}
<input class="form-control" type="text" maxlength="100" name="target_db" value="{{ db }}" aria-label="{% trans 'Database' %}">
{% endif %}
<div class="input-group-prepend input-group-append">
<span class="input-group-text">.</span>
</div>
<input class="form-control" type="text" name="new_name" maxlength="64" value="{{ table }}" aria-label="{% trans 'Table' %}" required>
</div>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="radio" name="what" id="whatRadio1" value="structure">
<label class="form-check-label" for="whatRadio1">
{% trans 'Structure only' %}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="what" id="whatRadio2" value="data" checked>
<label class="form-check-label" for="whatRadio2">
{% trans 'Structure and data' %}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="what" id="whatRadio3" value="dataonly">
<label class="form-check-label" for="whatRadio3">
{% trans 'Data only' %}
</label>
</div>
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="drop_if_exists" value="true" id="checkbox_drop">
<label class="form-check-label" for="checkbox_drop">{{ 'Add %s'|trans|format('DROP TABLE') }}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="sql_auto_increment" value="1" id="checkbox_auto_increment_cp">
<label class="form-check-label" for="checkbox_auto_increment_cp">{% trans 'Add AUTO_INCREMENT value' %}</label>
</div>
{% if has_foreign_keys %}
<div class="form-check">
<input class="form-check-input" type="checkbox" name="add_constraints" value="1" id="checkbox_constraints" checked>
<label class="form-check-label" for="checkbox_constraints">{% trans 'Add constraints' %}</label>
</div>
{% endif %}
<div class="form-check">
<input class="form-check-input" type="checkbox" name="adjust_privileges" value="1" id="checkbox_adjust_privileges"
{%- if has_privileges %} checked{% else %} title="
{%- trans 'You don\'t have sufficient privileges to perform this operation; Please refer to the documentation for more details.' %}" disabled{% endif %}>
<label class="form-check-label" for="checkbox_adjust_privileges">
{% trans 'Adjust privileges' %}
{{ show_docu('faq', 'faq6-39') }}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="switch_to_new" value="true" id="checkbox_switch"{{ switch_to_new ? ' checked' }}>
<label class="form-check-label" for="checkbox_switch">{% trans 'Switch to copied table' %}</label>
</div>
</div>
</div>
<div class="card-footer text-right">
<input class="btn btn-primary" type="submit" name="submit_copy" value="{% trans 'Go' %}">
</div>
</div>
</form>
<div class="card mb-2">
<div class="card-header">{% trans 'Table maintenance' %}</div>
<ul class="list-group list-group-flush" id="tbl_maintenance">
{% if storage_engine in ['MYISAM', 'ARIA', 'INNODB', 'BERKELEYDB', 'TOKUDB'] %}
<li class="list-group-item">
<a href="{{ url('/table/maintenance/analyze') }}" data-post="{{ get_common({'db': db, 'table': table, 'selected_tbl': [table]}) }}">
{% trans 'Analyze table' %}
</a>
{{ show_mysql_docu('ANALYZE_TABLE') }}
</li>
{% endif %}
{% if storage_engine in ['MYISAM', 'ARIA', 'INNODB', 'TOKUDB'] %}
<li class="list-group-item">
<a href="{{ url('/table/maintenance/check') }}" data-post="{{ get_common({'db': db, 'table': table, 'selected_tbl': [table]}) }}">
{% trans 'Check table' %}
</a>
{{ show_mysql_docu('CHECK_TABLE') }}
</li>
{% endif %}
<li class="list-group-item">
<a href="{{ url('/table/maintenance/checksum') }}" data-post="{{ get_common({'db': db, 'table': table, 'selected_tbl': [table]}) }}">
{% trans 'Checksum table' %}
</a>
{{ show_mysql_docu('CHECKSUM_TABLE') }}
</li>
{% if storage_engine == 'INNODB' %}
<li class="list-group-item">
<a class="maintain_action ajax" href="{{ url('/sql') }}" data-post="{{ get_common(url_params|merge({'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' ENGINE = InnoDB;'})) }}">
{% trans 'Defragment table' %}
</a>
{{ show_mysql_docu('InnoDB_File_Defragmenting') }}
</li>
{% endif %}
<li class="list-group-item">
<a class="maintain_action ajax" href="{{ url('/sql') }}" data-post="{{ get_common(url_params|merge({
'sql_query': 'FLUSH TABLE ' ~ backquote(table),
'message_to_show': 'Table %s has been flushed.'|trans|format(table|e),
'reload': true
})) }}">
{% trans 'Flush the table (FLUSH)' %}
</a>
{{ show_mysql_docu('FLUSH') }}
</li>
{% if storage_engine in ['MYISAM', 'ARIA', 'INNODB', 'BERKELEYDB', 'TOKUDB'] %}
<li class="list-group-item">
<a href="{{ url('/table/maintenance/optimize') }}" data-post="{{ get_common({'db': db, 'table': table, 'selected_tbl': [table]}) }}">
{% trans 'Optimize table' %}
</a>
{{ show_mysql_docu('OPTIMIZE_TABLE') }}
</li>
{% endif %}
{% if storage_engine in ['MYISAM', 'ARIA'] %}
<li class="list-group-item">
<a href="{{ url('/table/maintenance/repair') }}" data-post="{{ get_common({'db': db, 'table': table, 'selected_tbl': [table]}) }}">
{% trans 'Repair table' %}
</a>
{{ show_mysql_docu('REPAIR_TABLE') }}
</li>
{% endif %}
</ul>
</div>
{% if not is_system_schema %}
<div class="card mb-2">
<div class="card-header">{% trans 'Delete data or table' %}</div>
<ul class="list-group list-group-flush">
{% if not is_view %}
<li class="list-group-item">
{{ link_or_button(
url('/sql', url_params|merge({
'sql_query': 'TRUNCATE TABLE ' ~ backquote(table),
'goto': url('/table/structure'),
'reload': true,
'message_to_show': 'Table %s has been emptied.'|trans|format(table)|e
})),
'Empty the table (TRUNCATE)'|trans,
{
'id': 'truncate_tbl_anchor',
'class': 'text-danger ajax'
}
) }}
{{ show_mysql_docu('TRUNCATE_TABLE') }}
</li>
{% endif %}
<li class="list-group-item">
{{ link_or_button(
url('/sql', url_params|merge({
'sql_query': 'DROP TABLE ' ~ backquote(table),
'goto': url('/database/operations'),
'reload': true,
'purge': true,
'message_to_show': is_view ? 'View %s has been dropped.'|trans|format(table)|e : 'Table %s has been dropped.'|trans|format(table)|e,
'table': table
})),
'Delete the table (DROP)'|trans,
{
'id': 'drop_tbl_anchor',
'class': 'text-danger ajax'
}
) }}
{{ show_mysql_docu('DROP_TABLE') }}
</li>
</ul>
</div>
{% endif %}
{% if partitions is not empty %}
<form id="partitionsForm" class="ajax" method="post" action="{{ url('/table/operations') }}">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="submit_partition" value="1">
<div class="card mb-2">
<div class="card-header">
{% trans 'Partition maintenance' %}
{{ show_mysql_docu('partitioning_maintenance') }}
</div>
<div class="card-body">
<div class="form-group">
<label for="partition_name">{% trans 'Partition' %}</label>
<select class="form-control" id="partition_name" name="partition_name[]" multiple required>
{% for partition in partitions %}
<option value="{{ partition }}"{{ loop.first ? ' selected' }}>{{ partition }}</option>
{% endfor %}
</select>
</div>
<div class="form-group form-check-inline">
{% for value, description in partitions_choices %}
<div class="form-check">
<input class="form-check-input" type="radio" name="partition_operation" id="partitionOperationRadio{{ value|capitalize }}" value="{{ value }}"{{ value == 'ANALYZE' ? ' checked' }}>
<label class="form-check-label" for="partitionOperationRadio{{ value|capitalize }}">{{ description }}</label>
</div>
{% endfor %}
</div>
<div class="form-text">
<a href="{{ url('/sql', url_params|merge({
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' REMOVE PARTITIONING;'
})) }}">{% trans 'Remove partitioning' %}</a>
</div>
</div>
<div class="card-footer text-right">
<input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
</div>
</div>
</form>
{% endif %}
{% if foreigners is not empty %}
<div class="card mb-2">
<div class="card-header">{% trans 'Check referential integrity' %}</div>
<ul class="list-group list-group-flush">
{% for foreign in foreigners %}
<li class="list-group-item">
<a class="text-nowrap" href="{{ url('/sql', foreign.params) }}">
{{ foreign.master }} -> {{ foreign.db }}.{{ foreign.table }}.{{ foreign.field }}
</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>

View file

@ -0,0 +1,44 @@
<div class="container-fluid">
<form method="post" action="{{ url('/view/operations') }}">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="reload" value="1">
<input type="hidden" name="submitoptions" value="1">
<div class="card mb-2">
<div class="card-header">{% trans 'Operations' %}</div>
<div class="card-body">
<div class="form-inline">
<label for="newNameInput">{% trans 'Rename view to' %}</label>
<input id="newNameInput" class="form-control ml-2" type="text" name="new_name" onfocus="this.select()" value="{{ table }}" required>
</div>
</div>
<div class="card-footer text-right">
<input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
</div>
</div>
</form>
<div class="card mb-2">
<div class="card-header">{% trans 'Delete data or table' %}</div>
<div class="card-body">
<div class="card-text">
{{ link_or_button(
url('/sql', url_params|merge({
'sql_query': 'DROP VIEW ' ~ backquote(table),
'goto': url('/table/structure'),
'reload': true,
'purge': true,
'message_to_show': 'View %s has been dropped.'|trans|format(table)|e,
'table': table
})),
'Delete the view (DROP)'|trans,
{
'id': 'drop_view_anchor',
'class': 'text-danger ajax'
}
) }}
{{ show_mysql_docu('DROP VIEW') }}
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,19 @@
{% if cfg_relation['relwork'] or is_foreign_key_supported %}
<ul class="nav nav-pills m-2 d-print-none">
<li class="nav-item">
<a href="{{ url('/table/structure', {'db': db, 'table': table}) }}" id="table_structure_id" class="nav-link{{ route == '/table/structure' ? ' active' }}">
{{ get_icon('b_props', 'Table structure'|trans, true) }}
</a>
</li>
<li class="nav-item">
<a href="{{ url('/table/relation', {'db': db, 'table': table}) }}" id="table_relation_id" class="nav-link{{ route == '/table/relation' ? ' active' }}">
{{ get_icon('b_relations', 'Relation view'|trans, true) }}
</a>
</li>
</ul>
{% endif %}
<div id="structure_content">
{% block content %}{% endblock %}
</div>

View file

@ -0,0 +1,36 @@
<div class="container-fluid">
<h2>{% trans 'Analyze partition' %}</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }} ({{ partition_name }})</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'analyze' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>

View file

@ -0,0 +1,36 @@
<div class="container-fluid">
<h2>{% trans 'Check partition' %}</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }} ({{ partition_name }})</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'check' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>

View file

@ -0,0 +1,5 @@
<div class="container-fluid">
<h2>{% trans 'Drop partition' %}</h2>
{{ message|raw }}
</div>

View file

@ -0,0 +1,36 @@
<div class="container-fluid">
<h2>{% trans 'Optimize partition' %}</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }} ({{ partition_name }})</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'optimize' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>

View file

@ -0,0 +1,5 @@
<div class="container-fluid">
<h2>{% trans 'Rebuild partition' %}</h2>
{{ message|raw }}
</div>

View file

@ -0,0 +1,36 @@
<div class="container-fluid">
<h2>{% trans 'Repair partition' %}</h2>
{{ message|raw }}
{% for name, table in rows %}
<div class="card mb-3">
<div class="card-header">{{ name }} ({{ partition_name }})</div>
<ul class="list-group list-group-flush">
{% for row in table %}
<li class="list-group-item">
{% if row.Op|lower != 'repair' %}
<span class="badge badge-secondary">{{ row.Op|title }}</span>
{% endif %}
{% set badge_variation %}
{%- if row.Msg_type|lower == 'error' -%}
badge-danger
{%- elseif row.Msg_type|lower == 'warning' -%}
badge-warning
{%- elseif row.Msg_type|lower == 'info' or row.Msg_type|lower == 'note' -%}
badge-info
{%- else -%}
badge-secondary
{%- endif -%}
{% endset %}
<span class="badge {{ badge_variation }}">{{ row.Msg_type|title }}</span>
{{ row.Msg_text }}
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>

View file

@ -0,0 +1,5 @@
<div class="container-fluid">
<h2>{% trans 'Truncate partition' %}</h2>
{{ message|raw }}
</div>

View file

@ -0,0 +1,145 @@
{% if is_superuser %}
<form id="usersForm" action="{{ url('/server/privileges') }}">
{{ get_hidden_inputs(db, table) }}
<fieldset>
<legend>
{{ get_icon('b_usrcheck') }}
{{ 'Users having access to "%s"'|trans|format('<a href="' ~ table_url ~ get_common({
'db': db,
'table': table
}, '&') ~ '">' ~ db|escape('html') ~ '.' ~ table|escape('html') ~ '</a>')|raw }}
</legend>
<div class="table-responsive-md jsresponsive">
<table class="table table-light table-striped table-hover w-auto">
<thead class="thead-light">
<tr>
<th></th>
<th>{% trans 'User name' %}</th>
<th>{% trans 'Host name' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Privileges' %}</th>
<th>{% trans 'Grant' %}</th>
<th colspan="2">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
{% for privilege in privileges %}
{% set privileges_amount = privilege.privileges|length %}
<tr>
<td{% if privileges_amount > 1 %} class="align-middle" rowspan="{{ privileges_amount }}"{% endif %}>
<input type="checkbox" class="checkall" name="selected_usr[]" id="checkbox_sel_users_{{ loop.index0 }}" value="
{{- privilege.user ~ '&amp;#27;' ~ privilege.host }}">
</td>
<td{% if privileges_amount > 1 %} class="align-middle" rowspan="{{ privileges_amount }}"{% endif %}>
{% if privilege.user is empty %}
<span class="text-danger">{% trans 'Any' %}</span>
{% else %}
{{ privilege.user }}
{% endif %}
</td>
<td{% if privileges_amount > 1 %} class="align-middle" rowspan="{{ privileges_amount }}"{% endif %}>
{{ privilege.host }}
</td>
{% for priv in privilege.privileges %}
<td>
{% if priv.type == 'g' %}
{% trans 'global' %}
{% elseif priv.type == 'd' %}
{% if priv.database == db|replace({'_': '\\_', '%': '\\%'}) %}
{% trans 'database-specific' %}
{% else %}
{% trans 'wildcard' %}: <code>{{ priv.database }}</code>
{% endif %}
{% elseif priv.type == 't' %}
{% trans 'table-specific' %}
{% elseif priv.type == 'r' %}
{% trans 'routine' %}
{% endif %}
</td>
<td>
<code>
{% if priv.type == 'r' %}
{{ priv.routine }}
({{ priv.privileges|join(', ')|upper }})
{% else %}
{{ priv.privileges|join(', ')|raw }}
{% endif %}
</code>
</td>
<td>
{{ priv.has_grant ? 'Yes'|trans : 'No'|trans }}
</td>
<td>
{% if is_grantuser %}
<a class="edit_user_anchor" href="{{ url('/server/privileges', {
'username': privilege.user,
'hostname': privilege.host,
'dbname': priv.database != '*' ? priv.database,
'tablename': priv.table is defined and priv.table != '*' ? priv.table,
'routinename': priv.routine ?? ''
}) }}">
{{ get_icon('b_usredit', 'Edit privileges'|trans) }}
</a>
{% endif %}
</td>
<td class="text-center">
<a class="export_user_anchor ajax" href="{{ url('/server/privileges', {
'username': privilege.user,
'hostname': privilege.host,
'export': true,
'initial': ''
}) }}">
{{ get_icon('b_tblexport', 'Export'|trans) }}
</a>
</td>
</tr>
{% if privileges_amount > 1 %}
<tr class="noclick">
{% endif %}
{% endfor %}
{% else %}
<tr>
<td colspan="7">
{% trans 'No user found.' %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="floatleft">
<img class="selectallarrow" src="{{ theme_image_path }}arrow_{{ text_dir }}.png" alt="
{%- trans 'With selected:' %}" width="38" height="22">
<input type="checkbox" id="usersForm_checkall" class="checkall_box" title="{% trans 'Check all' %}">
<label for="usersForm_checkall">{% trans 'Check all' %}</label>
<em class="with-selected">{% trans 'With selected:' %}</em>
<button class="btn btn-link mult_submit" type="submit" name="submit_mult" value="export" title="{% trans 'Export' %}">
{{ get_icon('b_tblexport', 'Export'|trans) }}
</button>
</div>
</fieldset>
</form>
{% else %}
{{ 'Not enough privilege to view users.'|trans|error }}
{% endif %}
{% if is_createuser %}
<div class="row">
<div class="col-12">
<fieldset id="fieldset_add_user">
<legend>{% trans %}New{% context %}Create new user{% endtrans %}</legend>
<a id="add_user_anchor" href="{{ url('/server/privileges', {
'adduser': true,
'dbname': db,
'tablename': table
}) }}" rel="{{ get_common({'checkprivsdb': db, 'checkprivstable': table}) }}">
{{ get_icon('b_usradd', 'Add user account'|trans) }}
</a>
</fieldset>
</div>
</div>
{% endif %}

View file

@ -0,0 +1,226 @@
{% extends 'table/page_with_secondary_tabs.twig' %}
{% block content %}
<form method="post" action="{{ url('/table/relation') }}">
{{ get_hidden_inputs(db, table) }}
{# InnoDB #}
{% if is_foreign_key_supported(tbl_storage_engine) %}
<fieldset>
<legend>{% trans 'Foreign key constraints' %}</legend>
<div class="table-responsive-md jsresponsive">
<table class="relationalTable table table-light table-striped w-auto">
<thead class="thead-light">
<tr>
<th>{% trans 'Actions' %}</th>
<th>{% trans 'Constraint properties' %}</th>
{% if tbl_storage_engine|upper == 'INNODB' %}
<th>
{% trans 'Column' %}
{{ show_hint('Creating a foreign key over a non-indexed column would automatically create an index on it. Alternatively, you can define an index below, before creating the foreign key.'|trans) }}
</th>
{% else %}
<th>
{% trans 'Column' %}
{{ show_hint('Only columns with index will be displayed. You can define an index below.'|trans) }}
</th>
{% endif %}
<th colspan="3">
{% trans 'Foreign key constraint' %}
({{ tbl_storage_engine }})
</th>
</tr>
<tr>
<th></th>
<th></th>
<th></th>
<th>{% trans 'Database' %}</th>
<th>{% trans 'Table' %}</th>
<th>{% trans 'Column' %}</th>
</tr></thead>
{% set i = 0 %}
{% if existrel_foreign is not empty %}
{% for key, one_key in existrel_foreign %}
{# Foreign database dropdown #}
{% set foreign_db = one_key['ref_db_name'] is defined
and one_key['ref_db_name'] is not null
? one_key['ref_db_name'] : db %}
{% set foreign_table = false %}
{% if foreign_db %}
{% set foreign_table = one_key['ref_table_name'] is defined
and one_key['ref_table_name'] is not null
? one_key['ref_table_name'] : false %}
{% endif %}
{% set unique_columns = [] %}
{% if foreign_db and foreign_table %}
{% set table_obj = table_get(foreign_table, foreign_db) %}
{% set unique_columns = table_obj.getUniqueColumns(false, false) %}
{% endif %}
{% include 'table/relation/foreign_key_row.twig' with {
'i': i,
'one_key': one_key,
'column_array': column_array,
'options_array': options_array,
'tbl_storage_engine': tbl_storage_engine,
'db': db,
'table': table,
'url_params': url_params,
'databases': databases,
'foreign_db': foreign_db,
'foreign_table': foreign_table,
'unique_columns': unique_columns
} only %}
{% set i = i + 1 %}
{% endfor %}
{% endif %}
{% include 'table/relation/foreign_key_row.twig' with {
'i': i,
'one_key': [],
'column_array': column_array,
'options_array': options_array,
'tbl_storage_engine': tbl_storage_engine,
'db': db,
'table': table,
'url_params': url_params,
'databases': databases,
'foreign_db': foreign_db,
'foreign_table': foreign_table,
'unique_columns': unique_columns
} only %}
{% set i = i + 1 %}
<tr>
<th colspan="6">
<a class="formelement clearfloat add_foreign_key" href="">
{% trans '+ Add constraint' %}
</a>
</th>
</tr>
</table>
</div>
</fieldset>
{% endif %}
{% if cfg_relation['relwork'] %}
{% if is_foreign_key_supported(tbl_storage_engine) %}
<div id="ir_div"{% if default_sliders_state != 'disabled' -%}
{{- default_sliders_state == 'closed' ? ' style="display: none; overflow:auto;"' }} class="pma_auto_slider" title="{% trans 'Internal relationships' %}"
{%- endif %}>
{% endif %}
<fieldset>
<legend>
{% trans 'Internal relationships' %}
{{ show_docu('config', 'cfg_Servers_relation') }}
</legend>
<table class="relationalTable table table-light table-striped table-hover table-sm w-auto">
<thead class="thead-light">
<tr>
<th>{% trans 'Column' %}</th>
<th>
{% trans 'Internal relation' %}
{% if is_foreign_key_supported(tbl_storage_engine) %}
{{ show_hint('An internal relation is not necessary when a corresponding FOREIGN KEY relation exists.'|trans) }}
{% endif %}
</th>
</tr>
</thead>
<tbody>
{% set saved_row_cnt = save_row|length - 1 %}
{% for i in 0..saved_row_cnt %}
{% set myfield = save_row[i]['Field'] %}
{# Use an md5 as array index to avoid having special characters
in the name attribute (see bug #1746964 ) #}
{% set myfield_md5 = column_hash_array[myfield] %}
{% set foreign_table = false %}
{% set foreign_column = false %}
{# Database dropdown #}
{% if existrel[myfield] is defined %}
{% set foreign_db = existrel[myfield]['foreign_db'] %}
{% else %}
{% set foreign_db = db %}
{% endif %}
{# Table dropdown #}
{% set tables = [] %}
{% if foreign_db %}
{% if existrel[myfield] is defined %}
{% set foreign_table = existrel[myfield]['foreign_table'] %}
{% endif %}
{% set tables = dbi.getTables(foreign_db) %}
{% endif %}
{# Column dropdown #}
{% set unique_columns = [] %}
{% if foreign_db and foreign_table %}
{% if existrel[myfield] is defined %}
{% set foreign_column = existrel[myfield]['foreign_field'] %}
{% endif %}
{% set table_obj = table_get(foreign_table, foreign_db) %}
{% set unique_columns = table_obj.getUniqueColumns(false, false) %}
{% endif %}
<tr>
<td class="vmiddle">
<strong>{{ myfield }}</strong>
<input type="hidden" name="fields_name[{{ myfield_md5 }}]"
value="{{ myfield }}">
</td>
<td>
{% include 'table/relation/relational_dropdown.twig' with {
'name': 'destination_db[' ~ myfield_md5 ~ ']',
'title': 'Database'|trans,
'values': databases,
'foreign': foreign_db
} only %}
{% include 'table/relation/relational_dropdown.twig' with {
'name': 'destination_table[' ~ myfield_md5 ~ ']',
'title': 'Table'|trans,
'values': tables,
'foreign': foreign_table
} only %}
{% include 'table/relation/relational_dropdown.twig' with {
'name': 'destination_column[' ~ myfield_md5 ~ ']',
'title': 'Column'|trans,
'values': unique_columns,
'foreign': foreign_column
} only %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</fieldset>
{% if is_foreign_key_supported(tbl_storage_engine) %}
</div>
{% endif %}
{% endif %}
{% if cfg_relation['displaywork'] %}
{% set disp = get_display_field(db, table) %}
<fieldset>
<label>{% trans 'Choose column to display:' %}</label>
<select name="display_field">
<option value="">---</option>
{% for row in save_row %}
<option value="{{ row['Field'] }}"
{%- if disp is defined and row['Field'] == disp %}
selected="selected"
{%- endif %}>
{{ row['Field'] }}
</option>
{% endfor %}
</select>
</fieldset>
{% endif %}
<fieldset class="tblFooters">
<input class="btn btn-secondary preview_sql" type="button" value="{% trans 'Preview SQL' %}">
<input class="btn btn-primary" type="submit" value="{% trans 'Save' %}">
</fieldset>
</form>
{% endblock %}

View file

@ -0,0 +1,9 @@
{{ dropdown_question is not empty ? dropdown_question -}}
<select name="{{ select_name }}">
{% for one_value, one_label in choices %}
<option value="{{ one_value }}"
{%- if selected_value == one_value %} selected="selected"{% endif %}>
{{ one_label }}
</option>
{% endfor %}
</select>

View file

@ -0,0 +1,139 @@
<tr>
{# Drop key anchor #}
<td>
{% set js_msg = '' %}
{% set this_params = null %}
{% if one_key['constraint'] is defined %}
{% set drop_fk_query = 'ALTER TABLE ' ~ backquote(db) ~ '.' ~ backquote(table)
~ ' DROP FOREIGN KEY '
~ backquote(one_key['constraint']) ~ ';'
%}
{% set this_params = url_params %}
{% set this_params = {
'goto': url('/table/relation'),
'back': url('/table/relation'),
'sql_query': drop_fk_query,
'message_to_show': 'Foreign key constraint %s has been dropped'|trans|format(
one_key['constraint']
)
} %}
{% set js_msg = 'ALTER TABLE ' ~ db ~ '.' ~ table ~ ' DROP FOREIGN KEY ' ~ one_key['constraint'] ~ ';'|js_format %}
{% endif %}
{% if one_key['constraint'] is defined %}
<input type="hidden" class="drop_foreign_key_msg" value="
{{- js_msg }}">
{% set drop_url = url('/sql', this_params) %}
{% set drop_str = get_icon('b_drop', 'Drop'|trans) %}
{{ link_or_button(drop_url, drop_str, {'class': 'drop_foreign_key_anchor ajax'}) }}
{% endif %}
</td>
<td>
<span class="formelement clearfloat">
<input type="text" name="constraint_name[{{ i }}]" value="
{{- one_key['constraint'] is defined ? one_key['constraint'] -}}
" placeholder="{% trans 'Constraint name' %}" maxlength="64">
</span>
<div class="floatleft">
{# For ON DELETE and ON UPDATE, the default action
is RESTRICT as per MySQL doc; however, a SHOW CREATE TABLE
won't display the clause if it's set as RESTRICT. #}
{% set on_delete = one_key['on_delete'] is defined
? one_key['on_delete'] : 'RESTRICT' %}
{% set on_update = one_key['on_update'] is defined
? one_key['on_update'] : 'RESTRICT' %}
<span class="formelement">
{% include 'table/relation/dropdown_generate.twig' with {
'dropdown_question': 'ON DELETE',
'select_name': 'on_delete[' ~ i ~ ']',
'choices': options_array,
'selected_value': on_delete
} only %}
</span>
<span class="formelement">
{% include 'table/relation/dropdown_generate.twig' with {
'dropdown_question': 'ON UPDATE',
'select_name': 'on_update[' ~ i ~ ']',
'choices': options_array,
'selected_value': on_update
} only %}
</span>
</div>
</td>
<td>
{% if one_key['index_list'] is defined %}
{% for key, column in one_key['index_list'] %}
<span class="formelement clearfloat">
{% include 'table/relation/dropdown_generate.twig' with {
'dropdown_question': '',
'select_name': 'foreign_key_fields_name[' ~ i ~ '][]',
'choices': column_array,
'selected_value': column
} only %}
</span>
{% endfor %}
{% else %}
<span class="formelement clearfloat">
{% include 'table/relation/dropdown_generate.twig' with {
'dropdown_question': '',
'select_name': 'foreign_key_fields_name[' ~ i ~ '][]',
'choices': column_array,
'selected_value': ''
} only %}
</span>
{% endif %}
<a class="formelement clearfloat add_foreign_key_field" data-index="
{{- i }}" href="">
{% trans '+ Add column' %}
</a>
</td>
{% set tables = [] %}
{% if foreign_db %}
{% set tables = get_tables(foreign_db, tbl_storage_engine) %}
{% else %}
{% set tables = get_tables(db, tbl_storage_engine) %}
{% endif %}
<td>
<span class="formelement clearfloat">
{% include 'table/relation/relational_dropdown.twig' with {
'name': 'destination_foreign_db[' ~ i ~ ']',
'title': 'Database'|trans,
'values': databases,
'foreign': foreign_db,
'db': db
} only %}
</span>
</td>
<td>
<span class="formelement clearfloat">
{% include 'table/relation/relational_dropdown.twig' with {
'name': 'destination_foreign_table[' ~ i ~ ']',
'title': 'Table'|trans,
'values': tables,
'foreign': foreign_table
} only %}
</span>
</td>
<td>
{% if foreign_db and foreign_table %}
{% for foreign_column in one_key['ref_index_list'] %}
<span class="formelement clearfloat">
{% include 'table/relation/relational_dropdown.twig' with {
'name': 'destination_foreign_column[' ~ i ~ '][]',
'title': 'Column'|trans,
'values': unique_columns,
'foreign': foreign_column
} only %}
</span>
{% endfor %}
{% else %}
<span class="formelement clearfloat">
{% include 'table/relation/relational_dropdown.twig' with {
'name': 'destination_foreign_column[' ~ i ~ '][]',
'title': 'Column'|trans,
'values': [],
'foreign': ''
} only %}
</span>
{% endif %}
</td>
</tr>

View file

@ -0,0 +1,19 @@
<select name="{{ name }}" title="{{ title }}">
<option value=""></option>
{% set seen_key = false %}
{% for value in values %}
<option value="{{ value }}"
{%- if (foreign is not same as(false) and value == foreign) or
(not foreign and db is defined and db is same as (value)) %}
selected="selected"
{%- set seen_key = true -%}
{%- endif %}>
{{ value }}
</option>
{% endfor %}
{% if foreign is not same as(false) and foreign != "" and not seen_key %}
<option value="{{ foreign }}" selected="selected">
{{ foreign }}
</option>
{% endif %}
</select>

View file

@ -0,0 +1,3 @@
<select class="column-operator" id="ColumnOperator{{ search_index }}" name="criteriaColumnOperators[{{ search_index }}]">
{{ type_operators|raw }}
</select>

View file

@ -0,0 +1,164 @@
<ul class="nav nav-pills m-2">
<li class="nav-item">
<a class="nav-link active" href="{{ url('/table/search', {'db': db, 'table': table, 'pos': 0}) }}">
{{ get_icon('b_search', 'Table search'|trans, false, false, 'TabsMode') }}
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url('/table/zoom-search', {'db': db, 'table': table}) }}">
{{ get_icon('b_select', 'Zoom search'|trans, false, false, 'TabsMode') }}
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url('/table/find-replace', {'db': db, 'table': table}) }}">
{{ get_icon('b_find_replace', 'Find and replace'|trans, false, false, 'TabsMode') }}
</a>
</li>
</ul>
<form method="post" action="{{ url('/table/search') }}" name="insertForm" id="tbl_search_form" class="ajax lock-page">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="goto" value="{{ goto }}">
<input type="hidden" name="back" value="{{ url('/table/search') }}">
<fieldset id="fieldset_table_search">
<fieldset id="fieldset_table_qbe">
<legend>
{% trans 'Do a "query by example" (wildcard: "%")' %}
</legend>
<div class="table-responsive-md jsresponsive">
<table class="table table-light table-striped table-hover table-sm w-auto">
<thead class="thead-light">
<tr>
{% if geom_column_flag %}
<th>{% trans 'Function' %}</th>
{% endif %}
<th>{% trans 'Column' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Collation' %}</th>
<th>{% trans 'Operator' %}</th>
<th>{% trans 'Value' %}</th>
</tr>
</thead>
<tbody>
{% for column_index in 0..column_names|length - 1 %}
<tr class="noclick">
{# If 'Function' column is present trying to change comment #}
{% if geom_column_flag %}
{# Displays 'Function' column if it is present #}
<td>
{% set geom_types = get_gis_datatypes() %}
{% if column_types[column_index] in geom_types %}
<select class="geom_func" name="geom_func[{{ column_index }}]">
{# get the relevant list of GIS functions #}
{% set funcs = get_gis_functions(column_types[column_index], true, true) %}
{% for func_name, func in funcs %}
{% set name = func['display'] is defined ? func['display'] : func_name %}
<option value="{{ name }}">
{{ name }}
</option>
{% endfor %}
</select>
{% endif %}
</td>
{% endif %}
{# Displays column's name, type, collation and value #}
<th>
{#- Keep this without extra spaces because it is used for a request to build the BETWEEN modal -#}
{{- column_names[column_index] -}}
</th>
{% set properties = self.getColumnProperties(column_index, column_index) %}
<td dir="ltr">
{{ properties['type'] }}
</td>
<td>
{{ properties['collation'] }}
</td>
<td>
{{ properties['func']|raw }}
</td>
{# here, the data-type attribute is needed for a date/time picker #}
<td data-type="{{ properties['type'] }}">
{{ properties['value']|raw }}
{# Displays hidden fields #}
<input type="hidden" name="criteriaColumnNames[{{ column_index }}]" value="{{ column_names[column_index] }}">
<input type="hidden" name="criteriaColumnTypes[{{ column_index }}]" value="{{ column_types[column_index] }}">
<input type="hidden" name="criteriaColumnCollations[{{ column_index }}]" value="{{ column_collations[column_index] }}">
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div id="gis_editor"></div>
<div id="popup_background"></div>
</fieldset>
<div id="searchoptions"{% if default_sliders_state != 'disabled' -%}
{{- default_sliders_state == 'closed' ? ' style="display: none; overflow:auto;"' }} class="pma_auto_slider" title="{% trans 'Options' %}"
{%- endif %}>
{# Displays columns select list for selecting distinct columns in the search #}
<fieldset id="fieldset_select_fields">
<legend>
{% trans 'Select columns (at least one):' %}
</legend>
<select name="columnsToDisplay[]" size="{{ min(column_names|length, 10) }}" multiple>
{% for each_field in column_names %}
<option value="{{ each_field }}" selected>
{{ each_field }}
</option>
{% endfor %}
</select>
<input type="checkbox" name="distinct" value="DISTINCT" id="oDistinct">
<label for="oDistinct">DISTINCT</label>
</fieldset>
{# Displays input box for custom 'Where' clause to be used in the search #}
<fieldset id="fieldset_search_conditions">
<legend>
<em>{% trans 'Or' %}</em>
{% trans 'Add search conditions (body of the "where" clause):' %}
</legend>
{{ show_mysql_docu('Functions') }}
<input type="text" name="customWhereClause" class="textfield" size="64">
</fieldset>
{# Displays option of changing default number of rows displayed per page #}
<fieldset id="fieldset_limit_rows">
<legend>{% trans 'Number of rows per page' %}</legend>
<input type="number" name="session_max_rows" min="1" value="{{ max_rows }}" class="textfield" required>
</fieldset>
{# Displays option for ordering search results by a column value (Asc or Desc) #}
<fieldset id="fieldset_display_order">
<legend>{% trans 'Display order:' %}</legend>
<select name="orderByColumn"><option value="--nil--"></option>
{% for each_field in column_names %}
<option value="{{ each_field }}">
{{ each_field }}
</option>
{% endfor %}
</select>
<div class="formelement">
<input type="radio" name="order" id="orderByAscRadio" value="ASC" checked>
<label for="orderByAscRadio">{% trans 'Ascending' %}</label>
</div>
<div class="formelement">
<input type="radio" name="order" id="orderByDescRadio" value="DESC">
<label for="orderByDescRadio">{% trans 'Descending' %}</label>
</div>
</fieldset>
<div class="clearfloat"></div>
</div>
</fieldset>
<fieldset class="tblFooters">
<input class="btn btn-primary" type="submit" name="submit" value="{% trans 'Go' %}">
</fieldset>
</form>
<div id="sqlqueryresultsouter"></div>

View file

@ -0,0 +1,98 @@
{# Get inputbox based on different column types (Foreign key, geometrical, enum) #}
{% if foreigners and search_column_in_foreigners(foreigners, column_name) %}
{% if foreign_data['disp_row'] is iterable %}
<select name="criteriaValues[{{ column_index }}]"
id="{{ column_id }}{{ column_index }}">
{{ foreign_dropdown(
foreign_data['disp_row'],
foreign_data['foreign_field'],
foreign_data['foreign_display'],
'',
foreign_max_limit
) }}
</select>
{% elseif foreign_data['foreign_link'] == true %}
<input type="text"
id="{{ column_id }}{{ column_index }}"
name="criteriaValues[{{ column_index }}]"
id="field_{{ column_name_hash }}[{{ column_index }}]"
class="textfield"
{% if criteria_values[column_index] is defined %}
value="{{ criteria_values[column_index] }}"
{% endif %}>
<a class="ajax browse_foreign" href="{{ url('/browse-foreigners') }}" data-post="
{{- get_common({'db': db, 'table': table}, '') -}}
&amp;field={{ column_name|url_encode }}&amp;fieldkey=
{{- column_index }}&amp;fromsearch=1">
{{ get_icon('b_browse', 'Browse foreign values'|trans) }}
</a>
{% endif %}
{% elseif column_type in get_gis_datatypes() %}
<input type="text"
name="criteriaValues[{{ column_index }}]"
size="40"
class="textfield"
id="field_{{ column_index }}">
{% if in_fbs %}
{% set edit_str = get_icon('b_edit', 'Edit/Insert'|trans) %}
<span class="open_search_gis_editor">
{{ link_or_button(url('/gis-data-editor'), edit_str, [], '_blank') }}
</span>
{% endif %}
{% elseif column_type starts with 'enum'
or (column_type starts with 'set' and in_zoom_search_edit) %}
{% set in_zoom_search_edit = false %}
{% set value = column_type|e|slice(5, -1)|replace({'&#039;': ''})|split(', ') %}
{% set cnt_value = value|length %}
{#
Enum in edit mode --> dropdown
Enum in search mode --> multiselect
Set in edit mode --> multiselect
Set in search mode --> input (skipped here, so the 'else' section would handle it)
#}
{% if (column_type starts with 'enum' and not in_zoom_search_edit)
or (column_type starts with 'set' and in_zoom_search_edit) %}
<select name="criteriaValues[{{ column_index }}]"
id="{{ column_id }}{{ column_index }}">
{% else %}
<select name="criteriaValues[{{ column_index }}]"
id="{{ column_id }}{{ column_index }}"
multiple="multiple"
size="{{ min(3, cnt_value) }}">
{% endif %}
{# Add select options #}
<option value=""></option>
{% for i in 0..cnt_value - 1 %}
{% if criteria_values[column_index] is defined
and criteria_values[column_index] is iterable
and value[i] in criteria_values[column_index] %}
<option value="{{ value[i]|raw }}" selected>
{{ value[i]|raw }}
</option>
{% else %}
<option value="{{ value[i]|raw }}">
{{ value[i]|raw }}
</option>
{% endif %}
{% endfor %}
</select>
{% else %}
{% set the_class = 'textfield' %}
{% if column_type == 'date' %}
{% set the_class = the_class ~ ' datefield' %}
{% elseif column_type == 'datetime' or column_type starts with 'timestamp' %}
{% set the_class = the_class ~ ' datetimefield' %}
{% elseif column_type starts with 'bit' %}
{% set the_class = the_class ~ ' bit' %}
{% endif %}
<input type="text"
name="criteriaValues[{{ column_index }}]"
data-type="{{ column_data_type }}"
{{ html_attributes|raw }}
size="40"
class="{{ the_class }}"
id="{{ column_id }}{{ column_index }}"
{% if criteria_values[column_index] is defined %}
value="{{ criteria_values[column_index] }}"
{%- endif %}>
{% endif %}

View file

@ -0,0 +1,210 @@
<div id="partitions">
<fieldset>
<legend>
{% trans 'Partitions' %}
{{ show_mysql_docu('partitioning') }}
</legend>
{% if partitions is empty %}
{{ 'No partitioning defined!'|trans|notice }}
{% else %}
<p>
{% trans 'Partitioned by:' %}
<code>{{ partition_method }}({{ partition_expression }})</code>
</p>
{% if has_sub_partitions %}
<p>
{% trans 'Sub partitioned by:' %}
<code>{{ sub_partition_method }}({{ sub_partition_expression }})</code>
<p>
{% endif %}
<table class="table table-light table-striped table-hover table-sm">
<thead class="thead-light">
<tr>
<th colspan="2">#</th>
<th>{% trans 'Partition' %}</th>
{% if has_description %}
<th>{% trans 'Expression' %}</th>
{% endif %}
<th>{% trans 'Rows' %}</th>
<th>{% trans 'Data length' %}</th>
<th>{% trans 'Index length' %}</th>
<th>{% trans 'Comment' %}</th>
<th colspan="{{ range_or_list ? '7' : '6' }}">
{% trans 'Action' %}
</th>
</tr>
</thead>
<tbody>
{% for partition in partitions %}
<tr class="noclick{{ has_sub_partitions ? ' table-active' }}">
{% if has_sub_partitions %}
<td>{{ partition.getOrdinal() }}</td>
<td></td>
{% else %}
<td colspan="2">{{ partition.getOrdinal() }}</td>
{% endif %}
<th>{{ partition.getName() }}</th>
{% if has_description %}
<td>
<code>
{{- partition.getExpression() -}}
{{- partition.getMethod() == 'LIST' ? ' IN (' : ' < ' -}}
{{- partition.getDescription() -}}
{{- partition.getMethod() == 'LIST' ? ')' -}}
</code>
</td>
{% endif %}
<td class="value">{{ partition.getRows() }}</td>
<td class="value">
{% set data_length = format_byte_down(
partition.getDataLength(),
3,
1
) %}
<span>{{ data_length[0] }}</span>
<span class="unit">{{ data_length[1] }}</span>
</td>
<td class="value">
{% set index_length = format_byte_down(
partition.getIndexLength(),
3,
1
) %}
<span>{{ index_length[0] }}</span>
<span class="unit">{{ index_length[1] }}</span>
</td>
<td>{{ partition.getComment() }}</td>
<td>
<a id="partition_action_ANALYZE" class="ajax" href="{{ url('/table/partition/analyze') }}" data-post="{{ get_common({
'db': db,
'table': table,
'partition_name': partition.getName(),
}) }}">
{{ get_icon('b_search', 'Analyze'|trans) }}
</a>
</td>
<td>
<a id="partition_action_CHECK" class="ajax" href="{{ url('/table/partition/check') }}" data-post="{{ get_common({
'db': db,
'table': table,
'partition_name': partition.getName(),
}) }}">
{{ get_icon('eye', 'Check'|trans) }}
</a>
</td>
<td>
<a id="partition_action_OPTIMIZE" class="ajax" href="{{ url('/table/partition/optimize') }}" data-post="{{ get_common({
'db': db,
'table': table,
'partition_name': partition.getName(),
}) }}">
{{ get_icon('normalize', 'Optimize'|trans) }}
</a>
</td>
<td>
<a id="partition_action_REBUILD" class="ajax" href="{{ url('/table/partition/rebuild') }}" data-post="{{ get_common({
'db': db,
'table': table,
'partition_name': partition.getName(),
}) }}">
{{ get_icon('s_tbl', 'Rebuild'|trans) }}
</a>
</td>
<td>
<a id="partition_action_REPAIR" class="ajax" href="{{ url('/table/partition/repair') }}" data-post="{{ get_common({
'db': db,
'table': table,
'partition_name': partition.getName(),
}) }}">
{{ get_icon('b_tblops', 'Repair'|trans) }}
</a>
</td>
<td>
<a id="partition_action_TRUNCATE" class="ajax" href="{{ url('/table/partition/truncate') }}" data-post="{{ get_common({
'db': db,
'table': table,
'partition_name': partition.getName(),
}) }}">
{{ get_icon('b_empty', 'Truncate'|trans) }}
</a>
</td>
{% if range_or_list %}
<td>
<a id="partition_action_DROP" class="ajax" href="{{ url('/table/partition/drop') }}" data-post="{{ get_common({
'db': db,
'table': table,
'partition_name': partition.getName(),
}) }}">
{{ get_icon('b_drop', 'Drop'|trans) }}
</a>
</td>
{% endif %}
{% if has_sub_partitions %}
{% for sub_partition in partition.getSubPartitions() %}
<tr class="noclick">
<td></td>
<td>{{ sub_partition.getOrdinal() }}</td>
<td>{{ sub_partition.getName() }}</td>
{% if has_description %}
<td></td>
{% endif %}
<td class="value">{{ sub_partition.getRows() }}</td>
<td class="value">
{% set data_length = format_byte_down(
sub_partition.getDataLength(),
3,
1
) %}
<span>{{ data_length[0] }}</span>
<span class="unit">{{ data_length[1] }}</span>
</td>
<td class="value">
{% set index_length = format_byte_down(
sub_partition.getIndexLength(),
3,
1
) %}
<span>{{ index_length[0] }}</span>
<span class="unit">{{ index_length[1] }}</span>
</td>
<td>{{ sub_partition.getComment() }}</td>
<td colspan="{{ range_or_list ? '7' : '6' }}"></td>
</tr>
{% endfor %}
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</fieldset>
<fieldset class="tblFooters print_ignore">
<form action="{{ url('/table/structure/partitioning') }}" method="post">
{{ get_hidden_inputs(db, table) }}
{% if partitions is empty %}
<input class="btn btn-secondary" type="submit" value="{% trans 'Partition table' %}">
{% else %}
{{ link_or_button(
url('/sql', {
'db': db,
'table': table,
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' REMOVE PARTITIONING'
}),
'Remove partitioning'|trans, {
'class': 'btn btn-secondary ajax',
'id': 'remove_partitioning'
}) }}
<input class="btn btn-secondary" type="submit" value="{% trans 'Edit partitioning' %}">
{% endif %}
</form>
</fieldset>
</div>

View file

@ -0,0 +1,561 @@
{% extends 'table/page_with_secondary_tabs.twig' %}
{% block content %}
<h1 class="d-none d-print-block">{{table}}</h1>
<form method="post" action="{{ url('/table/structure') }}" name="fieldsForm" id="fieldsForm"
class="ajax{{ hide_structure_actions ? ' HideStructureActions' }}">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="table_type" value=
{%- if db_is_system_schema -%}
"information_schema"
{%- elseif tbl_is_view -%}
"view"
{%- else -%}
"table"
{%- endif %}>
<div class="table-responsive-md">
<table id="tablestructure" class="table table-light table-striped table-hover w-auto">
{# Table header #}
<thead class="thead-light">
<tr>
<th class="print_ignore"></th>
<th>#</th>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Collation' %}</th>
<th>{% trans 'Attributes' %}</th>
<th>{% trans 'Null' %}</th>
<th>{% trans 'Default' %}</th>
{% if show_column_comments -%}
<th>{% trans 'Comments' %}</th>
{%- endif %}
<th>{% trans 'Extra' %}</th>
{# @see table/structure.js, function moreOptsMenuResize() #}
{% if not db_is_system_schema and not tbl_is_view %}
<th colspan="{{ show_icons('ActionLinksMode') ? '8' : '9' -}}
" class="action print_ignore">{% trans 'Action' %}</th>
{% endif %}
</tr>
</thead>
<tbody>
{# Table body #}
{% set rownum = 0 %}
{% for row in fields %}
{% set rownum = rownum + 1 %}
{% set extracted_columnspec = extracted_columnspecs[rownum] %}
{% set field_name = row['Field']|e %}
{# For column comments #}
{% set comments = row_comments[rownum] %}
{# Underline commented fields and display a hover-title (CSS only) #}
<tr>
<td class="text-center print_ignore">
<input type="checkbox" class="checkall" name="selected_fld[]" value="{{ row['Field'] }}" id="checkbox_row_{{ rownum }}">
</td>
<td class="right">{{ rownum }}</td>
<th class="nowrap">
<label for="checkbox_row_{{ rownum }}">
{% if displayed_fields[rownum].comment is defined %}
<span class="commented_column" title="{{ displayed_fields[rownum].comment }}">{{ displayed_fields[rownum].text }}</span>
{% else %}
{{ displayed_fields[rownum].text }}
{% endif %}
{{ displayed_fields[rownum].icon|raw }}
</label>
</th>
<td{{ 'set' != extracted_columnspec['type'] and 'enum' != extracted_columnspec['type'] ? ' class="nowrap"' }}>
<bdo dir="ltr" lang="en">
{{ extracted_columnspec['displayed_type']|raw }}
{% if relation_commwork and relation_mimework and browse_mime
and mime_map[row['Field']]['mimetype'] is defined %}
<br>{% trans 'Media type:' %} {{ mime_map[row['Field']]['mimetype']|replace({'_': '/'})|lower }}
{% endif %}
</bdo>
</td>
<td>
{% if row['Collation'] is not empty %}
<dfn title="{{ collations[row['Collation']].description }}">{{ collations[row['Collation']].name }}</dfn>
{% endif %}
</td>
<td class="column_attribute nowrap">{{ attributes[rownum] }}</td>
<td>{{ row['Null'] == 'YES' ? 'Yes'|trans : 'No'|trans }}</td>
<td class="nowrap">
{% if row['Default'] is not null %}
{% if extracted_columnspec['type'] == 'bit' %}
{{ row['Default']|convert_bit_default_value }}
{% else %}
{{ row['Default'] }}
{% endif %}
{% elseif row['Null'] == 'YES' %}
<em>NULL</em>
{% else %}
<em>{% trans %}None{% context %}None for default{% endtrans %}</em>
{% endif %}
</td>
{% if show_column_comments %}
<td>
{{ comments }}
</td>
{% endif %}
<td class="nowrap">{{ row['Extra']|upper }}</td>
{% if not tbl_is_view and not db_is_system_schema %}
<td class="edit text-center print_ignore">
<a class="change_column_anchor ajax" href="{{ url('/table/structure/change', {
'db': db,
'table': table,
'field': row['Field'],
'change_column': 1
}) }}">
{{ get_icon('b_edit', 'Change'|trans) }}
</a>
</td>
<td class="drop text-center print_ignore">
<a class="drop_column_anchor ajax" href="{{ url('/sql') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' DROP ' ~ backquote(row['Field']) ~ ';',
'dropped_column': row['Field'],
'purge': true,
'message_to_show': 'Column %s has been dropped.'|trans|format(row['Field']|e)
}) }}">
{{ get_icon('b_drop', 'Drop'|trans) }}
</a>
</td>
{% endif %}
{% if not tbl_is_view and not db_is_system_schema %}
{% set type = extracted_columnspec['print_type'] is not empty ? extracted_columnspec['print_type'] %}
<td class="print_ignore">
<ul class="table-structure-actions resizable-menu">
{% if hide_structure_actions %}
<li class="submenu shown">
<a href="#" class="tab nowrap">{{ get_icon('b_more', 'More'|trans) }}</a>
<ul>
{% endif %}
<li class="primary nowrap">
{% if type == 'text' or type == 'blob' or tbl_storage_engine == 'ARCHIVE' or (primary and primary.hasColumn(field_name)) %}
{{ get_icon('bd_primary', 'Primary'|trans) }}
{% else %}
<a rel="samepage" class="ajax add_key print_ignore add_primary_key_anchor" href="{{ url('/table/structure/add-key') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ (primary ? ' DROP PRIMARY KEY,') ~ ' ADD PRIMARY KEY(' ~ backquote(row['Field']) ~ ');',
'message_to_show': 'A primary key has been added on %s.'|trans|format(row['Field']|e)
}) }}">
{{ get_icon('b_primary', 'Primary'|trans) }}
</a>
{% endif %}
</li>
<li class="add_unique unique nowrap">
{% if type == 'text' or type == 'blob' or tbl_storage_engine == 'ARCHIVE' or field_name in columns_with_unique_index %}
{{ get_icon('bd_unique', 'Unique'|trans) }}
{% else %}
<a rel="samepage" class="ajax add_key print_ignore add_unique_anchor" href="{{ url('/table/structure/add-key') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' ADD UNIQUE(' ~ backquote(row['Field']) ~ ');',
'message_to_show': 'An index has been added on %s.'|trans|format(row['Field']|e)
}) }}">
{{ get_icon('b_unique', 'Unique'|trans) }}
</a>
{% endif %}
</li>
<li class="add_index nowrap">
{% if type == 'text' or type == 'blob' or tbl_storage_engine == 'ARCHIVE' %}
{{ get_icon('bd_index', 'Index'|trans) }}
{% else %}
<a rel="samepage" class="ajax add_key print_ignore add_index_anchor" href="{{ url('/table/structure/add-key') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' ADD INDEX(' ~ backquote(row['Field']) ~ ');',
'message_to_show': 'An index has been added on %s.'|trans|format(row['Field']|e)
}) }}">
{{ get_icon('b_index', 'Index'|trans) }}
</a>
{% endif %}
</li>
{% set spatial_types = [
'geometry',
'point',
'linestring',
'polygon',
'multipoint',
'multilinestring',
'multipolygon',
'geomtrycollection'
] %}
<li class="spatial nowrap">
{% if type == 'text' or type == 'blob' or tbl_storage_engine == 'ARCHIVE' or (type not in spatial_types and (tbl_storage_engine == 'MYISAM' or mysql_int_version >= 50705)) %}
{{ get_icon('bd_spatial', 'Spatial'|trans) }}
{% else %}
<a rel="samepage" class="ajax add_key print_ignore add_spatial_anchor" href="{{ url('/table/structure/add-key') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' ADD SPATIAL(' ~ backquote(row['Field']) ~ ');',
'message_to_show': 'An index has been added on %s.'|trans|format(row['Field']|e)
}) }}">
{{ get_icon('b_spatial', 'Spatial'|trans) }}
</a>
{% endif %}
</li>
{# FULLTEXT is possible on TEXT, CHAR and VARCHAR #}
<li class="fulltext nowrap">
{% if tbl_storage_engine is not empty and (
tbl_storage_engine == 'MYISAM'
or tbl_storage_engine == 'ARIA'
or tbl_storage_engine == 'MARIA'
or (tbl_storage_engine == 'INNODB' and mysql_int_version >= 50604)
) and ('text' in type or 'char' in type) %}
<a rel="samepage" class="ajax add_key add_fulltext_anchor" href="{{ url('/table/structure/add-key') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' ADD FULLTEXT(' ~ backquote(row['Field']) ~ ');',
'message_to_show': 'An index has been added on %s.'|trans|format(row['Field']|e)
}) }}">
{{ get_icon('b_ftext', 'Fulltext'|trans) }}
</a>
{% else %}
{{ get_icon('bd_ftext', 'Fulltext'|trans) }}
{% endif %}
</li>
{# Distinct value action #}
<li class="browse nowrap">
<a href="{{ url('/sql') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'SELECT COUNT(*) AS ' ~ backquote('Rows'|trans)
~ ', ' ~ backquote(row['Field'])
~ ' FROM ' ~ backquote(table)
~ ' GROUP BY ' ~ backquote(row['Field'])
~ ' ORDER BY ' ~ backquote(row['Field']),
'is_browse_distinct': true
}) }}">
{{ get_icon('b_browse', 'Distinct values'|trans) }}
</a>
</li>
{% if central_columns_work %}
<li class="browse nowrap">
{% if row['Field'] in central_list %}
<a href="#" class="central_columns remove_button">
{{ get_icon('centralColumns_delete', 'Remove from central columns'|trans) }}
</a>
{% else %}
<a href="#" class="central_columns add_button">
{{ get_icon('centralColumns_add', 'Add to central columns'|trans) }}
</a>
{% endif %}
</li>
{% endif %}
{% if hide_structure_actions %}
</ul>
</li>
{% endif %}
</ul>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="print_ignore">
{% include 'select_all.twig' with {
'theme_image_path': theme_image_path,
'text_dir': text_dir,
'form_name': 'fieldsForm'
} only %}
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/browse') }}">
{{ get_icon('b_browse', 'Browse'|trans) }}
</button>
{% if not tbl_is_view and not db_is_system_schema %}
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/change') }}">
{{ get_icon('b_edit', 'Change'|trans) }}
</button>
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/drop-confirm') }}">
{{ get_icon('b_drop', 'Drop'|trans) }}
</button>
{% if tbl_storage_engine != 'ARCHIVE' %}
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/primary') }}">
{{ get_icon('b_primary', 'Primary'|trans) }}
</button>
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/unique') }}">
{{ get_icon('b_unique', 'Unique'|trans) }}
</button>
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/index') }}">
{{ get_icon('b_index', 'Index'|trans) }}
</button>
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/spatial') }}">
{{ get_icon('b_spatial', 'Spatial'|trans) }}
</button>
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/fulltext') }}">
{{ get_icon('b_ftext', 'Fulltext'|trans) }}
</button>
{% if central_columns_work %}
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/central-columns-add') }}">
{{ get_icon('centralColumns_add', 'Add to central columns'|trans) }}
</button>
<button class="btn btn-link mult_submit" type="submit" formaction="{{ url('/table/structure/central-columns-remove') }}">
{{ get_icon('centralColumns_delete', 'Remove from central columns'|trans) }}
</button>
{% endif %}
{% endif %}
{% endif %}
</div>
</form>
<hr class="print_ignore">
<div id="move_columns_dialog" class="hide" title="{% trans 'Move columns' %}">
<p>{% trans 'Move the columns by dragging them up and down.' %}</p>
<form action="{{ url('/table/structure/move-columns') }}" name="move_column_form" id="move_column_form">
<div>
{{ get_hidden_inputs(db, table) }}
<ul></ul>
</div>
</form>
</div>
{# Work on the table #}
<div id="structure-action-links">
{% if tbl_is_view and not db_is_system_schema %}
{{ link_or_button(
url('/view/create', {'db': db, 'table': table}),
get_icon('b_edit', 'Edit view'|trans, true)
) }}
{% endif %}
<a href="#" id="printView">{{ get_icon('b_print', 'Print'|trans, true) }}</a>
{% if not tbl_is_view and not db_is_system_schema %}
{# Only display propose table structure for MySQL < 8.0 #}
{% if mysql_int_version < 80000 or is_mariadb %}
<a class="mr-0" href="{{ url('/sql') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'SELECT * FROM ' ~ backquote(table) ~ ' PROCEDURE ANALYSE()',
'session_max_rows': 'all'
}) }}">
{{ get_icon(
'b_tblanalyse',
'Propose table structure'|trans,
true
) }}
</a>
{{ show_mysql_docu('procedure_analyse') }}
{% endif %}
{% if is_active %}
<a href="{{ url('/table/tracking', {'db': db, 'table': table}) }}">
{{ get_icon('eye', 'Track table'|trans, true) }}
</a>
{% endif %}
<a href="#" id="move_columns_anchor">
{{ get_icon('b_move', 'Move columns'|trans, true) }}
</a>
<a href="{{ url('/normalization', {'db': db, 'table': table}) }}">
{{ get_icon('normalize', 'Normalize'|trans, true) }}
</a>
{% endif %}
{% if tbl_is_view and not db_is_system_schema %}
{% if is_active %}
<a href="{{ url('/table/tracking', {'db': db, 'table': table}) }}">
{{ get_icon('eye', 'Track view'|trans, true) }}
</a>
{% endif %}
{% endif %}
</div>
{% if not tbl_is_view and not db_is_system_schema %}
<form method="post" action="{{ url('/table/add-field') }}" id="addColumns" name="addColumns">
{{ get_hidden_inputs(db, table) }}
{% if show_icons('ActionLinksMode') %}
{{ get_image('b_insrow', 'Add column'|trans) }}&nbsp;
{% endif %}
{% set num_fields -%}
<input type="number" name="num_fields" value="1" onfocus="this.select()" min="1" required>
{%- endset %}
{{ 'Add %s column(s)'|trans|format(num_fields)|raw }}
<input type="hidden" name="field_where" value="after">&nbsp;
{# I tried displaying the drop-down inside the label but with Firefox the drop-down was blinking #}
<select name="after_field">
<option value="first" data-pos="first">
{% trans 'at beginning of table' %}
</option>
{% for one_column_name in columns_list %}
<option value="{{ one_column_name }}"
{{- loop.revindex0 == 0 ? ' selected="selected"' }}>
{{ 'after %s'|trans|format(one_column_name) }}
</option>
{% endfor %}
</select>
<input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
</form>
{% endif %}
{% if not tbl_is_view and not db_is_system_schema and tbl_storage_engine != 'ARCHIVE' %}
<div id="index_div" class="w-100 ajax">
<fieldset class="index_info">
<legend id="index_header">
{% trans 'Indexes' %}
{{ show_mysql_docu('optimizing-database-structure') }}
</legend>
{% if indexes is not empty %}
{{ indexes_duplicates|raw }}
<div class="table-responsive jsresponsive">
<table class="table table-light table-striped table-hover table-sm w-auto" id="table_index">
<thead class="thead-light">
<tr>
<th colspan="3" class="print_ignore">{% trans 'Action' %}</th>
<th>{% trans 'Keyname' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Unique' %}</th>
<th>{% trans 'Packed' %}</th>
<th>{% trans 'Column' %}</th>
<th>{% trans 'Cardinality' %}</th>
<th>{% trans 'Collation' %}</th>
<th>{% trans 'Null' %}</th>
<th>{% trans 'Comment' %}</th>
</tr>
</thead>
{% for index in indexes %}
<tbody class="row_span">
{% set columns_count = index.getColumnCount() %}
<tr class="noclick">
<td rowspan="{{ columns_count }}" class="edit_index print_ignore ajax">
<a class="ajax" href="{{ url('/table/indexes') }}" data-post="{{ get_common({
'db': db,
'table': table,
'index': index.getName()
}, '') }}">
{{ get_icon('b_edit', 'Edit'|trans) }}
</a>
</td>
<td rowspan="{{ columns_count }}" class="rename_index print_ignore ajax" >
<a class="ajax" href="{{ url('/table/indexes/rename') }}" data-post="{{ get_common({
'db': db,
'table': table,
'index': index.getName()
}, '') }}">
{{ get_icon('b_rename', 'Rename'|trans) }}
</a>
</td>
<td rowspan="{{ columns_count }}" class="print_ignore">
{% if index.getName() == 'PRIMARY' %}
{% set index_params = {
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' DROP PRIMARY KEY;',
'message_to_show': 'The primary key has been dropped.'|trans
} %}
{% else %}
{% set index_params = {
'sql_query': 'ALTER TABLE ' ~ backquote(table) ~ ' DROP INDEX ' ~ backquote(index.getName()) ~ ';',
'message_to_show': 'Index %s has been dropped.'|trans|format(index.getName())
} %}
{% endif %}
<input type="hidden" class="drop_primary_key_index_msg" value="{{ index_params.sql_query|js_format(false) }}">
{{ link_or_button(
url('/sql', index_params|merge({'db': db, 'table': table})),
get_icon('b_drop', 'Drop'|trans),
{'class': 'drop_primary_key_index_anchor ajax'}
) }}
</td>
<th rowspan="{{ columns_count }}">{{ index.getName() }}</th>
<td rowspan="{{ columns_count }}">{{ index.getType()|default(index.getChoice()) }}</td>
<td rowspan="{{ columns_count }}">{{ index.isUnique() ? 'Yes'|trans : 'No'|trans }}</td>
<td rowspan="{{ columns_count }}">{{ index.isPacked()|raw }}</td>
{% for column in index.getColumns() %}
{% if column.getSeqInIndex() > 1 %}
<tr class="noclick">
{% endif %}
<td>
{{ column.getName() }}
{% if column.getSubPart() is not empty %}
({{ column.getSubPart() }})
{% endif %}
</td>
<td>{{ column.getCardinality() }}</td>
<td>{{ column.getCollation() }}</td>
<td>{{ column.getNull(true) }}</td>
{% if column.getSeqInIndex() == 1 %}
<td rowspan="{{ columns_count }}">{{ index.getComments() }}</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>
{% else %}
<div class="no_indexes_defined">{{ 'No index defined!'|trans|notice }}</div>
{% endif %}
</fieldset>
<fieldset class="tblFooters print_ignore text-left">
<form action="{{ url('/table/indexes') }}" method="post">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="create_index" value="1">
{% apply format('<input class="mx-2" type="number" name="added_fields" value="1" min="1" required>')|raw %}
{% trans %}Create an index on %s columns{% endtrans %}
{% endapply %}
<input class="btn btn-primary add_index ajax" type="submit" value="{% trans 'Go' %}">
</form>
</fieldset>
</div>
{% endif %}
{# Display partition details #}
{% if have_partitioning %}
{# Detect partitioning #}
{% if partition_names is not empty and partition_names[0] is not null %}
{% set first_partition = partitions[0] %}
{% set range_or_list = first_partition.getMethod() == 'RANGE'
or first_partition.getMethod() == 'RANGE COLUMNS'
or first_partition.getMethod() == 'LIST'
or first_partition.getMethod() == 'LIST COLUMNS' %}
{% set sub_partitions = first_partition.getSubPartitions() %}
{% set has_sub_partitions = first_partition.hasSubPartitions() %}
{% if has_sub_partitions %}
{% set first_sub_partition = sub_partitions[0] %}
{% endif %}
<div id="partitions-2"{% if default_sliders_state != 'disabled' -%}
{{- default_sliders_state == 'closed' ? ' style="display: none; overflow:auto;"' }} class="pma_auto_slider" title="{% trans 'Partitions' %}"
{%- endif %}>
{% include 'table/structure/display_partitions.twig' with {
'db': db,
'table': table,
'partitions': partitions,
'partition_method': first_partition.getMethod(),
'partition_expression': first_partition.getExpression(),
'has_description': first_partition.getDescription() is not empty,
'has_sub_partitions': has_sub_partitions,
'sub_partition_method': has_sub_partitions ? first_sub_partition.getMethod(),
'sub_partition_expression': has_sub_partitions ? first_sub_partition.getExpression(),
'range_or_list': range_or_list
} only %}
{% else %}
{% include 'table/structure/display_partitions.twig' with {
'db': db,
'table': table
} only %}
{% endif %}
</div>
{% endif %}
{# Displays Space usage and row statistics #}
{% if show_stats %}
{{ table_stats|raw }}
{% endif %}
<div class="clearfloat"></div>
{% endblock %}

View file

@ -0,0 +1,175 @@
<div id="tablestatistics">
<fieldset>
<legend>{% trans 'Information' %}</legend>
{% if showtable['TABLE_COMMENT'] %}
<p>
<strong>{% trans 'Table comments:' %}</strong>
{{ showtable['TABLE_COMMENT'] }}
</p>
{% endif %}
<a id="showusage"></a>
{% if not tbl_is_view and not db_is_system_schema %}
<table class="table table-light table-striped table-hover table-sm w-auto">
<caption>{% trans 'Space usage' %}</caption>
<tbody>
<tr>
<th class="name">{% trans 'Data' %}</th>
<td class="value">{{ data_size }}</td>
<td class="unit">{{ data_unit }}</td>
</tr>
{% if index_size is defined %}
<tr>
<th class="name">{% trans 'Index' %}</th>
<td class="value">{{ index_size }}</td>
<td class="unit">{{ index_unit }}</td>
</tr>
{% endif %}
{% if free_size is defined %}
<tr>
<th class="name">{% trans 'Overhead' %}</th>
<td class="value">{{ free_size }}</td>
<td class="unit">{{ free_unit }}</td>
</tr>
<tr>
<th class="name">{% trans 'Effective' %}</th>
<td class="value">{{ effect_size }}</td>
<td class="unit">{{ effect_unit }}</td>
</tr>
{% endif %}
{% if tot_size is defined and mergetable == false %}
<tr>
<th class="name">{% trans 'Total' %}</th>
<td class="value">{{ tot_size }}</td>
<td class="unit">{{ tot_unit }}</td>
</tr>
{% endif %}
</tbody>
{# Optimize link if overhead #}
{% if free_size is defined
and (tbl_storage_engine == 'MYISAM'
or tbl_storage_engine == 'ARIA'
or tbl_storage_engine == 'MARIA'
or tbl_storage_engine == 'BDB')
or (tbl_storage_engine == 'INNODB' and innodb_file_per_table == true) %}
<tfoot class="thead-light">
<tr class="print_ignore">
<th colspan="3" class="center">
<a href="{{ url('/sql') }}" data-post="{{ get_common({
'db': db,
'table': table,
'sql_query': 'OPTIMIZE TABLE ' ~ backquote(table),
'pos': 0
}) }}">
{{ get_icon('b_tbloptimize', 'Optimize table'|trans) }}
</a>
</th>
</tr>
</tfoot>
{% endif %}
</table>
{% endif %}
{% set avg_size = avg_size is defined ? avg_size : null %}
{% set avg_unit = avg_unit is defined ? avg_unit : null %}
<table class="table table-light table-striped table-hover table-sm w-auto">
<caption>{% trans 'Row statistics' %}</caption>
<tbody>
{% if showtable['Row_format'] is defined %}
<tr>
<th class="name">{% trans 'Format' %}</th>
{% if showtable['Row_format'] == 'Fixed' %}
<td class="value">{% trans 'static' %}</td>
{% elseif showtable['Row_format'] == 'Dynamic' %}
<td class="value">{% trans 'dynamic' %}</td>
{% else %}
<td class="value">{{ showtable['Row_format'] }}</td>
{% endif %}
</tr>
{% endif %}
{% if showtable['Create_options'] is not empty %}
<tr>
<th class="name">{% trans 'Options' %}</th>
{% if showtable['Create_options'] == 'partitioned' %}
<td class="value">{% trans 'partitioned' %}</td>
{% else %}
<td class="value">{{ showtable['Create_options'] }}</td>
{% endif %}
</tr>
{% endif %}
{% if table_collation is not empty %}
<tr>
<th class="name">{% trans 'Collation' %}</th>
<td class="value">
<dfn title="{{ table_collation.description }}">
{{ table_collation.name }}
</dfn>
</td>
</tr>
{% endif %}
{% if not is_innodb and showtable['Rows'] is defined %}
<tr>
<th class="name">{% trans 'Rows' %}</th>
<td class="value">{{ format_number(showtable['Rows'], 0) }}</td>
</tr>
{% endif %}
{% if not is_innodb
and showtable['Avg_row_length'] is defined
and showtable['Avg_row_length'] > 0 %}
<tr>
<th class="name">{% trans 'Row length' %}</th>
{% set avg_row_length = format_byte_down(showtable['Avg_row_length'], 6, 1) %}
<td class="value">{{ avg_row_length[0] }} {{ avg_row_length[1] }}</td>
</tr>
{% endif %}
{% if not is_innodb
and showtable['Data_length'] is defined
and showtable['Rows'] is defined
and showtable['Rows'] > 0
and mergetable == false %}
<tr>
<th class="name">{% trans 'Row size' %}</th>
<td class="value">{{ avg_size }} {{ avg_unit }}</td>
</tr>
{% endif %}
{% if showtable['Auto_increment'] is defined %}
<tr>
<th class="name">{% trans 'Next autoindex' %}</th>
<td class="value">{{ format_number(showtable['Auto_increment'], 0) }}</td>
</tr>
{% endif %}
{% if showtable['Create_time'] is defined %}
<tr>
<th class="name">{% trans 'Creation' %}</th>
<td class="value">{{ localised_date(showtable['Create_time']|date('U')) }}</td>
</tr>
{% endif %}
{% if showtable['Update_time'] is defined %}
<tr>
<th class="name">{% trans 'Last update' %}</th>
<td class="value">{{ localised_date(showtable['Update_time']|date('U')) }}</td>
</tr>
{% endif %}
{% if showtable['Check_time'] is defined %}
<tr>
<th class="name">{% trans 'Last check' %}</th>
<td class="value">{{ localised_date(showtable['Check_time']|date('U')) }}</td>
</tr>
{% endif %}
</tbody>
</table>
</fieldset>
</div>

View file

@ -0,0 +1,22 @@
<form action="{{ url('/table/structure/drop') }}" method="post">
{{ get_hidden_inputs({'db': db, 'table': table, 'selected': fields}) }}
<fieldset class="confirmation">
<legend>
{% trans 'Do you really want to execute the following query?' %}
</legend>
<code>
ALTER TABLE {{ backquote(table) }}<br>
{% for field in fields %}
&nbsp;&nbsp;DROP {{ backquote(field) }}
{%- if loop.last %};{% else %},<br>{% endif %}
{% endfor %}
</code>
</fieldset>
<fieldset class="tblFooters">
<input id="buttonYes" class="btn btn-secondary" type="submit" name="mult_btn" value="{% trans 'Yes' %}">
<input id="buttonNo" class="btn btn-secondary" type="submit" name="mult_btn" value="{% trans 'No' %}">
</fieldset>
</form>

View file

@ -0,0 +1,14 @@
<form action="{{ url('/table/structure/partitioning') }}" method="post">
{{ get_hidden_inputs(db, table) }}
<fieldset>
<legend>{% trans 'Edit partitioning' %}</legend>
{% include 'columns_definitions/partitions.twig' with {
'partition_details': partition_details,
'storage_engines': storage_engines
} only %}
</fieldset>
<fieldset class="tblFooters">
<input class="btn btn-primary" type="submit" name="save_partitioning" value="{% trans 'Save' %}">
</fieldset>
</form>

View file

@ -0,0 +1,25 @@
<form action="{{ url('/table/structure/primary') }}" method="post">
{{ get_hidden_inputs({'db': db, 'table': table, 'selected': selected}) }}
<fieldset class="confirmation">
<legend>
{% trans 'Do you really want to execute the following query?' %}
</legend>
<code>
ALTER TABLE {{ backquote(table) }}<br>
&nbsp;&nbsp;DROP PRIMARY KEY,<br>
&nbsp;&nbsp;&nbsp;ADD PRIMARY KEY(<br>
{% for field in selected %}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{ backquote(field) }}
{%- if not loop.last %},{% endif %}<br>
{% endfor %}
&nbsp;&nbsp;&nbsp;);
</code>
</fieldset>
<fieldset class="tblFooters">
<input id="buttonYes" class="btn btn-secondary" type="submit" name="mult_btn" value="{% trans 'Yes' %}">
<input id="buttonNo" class="btn btn-secondary" type="submit" name="mult_btn" value="{% trans 'No' %}">
</fieldset>
</form>

View file

@ -0,0 +1,27 @@
{{ active_message|raw }}
<br>
{{ action_message|raw }}
{{ delete_version|raw }}
{{ create_version|raw }}
{{ deactivate_tracking|raw }}
{{ activate_tracking|raw }}
{{ message|raw }}
{{ sql_dump|raw }}
{{ schema_snapshot|raw }}
{{ tracking_report_rows|raw }}
{{ tracking_report|raw }}
{{ main|raw }}
<br class="clearfloat">

View file

@ -0,0 +1,129 @@
{% if selectable_tables_num_rows > 0 %}
<form method="post" action="{{ url('/table/tracking', url_params) }}">
{{ get_hidden_inputs(db, table) }}
<select name="table" class="autosubmit">
{% for entry in selectable_tables_entries %}
<option value="{{ entry.table_name }}"
{{- entry.table_name == selected_table ? ' selected' }}>
{{ entry.db_name }}.{{ entry.table_name }}
{% if entry.is_tracked %}
({% trans 'active' %})
{% else %}
({% trans 'not active' %})
{% endif %}
</option>
{% endfor %}
</select>
<input type="hidden" name="show_versions_submit" value="1">
</form>
{% endif %}
<br>
{% if last_version > 0 %}
<form method="post" action="{{ url('/table/tracking') }}" name="versionsForm" id="versionsForm" class="ajax">
{{ get_hidden_inputs(db, table) }}
<table id="versions" class="table table-light table-striped table-hover table-sm w-auto">
<thead class="thead-light">
<tr>
<th></th>
<th>{% trans 'Version' %}</th>
<th>{% trans 'Created' %}</th>
<th>{% trans 'Updated' %}</th>
<th>{% trans 'Status' %}</th>
<th>{% trans 'Action' %}</th>
<th>{% trans 'Show' %}</th>
</tr>
</thead>
<tbody>
{% for version in versions %}
<tr>
<td class="text-center">
<input type="checkbox" name="selected_versions[]"
class="checkall" id="selected_versions_{{- version['version']|escape }}"
value="{{- version['version']|escape }}">
</td>
<td class="floatright">
<label for="selected_versions_{{- version['version']|escape }}">
<b>{{ version['version']|escape }}</b>
</label>
</td>
<td>{{ version['date_created']|escape }}</td>
<td>{{ version['date_updated']|escape }}</td>
{% if version['tracking_active'] == 1 %}
{% set last_version_status = 1 %}
<td>{% trans 'active' %}</td>
{% else %}
{% set last_version_status = 0 %}
<td>{% trans 'not active' %}</td>
{% endif %}
<td>
<a class="delete_version_anchor ajax" href="{{ url('/table/tracking') }}" data-post="
{{- get_common(url_params|merge({
'version': version['version'],
'submit_delete_version': true
}), '') }}">
{{ get_icon('b_drop', 'Delete version'|trans) }}
</a>
</td>
<td>
<a href="{{ url('/table/tracking') }}" data-post="
{{- get_common(url_params|merge({
'version': version['version'],
'report': 'true'
}), '') }}">
{{ get_icon('b_report', 'Tracking report'|trans) }}
</a>
<a href="{{ url('/table/tracking') }}" data-post="
{{- get_common(url_params|merge({
'version': version['version'],
'snapshot': 'true'
}), '') }}">
{{ get_icon('b_props', 'Structure snapshot'|trans) }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% include 'select_all.twig' with {
'theme_image_path': theme_image_path,
'text_dir': text_dir,
'form_name': 'versionsForm',
} only %}
<button class="btn btn-link mult_submit" type="submit" name="submit_mult" value="delete_version" title="{% trans 'Delete version' %}">
{{ get_icon('b_drop', 'Delete version'|trans) }}
</button>
</form>
{% set last_version_element = versions|first %}
<div>
<form method="post" action="{{ url('/table/tracking', url_params) }}">
{{ get_hidden_inputs(db, table) }}
<fieldset>
<legend>
{% if last_version_element['tracking_active'] == 0 %}
{% set legend = 'Activate tracking for %s'|trans %}
{% set value = 'activate_now' %}
{% set button = 'Activate now'|trans %}
{% else %}
{% set legend = 'Deactivate tracking for %s'|trans %}
{% set value = 'deactivate_now' %}
{% set button = 'Deactivate now'|trans %}
{% endif %}
{{ legend|format(db ~ '.' ~ table) }}
</legend>
<input type="hidden" name="version" value="{{ last_version }}">
<input type="hidden" name="toggle_activation" value="{{ value }}">
<input class="btn btn-secondary" type="submit" value="{{ button }}">
</fieldset>
</form>
</div>
{% endif %}
{% include 'create_tracking_version.twig' with {
'route': '/table/tracking',
'url_params': url_params,
'last_version': last_version,
'db': db,
'selected': [table],
'type': type,
'default_statements': default_statements,
} only %}

View file

@ -0,0 +1,27 @@
<table id="{{ table_id }}" class="table table-light table-striped table-hover">
<thead class="thead-light">
<tr>
<th>{% trans %}#{% context %}Number{% endtrans %}</th>
<th>{% trans 'Date' %}</th>
<th>{% trans 'Username' %}</th>
<th>{{ header_message }}</th>
<th>{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
{% for entry in entries %}
<tr class="noclick">
<td class="right"><small>{{ entry.line_number }}</small></td>
<td><small>{{ entry.date }}</small></td>
<td><small>{{ entry.username }}</small></td>
<td>{{ entry.formated_statement|raw }}</td>
<td class="nowrap">
<a class="delete_entry_anchor ajax" href="{{ url('/table/tracking') }}" data-post="
{{- entry.url_params|raw }}">
{{ drop_image_or_text|raw }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View file

@ -0,0 +1,56 @@
<h3>{% trans 'Structure' %}</h3>
<table id="tablestructure" class="table table-light table-striped table-hover w-auto">
<thead class="thead-light">
<tr>
<th>{% trans %}#{% context %}Number{% endtrans %}</th>
<th>{% trans 'Column' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Collation' %}</th>
<th>{% trans 'Null' %}</th>
<th>{% trans 'Default' %}</th>
<th>{% trans 'Extra' %}</th>
<th>{% trans 'Comment' %}</th>
</tr>
</thead>
<tbody>
{% set index = 1 %}
{% for field in columns %}
<tr class="noclick">
<td>{{ index }}</td>
{% set index = index + 1 %}
<td>
<strong>
{{ field['Field'] }}
{% if field['Key'] == 'PRI' %}
{{ get_image('b_primary', 'Primary'|trans) }}
{% elseif field['Key'] is not empty %}
{{ get_image('bd_primary', 'Index'|trans) }}
{% endif %}
</strong>
</td>
<td>{{ field['Type'] }}</td>
<td>{{ field['Collation'] }}</td>
<td>{{ field['Null'] == 'YES' ? 'Yes'|trans : 'No'|trans }}</td>
<td>
{% if field['Default'] is defined %}
{% set extracted_columnspec = extract_column_spec(field['Type']) %}
{% if extracted_columnspec['type'] == 'bit' %}
{# here, $field['Default'] contains something like b'010' #}
{{ field['Default']|convert_bit_default_value }}
{% else %}
{{ field['Default'] }}
{% endif %}
{% else %}
{% if field['Null'] == 'YES' %}
<em>NULL</em>
{% else %}
<em>{% trans %}None{% context %}None for default{% endtrans %}</em>
{% endif %}
{% endif %}
</td>
<td>{{ field['Extra'] }}</td>
<td>{{ field['Comment'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>

View file

@ -0,0 +1,33 @@
<h3>{% trans 'Indexes' %}</h3>
<table id="tablestructure_indexes" class="table table-light table-striped table-hover">
<thead class="thead-light">
<tr>
<th>{% trans 'Keyname' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Unique' %}</th>
<th>{% trans 'Packed' %}</th>
<th>{% trans 'Column' %}</th>
<th>{% trans 'Cardinality' %}</th>
<th>{% trans 'Collation' %}</th>
<th>{% trans 'Null' %}</th>
<th>{% trans 'Comment' %}</th>
</tr>
</thead>
<tbody>
{% for index in indexes %}
<tr class="noclick">
<td>
<strong>{{ index['Key_name'] }}</strong>
</td>
<td>{{ index['Index_type'] }}</td>
<td>{{ index['Non_unique'] == 0 ? 'Yes'|trans : 'No'|trans }}</td>
<td>{{ index['Packed'] != '' ? 'Yes'|trans : 'No'|trans }}</td>
<td>{{ index['Column_name'] }}</td>
<td>{{ index['Cardinality'] }}</td>
<td>{{ index['Collation'] }}</td>
<td>{{ index['Null'] }}</td>
<td>{{ index['Comment'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>

View file

@ -0,0 +1,158 @@
<ul class="nav nav-pills m-2">
<li class="nav-item">
<a class="nav-link" href="{{ url('/table/search', {'db': db, 'table': table, 'pos': 0}) }}">
{{ get_icon('b_search', 'Table search'|trans, false, false, 'TabsMode') }}
</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="{{ url('/table/zoom-search', {'db': db, 'table': table}) }}">
{{ get_icon('b_select', 'Zoom search'|trans, false, false, 'TabsMode') }}
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url('/table/find-replace', {'db': db, 'table': table}) }}">
{{ get_icon('b_find_replace', 'Find and replace'|trans, false, false, 'TabsMode') }}
</a>
</li>
</ul>
<form method="post" action="{{ url('/table/zoom-search') }}" name="insertForm" id="zoom_search_form" class="ajax lock-page">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="goto" value="{{ goto }}">
<input type="hidden" name="back" value="{{ url('/table/zoom-search') }}">
<fieldset id="fieldset_zoom_search">
<fieldset id="inputSection">
<legend>
{% trans 'Do a "query by example" (wildcard: "%") for two different columns' %}
</legend>
<table class="table table-light table-striped table-hover table-sm w-auto" id="tableFieldsId">
<thead class="thead-light">
<tr>
{% if geom_column_flag %}
<th>{% trans 'Function' %}</th>
{% endif %}
<th>{% trans 'Column' %}</th>
<th>{% trans 'Type' %}</th>
<th>{% trans 'Collation' %}</th>
<th>{% trans 'Operator' %}</th>
<th>{% trans 'Value' %}</th>
</tr>
</thead>
<tbody>
{% set type = [] %}
{% set collation = [] %}
{% set func = [] %}
{% set value = [] %}
{% for i in 0..3 %}
{# After X-Axis and Y-Axis column rows, display additional criteria option #}
{% if i == 2 %}
<tr>
<th>
{% trans 'Additional search criteria' %}
</th>
</tr>
{% endif %}
<tr class="noclick">
<th>
<select name="criteriaColumnNames[]" id="tableid_{{ i }}">
<option value="pma_null">
{% trans 'None' %}
</option>
{% for j in 0..column_names|length - 1 %}
{% if criteria_column_names[i] is defined and criteria_column_names[i] == column_names[j] %}
<option value="{{ column_names[j] }}" selected>
{{ column_names[j] }}
</option>
{% else %}
<option value="{{ column_names[j] }}">
{{ column_names[j] }}
</option>
{% endif %}
{% endfor %}
</select>
</th>
{% if criteria_column_names[i] is defined and criteria_column_names[i] != 'pma_null' %}
{% set key = keys[criteria_column_names[i]] %}
{% set properties = self.getColumnProperties(i, key) %}
{% set type = type|merge({(i): properties['type']}) %}
{% set collation = collation|merge({(i): properties['collation']}) %}
{% set func = func|merge({(i): properties['func']}) %}
{% set value = value|merge({(i): properties['value']}) %}
{% endif %}
{# Column type #}
<td dir="ltr">
{{ type[i] is defined ? type[i] }}
</td>
{# Column Collation #}
<td>
{{ collation[i] is defined ? collation[i] }}
</td>
{# Select options for column operators #}
<td>
{{ func[i] is defined ? func[i]|raw }}
</td>
{# Inputbox for search criteria value #}
<td>
{{ value[i] is defined ? value[i]|raw }}
</td>
<td>
{# Displays hidden fields #}
<input type="hidden" name="criteriaColumnTypes[{{ i }}]" id="types_{{ i }}"
{%- if criteria_column_types[i] is defined %} value="{{ criteria_column_types[i] }}"{% endif %}>
<input type="hidden" name="criteriaColumnCollations[{{ i }}]" id="collations_{{ i }}">
</td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table table-borderless table-sm w-auto">
<tr>
<td>
<label for="dataLabel">
{% trans 'Use this column to label each point' %}
</label>
</td>
<td>
<select name="dataLabel" id="dataLabel">
<option value="">
{% trans 'None' %}
</option>
{% for i in 0..column_names|length - 1 %}
{% if data_label is defined and data_label == column_names[i]|e %}
<option value="{{ column_names[i] }}" selected>
{{ column_names[i] }}
</option>
{% else %}
<option value="{{ column_names[i] }}">
{{ column_names[i] }}
</option>
{% endif %}
{% endfor %}
</select>
</td>
</tr>
<tr>
<td>
<label for="maxRowPlotLimit">
{% trans 'Maximum rows to plot' %}
</label>
</td>
<td>
<input type="number" name="maxPlotLimit" id="maxRowPlotLimit" required="required" value="{{ max_plot_limit }}">
</td>
</tr>
</table>
</fieldset>
</fieldset>
<fieldset class="tblFooters">
<input class="btn btn-primary" type="submit" name="zoom_submit" id="inputFormSubmitId" value="{% trans 'Go' %}">
</fieldset>
</form>
<div id="sqlqueryresultsouter"></div>

View file

@ -0,0 +1,83 @@
<form method="post" action="{{ url('/table/zoom-search') }}" name="displayResultForm" id="zoom_display_form" class="ajax">
{{ get_hidden_inputs(db, table) }}
<input type="hidden" name="goto" value="{{ goto }}">
<input type="hidden" name="back" value="{{ url('/table/zoom-search') }}">
<fieldset id="displaySection">
<legend>{% trans 'Browse/Edit the points' %}</legend>
{# JSON encode the data(query result) #}
<div class="text-center">
{% if zoom_submit and data is not empty %}
<div id="resizer">
<a class="text-center" id="help_dialog" href="#">
{% trans 'How to use' %}
</a>
<div id="querydata" class="hide">
{{ data_json }}
</div>
<div id="querychart"></div>
<button class="btn btn-primary button-reset">
{% trans 'Reset zoom' %}
</button>
</div>
{% endif %}
</div>
{# Displays rows in point edit form #}
<div id="dataDisplay" class="hide">
<table class="pma-table">
<thead>
<tr>
<th>{% trans 'Column' %}</th>
<th>{% trans 'Null' %}</th>
<th>{% trans 'Value' %}</th>
</tr>
</thead>
<tbody>
{% for column_index in 0..column_names|length - 1 %}
{% set field_popup = column_names[column_index] %}
{% set foreign_data = get_foreign_data(
foreigners,
field_popup,
false,
'',
''
) %}
<tr class="noclick">
<th>{{ column_names[column_index] }}</th>
{# Null checkbox if column can be null #}
<th>
{% if column_null_flags[column_index] == 'YES' %}
<input type="checkbox" class="checkbox_null"
name="criteriaColumnNullFlags[{{ column_index }}]"
id="edit_fields_null_id_{{ column_index }}">
{% endif %}
</th>
{# Column's Input box #}
<th>
{% include 'table/search/input_box.twig' with {
'str': '',
'column_type': column_types[column_index],
'column_id': column_types[column_index] ? 'edit_fieldID_' : 'fieldID_',
'in_zoom_search_edit': true,
'foreigners': foreigners,
'column_name': field_popup,
'column_name_hash': column_name_hashes[field_popup],
'foreign_data': foreign_data,
'table': table,
'column_index': column_index,
'foreign_max_limit': foreign_max_limit,
'criteria_values': '',
'db': db,
'in_fbs': false
} only %}
</th>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<input type="hidden" id="queryID" name="sql_query">
</fieldset>
</form>