DBQbe.class.php 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Handles DB QBE search
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. * Class to handle database QBE search
  13. *
  14. * @package PhpMyAdmin
  15. */
  16. class PMA_DbQbe
  17. {
  18. /**
  19. * Database name
  20. *
  21. * @access private
  22. * @var string
  23. */
  24. private $_db;
  25. /**
  26. * Table Names (selected/non-selected)
  27. *
  28. * @access private
  29. * @var array
  30. */
  31. private $_criteriaTables;
  32. /**
  33. * Column Names
  34. *
  35. * @access private
  36. * @var array
  37. */
  38. private $_columnNames;
  39. /**
  40. * Number of columns
  41. *
  42. * @access private
  43. * @var integer
  44. */
  45. private $_criteria_column_count;
  46. /**
  47. * Number of Rows
  48. *
  49. * @access private
  50. * @var integer
  51. */
  52. private $_criteria_row_count;
  53. /**
  54. * Whether to insert a new column
  55. *
  56. * @access private
  57. * @var array
  58. */
  59. private $_criteriaColumnInsert;
  60. /**
  61. * Whether to delete a column
  62. *
  63. * @access private
  64. * @var array
  65. */
  66. private $_criteriaColumnDelete;
  67. /**
  68. * Whether to insert a new row
  69. *
  70. * @access private
  71. * @var array
  72. */
  73. private $_criteriaRowInsert;
  74. /**
  75. * Already set criteria values
  76. *
  77. * @access private
  78. * @var array
  79. */
  80. private $_criteria;
  81. /**
  82. * Previously set criteria values
  83. *
  84. * @access private
  85. * @var array
  86. */
  87. private $_prev_criteria;
  88. /**
  89. * AND/OR relation b/w criteria columns
  90. *
  91. * @access private
  92. * @var array
  93. */
  94. private $_criteriaAndOrColumn;
  95. /**
  96. * AND/OR relation b/w criteria rows
  97. *
  98. * @access private
  99. * @var array
  100. */
  101. private $_criteriaAndOrRow;
  102. /**
  103. * Larget width of a column
  104. *
  105. * @access private
  106. * @var string
  107. */
  108. private $_realwidth;
  109. /**
  110. * Minimum width of a column
  111. *
  112. * @access private
  113. * @var string
  114. */
  115. private $_form_column_width;
  116. /**
  117. * Current criteria field
  118. *
  119. * @access private
  120. * @var array
  121. */
  122. private $_curField;
  123. /**
  124. * Current criteria Sort options
  125. *
  126. * @access private
  127. * @var array
  128. */
  129. private $_curSort;
  130. /**
  131. * Current criteria Show options
  132. *
  133. * @access private
  134. * @var array
  135. */
  136. private $_curShow;
  137. /**
  138. * Current criteria values
  139. *
  140. * @access private
  141. * @var array
  142. */
  143. private $_curCriteria;
  144. /**
  145. * Current criteria AND/OR column realtions
  146. *
  147. * @access private
  148. * @var array
  149. */
  150. private $_curAndOrCol;
  151. /**
  152. * New column count in case of add/delete
  153. *
  154. * @access private
  155. * @var integer
  156. */
  157. private $_new_column_count;
  158. /**
  159. * New row count in case of add/delete
  160. *
  161. * @access private
  162. * @var integer
  163. */
  164. private $_new_row_count;
  165. /**
  166. * Public Constructor
  167. *
  168. * @param string $db Database name
  169. */
  170. public function __construct($db)
  171. {
  172. $this->_db = $db;
  173. // Sets criteria parameters
  174. $this->_setSearchParams();
  175. $this->_setCriteriaTablesAndColumns();
  176. }
  177. /**
  178. * Sets search parameters
  179. *
  180. * @return void
  181. */
  182. private function _setSearchParams()
  183. {
  184. // sets column count
  185. $criteriaColumnCount = PMA_ifSetOr(
  186. $_REQUEST['criteriaColumnCount'],
  187. 3,
  188. 'numeric'
  189. );
  190. $criteriaColumnAdd = PMA_ifSetOr(
  191. $_REQUEST['criteriaColumnAdd'],
  192. 0,
  193. 'numeric'
  194. );
  195. $this->_criteria_column_count = max(
  196. $criteriaColumnCount + $criteriaColumnAdd,
  197. 0
  198. );
  199. // sets row count
  200. $rows = PMA_ifSetOr($_REQUEST['rows'], 0, 'numeric');
  201. $criteriaRowAdd = PMA_ifSetOr($_REQUEST['criteriaRowAdd'], 0, 'numeric');
  202. $this->_criteria_row_count = min(
  203. max($rows + $criteriaRowAdd, 0),
  204. 100
  205. );
  206. $this->_criteriaColumnInsert = PMA_ifSetOr(
  207. $_REQUEST['criteriaColumnInsert'],
  208. null,
  209. 'array'
  210. );
  211. $this->_criteriaColumnDelete = PMA_ifSetOr(
  212. $_REQUEST['criteriaColumnDelete'],
  213. null,
  214. 'array'
  215. );
  216. $this->_prev_criteria = isset($_REQUEST['prev_criteria'])
  217. ? $_REQUEST['prev_criteria']
  218. : array();
  219. $this->_criteria = isset($_REQUEST['criteria'])
  220. ? $_REQUEST['criteria']
  221. : array_fill(0, $criteriaColumnCount, '');
  222. $this->_criteriaRowInsert = isset($_REQUEST['criteriaRowInsert'])
  223. ? $_REQUEST['criteriaRowInsert']
  224. : array_fill(0, $criteriaColumnCount, '');
  225. $this->_criteriaRowDelete = isset($_REQUEST['criteriaRowDelete'])
  226. ? $_REQUEST['criteriaRowDelete']
  227. : array_fill(0, $criteriaColumnCount, '');
  228. $this->_criteriaAndOrRow = isset($_REQUEST['criteriaAndOrRow'])
  229. ? $_REQUEST['criteriaAndOrRow']
  230. : array_fill(0, $criteriaColumnCount, '');
  231. $this->_criteriaAndOrColumn = isset($_REQUEST['criteriaAndOrColumn'])
  232. ? $_REQUEST['criteriaAndOrColumn']
  233. : array_fill(0, $criteriaColumnCount, '');
  234. // sets minimum width
  235. $this->_form_column_width = 12;
  236. $this->_curField = array();
  237. $this->_curSort = array();
  238. $this->_curShow = array();
  239. $this->_curCriteria = array();
  240. $this->_curAndOrRow = array();
  241. $this->_curAndOrCol = array();
  242. }
  243. /**
  244. * Sets criteria tables and columns
  245. *
  246. * @return void
  247. */
  248. private function _setCriteriaTablesAndColumns()
  249. {
  250. // The tables list sent by a previously submitted form
  251. if (PMA_isValid($_REQUEST['TableList'], 'array')) {
  252. foreach ($_REQUEST['TableList'] as $each_table) {
  253. $this->_criteriaTables[$each_table] = ' selected="selected"';
  254. }
  255. } // end if
  256. $all_tables = PMA_DBI_query(
  257. 'SHOW TABLES FROM ' . PMA_Util::backquote($this->_db) . ';',
  258. null,
  259. PMA_DBI_QUERY_STORE
  260. );
  261. $all_tables_count = PMA_DBI_num_rows($all_tables);
  262. if (0 == $all_tables_count) {
  263. PMA_Message::error(__('No tables found in database.'))->display();
  264. exit;
  265. }
  266. // The tables list gets from MySQL
  267. while (list($table) = PMA_DBI_fetch_row($all_tables)) {
  268. $columns = PMA_DBI_get_columns($this->_db, $table);
  269. if (empty($this->_criteriaTables[$table])
  270. && ! empty($_REQUEST['TableList'])
  271. ) {
  272. $this->_criteriaTables[$table] = '';
  273. } else {
  274. $this->_criteriaTables[$table] = ' selected="selected"';
  275. } // end if
  276. // The fields list per selected tables
  277. if ($this->_criteriaTables[$table] == ' selected="selected"') {
  278. $each_table = PMA_Util::backquote($table);
  279. $this->_columnNames[] = $each_table . '.*';
  280. foreach ($columns as $each_column) {
  281. $each_column = $each_table . '.'
  282. . PMA_Util::backquote($each_column['Field']);
  283. $this->_columnNames[] = $each_column;
  284. // increase the width if necessary
  285. $this->_form_column_width = max(
  286. strlen($each_column),
  287. $this->_form_column_width
  288. );
  289. } // end foreach
  290. } // end if
  291. } // end while
  292. PMA_DBI_free_result($all_tables);
  293. // sets the largest width found
  294. $this->_realwidth = $this->_form_column_width . 'ex';
  295. }
  296. /**
  297. * Provides select options list containing column names
  298. *
  299. * @param integer $column_number Column Number (0,1,2) or more
  300. * @param string $selected Selected criteria column name
  301. *
  302. * @return HTML for select options
  303. */
  304. private function _showColumnSelectCell($column_number, $selected = '')
  305. {
  306. $html_output = '';
  307. $html_output .= '<td class="center">';
  308. $html_output .= '<select name="criteriaColumn[' . $column_number . ']" size="1">';
  309. $html_output .= '<option value="">&nbsp;</option>';
  310. foreach ($this->_columnNames as $column) {
  311. $html_output .= '<option value="' . htmlspecialchars($column) . '"'
  312. . (($column === $selected) ? ' selected="selected"' : '') . '>'
  313. . str_replace(' ', '&nbsp;', htmlspecialchars($column))
  314. . '</option>';
  315. }
  316. $html_output .= '</select>';
  317. $html_output .= '</td>';
  318. return $html_output;
  319. }
  320. /**
  321. * Provides select options list containing sort options (ASC/DESC)
  322. *
  323. * @param integer $column_number Column Number (0,1,2) or more
  324. * @param string $asc_selected Selected criteria 'Ascending'
  325. * @param string $desc_selected Selected criteria 'Descending'
  326. *
  327. * @return HTML for select options
  328. */
  329. private function _getSortSelectCell($column_number, $asc_selected = '',
  330. $desc_selected = ''
  331. ) {
  332. $html_output = '<td class="center">';
  333. $html_output .= '<select style="width: ' . $this->_realwidth
  334. . '" name="criteriaSort[' . $column_number . ']" size="1">';
  335. $html_output .= '<option value="">&nbsp;</option>';
  336. $html_output .= '<option value="ASC"' . $asc_selected . '>'
  337. . __('Ascending')
  338. . '</option>';
  339. $html_output .= '<option value="DESC"' . $desc_selected . '>'
  340. . __('Descending')
  341. . '</option>';
  342. $html_output .= '</select>';
  343. $html_output .= '</td>';
  344. return $html_output;
  345. }
  346. /**
  347. * Provides search form's row containing column select options
  348. *
  349. * @return HTML for search table's row
  350. */
  351. private function _getColumnNamesRow()
  352. {
  353. $html_output = '<tr class="odd noclick">';
  354. $html_output .= '<th>' . __('Column') . ':</th>';
  355. $new_column_count = 0;
  356. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  357. if (isset($this->_criteriaColumnInsert[$column_index])
  358. && $this->_criteriaColumnInsert[$column_index] == 'on'
  359. ) {
  360. $html_output .= $this->_showColumnSelectCell(
  361. $new_column_count
  362. );
  363. $new_column_count++;
  364. }
  365. if (! empty($this->_criteriaColumnDelete)
  366. && isset($this->_criteriaColumnDelete[$column_index])
  367. && $this->_criteriaColumnDelete[$column_index] == 'on'
  368. ) {
  369. continue;
  370. }
  371. $selected = '';
  372. if (isset($_REQUEST['criteriaColumn'][$column_index])) {
  373. $selected = $_REQUEST['criteriaColumn'][$column_index];
  374. $this->_curField[$new_column_count]
  375. = $_REQUEST['criteriaColumn'][$column_index];
  376. }
  377. $html_output .= $this->_showColumnSelectCell(
  378. $new_column_count,
  379. $selected
  380. );
  381. $new_column_count++;
  382. } // end for
  383. $this->_new_column_count = $new_column_count;
  384. $html_output .= '</tr>';
  385. return $html_output;
  386. }
  387. /**
  388. * Provides search form's row containing sort(ASC/DESC) select options
  389. *
  390. * @return HTML for search table's row
  391. */
  392. private function _getSortRow()
  393. {
  394. $html_output = '<tr class="even noclick">';
  395. $html_output .= '<th>' . __('Sort') . ':</th>';
  396. $new_column_count = 0;
  397. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  398. if (! empty($this->_criteriaColumnInsert)
  399. && isset($this->_criteriaColumnInsert[$column_index])
  400. && $this->_criteriaColumnInsert[$column_index] == 'on'
  401. ) {
  402. $html_output .= $this->_getSortSelectCell($new_column_count);
  403. $new_column_count++;
  404. } // end if
  405. if (! empty($this->_criteriaColumnDelete)
  406. && isset($this->_criteriaColumnDelete[$column_index])
  407. && $this->_criteriaColumnDelete[$column_index] == 'on'
  408. ) {
  409. continue;
  410. }
  411. // If they have chosen all fields using the * selector,
  412. // then sorting is not available, Fix for Bug #570698
  413. if (isset($_REQUEST['criteriaSort'][$column_index])
  414. && isset($_REQUEST['criteriaColumn'][$column_index])
  415. && substr($_REQUEST['criteriaColumn'][$column_index], -2) == '.*'
  416. ) {
  417. $_REQUEST['criteriaSort'][$column_index] = '';
  418. } //end if
  419. // Set asc_selected
  420. if (isset($_REQUEST['criteriaSort'][$column_index])
  421. && $_REQUEST['criteriaSort'][$column_index] == 'ASC'
  422. ) {
  423. $this->_curSort[$new_column_count]
  424. = $_REQUEST['criteriaSort'][$column_index];
  425. $asc_selected = ' selected="selected"';
  426. } else {
  427. $asc_selected = '';
  428. } // end if
  429. // Set desc selected
  430. if (isset($_REQUEST['criteriaSort'][$column_index])
  431. && $_REQUEST['criteriaSort'][$column_index] == 'DESC'
  432. ) {
  433. $this->_curSort[$new_column_count]
  434. = $_REQUEST['criteriaSort'][$column_index];
  435. $desc_selected = ' selected="selected"';
  436. } else {
  437. $desc_selected = '';
  438. } // end if
  439. $html_output .= $this->_getSortSelectCell(
  440. $new_column_count, $asc_selected, $desc_selected
  441. );
  442. $new_column_count++;
  443. } // end for
  444. $html_output .= '</tr>';
  445. return $html_output;
  446. }
  447. /**
  448. * Provides search form's row containing SHOW checkboxes
  449. *
  450. * @return HTML for search table's row
  451. */
  452. private function _getShowRow()
  453. {
  454. $html_output = '<tr class="odd noclick">';
  455. $html_output .= '<th>' . __('Show') . ':</th>';
  456. $new_column_count = 0;
  457. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  458. if (! empty($this->_criteriaColumnInsert)
  459. && isset($this->_criteriaColumnInsert[$column_index])
  460. && $this->_criteriaColumnInsert[$column_index] == 'on'
  461. ) {
  462. $html_output .= '<td class="center">';
  463. $html_output .= '<input type="checkbox"'
  464. . ' name="criteriaShow[' . $new_column_count . ']" />';
  465. $html_output .= '</td>';
  466. $new_column_count++;
  467. } // end if
  468. if (! empty($this->_criteriaColumnDelete)
  469. && isset($this->_criteriaColumnDelete[$column_index])
  470. && $this->_criteriaColumnDelete[$column_index] == 'on'
  471. ) {
  472. continue;
  473. }
  474. if (isset($_REQUEST['criteriaShow'][$column_index])) {
  475. $checked_options = ' checked="checked"';
  476. $this->_curShow[$new_column_count]
  477. = $_REQUEST['criteriaShow'][$column_index];
  478. } else {
  479. $checked_options = '';
  480. }
  481. $html_output .= '<td class="center">';
  482. $html_output .= '<input type="checkbox"'
  483. . ' name="criteriaShow[' . $new_column_count . ']"'
  484. . $checked_options . ' />';
  485. $html_output .= '</td>';
  486. $new_column_count++;
  487. } // end for
  488. $html_output .= '</tr>';
  489. return $html_output;
  490. }
  491. /**
  492. * Provides search form's row containing criteria Inputboxes
  493. *
  494. * @return HTML for search table's row
  495. */
  496. private function _getCriteriaInputboxRow()
  497. {
  498. $html_output = '<tr class="even noclick">';
  499. $html_output .= '<th>' . __('Criteria') . ':</th>';
  500. $new_column_count = 0;
  501. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  502. if (! empty($this->_criteriaColumnInsert)
  503. && isset($this->_criteriaColumnInsert[$column_index])
  504. && $this->_criteriaColumnInsert[$column_index] == 'on'
  505. ) {
  506. $html_output .= '<td class="center">';
  507. $html_output .= '<input type="text"'
  508. . ' name="criteria[' . $new_column_count . ']"'
  509. . ' value=""'
  510. . ' class="textfield"'
  511. . ' style="width: ' . $this->_realwidth . '"'
  512. . ' size="20" />';
  513. $html_output .= '</td>';
  514. $new_column_count++;
  515. } // end if
  516. if (! empty($this->_criteriaColumnDelete)
  517. && isset($this->_criteriaColumnDelete[$column_index])
  518. && $this->_criteriaColumnDelete[$column_index] == 'on'
  519. ) {
  520. continue;
  521. }
  522. if (isset($this->_criteria[$column_index])) {
  523. $tmp_criteria = $this->_criteria[$column_index];
  524. }
  525. if ((empty($this->_prev_criteria)
  526. || ! isset($this->_prev_criteria[$column_index]))
  527. || $this->_prev_criteria[$column_index] != htmlspecialchars($tmp_criteria)
  528. ) {
  529. $this->_curCriteria[$new_column_count] = $tmp_criteria;
  530. } else {
  531. $this->_curCriteria[$new_column_count]
  532. = $this->_prev_criteria[$column_index];
  533. }
  534. $html_output .= '<td class="center">';
  535. $html_output .= '<input type="hidden"'
  536. . ' name="prev_criteria[' . $new_column_count . ']"'
  537. . ' value="' . htmlspecialchars($this->_curCriteria[$new_column_count]) . '" />';
  538. $html_output .= '<input type="text"'
  539. . ' name="criteria[' . $new_column_count . ']"'
  540. . ' value="' . htmlspecialchars($tmp_criteria) . '"'
  541. . ' class="textfield"'
  542. . ' style="width: ' . $this->_realwidth . '"'
  543. . ' size="20" />';
  544. $html_output .= '</td>';
  545. $new_column_count++;
  546. } // end for
  547. $html_output .= '</tr>';
  548. return $html_output;
  549. }
  550. /**
  551. * Provides footer options for adding/deleting row/columns
  552. *
  553. * @param string $type Whether row or column
  554. *
  555. * @return HTML for footer options
  556. */
  557. private function _getFootersOptions($type)
  558. {
  559. $html_output = '<div class="floatleft">';
  560. $html_output .= (($type == 'row')
  561. ? __('Add/Delete criteria rows') : __('Add/Delete columns'));
  562. $html_output .= ':<select size="1" name="'
  563. . (($type == 'row') ? 'criteriaRowAdd' : 'criteriaColumnAdd') . '">';
  564. $html_output .= '<option value="-3">-3</option>';
  565. $html_output .= '<option value="-2">-2</option>';
  566. $html_output .= '<option value="-1">-1</option>';
  567. $html_output .= '<option value="0" selected="selected">0</option>';
  568. $html_output .= '<option value="1">1</option>';
  569. $html_output .= '<option value="2">2</option>';
  570. $html_output .= '<option value="3">3</option>';
  571. $html_output .= '</select>';
  572. $html_output .= '</div>';
  573. return $html_output;
  574. }
  575. /**
  576. * Provides search form table's footer options
  577. *
  578. * @return HTML for table footer
  579. */
  580. private function _getTableFooters()
  581. {
  582. $html_output = '<fieldset class="tblFooters">';
  583. $html_output .= $this->_getFootersOptions("row");
  584. $html_output .= $this->_getFootersOptions("column");
  585. $html_output .= '<div class="floatleft">';
  586. $html_output .= '<input type="submit" name="modify"'
  587. . 'value="' . __('Update Query') . '" />';
  588. $html_output .= '</div>';
  589. $html_output .= '</fieldset>';
  590. return $html_output;
  591. }
  592. /**
  593. * Provides a select list of database tables
  594. *
  595. * @return HTML for table select list
  596. */
  597. private function _getTablesList()
  598. {
  599. $html_output = '<div class="floatleft">';
  600. $html_output .= '<fieldset>';
  601. $html_output .= '<legend>' . __('Use Tables') . '</legend>';
  602. // Build the options list for each table name
  603. $options = '';
  604. $numTableListOptions = 0;
  605. foreach ($this->_criteriaTables as $key => $val) {
  606. $options .= '<option value="' . htmlspecialchars($key) . '"' . $val . '>'
  607. . (str_replace(' ', '&nbsp;', htmlspecialchars($key))) . '</option>';
  608. $numTableListOptions++;
  609. }
  610. $html_output .= '<select name="TableList[]"'
  611. . ' multiple="multiple" id="listTable"'
  612. . ' size="' . (($numTableListOptions > 30) ? '15' : '7') . '">';
  613. $html_output .= $options;
  614. $html_output .= '</select>';
  615. $html_output .= '</fieldset>';
  616. $html_output .= '<fieldset class="tblFooters">';
  617. $html_output .= '<input type="submit" name="modify" value="'
  618. . __('Update Query') . '" />';
  619. $html_output .= '</fieldset>';
  620. $html_output .= '</div>';
  621. return $html_output;
  622. }
  623. /**
  624. * Provides And/Or modification cell along with Insert/Delete options
  625. * (For modifying search form's table columns)
  626. *
  627. * @param integer $column_number Column Number (0,1,2) or more
  628. * @param array $selected Selected criteria column name
  629. *
  630. * @return HTML for modification cell
  631. */
  632. private function _getAndOrColCell($column_number, $selected = null)
  633. {
  634. $html_output = '<td class="center">';
  635. $html_output .= '<strong>' . __('Or') . ':</strong>';
  636. $html_output .= '<input type="radio"'
  637. . ' name="criteriaAndOrColumn[' . $column_number . ']"'
  638. . ' value="or"' . $selected['or'] . ' />';
  639. $html_output .= '&nbsp;&nbsp;<strong>' . __('And') . ':</strong>';
  640. $html_output .= '<input type="radio"'
  641. . ' name="criteriaAndOrColumn[' . $column_number . ']"'
  642. . ' value="and"' . $selected['and'] . ' />';
  643. $html_output .= '<br />' . __('Ins');
  644. $html_output .= '<input type="checkbox"'
  645. . ' name="criteriaColumnInsert[' . $column_number . ']" />';
  646. $html_output .= '&nbsp;&nbsp;' . __('Del');
  647. $html_output .= '<input type="checkbox"'
  648. . ' name="criteriaColumnDelete[' . $column_number . ']" />';
  649. $html_output .= '</td>';
  650. return $html_output;
  651. }
  652. /**
  653. * Provides search form's row containing column modifications options
  654. * (For modifying search form's table columns)
  655. *
  656. * @return HTML for search table's row
  657. */
  658. private function _getModifyColumnsRow()
  659. {
  660. $html_output = '<tr class="even noclick">';
  661. $html_output .= '<th>' . __('Modify') . ':</th>';
  662. $new_column_count = 0;
  663. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  664. if (! empty($this->_criteriaColumnInsert)
  665. && isset($this->_criteriaColumnInsert[$column_index])
  666. && $this->_criteriaColumnInsert[$column_index] == 'on'
  667. ) {
  668. $html_output .= $this->_getAndOrColCell($new_column_count);
  669. $new_column_count++;
  670. } // end if
  671. if (! empty($this->_criteriaColumnDelete)
  672. && isset($this->_criteriaColumnDelete[$column_index])
  673. && $this->_criteriaColumnDelete[$column_index] == 'on'
  674. ) {
  675. continue;
  676. }
  677. if (isset($this->_criteriaAndOrColumn[$column_index])) {
  678. $this->_curAndOrCol[$new_column_count]
  679. = $this->_criteriaAndOrColumn[$column_index];
  680. }
  681. if (isset($this->_criteriaAndOrColumn[$column_index])
  682. && $this->_criteriaAndOrColumn[$column_index] == 'or'
  683. ) {
  684. $checked_options['or'] = ' checked="checked"';
  685. $checked_options['and'] = '';
  686. } else {
  687. $checked_options['and'] = ' checked="checked"';
  688. $checked_options['or'] = '';
  689. }
  690. $html_output .= $this->_getAndOrColCell(
  691. $new_column_count,
  692. $checked_options
  693. );
  694. $new_column_count++;
  695. } // end for
  696. $html_output .= '</tr>';
  697. return $html_output;
  698. }
  699. /**
  700. * Provides Insert/Delete options for criteria inputbox
  701. * with AND/OR relationship modification options
  702. *
  703. * @param integer $row_index Number of criteria row
  704. * @param string $checked_options If checked
  705. *
  706. * @return HTML
  707. */
  708. private function _getInsDelAndOrCell($row_index, $checked_options)
  709. {
  710. $html_output = '<td class="' . $GLOBALS['cell_align_right'] . ' nowrap">';
  711. $html_output .= '<!-- Row controls -->';
  712. $html_output .= '<table class="nospacing nopadding">';
  713. $html_output .= '<tr>';
  714. $html_output .= '<td class="' . $GLOBALS['cell_align_right'] . ' nowrap">';
  715. $html_output .= '<small>' . __('Ins') . ':</small>';
  716. $html_output .= '<input type="checkbox"'
  717. . ' name="criteriaRowInsert[' . $row_index . ']" />';
  718. $html_output .= '</td>';
  719. $html_output .= '<td class="' . $GLOBALS['cell_align_right'] . '">';
  720. $html_output .= '<strong>' . __('And') . ':</strong>';
  721. $html_output .= '</td>';
  722. $html_output .= '<td>';
  723. $html_output .= '<input type="radio"'
  724. . ' name="criteriaAndOrRow[' . $row_index . ']" value="and"'
  725. . $checked_options['and'] . ' />';
  726. $html_output .= '</td>';
  727. $html_output .= '</tr>';
  728. $html_output .= '<tr>';
  729. $html_output .= '<td class="' . $GLOBALS['cell_align_right'] . ' nowrap">';
  730. $html_output .= '<small>' . __('Del') . ':</small>';
  731. $html_output .= '<input type="checkbox"'
  732. . ' name="criteriaRowDelete[' . $row_index . ']" />';
  733. $html_output .= '</td>';
  734. $html_output .= '<td class="' . $GLOBALS['cell_align_right'] . '">';
  735. $html_output .= '<strong>' . __('Or') . ':</strong>';
  736. $html_output .= '</td>';
  737. $html_output .= '<td>';
  738. $html_output .= '<input type="radio"'
  739. . ' name="criteriaAndOrRow[' . $row_index . ']"'
  740. . ' value="or"' . $checked_options['or'] . ' />';
  741. $html_output .= '</td>';
  742. $html_output .= '</tr>';
  743. $html_output .= '</table>';
  744. $html_output .= '</td>';
  745. return $html_output;
  746. }
  747. /**
  748. * Provides rows for criteria inputbox Insert/Delete options
  749. * with AND/OR relationship modification options
  750. *
  751. * @param integer $new_row_index New row index if rows are added/deleted
  752. * @param integer $row_index Row index
  753. *
  754. * @return HTML table rows
  755. */
  756. private function _getInputboxRow($new_row_index, $row_index)
  757. {
  758. $html_output = '';
  759. $new_column_count = 0;
  760. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  761. if (! empty($this->_criteriaColumnInsert)
  762. && isset($this->_criteriaColumnInsert[$column_index])
  763. && $this->_criteriaColumnInsert[$column_index] == 'on'
  764. ) {
  765. $or = 'Or' . $new_row_index . '[' . $new_column_count . ']';
  766. $html_output .= '<td class="center">';
  767. $html_output .= '<input type="text"'
  768. . ' name="Or' . $or . '" class="textfield"'
  769. . ' style="width: ' . $this->_realwidth . '" size="20" />';
  770. $html_output .= '</td>';
  771. $new_column_count++;
  772. } // end if
  773. if (! empty($this->_criteriaColumnDelete)
  774. && isset($this->_criteriaColumnDelete[$column_index])
  775. && $this->_criteriaColumnDelete[$column_index] == 'on'
  776. ) {
  777. continue;
  778. }
  779. $or = 'Or' . $new_row_index;
  780. if (! empty($_POST[$or]) && isset($_POST[$or][$column_index])) {
  781. $tmp_or = $_POST[$or][$column_index];
  782. } else {
  783. $tmp_or = '';
  784. }
  785. $html_output .= '<td class="center">';
  786. $html_output .= '<input type="text"'
  787. . ' name="Or' . $new_row_index . '[' . $new_column_count . ']' . '"'
  788. . ' value="' . htmlspecialchars($tmp_or) . '" class="textfield"'
  789. . ' style="width: ' . $this->_realwidth . '" size="20" />';
  790. $html_output .= '</td>';
  791. if (! empty(${$or}) && isset(${$or}[$column_index])) {
  792. $GLOBALS[${'cur' . $or}][$new_column_count] = ${$or}[$column_index];
  793. }
  794. $new_column_count++;
  795. } // end for
  796. return $html_output;
  797. }
  798. /**
  799. * Provides rows for criteria inputbox Insert/Delete options
  800. * with AND/OR relationship modification options
  801. *
  802. * @return HTML table rows
  803. */
  804. private function _getInsDelAndOrCriteriaRows()
  805. {
  806. $html_output = '';
  807. $new_row_count = 0;
  808. $odd_row = true;
  809. for ($row_index = 0; $row_index <= $this->_criteria_row_count; $row_index++) {
  810. if (isset($this->_criteriaRowInsert[$row_index])
  811. && $this->_criteriaRowInsert[$row_index] == 'on'
  812. ) {
  813. $checked_options['or'] = ' checked="checked"';
  814. $checked_options['and'] = '';
  815. $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . ' noclick">';
  816. $html_output .= $this->_getInsDelAndOrCell(
  817. $new_row_count, $checked_options
  818. );
  819. $html_output .= $this->_getInputboxRow(
  820. $new_row_count, $row_index
  821. );
  822. $new_row_count++;
  823. $html_output .= '</tr>';
  824. $odd_row =! $odd_row;
  825. } // end if
  826. if (isset($this->_criteriaRowDelete[$row_index])
  827. && $this->_criteriaRowDelete[$row_index] == 'on'
  828. ) {
  829. continue;
  830. }
  831. if (isset($this->_criteriaAndOrRow[$row_index])) {
  832. $this->_curAndOrRow[$new_row_count]
  833. = $this->_criteriaAndOrRow[$row_index];
  834. }
  835. if (isset($this->_criteriaAndOrRow[$row_index])
  836. && $this->_criteriaAndOrRow[$row_index] == 'and'
  837. ) {
  838. $checked_options['and'] = ' checked="checked"';
  839. $checked_options['or'] = '';
  840. } else {
  841. $checked_options['or'] = ' checked="checked"';
  842. $checked_options['and'] = '';
  843. }
  844. $html_output .= '<tr class="' . ($odd_row ? 'odd' : 'even') . ' noclick">';
  845. $html_output .= $this->_getInsDelAndOrCell(
  846. $new_row_count, $checked_options
  847. );
  848. $html_output .= $this->_getInputboxRow(
  849. $new_row_count, $row_index
  850. );
  851. $new_row_count++;
  852. $html_output .= '</tr>';
  853. $odd_row =! $odd_row;
  854. } // end for
  855. $this->_new_row_count = $new_row_count;
  856. return $html_output;
  857. }
  858. /**
  859. * Provides SELECT clause for building SQL query
  860. *
  861. * @return Select clause
  862. */
  863. private function _getSelectClause()
  864. {
  865. $select_clause = '';
  866. $select_clauses = array();
  867. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  868. if (! empty($this->_curField[$column_index])
  869. && isset($this->_curShow[$column_index])
  870. && $this->_curShow[$column_index] == 'on'
  871. ) {
  872. $select_clauses[] = $this->_curField[$column_index];
  873. }
  874. } // end for
  875. if ($select_clauses) {
  876. $select_clause = 'SELECT '
  877. . htmlspecialchars(implode(", ", $select_clauses)) . "\n";
  878. }
  879. return $select_clause;
  880. }
  881. /**
  882. * Provides WHERE clause for building SQL query
  883. *
  884. * @return Where clause
  885. */
  886. private function _getWhereClause()
  887. {
  888. $where_clause = '';
  889. $criteria_cnt = 0;
  890. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  891. if (! empty($this->_curField[$column_index])
  892. && ! empty($this->_curCriteria[$column_index])
  893. && $column_index
  894. && isset($last_where)
  895. && isset($this->_curAndOrCol)
  896. ) {
  897. $where_clause .= ' ' . strtoupper($this->_curAndOrCol[$last_where]) . ' ';
  898. }
  899. if (! empty($this->_curField[$column_index])
  900. && ! empty($this->_curCriteria[$column_index])
  901. ) {
  902. $where_clause .= '(' . $this->_curField[$column_index] . ' '
  903. . $this->_curCriteria[$column_index] . ')';
  904. $last_where = $column_index;
  905. $criteria_cnt++;
  906. }
  907. } // end for
  908. if ($criteria_cnt > 1) {
  909. $where_clause = '(' . $where_clause . ')';
  910. }
  911. // OR rows ${'cur' . $or}[$column_index]
  912. if (! isset($this->_curAndOrRow)) {
  913. $this->_curAndOrRow = array();
  914. }
  915. for ($row_index = 0; $row_index <= $this->_criteria_row_count; $row_index++) {
  916. $criteria_cnt = 0;
  917. $qry_orwhere = '';
  918. $last_orwhere = '';
  919. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  920. if (! empty($this->_curField[$column_index])
  921. && ! empty(${'curOr' . $row_index}[$column_index])
  922. && $column_index
  923. ) {
  924. $qry_orwhere .= ' ' . strtoupper($this->_curAndOrCol[$last_orwhere]) . ' ';
  925. }
  926. if (! empty($this->_curField[$column_index])
  927. && ! empty(${'curOr' . $row_index}[$column_index])
  928. ) {
  929. $qry_orwhere .= '(' . $this->_curField[$column_index]
  930. . ' '
  931. . ${'curOr' . $row_index}[$column_index]
  932. . ')';
  933. $last_orwhere = $column_index;
  934. $criteria_cnt++;
  935. }
  936. } // end for
  937. if ($criteria_cnt > 1) {
  938. $qry_orwhere = '(' . $qry_orwhere . ')';
  939. }
  940. if (! empty($qry_orwhere)) {
  941. $where_clause .= "\n"
  942. . strtoupper(
  943. isset($this->_curAndOrRow[$row_index])
  944. ? $this->_curAndOrRow[$row_index] . ' '
  945. : ''
  946. )
  947. . $qry_orwhere;
  948. } // end if
  949. } // end for
  950. if (! empty($where_clause) && $where_clause != '()') {
  951. $where_clause = 'WHERE ' . htmlspecialchars($where_clause) . "\n";
  952. } // end if
  953. return $where_clause;
  954. }
  955. /**
  956. * Provides ORDER BY clause for building SQL query
  957. *
  958. * @return Order By clause
  959. */
  960. private function _getOrderByClause()
  961. {
  962. $orderby_clause = '';
  963. $orderby_clauses = array();
  964. for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
  965. // if all columns are chosen with * selector,
  966. // then sorting isn't available
  967. // Fix for Bug #570698
  968. if (! empty($this->_curField[$column_index])
  969. && ! empty($this->_curSort[$column_index])
  970. ) {
  971. if (substr($this->_curField[$column_index], -2) == '.*') {
  972. continue;
  973. }
  974. $orderby_clauses[] = $this->_curField[$column_index] . ' '
  975. . $this->_curSort[$column_index];
  976. }
  977. } // end for
  978. if ($orderby_clauses) {
  979. $orderby_clause = 'ORDER BY '
  980. . htmlspecialchars(implode(", ", $orderby_clauses)) . "\n";
  981. }
  982. return $orderby_clause;
  983. }
  984. /**
  985. * Provides UNIQUE columns and INDEX columns present in criteria tables
  986. *
  987. * @param array $all_tables Tables involved in the search
  988. * @param array $all_columns Columns involved in the search
  989. * @param array $where_clause_columns Columns having criteria where clause
  990. *
  991. * @return array having UNIQUE and INDEX columns
  992. */
  993. private function _getIndexes($all_tables, $all_columns,
  994. $where_clause_columns
  995. ) {
  996. $unique_columns = array();
  997. $index_columns = array();
  998. foreach ($all_tables as $table) {
  999. $indexes = PMA_DBI_get_table_indexes($this->_db, $table);
  1000. foreach ($indexes as $index) {
  1001. $column = $table . '.' . $index['Column_name'];
  1002. if (isset($all_columns[$column])) {
  1003. if ($index['Non_unique'] == 0) {
  1004. if (isset($where_clause_columns[$column])) {
  1005. $unique_columns[$column] = 'Y';
  1006. } else {
  1007. $unique_columns[$column] = 'N';
  1008. }
  1009. } else {
  1010. if (isset($where_clause_columns[$column])) {
  1011. $index_columns[$column] = 'Y';
  1012. } else {
  1013. $index_columns[$column] = 'N';
  1014. }
  1015. }
  1016. }
  1017. } // end while (each index of a table)
  1018. } // end while (each table)
  1019. return array(
  1020. 'unique' => $unique_columns,
  1021. 'index' => $index_columns
  1022. );
  1023. }
  1024. /**
  1025. * Provides UNIQUE columns and INDEX columns present in criteria tables
  1026. *
  1027. * @param array $all_tables Tables involved in the search
  1028. * @param array $all_columns Columns involved in the search
  1029. * @param array $where_clause_columns Columns having criteria where clause
  1030. *
  1031. * @return array having UNIQUE and INDEX columns
  1032. */
  1033. private function _getLeftJoinColumnCandidates($all_tables, $all_columns,
  1034. $where_clause_columns
  1035. ) {
  1036. PMA_DBI_select_db($this->_db);
  1037. $candidate_columns = array();
  1038. // Get unique columns and index columns
  1039. $indexes = $this->_getIndexes(
  1040. $all_tables, $all_columns, $where_clause_columns
  1041. );
  1042. $unique_columns = $indexes['unique'];
  1043. $index_columns = $indexes['index'];
  1044. // now we want to find the best.
  1045. if (isset($unique_columns) && count($unique_columns) > 0) {
  1046. $candidate_columns = $unique_columns;
  1047. $needsort = 1;
  1048. } elseif (isset($index_columns) && count($index_columns) > 0) {
  1049. $candidate_columns = $index_columns;
  1050. $needsort = 1;
  1051. } elseif (isset($where_clause_columns) && count($where_clause_columns) > 0) {
  1052. $candidate_columns = $where_clause_columns;
  1053. $needsort = 0;
  1054. } else {
  1055. $candidate_columns = $all_tables;
  1056. $needsort = 0;
  1057. }
  1058. // If we came up with $unique_columns (very good) or $index_columns (still
  1059. // good) as $candidate_columns we want to check if we have any 'Y' there
  1060. // (that would mean that they were also found in the whereclauses
  1061. // which would be great). if yes, we take only those
  1062. if ($needsort == 1) {
  1063. foreach ($candidate_columns as $column => $is_where) {
  1064. $table = explode('.', $column);
  1065. $table = $table[0];
  1066. if ($is_where == 'Y') {
  1067. $vg[$column] = $table;
  1068. } else {
  1069. $sg[$column] = $table;
  1070. }
  1071. }
  1072. if (isset($vg)) {
  1073. $candidate_columns = $vg;
  1074. // Candidates restricted in index+where
  1075. } else {
  1076. $candidate_columns = $sg;
  1077. // None of the candidates where in a where-clause
  1078. }
  1079. }
  1080. return $candidate_columns;
  1081. }
  1082. /**
  1083. * Provides the main table to form the LEFT JOIN clause
  1084. *
  1085. * @param array $all_tables Tables involved in the search
  1086. * @param array $all_columns Columns involved in the search
  1087. * @param array $where_clause_columns Columns having criteria where clause
  1088. * @param array $where_clause_tables Tables having criteria where clause
  1089. *
  1090. * @return string table name
  1091. */
  1092. private function _getMasterTable($all_tables, $all_columns,
  1093. $where_clause_columns, $where_clause_tables
  1094. ) {
  1095. $master = '';
  1096. if (count($where_clause_tables) == 1) {
  1097. // If there is exactly one column that has a decent where-clause
  1098. // we will just use this
  1099. $master = key($where_clause_tables);
  1100. } else {
  1101. // Now let's find out which of the tables has an index
  1102. // (When the control user is the same as the normal user
  1103. // because he is using one of his databases as pmadb,
  1104. // the last db selected is not always the one where we need to work)
  1105. $candidate_columns = $this->_getLeftJoinColumnCandidates(
  1106. $all_tables, $all_columns, $where_clause_columns
  1107. );
  1108. // If our array of candidates has more than one member we'll just
  1109. // find the smallest table.
  1110. // Of course the actual query would be faster if we check for
  1111. // the Criteria which gives the smallest result set in its table,
  1112. // but it would take too much time to check this
  1113. if (count($candidate_columns) > 1) {
  1114. // Of course we only want to check each table once
  1115. $checked_tables = $candidate_columns;
  1116. foreach ($candidate_columns as $table) {
  1117. if ($checked_tables[$table] != 1) {
  1118. $tsize[$table] = PMA_Table::countRecords(
  1119. $this->_db,
  1120. $table,
  1121. false
  1122. );
  1123. $checked_tables[$table] = 1;
  1124. }
  1125. $csize[$table] = $tsize[$table];
  1126. }
  1127. asort($csize);
  1128. reset($csize);
  1129. $master = key($csize); // Smallest
  1130. } else {
  1131. reset($candidate_columns);
  1132. $master = current($candidate_columns); // Only one single candidate
  1133. }
  1134. } // end if (exactly one where clause)
  1135. return $master;
  1136. }
  1137. /**
  1138. * Provides columns and tables that have valid where clause criteria
  1139. *
  1140. * @return array
  1141. */
  1142. private function _getWhereClauseTablesAndColumns()
  1143. {
  1144. $where_clause_columns = array();
  1145. $where_clause_tables = array();
  1146. // Now we need all tables that we have in the where clause
  1147. for ($column_index = 0; $column_index < count($this->_criteria); $column_index++) {
  1148. $current_table = explode('.', $_POST['criteriaColumn'][$column_index]);
  1149. if (empty($current_table[0]) || empty($current_table[1])) {
  1150. continue;
  1151. } // end if
  1152. $table = str_replace('`', '', $current_table[0]);
  1153. $column = str_replace('`', '', $current_table[1]);
  1154. $column = $table . '.' . $column;
  1155. // Now we know that our array has the same numbers as $criteria
  1156. // we can check which of our columns has a where clause
  1157. if (! empty($this->_criteria[$column_index])) {
  1158. if (substr($this->_criteria[$column_index], 0, 1) == '='
  1159. || stristr($this->_criteria[$column_index], 'is')
  1160. ) {
  1161. $where_clause_columns[$column] = $column;
  1162. $where_clause_tables[$table] = $table;
  1163. }
  1164. } // end if
  1165. } // end for
  1166. return array(
  1167. 'where_clause_tables' => $where_clause_tables,
  1168. 'where_clause_columns' => $where_clause_columns
  1169. );
  1170. }
  1171. /**
  1172. * Provides FROM clause for building SQL query
  1173. *
  1174. * @param string $cfgRelation Relation Settings
  1175. *
  1176. * @return FROM clause
  1177. */
  1178. private function _getFromClause($cfgRelation)
  1179. {
  1180. $from_clause = '';
  1181. if (isset($_POST['criteriaColumn']) && count($_POST['criteriaColumn']) > 0) {
  1182. // Initialize some variables
  1183. $all_tables = $all_columns = $known_tables = $remaining_tables = array();
  1184. $left_join = '';
  1185. // We only start this if we have fields, otherwise it would be dumb
  1186. foreach ($_POST['criteriaColumn'] as $value) {
  1187. $parts = explode('.', $value);
  1188. if (! empty($parts[0]) && ! empty($parts[1])) {
  1189. $table = str_replace('`', '', $parts[0]);
  1190. $all_tables[$table] = $table;
  1191. $all_columns[] = $table . '.' . str_replace('`', '', $parts[1]);
  1192. }
  1193. } // end while
  1194. // Create LEFT JOINS out of Relations
  1195. if ($cfgRelation['relwork'] && count($all_tables) > 0) {
  1196. // Get tables and columns with valid where clauses
  1197. $valid_where_clauses = $this->_getWhereClauseTablesAndColumns();
  1198. $where_clause_tables = $valid_where_clauses['where_clause_tables'];
  1199. $where_clause_columns = $valid_where_clauses['where_clause_columns'];
  1200. // Get master table
  1201. $master = $this->_getMasterTable(
  1202. $all_tables, $all_columns,
  1203. $where_clause_columns, $where_clause_tables
  1204. );
  1205. $from_clause = PMA_Util::backquote($master)
  1206. . PMA_getRelatives($all_tables, $master);
  1207. } // end if ($cfgRelation['relwork'] && count($all_tables) > 0)
  1208. } // end count($_POST['criteriaColumn']) > 0
  1209. // In case relations are not defined, just generate the FROM clause
  1210. // from the list of tables, however we don't generate any JOIN
  1211. if (empty($from_clause) && isset($all_tables)) {
  1212. $from_clause = implode(', ', $all_tables);
  1213. }
  1214. return $from_clause;
  1215. }
  1216. /**
  1217. * Provides the generated SQL query
  1218. *
  1219. * @param string $cfgRelation Relation Settings
  1220. *
  1221. * @return string SQL query
  1222. */
  1223. private function _getSQLQuery($cfgRelation)
  1224. {
  1225. $sql_query = '';
  1226. // get SELECT clause
  1227. $sql_query .= $this->_getSelectClause();
  1228. // get FROM clause
  1229. $from_clause = $this->_getFromClause($cfgRelation);
  1230. if (! empty($from_clause)) {
  1231. $sql_query .= 'FROM ' . htmlspecialchars($from_clause) . "\n";
  1232. }
  1233. // get WHERE clause
  1234. $sql_query .= $this->_getWhereClause();
  1235. // get ORDER BY clause
  1236. $sql_query .= $this->_getOrderByClause();
  1237. return $sql_query;
  1238. }
  1239. /**
  1240. * Provides the generated QBE form
  1241. *
  1242. * @param string $cfgRelation Relation Settings
  1243. *
  1244. * @return string QBE form
  1245. */
  1246. public function getSelectionForm($cfgRelation)
  1247. {
  1248. $html_output = '<form action="db_qbe.php" method="post">';
  1249. $html_output .= '<fieldset>';
  1250. $html_output .= '<table class="data" style="width: 100%;">';
  1251. // Get table's <tr> elements
  1252. $html_output .= $this->_getColumnNamesRow();
  1253. $html_output .= $this->_getSortRow();
  1254. $html_output .= $this->_getShowRow();
  1255. $html_output .= $this->_getCriteriaInputboxRow();
  1256. $html_output .= $this->_getInsDelAndOrCriteriaRows();
  1257. $html_output .= $this->_getModifyColumnsRow();
  1258. $html_output .= '</table>';
  1259. $this->_new_row_count--;
  1260. $url_params['db'] = $this->_db;
  1261. $url_params['criteriaColumnCount'] = $this->_new_column_count;
  1262. $url_params['rows'] = $this->_new_row_count;
  1263. $html_output .= PMA_generate_common_hidden_inputs($url_params);
  1264. $html_output .= '</fieldset>';
  1265. // get footers
  1266. $html_output .= $this->_getTableFooters();
  1267. // get tables select list
  1268. $html_output .= $this->_getTablesList();
  1269. $html_output .= '</form>';
  1270. $html_output .= '<form action="db_qbe.php" method="post">';
  1271. $html_output .= PMA_generate_common_hidden_inputs(array('db' => $this->_db));
  1272. // get SQL query
  1273. $html_output .= '<div class="floatleft">';
  1274. $html_output .= '<fieldset>';
  1275. $html_output .= '<legend>'
  1276. . sprintf(
  1277. __('SQL query on database <b>%s</b>:'),
  1278. PMA_Util::getDbLink($this->_db)
  1279. );
  1280. $html_output .= '</legend>';
  1281. $text_dir = 'ltr';
  1282. $html_output .= '<textarea cols="80" name="sql_query" id="textSqlquery"'
  1283. . ' rows="' . ((count($this->_criteriaTables) > 30) ? '15' : '7') . '"'
  1284. . ' dir="' . $text_dir . '">';
  1285. $html_output .= $this->_getSQLQuery($cfgRelation);
  1286. $html_output .= '</textarea>';
  1287. $html_output .= '</fieldset>';
  1288. // displays form's footers
  1289. $html_output .= '<fieldset class="tblFooters">';
  1290. $html_output .= '<input type="hidden" name="submit_sql" value="1" />';
  1291. $html_output .= '<input type="submit" value="' . __('Submit Query') . '" />';
  1292. $html_output .= '</fieldset>';
  1293. $html_output .= '</div>';
  1294. $html_output .= '</form>';
  1295. return $html_output;
  1296. }
  1297. }
  1298. ?>