display_structure.twig 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. {% extends 'table/page_with_secondary_tabs.twig' %}
  2. {% block content %}
  3. <form method="post" action="tbl_structure.php" name="fieldsForm" id="fieldsForm"
  4. class="ajax{{ hide_structure_actions ? ' HideStructureActions' }}">
  5. {{ get_hidden_inputs(db, table) }}
  6. <input type="hidden" name="table_type" value=
  7. {%- if db_is_system_schema -%}
  8. "information_schema"
  9. {%- elseif tbl_is_view -%}
  10. "view"
  11. {%- else -%}
  12. "table"
  13. {%- endif %}>
  14. <div class="responsivetable">
  15. <table id="tablestructure" class="data topmargin">
  16. {# Table header #}
  17. <thead>
  18. <tr>
  19. <th class="print_ignore"></th>
  20. <th>#</th>
  21. <th>{% trans 'Name' %}</th>
  22. <th>{% trans 'Type' %}</th>
  23. <th>{% trans 'Collation' %}</th>
  24. <th>{% trans 'Attributes' %}</th>
  25. <th>{% trans 'Null' %}</th>
  26. <th>{% trans 'Default' %}</th>
  27. {% if show_column_comments -%}
  28. <th>{% trans 'Comments' %}</th>
  29. {%- endif %}
  30. <th>{% trans 'Extra' %}</th>
  31. {# @see table/structure.js, function moreOptsMenuResize() #}
  32. {% if not db_is_system_schema and not tbl_is_view %}
  33. <th colspan="{{ show_icons('ActionLinksMode') ? '8' : '9' -}}
  34. " class="action print_ignore">{% trans 'Action' %}</th>
  35. {% endif %}
  36. </tr>
  37. </thead>
  38. <tbody>
  39. {# Table body #}
  40. {% set rownum = 0 %}
  41. {% for row in fields %}
  42. {% set rownum = rownum + 1 %}
  43. {% set extracted_columnspec = extracted_columnspecs[rownum] %}
  44. {% set field_name = row['Field']|e %}
  45. {# For column comments #}
  46. {% set comments = row_comments[rownum] %}
  47. {# Underline commented fields and display a hover-title (CSS only) #}
  48. <tr>
  49. <td class="center print_ignore">
  50. <input type="checkbox" class="checkall" name="selected_fld[]" value="{{ row['Field'] }}" id="checkbox_row_{{ rownum }}">
  51. </td>
  52. <td class="right">{{ rownum }}</td>
  53. <th class="nowrap">
  54. <label for="checkbox_row_{{ rownum }}">
  55. {% if displayed_fields[rownum].comment is defined %}
  56. <span class="commented_column" title="{{ displayed_fields[rownum].comment }}">{{ displayed_fields[rownum].text }}</span>
  57. {% else %}
  58. {{ displayed_fields[rownum].text }}
  59. {% endif %}
  60. {{ displayed_fields[rownum].icon|raw }}
  61. </label>
  62. </th>
  63. <td{{ 'set' != extracted_columnspec['type'] and 'enum' != extracted_columnspec['type'] ? ' class="nowrap"' }}>
  64. <bdo dir="ltr" lang="en">
  65. {{ extracted_columnspec['displayed_type']|raw }}
  66. {% if relation_commwork and relation_mimework and browse_mime
  67. and mime_map[row['Field']]['mimetype'] is defined %}
  68. <br>{% trans 'Media (MIME) type:' %} {{ mime_map[row['Field']]['mimetype']|replace({'_': '/'})|lower }}
  69. {% endif %}
  70. </bdo>
  71. </td>
  72. <td>
  73. {% if row['Collation'] is not empty %}
  74. <dfn title="{{ collations[row['Collation']].description }}">{{ collations[row['Collation']].name }}</dfn>
  75. {% endif %}
  76. </td>
  77. <td class="column_attribute nowrap">{{ attributes[rownum] }}</td>
  78. <td>{{ row['Null'] == 'YES' ? 'Yes'|trans : 'No'|trans }}</td>
  79. <td class="nowrap">
  80. {% if row['Default'] is not null %}
  81. {% if extracted_columnspec['type'] == 'bit' %}
  82. {{ row['Default']|convert_bit_default_value }}
  83. {% else %}
  84. {{ row['Default'] }}
  85. {% endif %}
  86. {% elseif row['Null'] == 'YES' %}
  87. <em>NULL</em>
  88. {% else %}
  89. <em>{% trans %}None{% context %}None for default{% endtrans %}</em>
  90. {% endif %}
  91. </td>
  92. {% if show_column_comments %}
  93. <td>
  94. {{ comments }}
  95. </td>
  96. {% endif %}
  97. <td class="nowrap">{{ row['Extra']|upper }}</td>
  98. {% if not tbl_is_view and not db_is_system_schema %}
  99. <td class="edit center print_ignore">
  100. <a class="change_column_anchor ajax" href="tbl_structure.php
  101. {{- url_query }}&amp;field={{ row['Field']|url_encode }}&amp;change_column=1">
  102. {{ titles['Change']|raw }}
  103. </a>
  104. </td>
  105. <td class="drop center print_ignore">
  106. <a class="drop_column_anchor ajax" href="sql.php" data-post="{{ url_query }}&amp;sql_query=
  107. {{- ('ALTER TABLE ' ~ backquote(table)
  108. ~ ' DROP ' ~ backquote(row['Field']) ~ ';')|url_encode -}}
  109. &amp;dropped_column={{ row['Field']|url_encode }}&amp;purge=1&amp;message_to_show=
  110. {{- ('Column %s has been dropped.'|trans|format(row['Field']|e))|url_encode }}">
  111. {{ titles['Drop']|raw }}
  112. </a>
  113. </td>
  114. {% endif %}
  115. {% if not tbl_is_view and not db_is_system_schema %}
  116. {% set type = extracted_columnspec['print_type'] is not empty ? extracted_columnspec['print_type'] %}
  117. <td class="print_ignore">
  118. <ul class="table-structure-actions resizable-menu">
  119. {% if hide_structure_actions %}
  120. <li class="submenu shown">
  121. <a href="#" class="tab nowrap">{{ get_icon('b_more', 'More'|trans) }}</a>
  122. <ul>
  123. {% endif %}
  124. {# Add primary #}
  125. {% include 'table/structure/action_row_in_structure_table.twig' with {
  126. 'type': type,
  127. 'tbl_storage_engine': tbl_storage_engine,
  128. 'class': 'primary nowrap',
  129. 'has_field': primary and primary.hasColumn(field_name),
  130. 'has_link_class': true,
  131. 'url_query': url_query,
  132. 'primary': primary,
  133. 'syntax': 'ADD PRIMARY KEY',
  134. 'message': 'A primary key has been added on %s.'|trans,
  135. 'action': 'Primary',
  136. 'titles': titles,
  137. 'row': row,
  138. 'is_primary': true,
  139. 'table': table
  140. } only %}
  141. {# Add unique #}
  142. {% include 'table/structure/action_row_in_structure_table.twig' with {
  143. 'type': type,
  144. 'tbl_storage_engine': tbl_storage_engine,
  145. 'class': 'add_unique unique nowrap',
  146. 'has_field': field_name in columns_with_unique_index,
  147. 'has_link_class': false,
  148. 'url_query': url_query,
  149. 'primary': primary,
  150. 'syntax': 'ADD UNIQUE',
  151. 'message': 'An index has been added on %s.'|trans,
  152. 'action': 'Unique',
  153. 'titles': titles,
  154. 'row': row,
  155. 'is_primary': false,
  156. 'table': table
  157. } only %}
  158. {# Add index #}
  159. {% include 'table/structure/action_row_in_structure_table.twig' with {
  160. 'type': type,
  161. 'tbl_storage_engine': tbl_storage_engine,
  162. 'class': 'add_index nowrap',
  163. 'has_field': false,
  164. 'has_link_class': false,
  165. 'url_query': url_query,
  166. 'primary': primary,
  167. 'syntax': 'ADD INDEX',
  168. 'message': 'An index has been added on %s.'|trans,
  169. 'action': 'Index',
  170. 'titles': titles,
  171. 'row': row,
  172. 'is_primary': false,
  173. 'table': table
  174. } only %}
  175. {# Add spatial #}
  176. {% set spatial_types = [
  177. 'geometry',
  178. 'point',
  179. 'linestring',
  180. 'polygon',
  181. 'multipoint',
  182. 'multilinestring',
  183. 'multipolygon',
  184. 'geomtrycollection'
  185. ] %}
  186. {% include 'table/structure/action_row_in_structure_table.twig' with {
  187. 'type': type,
  188. 'tbl_storage_engine': tbl_storage_engine,
  189. 'class': 'spatial nowrap',
  190. 'has_field': type not in spatial_types and
  191. (tbl_storage_engine == 'MYISAM' or mysql_int_version >= 50705),
  192. 'has_link_class': false,
  193. 'url_query': url_query,
  194. 'primary': primary,
  195. 'syntax': 'ADD SPATIAL',
  196. 'message': 'An index has been added on %s.'|trans,
  197. 'action': 'Spatial',
  198. 'titles': titles,
  199. 'row': row,
  200. 'is_primary': false,
  201. 'table': table
  202. } only %}
  203. {# FULLTEXT is possible on TEXT, CHAR and VARCHAR #}
  204. <li class="fulltext nowrap">
  205. {% if tbl_storage_engine is not empty and (
  206. tbl_storage_engine == 'MYISAM'
  207. or tbl_storage_engine == 'ARIA'
  208. or tbl_storage_engine == 'MARIA'
  209. or (tbl_storage_engine == 'INNODB' and mysql_int_version >= 50604)
  210. ) and ('text' in type or 'char' in type) %}
  211. <a rel="samepage" class="ajax add_key add_fulltext_anchor" href="tbl_structure.php"
  212. data-post="{{- url_query|raw }}&amp;add_key=1&amp;sql_query=
  213. {{- ('ALTER TABLE ' ~ backquote(table)
  214. ~ ' ADD FULLTEXT(' ~ backquote(row['Field'])
  215. ~ ');')|url_encode }}&amp;message_to_show=
  216. {{- ('An index has been added on %s.'|trans|format(row['Field']|e))|url_encode }}">
  217. {{ titles['IdxFulltext']|raw }}
  218. </a>
  219. {% else %}
  220. {{ titles['NoIdxFulltext']|raw }}
  221. {% endif %}
  222. </li>
  223. {# Distinct value action #}
  224. <li class="browse nowrap">
  225. <a href="sql.php" data-post="{{ url_query|raw }}&amp;sql_query=
  226. {{- ('SELECT COUNT(*) AS ' ~ backquote('Rows'|trans)
  227. ~ ', ' ~ backquote(row['Field'])
  228. ~ ' FROM ' ~ backquote(table)
  229. ~ ' GROUP BY ' ~ backquote(row['Field'])
  230. ~ ' ORDER BY ' ~ backquote(row['Field']))|url_encode -}}
  231. &amp;is_browse_distinct=1">
  232. {{ titles['DistinctValues']|raw }}
  233. </a>
  234. </li>
  235. {% if central_columns_work %}
  236. <li class="browse nowrap">
  237. {% if row['Field'] in central_list %}
  238. <a href="#" class="central_columns remove_button">
  239. {{ get_icon('centralColumns_delete', 'Remove from central columns'|trans) }}
  240. </a>
  241. {% else %}
  242. <a href="#" class="central_columns add_button">
  243. {{ get_icon('centralColumns_add', 'Add to central columns'|trans) }}
  244. </a>
  245. {% endif %}
  246. </li>
  247. {% endif %}
  248. {% if hide_structure_actions %}
  249. </ul>
  250. </li>
  251. {% endif %}
  252. </ul>
  253. </td>
  254. {% endif %}
  255. </tr>
  256. {% endfor %}
  257. </tbody>
  258. </table>
  259. </div>
  260. <div class="print_ignore">
  261. {% include 'select_all.twig' with {
  262. 'pma_theme_image': pma_theme_image,
  263. 'text_dir': text_dir,
  264. 'form_name': 'fieldsForm'
  265. } only %}
  266. {{ get_button_or_image(
  267. 'submit_mult',
  268. 'mult_submit',
  269. 'Browse'|trans,
  270. 'b_browse',
  271. 'browse'
  272. ) }}
  273. {% if not tbl_is_view and not db_is_system_schema %}
  274. {{ get_button_or_image(
  275. 'submit_mult',
  276. 'mult_submit change_columns_anchor ajax',
  277. 'Change'|trans,
  278. 'b_edit',
  279. 'change'
  280. ) }}
  281. {{ get_button_or_image(
  282. 'submit_mult',
  283. 'mult_submit',
  284. 'Drop'|trans,
  285. 'b_drop',
  286. 'drop'
  287. ) }}
  288. {% if tbl_storage_engine != 'ARCHIVE' %}
  289. {{ get_button_or_image(
  290. 'submit_mult',
  291. 'mult_submit',
  292. 'Primary'|trans,
  293. 'b_primary',
  294. 'primary'
  295. ) }}
  296. {{ get_button_or_image(
  297. 'submit_mult',
  298. 'mult_submit',
  299. 'Unique'|trans,
  300. 'b_unique',
  301. 'unique'
  302. ) }}
  303. {{ get_button_or_image(
  304. 'submit_mult',
  305. 'mult_submit',
  306. 'Index'|trans,
  307. 'b_index',
  308. 'index'
  309. ) }}
  310. {{ get_button_or_image(
  311. 'submit_mult',
  312. 'mult_submit',
  313. 'Fulltext'|trans,
  314. 'b_ftext',
  315. 'ftext'
  316. ) }}
  317. {% if tbl_storage_engine is not empty and (
  318. tbl_storage_engine == 'MYISAM'
  319. or tbl_storage_engine == 'ARIA'
  320. or tbl_storage_engine == 'MARIA') %}
  321. {{ get_button_or_image(
  322. 'submit_mult',
  323. 'mult_submit',
  324. 'Fulltext'|trans,
  325. 'b_ftext',
  326. 'ftext'
  327. ) }}
  328. {% endif %}
  329. {% if central_columns_work %}
  330. {{ get_button_or_image(
  331. 'submit_mult',
  332. 'mult_submit',
  333. 'Add to central columns'|trans,
  334. 'centralColumns_add',
  335. 'add_to_central_columns'
  336. ) }}
  337. {{ get_button_or_image(
  338. 'submit_mult',
  339. 'mult_submit',
  340. 'Remove from central columns'|trans,
  341. 'centralColumns_delete',
  342. 'remove_from_central_columns'
  343. ) }}
  344. {% endif %}
  345. {% endif %}
  346. {% endif %}
  347. </div>
  348. </form>
  349. <hr class="print_ignore">
  350. <div id="move_columns_dialog" class="hide" title="{% trans 'Move columns' %}">
  351. <p>{% trans 'Move the columns by dragging them up and down.' %}</p>
  352. <form action="tbl_structure.php" name="move_column_form" id="move_column_form">
  353. <div>
  354. {{ get_hidden_inputs(db, table) }}
  355. <ul></ul>
  356. </div>
  357. </form>
  358. </div>
  359. {# Work on the table #}
  360. <div id="structure-action-links">
  361. {% if tbl_is_view and not db_is_system_schema %}
  362. {% set edit_view_url = 'view_create.php' ~ edit_view_url %}
  363. {{ link_or_button(
  364. edit_view_url,
  365. get_icon('b_edit', 'Edit view'|trans, true)
  366. ) }}
  367. {% endif %}
  368. <a href="#" id="printView">{{ get_icon('b_print', 'Print'|trans, true) }}</a>
  369. {% if not tbl_is_view and not db_is_system_schema %}
  370. {# Only display propose table structure for MySQL < 8.0 #}
  371. {% if mysql_int_version < 80000 or is_mariadb %}
  372. <a href="sql.php" data-post="{{ url_query|raw }}&amp;session_max_rows=all&amp;sql_query=
  373. {{- ('SELECT * FROM ' ~ backquote(table) ~ ' PROCEDURE ANALYSE()')|url_encode -}}
  374. " style="margin-right: 0;">
  375. {{ get_icon(
  376. 'b_tblanalyse',
  377. 'Propose table structure'|trans,
  378. true
  379. ) }}
  380. </a>
  381. {{ show_mysql_docu('procedure_analyse') }}
  382. {% endif %}
  383. {% if is_active %}
  384. <a href="tbl_tracking.php{{ url_query|raw }}">
  385. {{ get_icon('eye', 'Track table'|trans, true) }}
  386. </a>
  387. {% endif %}
  388. <a href="#" id="move_columns_anchor">
  389. {{ get_icon('b_move', 'Move columns'|trans, true) }}
  390. </a>
  391. <a href="normalization.php{{ url_query|raw }}">
  392. {{ get_icon('normalize', 'Normalize'|trans, true) }}
  393. </a>
  394. {% endif %}
  395. {% if tbl_is_view and not db_is_system_schema %}
  396. {% if is_active %}
  397. <a href="tbl_tracking.php{{ url_query|raw }}">
  398. {{ get_icon('eye', 'Track view'|trans, true) }}
  399. </a>
  400. {% endif %}
  401. {% endif %}
  402. </div>
  403. {% if not tbl_is_view and not db_is_system_schema %}
  404. <form method="post" action="tbl_addfield.php" id="addColumns" name="addColumns">
  405. {{ get_hidden_inputs(db, table) }}
  406. {% if show_icons('ActionLinksMode') %}
  407. {{ get_image('b_insrow', 'Add column'|trans) }}&nbsp;
  408. {% endif %}
  409. {% set num_fields -%}
  410. <input type="number" name="num_fields" value="1" onfocus="this.select()" min="1" required>
  411. {%- endset %}
  412. {{ 'Add %s column(s)'|trans|format(num_fields)|raw }}
  413. <input type="hidden" name="field_where" value="after">&nbsp;
  414. {# I tried displaying the drop-down inside the label but with Firefox the drop-down was blinking #}
  415. <select name="after_field">
  416. <option value="first" data-pos="first">
  417. {% trans 'at beginning of table' %}
  418. </option>
  419. {% for one_column_name in columns_list %}
  420. <option value="{{ one_column_name }}"
  421. {{- loop.revindex0 == 0 ? ' selected="selected"' }}>
  422. {{ 'after %s'|trans|format(one_column_name) }}
  423. </option>
  424. {% endfor %}
  425. </select>
  426. <input class="btn btn-primary" type="submit" value="{% trans 'Go' %}">
  427. </form>
  428. {% endif %}
  429. {# Displays indexes #}
  430. {% if not tbl_is_view and not db_is_system_schema
  431. and 'ARCHIVE' != tbl_storage_engine %}
  432. {{ displayIndexesHtml|raw }}
  433. {% endif %}
  434. {# Display partition details #}
  435. {% if have_partitioning %}
  436. {# Detect partitioning #}
  437. {% if partition_names is not empty and partition_names[0] is not null %}
  438. {% set first_partition = partitions[0] %}
  439. {% set range_or_list = first_partition.getMethod() == 'RANGE'
  440. or first_partition.getMethod() == 'RANGE COLUMNS'
  441. or first_partition.getMethod() == 'LIST'
  442. or first_partition.getMethod() == 'LIST COLUMNS' %}
  443. {% set sub_partitions = first_partition.getSubPartitions() %}
  444. {% set has_sub_partitions = first_partition.hasSubPartitions() %}
  445. {% if has_sub_partitions %}
  446. {% set first_sub_partition = sub_partitions[0] %}
  447. {% endif %}
  448. {% set action_icons = {
  449. 'ANALYZE': get_icon('b_search', 'Analyze'|trans),
  450. 'CHECK': get_icon('eye', 'Check'|trans),
  451. 'OPTIMIZE': get_icon('normalize', 'Optimize'|trans),
  452. 'REBUILD': get_icon('s_tbl', 'Rebuild'|trans),
  453. 'REPAIR': get_icon('b_tblops', 'Repair'|trans),
  454. 'TRUNCATE': get_icon('b_empty', 'Truncate'|trans),
  455. } %}
  456. {% if range_or_list %}
  457. {% set action_icons = action_icons|merge({'DROP': get_icon('b_drop', 'Drop'|trans)}) %}
  458. {% endif %}
  459. {# open Slider Effect div #}
  460. {% include 'div_for_slider_effect.twig' with {
  461. 'id': 'partitions-2',
  462. 'message': 'Partitions'|trans,
  463. 'initial_sliders_state': default_sliders_state
  464. } only %}
  465. {% set remove_sql = 'ALTER TABLE ' ~ backquote(table) ~ ' REMOVE PARTITIONING' %}
  466. {% set remove_url = 'sql.php' ~ url_query ~ '&sql_query=' ~ remove_sql|url_encode %}
  467. {% include 'table/structure/display_partitions.twig' with {
  468. 'db': db,
  469. 'table': table,
  470. 'url_query': url_query,
  471. 'partitions': partitions,
  472. 'partition_method': first_partition.getMethod(),
  473. 'partition_expression': first_partition.getExpression(),
  474. 'has_description': first_partition.getDescription() is not empty,
  475. 'has_sub_partitions': has_sub_partitions,
  476. 'sub_partition_method': has_sub_partitions ? first_sub_partition.getMethod(),
  477. 'sub_partition_expression': has_sub_partitions ? first_sub_partition.getExpression(),
  478. 'action_icons': action_icons,
  479. 'range_or_list': range_or_list,
  480. 'remove_url': remove_url
  481. } only %}
  482. {% else %}
  483. {% include 'table/structure/display_partitions.twig' with {
  484. 'db': db,
  485. 'table': table
  486. } only %}
  487. {% endif %}
  488. {# For closing Slider effect div #}
  489. </div>
  490. {% endif %}
  491. {# Displays Space usage and row statistics #}
  492. {% if show_stats %}
  493. {{ table_stats|raw }}
  494. {% endif %}
  495. <div class="clearfloat"></div>
  496. {% endblock %}