1<?php
2
3	/**
4	 * List indexes on a table
5	 *
6	 * $Id: indexes.php,v 1.46 2008/01/08 22:50:29 xzilla Exp $
7	 */
8
9	// Include application functions
10	include_once('./libraries/lib.inc.php');
11	include_once('./classes/class.select.php');
12
13	$action = (isset($_REQUEST['action'])) ? $_REQUEST['action'] : '';
14
15	/**
16	 * Show confirmation of cluster index and perform actual cluster
17	 */
18	function doClusterIndex($confirm) {
19		global $data, $misc, $action;
20		global $lang;
21
22		if ($confirm) {
23			// Default analyze to on
24			$_REQUEST['analyze'] = true;
25
26			$misc->printTrail('index');
27			$misc->printTitle($lang['strclusterindex'],'pg.index.cluster');
28
29			echo "<p>", sprintf($lang['strconfcluster'], $misc->printVal($_REQUEST['index'])), "</p>\n";
30
31			echo "<form action=\"indexes.php\" method=\"post\">\n";
32			echo "<p><input type=\"checkbox\" id=\"analyze\" name=\"analyze\"", (isset($_REQUEST['analyze']) ? ' checked="checked"' : ''), " /><label for=\"analyze\">{$lang['stranalyze']}</label></p>\n";
33			echo "<input type=\"hidden\" name=\"action\" value=\"cluster_index\" />\n";
34			echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
35			echo "<input type=\"hidden\" name=\"index\" value=\"", htmlspecialchars($_REQUEST['index']), "\" />\n";
36			echo $misc->form;
37			echo "<input type=\"submit\" name=\"cluster\" value=\"{$lang['strclusterindex']}\" />\n";
38			echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
39			echo "</form>\n";
40		}
41		else {
42			$status = $data->clusterIndex($_POST['table'], $_POST['index']);
43			if ($status == 0)
44				if (isset($_POST['analyze'])){
45					$status = $data->analyzeDB($_POST['table']);
46					if ($status == 0)
47						doDefault($lang['strclusteredgood'] . ' ' . $lang['stranalyzegood']);
48					else
49						doDefault($lang['stranalyzebad']);
50				} else
51					doDefault($lang['strclusteredgood']);
52			else
53				doDefault($lang['strclusteredbad']);
54		}
55
56	}
57
58	function doReindex() {
59		global $data, $lang;
60
61		$status = $data->reindex('INDEX', $_REQUEST['index']);
62		if ($status == 0)
63			doDefault($lang['strreindexgood']);
64		else
65			doDefault($lang['strreindexbad']);
66	}
67
68	/**
69	 * Displays a screen where they can enter a new index
70	 */
71	function doCreateIndex($msg = '') {
72		global $data, $misc;
73		global $lang;
74
75		if (!isset($_POST['formIndexName'])) $_POST['formIndexName'] = '';
76		if (!isset($_POST['formIndexType'])) $_POST['formIndexType'] = null;
77		if (!isset($_POST['formCols'])) $_POST['formCols'] = '';
78		if (!isset($_POST['formWhere'])) $_POST['formWhere'] = '';
79		if (!isset($_POST['formSpc'])) $_POST['formSpc'] = '';
80
81		$attrs = $data->getTableAttributes($_REQUEST['table']);
82		// Fetch all tablespaces from the database
83		if ($data->hasTablespaces()) $tablespaces = $data->getTablespaces();
84
85		$misc->printTrail('table');
86		$misc->printTitle($lang['strcreateindex'],'pg.index.create');
87		$misc->printMsg($msg);
88
89		$selColumns = new XHTML_select("TableColumnList",true,10);
90		$selColumns->set_style("width: 10em;");
91
92		if ($attrs->recordCount() > 0) {
93			while (!$attrs->EOF) {
94                $XHTML_Option = new XHTML_Option($attrs->fields['attname']);
95                $selColumns->add($XHTML_Option);
96				$attrs->moveNext();
97			}
98		}
99
100		$selIndex = new XHTML_select("IndexColumnList[]", true, 10);
101		$selIndex->set_style("width: 10em;");
102		$selIndex->set_attribute("id", "IndexColumnList");
103		$buttonAdd    = new XHTML_Button("add", ">>");
104		$buttonAdd->set_attribute("onclick", "buttonPressed(this);");
105		$buttonAdd->set_attribute("type", "button");
106
107		$buttonRemove = new XHTML_Button("remove", "<<");
108		$buttonRemove->set_attribute("onclick", "buttonPressed(this);");
109		$buttonRemove->set_attribute("type", "button");
110
111		echo "<form onsubmit=\"doSelectAll();\" name=\"formIndex\" action=\"indexes.php\" method=\"post\">\n";
112
113
114		echo "<table>\n";
115		echo "<tr><th class=\"data required\" colspan=\"3\">{$lang['strindexname']}</th></tr>";
116		echo "<tr>";
117		echo "<td class=\"data1\" colspan=\"3\"><input type=\"text\" name=\"formIndexName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
118			htmlspecialchars($_POST['formIndexName']), "\" /></td></tr>";
119		echo "<tr><th class=\"data\">{$lang['strtablecolumnlist']}</th><th class=\"data\">&nbsp;</th>";
120		echo "<th class=\"data required\">{$lang['strindexcolumnlist']}</th></tr>\n";
121		echo "<tr><td class=\"data1\">" . $selColumns->fetch() . "</td>\n";
122		echo "<td class=\"data1\">" . $buttonRemove->fetch() . $buttonAdd->fetch() . "</td>";
123		echo "<td class=\"data1\">" . $selIndex->fetch() . "</td></tr>\n";
124		echo "</table>\n";
125
126		echo "<table> \n";
127		echo "<tr>";
128		echo "<th class=\"data left required\" scope=\"row\">{$lang['strindextype']}</th>";
129		echo "<td class=\"data1\"><select name=\"formIndexType\">";
130		foreach ($data->typIndexes as $v) {
131			echo "<option value=\"", htmlspecialchars($v), "\"",
132				($v == $_POST['formIndexType']) ? ' selected="selected"' : '', ">", htmlspecialchars($v), "</option>\n";
133		}
134		echo "</select></td></tr>\n";
135		echo "<tr>";
136		echo "<th class=\"data left\" scope=\"row\"><label for=\"formUnique\">{$lang['strunique']}</label></th>";
137		echo "<td class=\"data1\"><input type=\"checkbox\" id=\"formUnique\" name=\"formUnique\"", (isset($_POST['formUnique']) ? 'checked="checked"' : ''), " /></td>";
138		echo "</tr>";
139		echo "<tr>";
140		echo "<th class=\"data left\" scope=\"row\">{$lang['strwhere']}</th>";
141		echo "<td class=\"data1\">(<input name=\"formWhere\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
142			htmlspecialchars($_POST['formWhere']), "\" />)</td>";
143		echo "</tr>";
144
145		// Tablespace (if there are any)
146		if ($data->hasTablespaces() && $tablespaces->recordCount() > 0) {
147			echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strtablespace']}</th>\n";
148			echo "\t\t<td class=\"data1\">\n\t\t\t<select name=\"formSpc\">\n";
149			// Always offer the default (empty) option
150			echo "\t\t\t\t<option value=\"\"",
151				($_POST['formSpc'] == '') ? ' selected="selected"' : '', "></option>\n";
152			// Display all other tablespaces
153			while (!$tablespaces->EOF) {
154				$spcname = htmlspecialchars($tablespaces->fields['spcname']);
155				echo "\t\t\t\t<option value=\"{$spcname}\"",
156					($spcname == $_POST['formSpc']) ? ' selected="selected"' : '', ">{$spcname}</option>\n";
157				$tablespaces->moveNext();
158			}
159			echo "\t\t\t</select>\n\t\t</td>\n\t</tr>\n";
160		}
161
162		if ($data->hasConcurrentIndexBuild()) {
163			echo "<tr>";
164			echo "<th class=\"data left\" scope=\"row\"><label for=\"formConcur\">{$lang['strconcurrently']}</label></th>";
165			echo "<td class=\"data1\"><input type=\"checkbox\" id=\"formConcur\" name=\"formConcur\"", (isset($_POST['formConcur']) ? 'checked="checked"' : ''), " /></td>";
166			echo "</tr>";
167		}
168
169		echo "</table>";
170
171		echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create_index\" />\n";
172		echo $misc->form;
173		echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
174		echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
175		echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
176		echo "</form>\n";
177	}
178
179	/**
180	 * Actually creates the new index in the database
181	 * @@ Note: this function can't handle columns with commas in them
182	 */
183	function doSaveCreateIndex() {
184		global $data;
185		global $lang;
186
187		// Handle databases that don't have partial indexes
188		if (!isset($_POST['formWhere'])) $_POST['formWhere'] = '';
189		// Default tablespace to null if it isn't set
190		if (!isset($_POST['formSpc'])) $_POST['formSpc'] = null;
191
192		// Check that they've given a name and at least one column
193		if ($_POST['formIndexName'] == '') doCreateIndex($lang['strindexneedsname']);
194		elseif (!isset($_POST['IndexColumnList']) || $_POST['IndexColumnList'] == '') doCreateIndex($lang['strindexneedscols']);
195		else {
196			$status = $data->createIndex($_POST['formIndexName'], $_POST['table'], $_POST['IndexColumnList'],
197				$_POST['formIndexType'], isset($_POST['formUnique']), $_POST['formWhere'], $_POST['formSpc'],
198				isset($_POST['formConcur']));
199			if ($status == 0)
200				doDefault($lang['strindexcreated']);
201			else
202				doCreateIndex($lang['strindexcreatedbad']);
203		}
204	}
205
206	/**
207	 * Show confirmation of drop index and perform actual drop
208	 */
209	function doDropIndex($confirm) {
210		global $data, $misc;
211		global $lang;
212
213		if ($confirm) {
214			$misc->printTrail('index');
215			$misc->printTitle($lang['strdrop'],'pg.index.drop');
216
217			echo "<p>", sprintf($lang['strconfdropindex'], $misc->printVal($_REQUEST['index'])), "</p>\n";
218
219			echo "<form action=\"indexes.php\" method=\"post\">\n";
220			echo "<input type=\"hidden\" name=\"action\" value=\"drop_index\" />\n";
221			echo "<input type=\"hidden\" name=\"table\" value=\"", htmlspecialchars($_REQUEST['table']), "\" />\n";
222			echo "<input type=\"hidden\" name=\"index\" value=\"", htmlspecialchars($_REQUEST['index']), "\" />\n";
223			echo $misc->form;
224			echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
225			echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
226			echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
227			echo "</form>\n";
228		}
229		else {
230			$status = $data->dropIndex($_POST['index'], isset($_POST['cascade']));
231			if ($status == 0)
232				doDefault($lang['strindexdropped']);
233			else
234				doDefault($lang['strindexdroppedbad']);
235		}
236
237	}
238
239	function doDefault($msg = '') {
240		global $data, $misc;
241		global $lang;
242
243		function indPre(&$rowdata, $actions) {
244			global $data, $lang;
245
246			if ($data->phpBool($rowdata->fields['indisprimary'])) {
247				$rowdata->fields['+constraints'] = $lang['strprimarykey'];
248				$actions['drop']['disable'] = true;
249			}
250			elseif ($data->phpBool($rowdata->fields['indisunique'])) {
251				$rowdata->fields['+constraints'] = $lang['struniquekey'];
252				$actions['drop']['disable'] = true;
253			}
254			else
255				$rowdata->fields['+constraints'] = '';
256
257			return $actions;
258		}
259
260		$misc->printTrail('table');
261		$misc->printTabs('table','indexes');
262		$misc->printMsg($msg);
263
264		$indexes = $data->getIndexes($_REQUEST['table']);
265
266		$columns = array(
267			'index' => array(
268				'title' => $lang['strname'],
269				'field' => field('indname'),
270			),
271			'definition' => array(
272				'title' => $lang['strdefinition'],
273				'field' => field('inddef'),
274			),
275			'constraints' => array(
276				'title' => $lang['strconstraints'],
277				'field' => field('+constraints'),
278				'type'  => 'verbatim',
279				'params'=> array('align' => 'center'),
280			),
281			'clustered' => array(
282				'title' => $lang['strclustered'],
283				'field' => field('indisclustered'),
284				'type'  => 'yesno',
285			),
286			'actions' => array(
287				'title' => $lang['stractions'],
288			),
289			'comment' => array(
290				'title' => $lang['strcomment'],
291				'field' => field('idxcomment'),
292			),
293		);
294
295		$actions = array(
296			'cluster' => array(
297				'content' => $lang['strclusterindex'],
298				'attr'=> array (
299					'href' => array (
300						'url' => 'indexes.php',
301						'urlvars' => array (
302							'action' => 'confirm_cluster_index',
303							'table' => $_REQUEST['table'],
304							'index' => field('indname')
305						)
306					)
307				)
308			),
309			'reindex' => array(
310				'content' => $lang['strreindex'],
311				'attr'=> array (
312					'href' => array (
313						'url' => 'indexes.php',
314						'urlvars' => array (
315							'action' => 'reindex',
316							'table' => $_REQUEST['table'],
317							'index' => field('indname')
318						)
319					)
320				)
321			),
322			'drop' => array(
323				'content' => $lang['strdrop'],
324				'attr'=> array (
325					'href' => array (
326						'url' => 'indexes.php',
327						'urlvars' => array (
328							'action' => 'confirm_drop_index',
329							'table' => $_REQUEST['table'],
330							'index' => field('indname')
331						)
332					)
333				)
334			)
335		);
336
337		$misc->printTable($indexes, $columns, $actions, 'indexes-indexes', $lang['strnoindexes'], 'indPre');
338
339		$misc->printNavLinks(array (
340			'create' => array (
341				'attr'=> array (
342					'href' => array (
343						'url' => 'indexes.php',
344						'urlvars' => array (
345							'action' => 'create_index',
346							'server' => $_REQUEST['server'],
347							'database' => $_REQUEST['database'],
348							'schema' => $_REQUEST['schema'],
349							'table' => $_REQUEST['table']
350						)
351					)
352				),
353				'content' => $lang['strcreateindex']
354			)
355		), 'indexes-indexes', get_defined_vars());
356	}
357
358	function doTree() {
359		global $misc, $data;
360
361		$indexes = $data->getIndexes($_REQUEST['table']);
362
363		$reqvars = $misc->getRequestVars('table');
364
365		function getIcon($f) {
366			if ($f['indisprimary'] == 't')
367				return 'PrimaryKey';
368			if ($f['indisunique'] == 't')
369				return 'UniqueConstraint';
370			return 'Index';
371		}
372
373		$attrs = array(
374			'text'   => field('indname'),
375			'icon'   => callback('getIcon'),
376		);
377
378		$misc->printTree($indexes, $attrs, 'indexes');
379		exit;
380	}
381
382	if ($action == 'tree') doTree();
383
384	$misc->printHeader($lang['strindexes'], "<script src=\"indexes.js\" type=\"text/javascript\"></script>");
385
386	if ($action == 'create_index' || $action == 'save_create_index')
387		echo "<body onload=\"init();\">";
388	else
389		$misc->printBody();
390
391	switch ($action) {
392		case 'cluster_index':
393			if (isset($_POST['cluster'])) doClusterIndex(false);
394			else doDefault();
395			break;
396		case 'confirm_cluster_index':
397			doClusterIndex(true);
398			break;
399		case 'reindex':
400			doReindex();
401			break;
402		case 'save_create_index':
403			if (isset($_POST['cancel'])) doDefault();
404			else doSaveCreateIndex();
405			break;
406		case 'create_index':
407			doCreateIndex();
408			break;
409		case 'drop_index':
410			if (isset($_POST['drop'])) doDropIndex(false);
411			else doDefault();
412			break;
413		case 'confirm_drop_index':
414			doDropIndex(true);
415			break;
416		default:
417			doDefault();
418			break;
419	}
420
421	$misc->printFooter();
422
423?>
424