The branch, master has been updated via 61329e5c87cc7062eff02a71ee08084a8f2b9a12 (commit) via 0ae05939011d842c0b612a61eba97393f9a0ca61 (commit) via ae55e9b8f8ca0d7d3f65b7d9945a726738826ce1 (commit) via 223832b68ddacceab0e29825f28eaa9d38815b1e (commit) via 3829f2280f48f86059c616d118112356bd8be96a (commit) via db6ae660cf04df2922fbc63d22f378651946d721 (commit) via a0504f47d60855bae9a329b366beb53e1cd2abd8 (commit) via 71abc9f8d096e19fcc0d8b64a9475c75a4d1531c (commit) via 6ba8170aab54035346dc4a33b15f9795805588ae (commit) via a5a43128256bee452004d71ecfc60fc116a9ac7f (commit) via 9b77820b7d4dd8c9975143effd5e30044146220f (commit) via a63b2188be23ed2077a7a61d3d7a4cdecb083e24 (commit) via 8410e8e520fd660a0106e0e5f40cd1af8ca74664 (commit) via c2fb87aff5929f2229c60a0ecdd957ac02bdee5e (commit) via 8d5cc0bbbcaa39f455d02e5f7b6aaaee8bced815 (commit) via c0ceb2d75cea340ccc42c12a39a8283960c73136 (commit) via f8c3da7885090d516fdaabfd71d959e40314e6d2 (commit) via 16185ac4f504a4f55fbca3b4dd64adbdbe2d1f7d (commit) via 657cbc8672939eaba5f66c1b177d61821754c6cf (commit) via a8f8d3e7a8ac0f083fd7c2decc1c522c8cc6824b (commit) via 4047020d789217d393c597f726bf76e8a01d765c (commit) via 2cd59139ec5960a5809b56edd17ddeed6ece8660 (commit) via dda7ce9c39c97f814304f9403f8b1619b3c89ba6 (commit) via 58c4ab431f33585e0006b79a38edf9fd0d855071 (commit) via 279ef37298727ace79dc8cce58ef4df98f14bc66 (commit) via 48681dfd81be21eea86d1b8e6deefd530a0028c5 (commit) via cde93fe9496d2573790b3cfcc19699ec104338af (commit) via 31b42160d89b222e8d9ba44a6cfc2848db2048ad (commit) via 1c019d785f90482fc7afb4e97674208eb85a4683 (commit) via 041d5bd9d4beb4e856b51cca7b077788d7cba5eb (commit) via c220bb4e134ed1d371c864c9190d68796fd344cd (commit) via e2834cd49da5df098cc34d3919c2a67c449ee695 (commit) via 889cce858304aca13a0a94ef6e45f5717b79da99 (commit) via ebfa1dd50603f25a52fcbdca6174b8b1fec78845 (commit) via 8db8527337182e7ccec5a4e4c87b1eb3af0641b2 (commit) via 17b8f21ccd8bd9a3927c8004ffdf9146060c91b3 (commit) via d8da233e0cf63883e02f69bcdc17b6a0f00bbd70 (commit) via 2a7848fe9c373faad6b789e2ab669330f6b7d2f5 (commit) via 90af8e9dc5abdb30dc18a5e709ba9f008fb16849 (commit) via d44d191d516405bfbab94e20188cb5b93101a00f (commit) via 2bc9529d69348bc95069fb5e8b1bf01a80126bd8 (commit) via d14df11efb2772592e5f4c8e21db1a3c73d7fdd0 (commit) via d7767b978c86aac6e048f3dc541f29416d448de1 (commit) via 4a455c3e626163b95a20fbfe85494ebcacab0224 (commit) via aa2692c12f1285e62cb69f2269538a5d91866565 (commit) via 9a380a59356a39177f3176904f838a2f21493d79 (commit) via 11e3b20a9e5a7fbe492fd3af9d80350d85558773 (commit) via 2b09c553be186df319592e6a46c74011b156ec56 (commit) via 91a4c157961acc0f34e42c8c37621f52532b5b32 (commit) via e0f4b36c73faa9d9eae1888fbd5fc0d1d623242e (commit) via a07a1d997c1ce547bf0800fee108fba0f053f4f6 (commit) via 463a49a3ec82d814e70542ed8b704b1fe2d35c47 (commit) via 4baa133671fb7c30f134ae10c49a17da5b539847 (commit) via 82847a80b8fec01a5d7c1de3ec62db175d0d98d2 (commit) via 40a7510fa74b6b09ff272ab093ff29b7c13623ce (commit) via 43819596c8b5a72c7be41409fc43a7d13549404b (commit) via 3a6a30d5ba76821975dcf441dc19c02efbe15c96 (commit) via dcf6969534a47d12639852f2a29d35d5a5f89bcf (commit) via a9787c89b98eb00bf328f5b12666bf03edc2430c (commit) via 3f8efed7f102ae885d330151dcdceed46fb737cd (commit) via 6500912511e4704415d031c3b28ab86071848dcb (commit) via 6752d54b84adcbceb86e7d4ca5a30d346f344138 (commit) via 5343e6ee9ee6078770707f7f4cd78b4d571d2b67 (commit) via 3983253371f6567bdbd5967958f897106faf9492 (commit) via 0189a62776fbaed70b2072eaed7d034384dd66ff (commit) via 48532dfad0751e7e6d8e2ed8c20a8a1c45147a6c (commit) via 62f1d89ff6ba0ef91d5c44cce8330225f4799221 (commit) via 870ab261ae9c48e965c18c786209c5989cf8fe02 (commit) via c27b2e776b754b3caaf7bdb30f4c3ee2b281ad6d (commit) via 493e573f52c6c38dd70d40744796a589f3c54b50 (commit) via 6f7b52627b17b2c8ca3365fc4260cb55f8faa9fc (commit) via c830bdd85704cc9097467eed832234e3896cf4e7 (commit) via 8f670c6ae2ac59836d454280b87712d41cbf0cba (commit) via bab400e1d036ea70ec8e1d010a81526a1d7c9d63 (commit) via 35454870e5249cbe527d9ea059986e8b3fcd5f88 (commit) via 7e4c5d5ef75f0736ed3962f20eb4624aee9fffe9 (commit) via 2434f0628c6673e45b7579c1c10e1c9cd3d16ecc (commit) via d5358316998ff5bc0ecea9c8362fe62ed24a91ce (commit) via 008f5db63d7ab94ed5ce4b4e6e84c2fb11ab62a5 (commit) via 9bf9726bf9df2952953d04697f71552aa4305892 (commit) via 7103156e509030d76c314f2ce17d512aa673b804 (commit) via 255d7dcf0019b02554306e80ac550fdca9bd3bbd (commit) via 30d417cfe199aac561e876df323d5b14a4ddce0f (commit) via 9a36c3bd952912a15bc4bee8ca23106328805544 (commit) via e2e58f1446fa6f572733af4c2806c6e37c80f7ed (commit) via 3b150147609027cc39392cc1f2d7a6f484dfa26a (commit) via 0c131ac95e7b4937dd8bc6fbbb13c09c564a3fb6 (commit) via 92d6e2d5c78da2bdcfff8fc06c346efc5a4a1835 (commit) via 5f9fed0b5c3ab373d953e07eab90c6cd276ab0eb (commit) via 80fa502e22a68ee0bc86ae9ea6f71f01e6ff544f (commit) via 15bc50543193b12b1fe9fd7fa3bd5f8129dfcc23 (commit) via a31c41a6699e6f3fe0afa301be89a3d1792b4f4e (commit) via bfb1102da4ce23a520ad457653af8742dba61cb9 (commit) via c6254910b21063e38c5bbae36db13faaca8a4a77 (commit) via 0bd514ee8d56e7c4088baebc007fea7cb5b7665e (commit) via e2250a3f99605fe11be5d572936f2bef075f2ad0 (commit) via 409dcfcde535e6ce6ff25473fbca385e44883a3d (commit) via 9e19d03ed5c881776bd40e30529ddd1f58d9d439 (commit) via 97e6b7aa5686fa57e73e01ed9e92eb00c4851b39 (commit) via 6077cfb9a2d8f090a357c15104216ce16e40bd98 (commit) via c33fc8e7660a296a193f3a88d43e41babe74bf93 (commit) via 42477ca0e92bd54c5b6087273617f46573659d9e (commit) via a126fc22e8684c59d51a6e2a64455eeaf116d567 (commit) via f3158122bbca91eacacf6a156d5c53030894eb19 (commit) via 98d36b41bdd1e0cf14f413422f16abf161ff6596 (commit) via f964639676eb9d99fba4b339fa3d823be709047b (commit) via 77c8f4c624cded54ba2f2d9c4e256e1191485b63 (commit) via 054fd49a043d34deffba4882cb122bc713234ef2 (commit) via 5673db8f7a3eea42a698d7ea0647fa1b899aae31 (commit) via 3ae8cba7dc5ff3ab5c7433e10836428e426d8917 (commit) via 22c9117c061c1822e5e4bea7f68877d28fd768d7 (commit) via 6eb2f3e815febcb18ca4954656e3780ded858c48 (commit) via 36d060b862e87a132b5e1f0df297b8ee720063ff (commit) via 4643171415814b70d08a152072d4d6f6d8ba6063 (commit) via 2f24e5b6b54b89f3c8b5e20a09845858b300f23f (commit) via c5e6c7542d296ff3d0789d09c4211ea8f4a8e953 (commit) via 0b3121e722bcccc79fed750d997e81d17cdf09e2 (commit) via eb78483214184ae7446e730aedc38bfa6405a2c0 (commit) via f20c48fe829467e7f7e3638bc9feeeea8c724fb3 (commit) via 8ee7ac5b08b41d7f9dd3ac7f6b67513eaf2d8e75 (commit) via f0e651698da2eb40cb56fb9b07fb1d829c2ad9bd (commit) via 5cb0b867be0fe09ab3545379589499b5087bedda (commit) via 22da77c86cf2b92c2557d8ac67a74282e9c81e89 (commit) via 2ebaa77320fa143072ee0430005e2be2161f5aa7 (commit) via be504638350ccac7c736da32de48e6be87858698 (commit) via e7e97ee6c5e2bc8cbcac2cd9c8ad09d0a3a5f740 (commit) via 5c75a21a84ed36780d88eab02f7d3c9386904f61 (commit) via 132694ce80dc59add74ee8f6e2afaf4943884edb (commit) via 320c311b92ba33dee80d6e199e805e9af1e9a1c8 (commit) via 42aaf6c5c9cbd8a9a2c0e88446f6cec7f4cf960d (commit) via b1ef4fb11b81648158f4441555a0d9be80119ba6 (commit) via 8469bf8280c4935f4dcd455f522b5348db3d1e67 (commit) via 0659c39435b8373f8ddf21c307e9c531b4054e06 (commit) via 1db0f7b861d1481abeac12215d0f852fea6c9e9a (commit) via fc745f2dac4408800d073c64e0e3c5060846a211 (commit) via 6fd9e7c5aabf46d3cc7cf32b373793136383ba16 (commit) via 409b5ad5ff7c6f0a6a9823cd4d58613fbbbfc661 (commit) via f8f61518c2ccb48b299eb39301a1c7334e5ba4c2 (commit) via a73f6ad72389fbad9b82387959a72aa5216ae934 (commit) via db0d4b84b812df1ee418af90cf1216cfcc35b2f1 (commit) via 0c6cceef136e8ec3de7e2e34f91ac91637811588 (commit) via e80c65a88a6da66ace528a95f7ed7039ac856bfb (commit) via ebce205059a939b04d77f3dbfa2ec59d14693ee3 (commit) via 63693133e2cc01adfe7a2891feadb4d2864a7468 (commit) via d2728442f8807a051da28083f00a5779d1c5f00c (commit) via d3210ef1b67b91a7668c7c55aad909592b558a06 (commit) via 058b6175c12ac3f9335f369ef2161d93d4cf0e6c (commit) via 44301dd2502a409be99dfa34185bcef94d0fbae7 (commit) via aac4d59508b44346d9568d70a51dd3e0ee57f83b (commit) via 65474446738d03120dd153151f8af62bf221e060 (commit) via 6d156b4febec6b9a0890e95ba07a0dc359c8b496 (commit) from 6a5ea0a2199d2a44afad5a58d2e099fa58fdd89e (commit)
- Log ----------------------------------------------------------------- commit 61329e5c87cc7062eff02a71ee08084a8f2b9a12 Merge: 0ae05939011d842c0b612a61eba97393f9a0ca61 6a5ea0a2199d2a44afad5a58d2e099fa58fdd89e Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 20 18:26:50 2011 +0100
Merge branch 'master' into rte
commit 0ae05939011d842c0b612a61eba97393f9a0ca61 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 20 12:50:29 2011 +0100
Fixed incorrect escaping of some query parameters
commit ae55e9b8f8ca0d7d3f65b7d9945a726738826ce1 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 20 11:40:23 2011 +0100
Removed unnecessary AJAX messages from the routines functionalities.
commit 223832b68ddacceab0e29825f28eaa9d38815b1e Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 20 11:33:06 2011 +0100
E_ALL fix in PMA_currentUserHasPrivilege()
commit 3829f2280f48f86059c616d118112356bd8be96a Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 20 11:32:07 2011 +0100
More error handling for routine functionalities
commit db6ae660cf04df2922fbc63d22f378651946d721 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 20 10:44:37 2011 +0100
Removed duplicate function PMA_getSupportedCharsets() that was added by mistake into the routines functionality.
commit a0504f47d60855bae9a329b366beb53e1cd2abd8 Merge: 71abc9f8d096e19fcc0d8b64a9475c75a4d1531c 5f664dc7591d018ab15bb761ef7c44555ab97ca6 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 17:12:36 2011 +0100
Merge branch 'master' into rte
commit 71abc9f8d096e19fcc0d8b64a9475c75a4d1531c Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 17:02:33 2011 +0100
Fixed bug where the information about the return variable of a routine was not correctly loaded into the editor.
commit 6ba8170aab54035346dc4a33b15f9795805588ae Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 15:08:13 2011 +0100
Validation for fields that can be too long in routine ditor.
commit a5a43128256bee452004d71ecfc60fc116a9ac7f Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 14:40:18 2011 +0100
Submit Routines dialogs forms when the enter key is pressed.
commit 9b77820b7d4dd8c9975143effd5e30044146220f Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 14:03:26 2011 +0100
Focus on a relevant input element after opening a dialog (routines functionality).
commit a63b2188be23ed2077a7a61d3d7a4cdecb083e24 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 13:57:15 2011 +0100
When issuing warning about routine execution check for presence of mysql, not the absence of mysqli extentions.
commit 8410e8e520fd660a0106e0e5f40cd1af8ca74664 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 13:56:10 2011 +0100
Fixed casing of messages in routines functionality
commit c2fb87aff5929f2229c60a0ecdd957ac02bdee5e Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 13:44:14 2011 +0100
Expand the routine editor to use all available space.
commit 8d5cc0bbbcaa39f455d02e5f7b6aaaee8bced815 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 13:36:26 2011 +0100
Added an extra sanity check for query creation in routine editor
commit c0ceb2d75cea340ccc42c12a39a8283960c73136 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 13:16:05 2011 +0100
Added more animations to routine functionalities
commit f8c3da7885090d516fdaabfd71d959e40314e6d2 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 17 13:15:34 2011 +0100
Introduced JavaScript function PMA_slidingMessage()
commit 16185ac4f504a4f55fbca3b4dd64adbdbe2d1f7d Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 16 13:11:26 2011 +0100
Fixe whitespaces in db_routines.php
commit 657cbc8672939eaba5f66c1b177d61821754c6cf Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 16 13:10:06 2011 +0100
Fixed incorrect escaping of NULL results in routine execution.
commit a8f8d3e7a8ac0f083fd7c2decc1c522c8cc6824b Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 16 11:44:06 2011 +0100
Animate the insertion of new routines into the list
commit 4047020d789217d393c597f726bf76e8a01d765c Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 15 12:45:50 2011 +0100
Refactored code that generated the dropdown list of MySQL functions.
commit 2cd59139ec5960a5809b56edd17ddeed6ece8660 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 15 11:28:56 2011 +0100
Marged table headers in lists of Routines, Triggers and Events.
commit dda7ce9c39c97f814304f9403f8b1619b3c89ba6 Merge: 58c4ab431f33585e0006b79a38edf9fd0d855071 6c39191b03421d41d92bafc9252b0095862e71ed Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 19:44:09 2011 +0100
Merge branch 'master' into rte
commit 58c4ab431f33585e0006b79a38edf9fd0d855071 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 15:51:25 2011 +0100
Fixed bug where with JS disabled sql.php did not redirect the user back to list of routines after a DROP operation.
commit 279ef37298727ace79dc8cce58ef4df98f14bc66 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 15:45:39 2011 +0100
Warn the user if the definition of a stored function does not contain a return statement.
commit 48681dfd81be21eea86d1b8e6deefd530a0028c5 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 15:32:44 2011 +0100
Hide the parameter "length" for datatypes that do not support this in the routine editor.
commit cde93fe9496d2573790b3cfcc19699ec104338af Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 15:11:32 2011 +0100
Refactored code that generates parameter rows for the Routine Editor.
commit 31b42160d89b222e8d9ba44a6cfc2848db2048ad Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 14:36:06 2011 +0100
Moved all arbitrary code from routines.inc.php and renamed this file to routines.lib.php
commit 1c019d785f90482fc7afb4e97674208eb85a4683 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 14:26:47 2011 +0100
Renamed Routine functions to more meaningful names.
commit 041d5bd9d4beb4e856b51cca7b077788d7cba5eb Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 14:05:37 2011 +0100
Moved PMA_getSupportedCharsets() to common.lib.php
commit c220bb4e134ed1d371c864c9190d68796fd344cd Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 13:56:00 2011 +0100
Moved PMA_getSupportedDatatypes() to common.lib.php
commit e2834cd49da5df098cc34d3919c2a67c449ee695 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 11:54:05 2011 +0100
Generate the type dropdown for Routine editor in PHP, not JavaScript.
commit 889cce858304aca13a0a94ef6e45f5717b79da99 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 14 11:38:35 2011 +0100
Fixed inconsistent escaping of special characters in Routines functionalities.
commit ebfa1dd50603f25a52fcbdca6174b8b1fec78845 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 13 18:10:22 2011 +0100
Fixed "Commands out of sync" error when calling a stored routine from sql.php
commit 8db8527337182e7ccec5a4e4c87b1eb3af0641b2 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 13 15:14:31 2011 +0100
Show the sql_query to the user when dropping Routines, Events and triggers and fix classes in the list.
commit 17b8f21ccd8bd9a3927c8004ffdf9146060c91b3 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 13 10:26:43 2011 +0100
Fixed bug where new routines were not added to the list of routines, if the list was empty.
commit d8da233e0cf63883e02f69bcdc17b6a0f00bbd70 Merge: 2a7848fe9c373faad6b789e2ab669330f6b7d2f5 c3cba1170c4ca1073b301f875c8ad94704e025aa Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 18:46:59 2011 +0100
Merge branch 'master' into rte
commit 2a7848fe9c373faad6b789e2ab669330f6b7d2f5 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 18:44:57 2011 +0100
Moved code to generate a list of routines and a link to add a new routine into functions.
commit 90af8e9dc5abdb30dc18a5e709ba9f008fb16849 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 17:56:20 2011 +0100
Moved some code in db_routines.inc.php to logically separate arbitrary code from functions.
commit d44d191d516405bfbab94e20188cb5b93101a00f Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 17:48:36 2011 +0100
Removed outdated comment.
commit 2bc9529d69348bc95069fb5e8b1bf01a80126bd8 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 17:48:12 2011 +0100
Removed unnecessary global variable.
commit d14df11efb2772592e5f4c8e21db1a3c73d7fdd0 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 16:39:34 2011 +0100
Fixed E_ALL error: undefined index 'ajax_request'.
commit d7767b978c86aac6e048f3dc541f29416d448de1 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 16:26:11 2011 +0100
Updated comments for routines functions.
commit 4a455c3e626163b95a20fbfe85494ebcacab0224 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 16:05:38 2011 +0100
Fixed bug where the "Execute Routine" link was shown to unprivileged users.
commit aa2692c12f1285e62cb69f2269538a5d91866565 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 15:36:44 2011 +0100
Fixed call to undefined function.
commit 9a380a59356a39177f3176904f838a2f21493d79 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 15:31:29 2011 +0100
Fixed bug: return variable for a function was not correctly loaded into the routine editor.
commit 11e3b20a9e5a7fbe492fd3af9d80350d85558773 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 15:26:49 2011 +0100
Some small improvements to the AJAX integration of the Routines Editor
commit 2b09c553be186df319592e6a46c74011b156ec56 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 15:05:52 2011 +0100
HTML fixes for the Routine Editor.
commit 91a4c157961acc0f34e42c8c37621f52532b5b32 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 15:01:46 2011 +0100
AJAX integration for routine execution functionality.
commit e0f4b36c73faa9d9eae1888fbd5fc0d1d623242e Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 10 14:19:20 2011 +0100
Fail safely when a requested routine is not found in the db.
commit a07a1d997c1ce547bf0800fee108fba0f053f4f6 Merge: 463a49a3ec82d814e70542ed8b704b1fe2d35c47 1906a9b1bb848966eeed3053803ec5a2e74d7fdb Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 9 21:26:26 2011 +0100
Merge branch 'master' into rte
commit 463a49a3ec82d814e70542ed8b704b1fe2d35c47 Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 9 21:25:18 2011 +0100
Some small code improvements for db_routines.js
commit 4baa133671fb7c30f134ae10c49a17da5b539847 Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 9 21:23:01 2011 +0100
Comments and coding guidelines fixes for db_routines.js
commit 82847a80b8fec01a5d7c1de3ec62db175d0d98d2 Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 9 21:08:26 2011 +0100
JS integration for parameter options in Routines Editor.
commit 40a7510fa74b6b09ff272ab093ff29b7c13623ce Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 9 21:00:12 2011 +0100
Support for parameter options in Routines Editor.
commit 43819596c8b5a72c7be41409fc43a7d13549404b Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 8 13:01:01 2011 +0100
Fixed bug where the "Drop parameter" option disappeared in the Routine Editor if $cfg['PropertiesIconic'] was set to FALSE.
commit 3a6a30d5ba76821975dcf441dc19c02efbe15c96 Merge: dcf6969534a47d12639852f2a29d35d5a5f89bcf 6bc5a845f49d1f1b0864f37dceaeaa4b52fefdff Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 8 12:07:43 2011 +0100
Merge brach 'master' into 'rte'
commit dcf6969534a47d12639852f2a29d35d5a5f89bcf Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 8 11:29:39 2011 +0100
Use PMA_showMessage() for displaying the queries for creating and altering routines.
commit a9787c89b98eb00bf328f5b12666bf03edc2430c Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 7 19:20:21 2011 +0100
Improved form validation for the Routines Editor.
commit 3f8efed7f102ae885d330151dcdceed46fb737cd Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 7 18:34:58 2011 +0100
Improved functionality for execution of Routines
commit 6500912511e4704415d031c3b28ab86071848dcb Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 7 14:17:17 2011 +0100
Style fixes for Routines, Triggers and Events.
commit 6752d54b84adcbceb86e7d4ca5a30d346f344138 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 7 14:15:41 2011 +0100
Support "MySQL functions" in the Execute Routine functionality.
commit 5343e6ee9ee6078770707f7f4cd78b4d571d2b67 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 7 13:24:43 2011 +0100
Handle input parameters of type SET in routine execution functionality.
commit 3983253371f6567bdbd5967958f897106faf9492 Author: Rouslan Placella rouslan@placella.com Date: Tue Jun 7 10:40:13 2011 +0100
Made title of the Routine Editor dialog dynamic.
commit 0189a62776fbaed70b2072eaed7d034384dd66ff Merge: 48532dfad0751e7e6d8e2ed8c20a8a1c45147a6c 37eb5c0955b8e953527007a2a4818195c86bcada Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 17:18:35 2011 +0100
Merge branch 'master' into rte
commit 48532dfad0751e7e6d8e2ed8c20a8a1c45147a6c Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 16:51:27 2011 +0100
Fixed "Commands out of sync" error when executing stored Routines.
commit 62f1d89ff6ba0ef91d5c44cce8330225f4799221 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 13:57:35 2011 +0100
"SQL data access" on routine creation defaults incorrectly to "READS SQL DATA".
commit 870ab261ae9c48e965c18c786209c5989cf8fe02 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 13:55:56 2011 +0100
Consistent font size for the Export feature of Routines, Triggers and Events.
commit c27b2e776b754b3caaf7bdb30f4c3ee2b281ad6d Merge: 493e573f52c6c38dd70d40744796a589f3c54b50 37f18cc9be747235c6f7d3f48f43f0bd9a234296 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 12:44:15 2011 +0100
Merge branch 'master' into rte
commit 493e573f52c6c38dd70d40744796a589f3c54b50 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 12:40:54 2011 +0100
Integrated the Routine Editor with CodeMirror.
commit 6f7b52627b17b2c8ca3365fc4260cb55f8faa9fc Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 11:10:50 2011 +0100
Attached syntax highlited editor to Routine, Trigger and Event export dialogs.
commit c830bdd85704cc9097467eed832234e3896cf4e7 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 10:52:15 2011 +0100
Moved Routine Editor validation into a function.
commit 8f670c6ae2ac59836d454280b87712d41cbf0cba Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 10:50:40 2011 +0100
Better placement for the submit button in the Routine Editor.
commit bab400e1d036ea70ec8e1d010a81526a1d7c9d63 Author: Rouslan Placella rouslan@placella.com Date: Mon Jun 6 10:25:55 2011 +0100
Made Routine Editor dialog modal.
commit 35454870e5249cbe527d9ea059986e8b3fcd5f88 Merge: 7e4c5d5ef75f0736ed3962f20eb4624aee9fffe9 5d6a5a8adb55455a3bc152089fd5663eee508ce7 Author: Rouslan Placella rouslan@placella.com Date: Sat Jun 4 20:26:11 2011 +0100
Merge branch 'master' into rte
commit 7e4c5d5ef75f0736ed3962f20eb4624aee9fffe9 Author: Rouslan Placella rouslan@placella.com Date: Sat Jun 4 20:22:57 2011 +0100
Add CSS used by Routines, Triggers and Events to 'original' theme.
commit 2434f0628c6673e45b7579c1c10e1c9cd3d16ecc Author: Rouslan Placella rouslan@placella.com Date: Sat Jun 4 20:20:59 2011 +0100
AJAX integration for Routines editor.
commit d5358316998ff5bc0ecea9c8362fe62ed24a91ce Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 3 15:01:26 2011 +0100
Prototype Execute functionality for Routines.
commit 008f5db63d7ab94ed5ce4b4e6e84c2fb11ab62a5 Merge: 9bf9726bf9df2952953d04697f71552aa4305892 7cd81057f585ec97ea0055b5c88fd0c29981c552 Author: Rouslan Placella rouslan@placella.com Date: Fri Jun 3 10:52:12 2011 +0100
Merge branch 'master' into rte
commit 9bf9726bf9df2952953d04697f71552aa4305892 Merge: 7103156e509030d76c314f2ce17d512aa673b804 0cd84b36be4c6c11982649014606eb7a3debfdc3 Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 2 20:10:21 2011 +0100
Merge branch 'master' into rte
commit 7103156e509030d76c314f2ce17d512aa673b804 Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 2 20:09:06 2011 +0100
Moved some code around to ease merging with master.
commit 255d7dcf0019b02554306e80ac550fdca9bd3bbd Merge: 30d417cfe199aac561e876df323d5b14a4ddce0f 2da400447c6993d46b969a1c9c863fd81817f67e Author: Rouslan Placella rouslan@placella.com Date: Thu Jun 2 11:07:24 2011 +0100
Merge remote-tracking branch 'origin/master' into rte
commit 30d417cfe199aac561e876df323d5b14a4ddce0f Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 20:13:52 2011 +0100
A few more PHPDOC comments.
commit 9a36c3bd952912a15bc4bee8ca23106328805544 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 18:27:48 2011 +0100
Got rid of global $param_datatypes from db_routines.inc.php
commit e2e58f1446fa6f572733af4c2806c6e37c80f7ed Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 18:20:09 2011 +0100
Comments, whitespaces, etc...
commit 3b150147609027cc39392cc1f2d7a6f484dfa26a Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 17:32:24 2011 +0100
Removed duplicate function introduced earlier by mistake.
commit 0c131ac95e7b4937dd8bc6fbbb13c09c564a3fb6 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 17:16:16 2011 +0100
Allow users to change the name of a Routine in edit mode.
commit 92d6e2d5c78da2bdcfff8fc06c346efc5a4a1835 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 16:50:35 2011 +0100
Avoid passing the routine type in the HTTP request when exporting a routine.
commit 5f9fed0b5c3ab373d953e07eab90c6cd276ab0eb Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 16:11:06 2011 +0100
Refactored JS used to drop Routines, Triggers and Events.
commit 80fa502e22a68ee0bc86ae9ea6f71f01e6ff544f Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 15:27:50 2011 +0100
Refactored JS used to export Routines, Triggers and Events.
commit 15bc50543193b12b1fe9fd7fa3bd5f8129dfcc23 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 14:49:27 2011 +0100
Escape the database and table names in PMA_currentUserHasPrivilege()
commit a31c41a6699e6f3fe0afa301be89a3d1792b4f4e Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 14:11:12 2011 +0100
Cleaned up the code for displaying the list of routines.
commit bfb1102da4ce23a520ad457653af8742dba61cb9 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 12:49:09 2011 +0100
Disabled access to Routines features if the user does not have the required privileges.
commit c6254910b21063e38c5bbae36db13faaca8a4a77 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 12:15:18 2011 +0100
Intoduced PMA_currentUserHasPrivilege() to easily disable access to some features.
commit 0bd514ee8d56e7c4088baebc007fea7cb5b7665e Merge: e2250a3f99605fe11be5d572936f2bef075f2ad0 0dbc9f4a3c7fa46baed1477f001e37dad14fc908 a4d680782b166565b83a8614a148ff72975185f2 Author: Rouslan Placella rouslan@placella.com Date: Wed Jun 1 12:10:50 2011 +0100
Merge branch 'master', remote-tracking branch 'origin' into rte
commit e2250a3f99605fe11be5d572936f2bef075f2ad0 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 19:47:32 2011 +0100
E_ALL fixes.
commit 409dcfcde535e6ce6ff25473fbca385e44883a3d Merge: 9e19d03ed5c881776bd40e30529ddd1f58d9d439 575f265293ffe0625da6a8fc0877a84d595d5322 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 19:22:38 2011 +0100
Merge remote-tracking branch 'origin/master' into rte
commit 9e19d03ed5c881776bd40e30529ddd1f58d9d439 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 19:21:53 2011 +0100
Fixed jQuery animation when dropping Routines, Triggers and Events.
commit 97e6b7aa5686fa57e73e01ed9e92eb00c4851b39 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 19:14:30 2011 +0100
Improved parser for parameters of routines.
commit 6077cfb9a2d8f090a357c15104216ce16e40bd98 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 15:21:14 2011 +0100
Disabled the "Edit Routine" and "Export Routine" links if the user cannot perform these operations.
commit c33fc8e7660a296a193f3a88d43e41babe74bf93 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 14:29:11 2011 +0100
Moved code for generating the sql query that creates a routine into a function.
commit 42477ca0e92bd54c5b6087273617f46573659d9e Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 14:08:15 2011 +0100
Fixed broken handling of "SQL SECURITY" in routines.
commit a126fc22e8684c59d51a6e2a64455eeaf116d567 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 13:47:21 2011 +0100
Improve the parsing of parameters in routines editor.
commit f3158122bbca91eacacf6a156d5c53030894eb19 Merge: 98d36b41bdd1e0cf14f413422f16abf161ff6596 a47ac24a49d5d925553f8d3c92f6a9722ee8b0ad Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 12:14:02 2011 +0100
Merge branch 'master', remote-tracking branch 'origin' into rte
commit 98d36b41bdd1e0cf14f413422f16abf161ff6596 Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 12:13:22 2011 +0100
Show query on successful creation or edit of routines.
commit f964639676eb9d99fba4b339fa3d823be709047b Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 11:14:15 2011 +0100
Backquote Routine parameters in the generated query.
commit 77c8f4c624cded54ba2f2d9c4e256e1191485b63 Merge: 054fd49a043d34deffba4882cb122bc713234ef2 80701c70cf5ab0d78d05a24060c5c3560a2d8e2d Author: Rouslan Placella rouslan@placella.com Date: Tue May 31 10:58:55 2011 +0100
Merge remote-tracking branch 'origin' into rte
commit 054fd49a043d34deffba4882cb122bc713234ef2 Merge: 5673db8f7a3eea42a698d7ea0647fa1b899aae31 310466c489603511a1a615db8e36f1714e249bcd Author: Rouslan Placella rouslan@placella.com Date: Mon May 30 13:34:18 2011 +0100
Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into rte
commit 5673db8f7a3eea42a698d7ea0647fa1b899aae31 Merge: 3ae8cba7dc5ff3ab5c7433e10836428e426d8917 0b5f4410cd653b2ce132e5f7537e03949cef59f9 Author: Rouslan Placella rouslan@placella.com Date: Fri May 27 17:51:41 2011 +0100
Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into rte
commit 3ae8cba7dc5ff3ab5c7433e10836428e426d8917 Author: Rouslan Placella rouslan@placella.com Date: Fri May 27 17:43:23 2011 +0100
Removed some redundant includes in Routines, Triggers and Events files.
commit 22c9117c061c1822e5e4bea7f68877d28fd768d7 Author: Rouslan Placella rouslan@placella.com Date: Fri May 27 14:59:36 2011 +0100
Load the Export data for Routines asynchronously.
commit 6eb2f3e815febcb18ca4954656e3780ded858c48 Author: Rouslan Placella rouslan@placella.com Date: Fri May 27 12:49:59 2011 +0100
Improved query execution handling by the Routines Editor.
commit 36d060b862e87a132b5e1f0df297b8ee720063ff Author: Rouslan Placella rouslan@placella.com Date: Fri May 27 12:01:12 2011 +0100
Fixed conditional class in "Add a new Routine" link.
commit 4643171415814b70d08a152072d4d6f6d8ba6063 Author: Rouslan Placella rouslan@placella.com Date: Fri May 27 11:36:59 2011 +0100
Improved error handling in Routines editor.
commit 2f24e5b6b54b89f3c8b5e20a09845858b300f23f Merge: c5e6c7542d296ff3d0789d09c4211ea8f4a8e953 434d233e5b710dc6d3ac82b6825cf726aac22cb3 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 20:32:35 2011 +0100
Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into rte
commit c5e6c7542d296ff3d0789d09c4211ea8f4a8e953 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 20:32:22 2011 +0100
Added a few comments in db_routines.inc.php
commit 0b3121e722bcccc79fed750d997e81d17cdf09e2 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 20:31:37 2011 +0100
Fixed incorrect escaping of form fields in the Routines Editor.
commit eb78483214184ae7446e730aedc38bfa6405a2c0 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 20:28:28 2011 +0100
Refactored the Routines editor.
commit f20c48fe829467e7f7e3638bc9feeeea8c724fb3 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 14:48:53 2011 +0100
Fixed handling of function return type in routines dialog.
commit 8ee7ac5b08b41d7f9dd3ac7f6b67513eaf2d8e75 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 14:21:32 2011 +0100
Disable the 'Remove last parameter' button in the routines editor, if there are no parameters to remove.
commit f0e651698da2eb40cb56fb9b07fb1d829c2ad9bd Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 14:17:42 2011 +0100
Don't show any parameters in the dialog when editing a routine, if it doesn't have any.
commit 5cb0b867be0fe09ab3545379589499b5087bedda Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 14:04:24 2011 +0100
Don't handle parameter direction for stored functions, they don't support this.
commit 22da77c86cf2b92c2557d8ac67a74282e9c81e89 Merge: 2ebaa77320fa143072ee0430005e2be2161f5aa7 d012edac93bdd1f2a7b519b6e9ad0534cc45b1b4 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 13:07:47 2011 +0100
Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into rte
commit 2ebaa77320fa143072ee0430005e2be2161f5aa7 Author: Rouslan Placella rouslan@placella.com Date: Thu May 26 13:07:28 2011 +0100
Implemented a parser for routine parameters.
commit be504638350ccac7c736da32de48e6be87858698 Merge: e7e97ee6c5e2bc8cbcac2cd9c8ad09d0a3a5f740 76194fd122690cbe3947bfa25ae5d40de82d1d35 Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 21:16:46 2011 +0100
Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into rte
commit e7e97ee6c5e2bc8cbcac2cd9c8ad09d0a3a5f740 Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 21:15:04 2011 +0100
Hide the Routines, Triggers and Events tabs from Drizzle users.
commit 5c75a21a84ed36780d88eab02f7d3c9386904f61 Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 21:12:29 2011 +0100
Prototype handling of "Edit routine" functionality
commit 132694ce80dc59add74ee8f6e2afaf4943884edb Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 20:59:18 2011 +0100
Added code to handle the "Add a new routine" requests
commit 320c311b92ba33dee80d6e199e805e9af1e9a1c8 Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 20:29:22 2011 +0100
Added handling of 'length/values' for routine parameters in "Add new routine form"
commit 42aaf6c5c9cbd8a9a2c0e88446f6cec7f4cf960d Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 20:11:00 2011 +0100
Better handling for choosing routine type in the "Add new routine form"
commit b1ef4fb11b81648158f4441555a0d9be80119ba6 Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 11:56:06 2011 +0100
Display actual datatypes in the "Add a new Routine" form
commit 8469bf8280c4935f4dcd455f522b5348db3d1e67 Merge: 0659c39435b8373f8ddf21c307e9c531b4054e06 13f09c03cfa37ba3f05fde015826ce4893158293 Author: Rouslan Placella rouslan@placella.com Date: Wed May 25 11:05:58 2011 +0100
Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into rte
commit 0659c39435b8373f8ddf21c307e9c531b4054e06 Merge: 1db0f7b861d1481abeac12215d0f852fea6c9e9a 4e2cd5e998340f2f7262bc890d64e51c85970937 Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 22:33:51 2011 +0100
Merge branch 'master' of git://phpmyadmin.git.sourceforge.net/gitroot/phpmyadmin/phpmyadmin into rte
commit 1db0f7b861d1481abeac12215d0f852fea6c9e9a Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 22:32:23 2011 +0100
Created a prototype of "Add a new Procedure" functionality.
commit fc745f2dac4408800d073c64e0e3c5060846a211 Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 14:52:32 2011 +0100
Fix the "Return type" of Stored Functions not showing up in the Routines list.
commit 6fd9e7c5aabf46d3cc7cf32b373793136383ba16 Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 14:43:09 2011 +0100
Always show the "Add new" link for triggers.
This makes sense when there is nothing to show for a db-wise list of triggers.
commit 409b5ad5ff7c6f0a6a9823cd4d58613fbbbfc661 Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 14:41:08 2011 +0100
No need to use $GLOBALS to access $url_query
commit f8f61518c2ccb48b299eb39301a1c7334e5ba4c2 Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 14:39:33 2011 +0100
Add Export functionality for Roustines, Triggers and Events when JS is disabled.
commit a73f6ad72389fbad9b82387959a72aa5216ae934 Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 14:06:19 2011 +0100
Improve the display of the "Event Scheduler fieldset"
commit db0d4b84b812df1ee418af90cf1216cfcc35b2f1 Merge: 755fc28b49b3012cc80881720f54f5c3781285ea 0c6cceef136e8ec3de7e2e34f91ac91637811588 Author: Rouslan Placella rouslan@placella.com Date: Tue May 24 13:01:02 2011 +0100
Merge branch 'master' of ssh://repo.or.cz/srv/git/phpmyadmin/roccivic into rte
commit 0c6cceef136e8ec3de7e2e34f91ac91637811588 Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 19:33:42 2011 +0100
E_ALL fixes
commit e80c65a88a6da66ace528a95f7ed7039ac856bfb Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 18:48:17 2011 +0100
Show status of the event scheduler and offer option to toggle it
commit ebce205059a939b04d77f3dbfa2ec59d14693ee3 Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 18:10:46 2011 +0100
Updated documentation
commit 63693133e2cc01adfe7a2891feadb4d2864a7468 Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:52:56 2011 +0100
Moved JS related to Routines, Triggers and Events into their own files.
commit d2728442f8807a051da28083f00a5779d1c5f00c Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:50:14 2011 +0100
Recycled old Events functionality and linked it to the new entry in the menu
commit d3210ef1b67b91a7668c7c55aad909592b558a06 Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:49:58 2011 +0100
Recycled old Triggers functionality and linked it to the new entry in the menu
commit 058b6175c12ac3f9335f369ef2161d93d4cf0e6c Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:49:22 2011 +0100
Recycled old Routines functionality and linked it to the new entry in the menu
commit 44301dd2502a409be99dfa34185bcef94d0fbae7 Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:43:19 2011 +0100
Added new tabs for Routines, Triggers and Events
commit aac4d59508b44346d9568d70a51dd3e0ee57f83b Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:41:30 2011 +0100
Support retreiving Triggers on a per-database basis.
commit 65474446738d03120dd153151f8af62bf221e060 Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:39:09 2011 +0100
Removed references to Routines, Triggers and Events from *_structute.php files
commit 6d156b4febec6b9a0890e95ba07a0dc359c8b496 Author: Rouslan <roccivic@roccivic-pc.(none)> Date: Sat May 21 17:36:48 2011 +0100
Added new graphics for Procedures, Triggers and Events
-----------------------------------------------------------------------
Summary of changes: Documentation.html | 7 + db_events.php | 38 + db_routines.php | 443 +++++++ db_structure.php | 15 - db_triggers.php | 38 + js/db_events.js | 2 + js/db_routines.js | 568 +++++++++ js/db_structure.js | 74 -- js/display_triggers.js | 2 + js/functions.js | 195 +++- js/messages.php | 6 +- libraries/common.inc.php | 1 + libraries/common.lib.php | 270 +++++- libraries/database_interface.lib.php | 24 +- libraries/db_events.inc.php | 127 ++- libraries/db_links.inc.php | 20 + libraries/db_routines.inc.php | 94 -- libraries/db_routines.lib.php | 1265 +++++++++++++++++++++ libraries/dbi/mysql.dbi.lib.php | 26 + libraries/dbi/mysqli.dbi.lib.php | 38 + libraries/display_triggers.inc.php | 123 ++ libraries/tbl_links.inc.php | 18 +- libraries/tbl_properties.inc.php | 23 +- libraries/tbl_triggers.inc.php | 58 - sql.php | 9 + tbl_change.php | 90 +-- tbl_structure.php | 2 - tbl_triggers.php | 35 + themes/original/css/theme_right.css.php | 13 + themes/original/img/b_event_add.png | Bin 0 -> 927 bytes themes/original/img/b_events.png | Bin 0 -> 969 bytes themes/{pmahomme => original}/img/b_nextpage.png | Bin 395 -> 395 bytes themes/original/img/b_routine_add.png | Bin 0 -> 651 bytes themes/original/img/b_routines.png | Bin 0 -> 666 bytes themes/original/img/b_trigger_add.png | Bin 0 -> 731 bytes themes/original/img/b_triggers.png | Bin 0 -> 707 bytes themes/original/img/bd_edit.png | Bin 0 -> 253 bytes themes/original/img/bd_export.png | Bin 0 -> 210 bytes themes/{pmahomme => original}/img/bd_nextpage.png | Bin 167 -> 167 bytes themes/pmahomme/css/theme_right.css.php | 13 + themes/pmahomme/img/b_event_add.png | Bin 0 -> 927 bytes themes/pmahomme/img/b_events.png | Bin 0 -> 969 bytes themes/pmahomme/img/b_routine_add.png | Bin 0 -> 651 bytes themes/pmahomme/img/b_routines.png | Bin 0 -> 666 bytes themes/pmahomme/img/b_trigger_add.png | Bin 0 -> 731 bytes themes/pmahomme/img/b_triggers.png | Bin 0 -> 707 bytes themes/pmahomme/img/bd_edit.png | Bin 0 -> 295 bytes themes/pmahomme/img/bd_export.png | Bin 0 -> 353 bytes 48 files changed, 3213 insertions(+), 424 deletions(-) create mode 100644 db_events.php create mode 100644 db_routines.php create mode 100644 db_triggers.php create mode 100644 js/db_events.js create mode 100644 js/db_routines.js create mode 100644 js/display_triggers.js delete mode 100644 libraries/db_routines.inc.php create mode 100644 libraries/db_routines.lib.php create mode 100644 libraries/display_triggers.inc.php delete mode 100644 libraries/tbl_triggers.inc.php create mode 100644 tbl_triggers.php create mode 100644 themes/original/img/b_event_add.png create mode 100644 themes/original/img/b_events.png copy themes/{pmahomme => original}/img/b_nextpage.png (100%) create mode 100644 themes/original/img/b_routine_add.png create mode 100644 themes/original/img/b_routines.png create mode 100644 themes/original/img/b_trigger_add.png create mode 100644 themes/original/img/b_triggers.png create mode 100644 themes/original/img/bd_edit.png create mode 100644 themes/original/img/bd_export.png copy themes/{pmahomme => original}/img/bd_nextpage.png (100%) create mode 100644 themes/pmahomme/img/b_event_add.png create mode 100644 themes/pmahomme/img/b_events.png create mode 100644 themes/pmahomme/img/b_routine_add.png create mode 100644 themes/pmahomme/img/b_routines.png create mode 100644 themes/pmahomme/img/b_trigger_add.png create mode 100644 themes/pmahomme/img/b_triggers.png create mode 100644 themes/pmahomme/img/bd_edit.png create mode 100644 themes/pmahomme/img/bd_export.png
diff --git a/Documentation.html b/Documentation.html index d2dea87..eb840d2 100644 --- a/Documentation.html +++ b/Documentation.html @@ -137,6 +137,8 @@ vim: expandtab ts=4 sw=4 sts=4 tw=78 <abbr title="Frequently Asked Questions">FAQ</abbr> 3.6)</a></li> <li>support mysqli, the improved MySQL extension <a href="#faq1_17"> (see <abbr title="Frequently Asked Questions">FAQ</abbr> 1.17)</a></li> + <li>create, edit, call, export and drop stored procedures and functions</li> + <li>create, edit, export and drop events and triggers</li> <li>communicate in <a href="http://www.phpmyadmin.net/home_page/translations.php">62 different languages</a> </li> <li>synchronize two databases residing on the same as well as remote servers @@ -5152,6 +5154,8 @@ Jakub Wilk, Thomas Michael Winningham, Vilius Zigmantas, "Manuzhai". <li><a href="http://www.wikipedia.org/wiki/Secure_Sockets_Layer">SSL (Secure Sockets Layer)</a> - a cryptographic protocol which provides secure communication on the Internet.</li> + <li><a href="http://en.wikipedia.org/wiki/Stored_procedure">Stored procedure</a> + - a subroutine available to applications accessing a relational database system</li> <li><a href="http://www.wikipedia.org/wiki/SQL">SQL</a> - Structured Query Language</li> <li><a href="http://www.wikipedia.org/wiki/Table_%28database%29">table</a> @@ -5163,6 +5167,9 @@ Jakub Wilk, Thomas Michael Winningham, Vilius Zigmantas, "Manuzhai". - a type of archive file format: the Tape ARchive format.</li> <li><a href="http://www.wikipedia.org/wiki/TCP">TCP (Transmission Control Protocol)</a> - one of the core protocols of the Internet protocol suite.</li> + <li><a href="http://en.wikipedia.org/wiki/Database_trigger">trigger</a> + - a procedural code that is automatically executed in response to + certain events on a particular table or view in a database</li> <li><a href="http://www.acko.net/node/56">UFPDF</a> - Unicode/UTF-8 extension for FPDF</li> <li><a href="http://www.wikipedia.org/wiki/URL">URL (Uniform Resource Locator)</a> diff --git a/db_events.php b/db_events.php new file mode 100644 index 0000000..6b39b83 --- /dev/null +++ b/db_events.php @@ -0,0 +1,38 @@ +<?php + +/** + * + */ +require_once './libraries/common.inc.php'; +require_once './libraries/common.lib.php'; + +$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; +$GLOBALS['js_include'][] = 'db_events.js'; + +/** + * Create labels for the list + */ +$titles = PMA_buildActionTitles(); + +/** + * Displays the header + */ +require_once './libraries/db_common.inc.php'; + +/** + * Displays the tabs + */ +require_once './libraries/db_info.inc.php'; + +/** + * Displays the list of events + */ +require_once './libraries/db_events.inc.php'; + +/** + * Displays the footer + */ +require './libraries/footer.inc.php'; + + +?> diff --git a/db_routines.php b/db_routines.php new file mode 100644 index 0000000..1d9523e --- /dev/null +++ b/db_routines.php @@ -0,0 +1,443 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @package phpMyAdmin + */ + +/** + * Include required files + */ +require_once './libraries/common.inc.php'; +require_once './libraries/common.lib.php'; +require_once './libraries/db_routines.lib.php'; +require_once './libraries/mysql_charsets.lib.php'; + +/** + * Include JavaScript libraries + */ +$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; +$GLOBALS['js_include'][] = 'jquery/timepicker.js'; +$GLOBALS['js_include'][] = 'db_routines.js'; + +/** + * Create labels for the list + */ +$titles = PMA_buildActionTitles(); + +if ($GLOBALS['is_ajax_request'] != true) { + /** + * Displays the header + */ + require_once './libraries/db_common.inc.php'; + /** + * Displays the tabs + */ + require_once './libraries/db_info.inc.php'; +} else { + if (strlen($db)) { + PMA_DBI_select_db($db); + if (! isset($url_query)) { + $url_query = PMA_generate_common_url($db); + } + } +} + +/** + * Process all requests + */ + +// Some definitions +$param_directions = array('IN', + 'OUT', + 'INOUT'); +$param_opts_num = array('UNSIGNED', + 'ZEROFILL', + 'UNSIGNED ZEROFILL'); +$param_sqldataaccess = array('NO SQL', + 'CONTAINS SQL', + 'READS SQL DATA', + 'MODIFIES SQL DATA'); + +/** + * Generate the conditional classes that will be used to attach jQuery events to links. + */ +$ajax_class = array( + 'add' => '', + 'edit' => '', + 'exec' => '', + 'drop' => '', + 'export' => '' + ); +if ($GLOBALS['cfg']['AjaxEnable']) { + $ajax_class['add'] = 'class="add_routine_anchor"'; + $ajax_class['edit'] = 'class="edit_routine_anchor"'; + $ajax_class['exec'] = 'class="exec_routine_anchor"'; + $ajax_class['drop'] = 'class="drop_routine_anchor"'; + $ajax_class['export'] = 'class="export_routine_anchor"'; +} + +/** + * Keep a list of errors that occured while processing an 'Add' or 'Edit' operation. + */ +$routine_errors = array(); + +/** + * Handle all user requests other than the default of listing routines + */ +if (! empty($_REQUEST['execute_routine']) && ! empty($_REQUEST['routine_name'])) { + // Build the queries + $routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name'], false); + if ($routine !== false) { + $queries = array(); + $end_query = array(); + $args = array(); + for ($i=0; $i<$routine['num_params']; $i++) { + if (isset($_REQUEST['params'][$routine['param_name'][$i]])) { + $value = $_REQUEST['params'][$routine['param_name'][$i]]; + if (is_array($value)) { // is SET type + $value = implode(',', $value); + } + $value = PMA_sqladdslashes($value); + if (! empty($_REQUEST['funcs'][$routine['param_name'][$i]]) + && in_array($_REQUEST['funcs'][$routine['param_name'][$i]], $cfg['Functions'])) { + $queries[] = "SET @p$i={$_REQUEST['funcs'][$routine['param_name'][$i]]}('$value');\n"; + } else { + $queries[] = "SET @p$i='$value';\n"; + } + $args[] = "@p$i"; + } else { + $args[] = "@p$i"; + } + if ($routine['type'] == 'PROCEDURE') { + if ($routine['param_dir'][$i] == 'OUT' || $routine['param_dir'][$i] == 'INOUT') { + $end_query[] = "@p$i AS " . PMA_backquote($routine['param_name'][$i]); + } + } + } + if ($routine['type'] == 'PROCEDURE') { + $queries[] = "CALL " . PMA_backquote($routine['name']) + . "(" . implode(', ', $args) . ");\n"; + if (count($end_query)) { + $queries[] = "SELECT " . implode(', ', $end_query) . ";\n"; + } + } else { + $queries[] = "SELECT " . PMA_backquote($routine['name']) + . "(" . implode(', ', $args) . ") " + . "AS " . PMA_backquote($routine['name']) . ";\n"; + } + // Execute the queries + $affected = 0; + $result = null; + $outcome = true; + foreach ($queries as $num => $query) { + $resource = PMA_DBI_try_query($query); + if ($resource === false) { + $outcome = false; + break; + } + while (true) { + if(! PMA_DBI_more_results()) { + break; + } + PMA_DBI_next_result(); + } + if (substr($query, 0, 6) == 'SELECT') { + $result = $resource; + } else if (substr($query, 0, 4) == 'CALL') { + $affected = PMA_DBI_affected_rows() - PMA_DBI_num_rows($resource); + } + } + // Generate output + if ($outcome) { + $message = __('Your SQL query has been executed successfully'); + if ($routine['type'] == 'PROCEDURE') { + $message .= '<br />'; + $message .= sprintf(__('%s row(s) affected by the last statement inside the procedure'), $affected); + } + $message = PMA_message::success($message); + // Pass the SQL queries through the "pretty printer" + $output = '<code class="sql" style="margin-bottom: 1em;">'; + $output .= PMA_SQP_formatHtml(PMA_SQP_parse(implode($queries))); + $output .= '</code>'; + // Display results + if ($result) { + $output .= "<fieldset><legend>"; + $output .= sprintf(__('Execution results of routine %s'), + PMA_backquote(htmlspecialchars($routine['name']))); + $output .= "</legend>"; + $output .= "<table><tr>"; + foreach (PMA_DBI_get_fields_meta($result) as $key => $field) { + $output .= "<th>" . htmlspecialchars($field->name) . "</th>"; + } + $output .= "</tr>"; + // Stored routines can only ever return ONE ROW. + $data = PMA_DBI_fetch_single_row($result); + foreach ($data as $key => $value) { + if ($value === null) { + $value = '<i>NULL</i>'; + } else { + $value = htmlspecialchars($value); + } + $output .= "<td class='odd'>" . $value . "</td>"; + } + $output .= "</table></fieldset>"; + } else { + $notice = __('MySQL returned an empty result set (i.e. zero rows).'); + $output .= PMA_message::notice($notice)->getDisplay(); + } + } else { + $output = ''; + $message = PMA_message::error(sprintf(__('Query "%s" failed'), $query) . '<br /><br />' + . __('MySQL said: ') . PMA_DBI_getError(null)); + } + // Print/send output + if ($GLOBALS['is_ajax_request']) { + $extra_data = array('dialog' => false); + PMA_ajaxResponse($message->getDisplay() . $output, $message->isSuccess(), $extra_data); + } else { + echo $message->getDisplay() . $output; + if ($message->isError()) { + // At least one query has failed, so shouldn't + // execute any more queries, so we quit. + exit; + } + unset($_POST); + // Now deliberately fall through to displaying the routines list + } + } else { + $message = __('Error in processing request') . ' : ' + . sprintf(__('No routine with name %s found in database %s'), + htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])), + htmlspecialchars(PMA_backquote($db))); + $message = PMA_message::error($message); + if ($GLOBALS['is_ajax_request']) { + PMA_ajaxResponse($message, $message->isSuccess()); + } else { + echo $message->getDisplay(); + unset($_POST); + } + } +} else if (! empty($_GET['execute_dialog']) && ! empty($_GET['routine_name'])) { + /** + * Display the execute form for a routine. + */ + $routine = PMA_RTN_getRoutineDataFromName($db, $_GET['routine_name'], false); + if ($routine !== false) { + $form = PMA_RTN_getExecuteForm($routine, $GLOBALS['is_ajax_request']); + if ($GLOBALS['is_ajax_request'] == true) { + $extra_data = array(); + $extra_data['dialog'] = true; + $extra_data['title'] = __("Execute routine") . " "; + $extra_data['title'] .= PMA_backquote(htmlentities($_GET['routine_name'], ENT_QUOTES)); + PMA_ajaxResponse($form, true, $extra_data); + } else { + echo "\n\n<h2>" . __("Execute routine") . "</h2>\n\n"; + echo $form; + require './libraries/footer.inc.php'; + // exit; + } + } else if (($GLOBALS['is_ajax_request'] == true)) { + PMA_ajaxResponse(PMA_message::error(), false); + } +} else if (! empty($_GET['exportroutine']) && ! empty($_GET['routine_name'])) { + /** + * Display the export for a routine. + */ + $routine_name = htmlspecialchars(PMA_backquote($_GET['routine_name'])); + $routine_type = PMA_DBI_fetch_value("SELECT ROUTINE_TYPE " + . "FROM INFORMATION_SCHEMA.ROUTINES " + . "WHERE ROUTINE_SCHEMA='" . PMA_sqlAddslashes($db) . "' " + . "AND SPECIFIC_NAME='" . PMA_sqlAddslashes($_GET['routine_name']) . "';"); + if (! empty($routine_type) && $create_proc = PMA_DBI_get_definition($db, $routine_type, $_GET['routine_name'])) { + $create_proc = '<textarea cols="40" rows="15" style="width: 100%;">' . htmlspecialchars($create_proc) . '</textarea>'; + if ($GLOBALS['is_ajax_request']) { + $extra_data = array('title' => sprintf(__('Export of routine %s'), $routine_name)); + PMA_ajaxResponse($create_proc, true, $extra_data); + } else { + echo '<fieldset>' . "\n" + . ' <legend>' . sprintf(__('Export of routine %s'), $routine_name) . '</legend>' . "\n" + . $create_proc . "\n" + . '</fieldset>'; + } + } else { + $response = __('Error in processing request') . ' : ' + . sprintf(__('No routine with name %s found in database %s'), + $routine_name, htmlspecialchars(PMA_backquote($db))); + $response = PMA_message::error($response); + if ($GLOBALS['is_ajax_request']) { + PMA_ajaxResponse($response, false); + } else { + $response->display(); + } + } +} else if (! empty($_REQUEST['routine_process_addroutine']) || ! empty($_REQUEST['routine_process_editroutine'])) { + /** + * Handle a request to create/edit a routine + */ + $sql_query = ''; + $routine_query = PMA_RTN_getQueryFromRequest(); + if (! count($routine_errors)) { // set by PMA_RTN_getQueryFromRequest() + // Execute the created query + if (! empty($_REQUEST['routine_process_editroutine'])) { + if (! in_array($_REQUEST['routine_original_type'], array('PROCEDURE', 'FUNCTION'))) { + $routine_errors[] = sprintf(__('Invalid routine type: "%s"'), htmlspecialchars($_REQUEST['routine_original_type'])); + } else { + // Backup the old routine, in case something goes wrong + $create_routine = PMA_DBI_get_definition($db, $_REQUEST['routine_original_type'], $_REQUEST['routine_original_name']); + $drop_routine = "DROP {$_REQUEST['routine_original_type']} " . PMA_backquote($_REQUEST['routine_original_name']) . ";\n"; + $result = PMA_DBI_try_query($drop_routine); + if (! $result) { + $routine_errors[] = sprintf(__('Query "%s" failed'), $drop_routine) . '<br />' + . __('MySQL said: ') . PMA_DBI_getError(null); + } else { + $result = PMA_DBI_try_query($routine_query); + if (! $result) { + $routine_errors[] = sprintf(__('Query "%s" failed'), $routine_query) . '<br />' + . __('MySQL said: ') . PMA_DBI_getError(null); + // We dropped the old routine, but were unable to create the new one + // Try to restore the backup query + $result = PMA_DBI_try_query($create_routine); + if (! $result) { + // OMG, this is really bad! We dropped the query, failed to create a new one + // and now even the backup query does not execute! + // This should not happen, but we better handle this just in case. + $routine_errors[] = __('Sorry, we failed to restore the dropped routine.') . '<br />' + . __('The backed up query was:') . "\"$create_routine\"" . '<br />' + . __('MySQL said: ') . PMA_DBI_getError(null); + } + } else { + $message = PMA_Message::success(__('Routine %1$s has been modified.')); + $message->addParam(PMA_backquote($_REQUEST['routine_name'])); + $sql_query = $drop_routine . $routine_query; + } + } + } + } else { + // 'Add a new routine' mode + $result = PMA_DBI_try_query($routine_query); + if (! $result) { + $routine_errors[] = sprintf(__('Query "%s" failed'), $routine_query) . '<br /><br />' + . __('MySQL said: ') . PMA_DBI_getError(null); + } else { + $message = PMA_Message::success(__('Routine %1$s has been created.')); + $message->addParam(PMA_backquote($_REQUEST['routine_name'])); + $sql_query = $routine_query; + } + } + } + + if (count($routine_errors)) { + $message = PMA_Message::error(__('<b>One or more errors have occured while processing your request:</b>')); + $message->addString('<ul>'); + foreach ($routine_errors as $num => $string) { + $message->addString('<li>' . $string . '</li>'); + } + $message->addString('</ul>'); + } + + $output = PMA_showMessage($message, $sql_query); + if ($GLOBALS['is_ajax_request']) { + $extra_data = array(); + if ($message->isSuccess()) { + $columns = "`SPECIFIC_NAME`, `ROUTINE_NAME`, `ROUTINE_TYPE`, `DTD_IDENTIFIER`, `ROUTINE_DEFINITION`"; + $where = "ROUTINE_SCHEMA='" . PMA_sqlAddslashes($db) . "' AND ROUTINE_NAME='" . PMA_sqlAddslashes($_REQUEST['routine_name']) . "'"; + $routine = PMA_DBI_fetch_single_row("SELECT $columns FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE $where;"); + $extra_data['name'] = htmlspecialchars(strtoupper($_REQUEST['routine_name'])); + $extra_data['new_row'] = PMA_RTN_getRowForRoutinesList($routine, 0, true); + $response = $output; + } else { + $response = $message; + } + PMA_ajaxResponse($response, $message->isSuccess(), $extra_data); + } +} + +/** + * Display a form used to add/edit a routine, if necessary + */ +if (count($routine_errors) || ( empty($_REQUEST['routine_process_addroutine']) && empty($_REQUEST['routine_process_editroutine']) && + (! empty($_REQUEST['addroutine']) || ! empty($_REQUEST['editroutine']) + || ! empty($_REQUEST['routine_addparameter']) || ! empty($_REQUEST['routine_removeparameter']) + || ! empty($_REQUEST['routine_changetype'])))) { // FIXME: this must be simpler than that + // Handle requests to add/remove parameters and changing routine type + // This is necessary when JS is disabled + $operation = ''; + if (! empty($_REQUEST['routine_addparameter'])) { + $operation = 'add'; + } else if (! empty($_REQUEST['routine_removeparameter'])) { + $operation = 'remove'; + } else if (! empty($_REQUEST['routine_changetype'])) { + $operation = 'change'; + } + // Get the data for the form (if any) + if (! empty($_REQUEST['addroutine'])) { + $title = __("Create routine"); + $routine = PMA_RTN_getRoutineDataFromRequest(); + $mode = 'add'; + } else if (! empty($_REQUEST['editroutine'])) { + $title = __("Edit routine"); + if (! $operation && ! empty($_REQUEST['routine_name']) && empty($_REQUEST['routine_process_editroutine'])) { + $routine = PMA_RTN_getRoutineDataFromName($db, $_REQUEST['routine_name']); + if ($routine !== false) { + $routine['original_name'] = $routine['name']; + $routine['original_type'] = $routine['type']; + } + } else { + $routine = PMA_RTN_getRoutineDataFromRequest(); + } + $mode = 'edit'; + } + if ($routine !== false) { + // Show form + $editor = PMA_RTN_getEditorForm($mode, $operation, $routine, $routine_errors, $GLOBALS['is_ajax_request']); + if ($GLOBALS['is_ajax_request']) { + $template = PMA_RTN_getParameterRow(); + $extra_data = array('title' => $title, 'param_template' => $template, 'type' => $routine['type']); + PMA_ajaxResponse($editor, true, $extra_data); + } + echo "\n\n<h2>$title</h2>\n\n$editor"; + require './libraries/footer.inc.php'; + // exit; + } else { + $message = __('Error in processing request') . ' : ' + . sprintf(__('No routine with name %s found in database %s'), + htmlspecialchars(PMA_backquote($_REQUEST['routine_name'])), + htmlspecialchars(PMA_backquote($db))); + $message = PMA_message::error($message); + if ($GLOBALS['is_ajax_request']) { + PMA_ajaxResponse($message, false); + } else { + $message->display(); + } + } +} + +/** + * Display a list of available routines + */ +echo PMA_RTN_getRoutinesList(); + +/** + * Display the form for adding a new routine, if the user has the privileges. + */ +echo PMA_RTN_getAddRoutineLink(); + +/** + * Display a warning for users with PHP's old "mysql" extension. + */ +if ($GLOBALS['cfg']['Server']['extension'] === 'mysql') { + trigger_error(__('You are using PHP\'s deprecated \'mysql\' extension, ' + . 'which is not capable of handling multi queries. ' + . '<b>The execution of some stored routines may fail!</b> ' + . 'Please use the improved \'mysqli\' extension to ' + . 'avoid any problems.'), E_USER_WARNING); +} + +if ($GLOBALS['is_ajax_request'] != true) { + /** + * Displays the footer + */ + require './libraries/footer.inc.php'; +} + +?> diff --git a/db_structure.php b/db_structure.php index b49b417..0054585 100644 --- a/db_structure.php +++ b/db_structure.php @@ -59,14 +59,6 @@ $titles = PMA_buildActionTitles(); if ($num_tables == 0) { echo '<p>' . __('No tables found in database') . '</p>' . "\n";
- // Routines - require './libraries/db_routines.inc.php'; - - // Events - if (PMA_MYSQL_INT_VERSION > 50100) { - require './libraries/db_events.inc.php'; - } - if (empty($db_is_information_schema)) { require './libraries/display_create_table.lib.php'; } // end if (Create Table dialog) @@ -546,13 +538,6 @@ PMA_listNavigator($total_num_tables, $pos, $_url_params, 'db_structure.php', 'fr <hr />
<?php -// Routines -require './libraries/db_routines.inc.php'; - -// Events -if (PMA_MYSQL_INT_VERSION > 50100) { - require './libraries/db_events.inc.php'; -}
/** * Work on the database diff --git a/db_triggers.php b/db_triggers.php new file mode 100644 index 0000000..416be77 --- /dev/null +++ b/db_triggers.php @@ -0,0 +1,38 @@ +<?php + +/** + * + */ +require_once './libraries/common.inc.php'; +require_once './libraries/common.lib.php'; + +$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; +$GLOBALS['js_include'][] = 'display_triggers.js'; + +/** + * Create labels for the list + */ +$titles = PMA_buildActionTitles(); + +/** + * Displays the header + */ +require_once './libraries/db_common.inc.php'; + +/** + * Displays the tabs + */ +require_once './libraries/db_info.inc.php'; + +/** + * Displays the list of triggers + */ +require_once './libraries/display_triggers.inc.php'; + +/** + * Displays the footer + */ +require './libraries/footer.inc.php'; + + +?> diff --git a/js/db_events.js b/js/db_events.js new file mode 100644 index 0000000..3a0ccd5 --- /dev/null +++ b/js/db_events.js @@ -0,0 +1,2 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + diff --git a/js/db_routines.js b/js/db_routines.js new file mode 100644 index 0000000..1c03b6b --- /dev/null +++ b/js/db_routines.js @@ -0,0 +1,568 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Validate routine editor form fields. + * + * @param syntaxHiglighter an object containing the reference to the + * codemirror editor. This will be used to + * focus the form on the codemirror editor + * if it contains invalid data. + */ +function validateRoutineEditor(syntaxHiglighter) { + /** + * @var inputname Will contain the value of the name + * attribute of input fields being checked. + */ + var inputname = ''; + /** + * @var $elm a jQuery object containing the reference + * to an element that is being validated. + */ + var $elm = null; + /** + * @var isError Stores the outcome of the validation. + */ + var isError = false; + + $elm = $('.rte_table').last().find('input[name=routine_name]'); + if ($elm.val() == '') { + $elm.focus(); + isError = true; + } else if ($elm.val().length > 64) { + alert(PMA_messages['strValueTooLong']); + $elm.focus().select(); + return false; + } + if (! isError) { + $elm = $('.rte_table').find('textarea[name=routine_definition]'); + if ($elm.val() == '') { + syntaxHiglighter.focus(); + isError = true; + } + } + if (! isError) { + $('.routine_params_table').last().find('tr').each(function() { + if (! isError) { + $(this).find(':input').each(function() { + inputname = $(this).attr('name'); + if (inputname.substr(0, 17) == 'routine_param_dir' || + inputname.substr(0, 18) == 'routine_param_name' || + inputname.substr(0, 18) == 'routine_param_type') { + if ($(this).val() == '') { + $(this).focus(); + isError = true; + return false; + } + } + }); + } + }); + } + if (! isError) { + // SET, ENUM, VARCHAR and VARBINARY fields must have length/values + $('.routine_params_table').last().find('tr').each(function() { + var $inputtyp = $(this).find('select[name^=routine_param_type]'); + var $inputlen = $(this).find('input[name^=routine_param_length]'); + if ($inputtyp.length && $inputlen.length) { + if (($inputtyp.val() == 'ENUM' || $inputtyp.val() == 'SET' || $inputtyp.val().substr(0,3) == 'VAR') + && $inputlen.val() == '') { + $inputlen.focus(); + isError = true; + return false; + } + } + }); + } + if (! isError && $('select[name=routine_type]').find(':selected').val() == 'FUNCTION') { + // The length/values of return variable for functions must + // be set, if the type is SET, ENUM, VARCHAR or VARBINARY. + var $returntyp = $('select[name=routine_returntype]'); + var $returnlen = $('input[name=routine_returnlength]'); + if (($returntyp.val() == 'ENUM' || $returntyp.val() == 'SET' || $returntyp.val().substr(0,3) == 'VAR') + && $returnlen.val() == '') { + $returnlen.focus(); + isError = true; + } + } + if (! isError && $('select[name=routine_type]').find(':selected').val() == 'FUNCTION') { + if ($('.rte_table').find('textarea[name=routine_definition]').val().toLowerCase().indexOf('return') < 0) { + syntaxHiglighter.focus(); + alert(PMA_messages['MissingReturn']); + return false; + } + } + if (! isError) { + $elm = $('.rte_table').last().find('input[name=routine_comment]'); + if ($elm.val().length > 64) { + alert(PMA_messages['strValueTooLong']); + $elm.focus().select(); + return false; + } + } + if (! isError) { + return true; + } else { + alert(PMA_messages['strFormEmpty']); + return false; + } +} // end validateRoutineEditor() + +/** + * Enable/disable the "options" dropdown and "length" input for + * parameters and the return variable in the routine editor + * as necessary. + * + * @param $type a jQuery object containing the reference + * to the "Type" dropdown box + * @param $len a jQuery object containing the reference + * to the "Length" input box + * @param $text a jQuery object containing the reference + * to the dropdown box with options for + * parameters of text type + * @param $num a jQuery object containing the reference + * to the dropdown box with options for + * parameters of numeric type + */ +function setOptionsForParameter($type, $len, $text, $num) { + // Process for parameter options + switch ($type.val()) { + case 'TINYINT': + case 'SMALLINT': + case 'MEDIUMINT': + case 'INT': + case 'BIGINT': + case 'DECIMAL': + case 'FLOAT': + case 'DOUBLE': + case 'REAL': + $text.parent().hide(); + $num.parent().show(); + break; + case 'TINYTEXT': + case 'TEXT': + case 'MEDIUMTEXT': + case 'LONGTEXT': + case 'CHAR': + case 'VARCHAR': + case 'SET': + case 'ENUM': + $text.parent().show(); + $text.show(); + $num.parent().hide(); + break; + default: + $text.parent().show(); + $text.hide(); + $num.parent().hide(); + break; + } + // Process for parameter length + switch ($type.val()) { + case 'DATE': + case 'DATETIME': + case 'TIME': + case 'TINYBLOB': + case 'TINYTEXT': + case 'BLOB': + case 'TEXT': + case 'MEDIUMBLOB': + case 'MEDIUMTEXT': + case 'LONGBLOB': + case 'LONGTEXT': + $len.hide(); + break; + default: + $len.show(); + break; + } +} + +/** + * Attach Ajax event handlers for the Routines functionalities. + * + * @see $cfg['AjaxEnable'] + */ +$(document).ready(function() { + /** + * @var $ajaxDialog jQuery object containing the reference to the + * dialog that contains the routine editor. + */ + var $ajaxDialog = null; + /** + * @var param_template This variable contains the template for one row + * of the parameters table that is attached to the + * dialog when a new parameter is added. + */ + var param_template = ''; + /** + * @var syntaxHiglighter Reference to the codemirror editor. + */ + var syntaxHiglighter = null; + /** + * @var button_options Object containing options for jQueryUI dialog buttons + */ + var button_options = {}; + + /** + * Attach Ajax event handlers for the Add/Edit routine functionality. + * + * @uses PMA_ajaxShowMessage() + * @uses PMA_ajaxRemoveMessage() + * + * @see $cfg['AjaxEnable'] + */ + $('.add_routine_anchor, .edit_routine_anchor').live('click', function(event) { + event.preventDefault(); + /** + * @var $edit_row jQuery object containing the reference to + * the row of the the routine being edited + * from the list of routines . + */ + var $edit_row = null; + if ($(this).hasClass('edit_routine_anchor')) { + // Remeber the row of the routine being edited for later, + // so that if the edit is successful, we can replace the + // row with info about the modified routine. + $edit_row = $(this).parents('tr'); + } + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user. + */ + var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); + $.get($(this).attr('href'), {'ajax_request': true}, function(data) { + if(data.success == true) { + PMA_ajaxRemoveMessage($msg); + button_options[PMA_messages['strGo']] = function() { + syntaxHiglighter.save(); + // Validate editor and submit request, if passed. + if (validateRoutineEditor(syntaxHiglighter)) { + /** + * @var data Form data to be sent in the AJAX request. + */ + var data = $('.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); + $.post('db_routines.php', data, function (data) { + if(data.success == true) { + // Routine created successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage($('#js_query_display'), data.message); + $ajaxDialog.dialog('close'); + // If we are in 'edit' mode, we must remove the reference to the old row. + if (mode == 'edit') { + $edit_row.remove(); + } + // Insert the new row at the correct location in the list of routines + /** + * @var text Contains the name of a routine from the list + * that is used in comparisons to find the correct + * location where to insert a new row. + */ + var text = ''; + /** + * @var inserted Whether a new has been inserted + * in the list of routines or not. + */ + var inserted = false; + $('table.data').find('tr').each(function() { + text = $(this).children('td').eq(0).find('strong').text().toUpperCase(); + if (text != '' && text > data.name) { + $(this).before(data.new_row); + inserted = true; + return false; + } + }); + if (! inserted) { + $('table.data').append(data.new_row); + } + // Fade-in the new row + $('.ajaxInsert').show('slow').removeClass('ajaxInsert'); + // Now we have inserted the row at the correct position, but surely + // at least some row classes are wrong now. So we will itirate + // throught all rows and assign correct classes to them. + /** + * @var ct Count of processed rows. + */ + var ct = 0; + $('table.data').find('tr').has('td').each(function() { + rowclass = (ct % 2 == 0) ? 'even' : 'odd'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + // If this is the first routine being added, remove the + // "No routines" message and show the list of routines. + if ($('table.data').find('tr').has('td').length > 0 && $('#nothing2display').is(':visible')) { + $('#nothing2display').hide("slow", function () { + $('table.data').show("slow"); + }); + } + } else { + PMA_ajaxShowMessage(data.error); + } + }); + } + } // end of function that handles the submission of the Editor + button_options[PMA_messages['strClose']] = function() { + $(this).dialog("close"); + } + /** + * Display the dialog to the user + */ + $ajaxDialog = $('<div style="font-size: 0.9em;">'+data.message+'</div>').dialog({ + width: 700, // TODO: make a better decision about the size + height: 550, // of the dialog based on the size of the viewport + buttons: button_options, + title: data.title, + modal: true, + close: function () { + $(this).remove(); + } + }); + $ajaxDialog.find('input[name=routine_name]').focus(); + /** + * @var mode Used to remeber whether the editor is in + * "Edit Routine" or "Add Routine" mode. + */ + var mode = 'add'; + if ($('input[name=routine_process_editroutine]').length > 0) { + mode = 'edit'; + } + // Cache the template for a parameter table row + param_template = data.param_template; + // Make adjustments in the dialog to make it AJAX compatible + $('.routine_param_remove').show(); + $('input[name=routine_removeparameter]').remove(); + $('input[name=routine_addparameter]').css('width', '100%'); + // Enable/disable the 'options' dropdowns for parameters as necessary + $('.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1'); + $('.routine_params_table').last().find('tr').has('td').each(function() { + setOptionsForParameter( + $(this).find('select[name^=routine_param_type]'), + $(this).find('input[name^=routine_param_length]'), + $(this).find('select[name^=routine_param_opts_text]'), + $(this).find('select[name^=routine_param_opts_num]') + ); + }); + // Enable/disable the 'options' dropdowns for function return value as necessary + setOptionsForParameter( + $('.rte_table').last().find('select[name=routine_returntype]'), + $('.rte_table').last().find('input[name=routine_returnlength]'), + $('.rte_table').last().find('select[name=routine_returnopts_text]'), + $('.rte_table').last().find('select[name=routine_returnopts_num]') + ); + // Attach syntax highlited editor to routine definition + /** + * @var $elm jQuery object containing the reference to + * the "Routine Definition" textarea. + */ + var $elm = $('textarea[name=routine_definition]').last(); + /** + * @var opts Options to pass to the codemirror editor. + */ + var opts = {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"}; + syntaxHiglighter = CodeMirror.fromTextArea($elm[0], opts); + // Hack to prevent the syntax highlighter from expanding beyond dialog boundries + $('.CodeMirror-scroll').find('div').first().css('width', '1px'); + } else { + PMA_ajaxShowMessage(data.error); + } + }) // end $.get() + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Add parameter to routine" functionality. + * + * @see $cfg['AjaxEnable'] + */ + $('input[name=routine_addparameter]').live('click', function(event) { + event.preventDefault(); + /** + * @var $routine_params_table jQuery object containing the reference + * to the routine parameters table. + */ + var $routine_params_table = $('.routine_params_table').last(); + /** + * @var $new_param_row A string containing the HTML code for the + * new row for the routine paramaters table. + */ + var new_param_row = param_template.replace(/%s/g, $routine_params_table.find('tr').length-1); + $routine_params_table.append(new_param_row); + if ($('.rte_table').find('select[name=routine_type]').val() == 'FUNCTION') { + $('.routine_return_row').show(); + $('.routine_direction_cell').hide(); + } + /** + * @var $newrow jQuery object containing the reference to the newly + * inserted row in the routine parameters table. + */ + var $newrow = $('.routine_params_table').last().find('tr').has('td').last(); + setOptionsForParameter( + $newrow.find('select[name^=routine_param_type]'), + $newrow.find('input[name^=routine_param_length]'), + $newrow.find('select[name^=routine_param_opts_text]'), + $newrow.find('select[name^=routine_param_opts_num]') + ); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Remove parameter from routine" functionality. + * + * @see $cfg['AjaxEnable'] + */ + $('.routine_param_remove_anchor').live('click', function (event) { + event.preventDefault(); + $(this).parent().parent().remove(); + // After removing a parameter, the indices of the name attributes in + // the input fields lose the correct order and need to be reordered. + /** + * @var index Counter used for reindexing the input + * fields in the routine parameters table. + */ + var index = 0; + $('.routine_params_table').last().find('tr').has('td').each(function() { + $(this).find(':input').each(function() { + /** + * @var inputname The value of the name attribute of + * the input field being reindexed. + */ + var inputname = $(this).attr('name'); + if (inputname.substr(0, 17) == 'routine_param_dir') { + $(this).attr('name', inputname.substr(0, 17) + '[' + index + ']'); + } else if (inputname.substr(0, 18) == 'routine_param_name') { + $(this).attr('name', inputname.substr(0, 18) + '[' + index + ']'); + } else if (inputname.substr(0, 18) == 'routine_param_type') { + $(this).attr('name', inputname.substr(0, 18) + '[' + index + ']'); + } else if (inputname.substr(0, 20) == 'routine_param_length') { + $(this).attr('name', inputname.substr(0, 20) + '[' + index + ']'); + } else if (inputname.substr(0, 23) == 'routine_param_opts_text') { + $(this).attr('name', inputname.substr(0, 23) + '[' + index + ']'); + } else if (inputname.substr(0, 22) == 'routine_param_opts_num') { + $(this).attr('name', inputname.substr(0, 22) + '[' + index + ']'); + } + }); + index++; + }); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change routine type" functionality. + * + * @see $cfg['AjaxEnable'] + */ + $('select[name=routine_type]').live('change', function() { + $('.routine_return_row, .routine_direction_cell').toggle(); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change parameter type" functionality. + * + * @see $cfg['AjaxEnable'] + */ + $('select[name^=routine_param_type]').live('change', function() { + /** + * @var $row jQuery object containing the reference to + * a row in the routine parameters table. + */ + var $row = $(this).parents('tr').first(); + setOptionsForParameter( + $row.find('select[name^=routine_param_type]'), + $row.find('input[name^=routine_param_length]'), + $row.find('select[name^=routine_param_opts_text]'), + $row.find('select[name^=routine_param_opts_num]') + ); + }); + + /** + * Attach Ajax event handlers for the "Change the type of return + * variable of function" functionality. + * + * @see $cfg['AjaxEnable'] + */ + $('select[name=routine_returntype]').live('change', function() { + setOptionsForParameter( + $('.rte_table').find('select[name=routine_returntype]'), + $('.rte_table').find('input[name=routine_returnlength]'), + $('.rte_table').find('select[name=routine_returnopts_text]'), + $('.rte_table').find('select[name=routine_returnopts_num]') + ); + }); + + /** + * Attach Ajax event handlers for the Execute routine functionality. + * + * @uses PMA_ajaxShowMessage() + * @uses PMA_ajaxRemoveMessage() + * + * @see $cfg['AjaxEnable'] + */ + $('.exec_routine_anchor').live('click', function(event) { + event.preventDefault(); + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user. + */ + var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); + $.get($(this).attr('href'), {'ajax_request': true}, function(data) { + if(data.success == true) { + PMA_ajaxRemoveMessage($msg); + if (data.dialog) { + button_options[PMA_messages['strGo']] = function() { + /** + * @var data Form data to be sent in the AJAX request. + */ + var data = $('.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); + $.post('db_routines.php', data, function (data) { + if(data.success == true) { + // Routine executed successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage($('#js_query_display'), data.message); + $ajaxDialog.dialog('close'); + } else { + PMA_ajaxShowMessage(data.error); + } + }); + } + button_options[PMA_messages['strClose']] = function() { + $(this).dialog("close"); + } + /** + * Display the dialog to the user + */ + $ajaxDialog = $('<div style="font-size: 0.9em;">'+data.message+'</div>').dialog({ + width: 650, // TODO: make a better decision about the size + // of the dialog based on the size of the viewport + buttons: button_options, + title: data.title, + modal: true, + close: function () { + $(this).remove(); + } + }); + $ajaxDialog.find('input[name^=params]').first().focus(); + } else { + // Routine executed successfully + PMA_slidingMessage($('#js_query_display'), data.message); + } + } else { + PMA_ajaxShowMessage(data.error); + } + }); + }); + + /** + * Attach Ajax event handlers for input fields in the routines editor + * and the routine execution dialog used to submit the Ajax request + * when the ENTER key is pressed. + * + * @see $cfg['AjaxEnable'] + */ + $('input[name^=routine], input[name^=params]').live('keydown', function(e) { + if (e.which == 13) { + e.preventDefault(); + if (typeof button_options[PMA_messages['strGo']] == 'function') { + button_options[PMA_messages['strGo']].call(); + } + } + }); +}); // end of $(document).ready() for the Routine Functionalities diff --git a/js/db_structure.js b/js/db_structure.js index 92dae86..ad55341 100644 --- a/js/db_structure.js +++ b/js/db_structure.js @@ -270,80 +270,6 @@ $(document).ready(function() { }); //end of Drop Table Ajax action
/** - * Ajax Event handler for 'Drop Event' - * - * @uses $.PMA_confirm() - * @uses PMA_ajaxShowMessage() - * @see $cfg['AjaxEnable'] - */ - $('.drop_event_anchor').live('click', function(event) { - event.preventDefault(); - - /** - * @var curr_event_row Object reference to current event's row - */ - var curr_event_row = $(this).parents('tr'); - /** - * @var curr_event_name String containing the name of {@link curr_event_row} - */ - var curr_event_name = $(curr_event_row).children('td:first').text(); - /** - * @var question String containing the question to be asked for confirmation - */ - var question = 'DROP EVENT ' + curr_event_name; - - $(this).PMA_confirm(question, $(this).attr('href') , function(url) { - - PMA_ajaxShowMessage(PMA_messages['strDroppingEvent']); - - $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { - if(data.success == true) { - PMA_ajaxShowMessage(data.message); - $(curr_event_row).hide("medium").remove(); - } - else { - PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error); - } - }) // end $.get() - }) // end $.PMA_confirm() - }) //end Drop Event - - /** - * Ajax Event handler for 'Drop Procedure' - * - * @uses $.PMA_confirm() - * @uses PMA_ajaxShowMessage() - * @see $cfg['AjaxEnable'] - */ - $('.drop_procedure_anchor').live('click', function(event) { - event.preventDefault(); - - /** - * @var curr_proc_row Object containing reference to the current procedure's row - */ - var curr_proc_row = $(this).parents('tr'); - /** - * @var question String containing the question to be asked for confirmation - */ - var question = $(curr_proc_row).children('td').children('.drop_procedure_sql').val(); - - $(this).PMA_confirm(question, $(this).attr('href'), function(url) { - - PMA_ajaxShowMessage(PMA_messages['strDroppingProcedure']); - - $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { - if(data.success == true) { - PMA_ajaxShowMessage(data.message); - $(curr_event_row).hide("medium").remove(); - } - else { - PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error); - } - }) // end $.get() - }) // end $.PMA_confirm() - }) //end Drop Procedure - - /** * Ajax Event handler for 'Drop tracking' * * @uses $.PMA_confirm() diff --git a/js/display_triggers.js b/js/display_triggers.js new file mode 100644 index 0000000..3a0ccd5 --- /dev/null +++ b/js/display_triggers.js @@ -0,0 +1,2 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + diff --git a/js/functions.js b/js/functions.js index 6657ac9..14f3b46 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1750,46 +1750,6 @@ $(document).ready(function() { }, 'top.frame_content'); //end $(document).ready for 'Create Table'
/** - * Attach Ajax event handlers for Drop Trigger. Used on tbl_structure.php - * @see $cfg['AjaxEnable'] - */ -$(document).ready(function() { - - $(".drop_trigger_anchor").live('click', function(event) { - event.preventDefault(); - - $anchor = $(this); - /** - * @var curr_row Object reference to the current trigger's <tr> - */ - var $curr_row = $anchor.parents('tr'); - /** - * @var question String containing the question to be asked for confirmation - */ - var question = 'DROP TRIGGER IF EXISTS `' + $curr_row.children('td:first').text() + '`'; - - $anchor.PMA_confirm(question, $anchor.attr('href'), function(url) { - - PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); - $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { - if(data.success == true) { - PMA_ajaxShowMessage(data.message); - $("#topmenucontainer") - .next('div') - .remove() - .end() - .after(data.sql_query); - $curr_row.hide("medium").remove(); - } - else { - PMA_ajaxShowMessage(data.error); - } - }) // end $.get() - }) // end $.PMA_confirm() - }) // end $().live() -}, 'top.frame_content'); //end $(document).ready() for Drop Trigger - -/** * Attach Ajax event handlers for Drop Database. Moved here from db_structure.js * as it was also required on db_create.php * @@ -2448,6 +2408,161 @@ $(document).ready(function() { }) // end of $(document).ready()
/** + * Attach Ajax event handlers for Export of Routines, Triggers and Events. + * + * @uses PMA_ajaxShowMessage() + * @uses PMA_ajaxRemoveMessage() + * + * @see $cfg['AjaxEnable'] + */ +$(document).ready(function() { + $('.export_routine_anchor, .export_trigger_anchor, .export_event_anchor').live('click', function(event) { + event.preventDefault(); + var $msg = PMA_ajaxShowMessage(PMA_messages['strLoading']); + $.get($(this).attr('href'), {'ajax_request': true}, function(data) { + if(data.success == true) { + PMA_ajaxRemoveMessage($msg); + /** + * @var button_options Object containing options for jQueryUI dialog buttons + */ + var button_options = {}; + button_options[PMA_messages['strClose']] = function() {$(this).dialog("close").remove();} + /** + * Display the dialog to the user + */ + var $ajaxDialog = $('<div style="font-size: 0.9em;">'+data.message+'</div>').dialog({ + width: 500, + buttons: button_options, + title: data.title + }); + // Attach syntax highlited editor to export dialog + var elm = $ajaxDialog.find('textarea'); + CodeMirror.fromTextArea(elm[0], {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"}); + } else { + PMA_ajaxShowMessage(data.error); + } + }) // end $.get() + }); // end $.live() +}); // end of $(document).ready() for Export of Routines, Triggers and Events. + +/** + * Creates a message inside an object with a sliding effect + * + * @param $obj a jQuery object containing the reference + * to the element where to put the message + * @param msg A string containing the text to display + * + * @return bool True on success, false on failure + */ +function PMA_slidingMessage($obj, msg) { + if ($obj != 'undefined' && $obj instanceof jQuery) { + if ($obj.has('div').length > 0) { + // If there already is a message inside the + // target object, we must get rid of it + $obj + .append('<div style="display: none;">' + msg + '</div>') + .find('div') + .first() + .fadeOut(function () { + $(this).remove(); + $obj.animate({ + height: $obj.find('div').first().height() + }); + $obj + .find('div') + .first() + .fadeIn(); + }); + } else { + // Object does not already have a message + // inside it, so we simply slide it down + $obj + .width('100%') + .html('<div style="display: none;">' + msg + '</div>') + .find('div') + .first() + .slideDown(function() { + // Set the height of the parent + // to the height of the child + $obj + .height( + $obj + .find('div') + .first() + .height() + ); + }); + } + return true; + } else { + return false; + } +} // end PMA_slidingMessage() + +/** + * Attach Ajax event handlers for Drop functionality of Routines, Triggers and Events. + * + * @uses $.PMA_confirm() + * @uses PMA_ajaxShowMessage() + * @see $cfg['AjaxEnable'] + */ +$(document).ready(function() { + $('.drop_routine_anchor, .drop_trigger_anchor, .drop_event_anchor').live('click', function(event) { + event.preventDefault(); + /** + * @var $curr_row Object containing reference to the current row + */ + var $curr_row = $(this).parents('tr'); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = $('<div></div>').text($curr_row.children('td').children('.drop_sql').html()); + $(this).PMA_confirm(question, $(this).attr('href'), function(url) { + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user. + */ + var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { + if(data.success == true) { + /** + * @var $table Object containing reference to the main list of elements. + */ + var $table = $curr_row.parent(); + if ($table.find('tr').length == 2) { + $table.hide("slow", function () { + $(this).find('tr.even, tr.odd').remove(); + $('#nothing2display').show("slow"); + }); + } else { + $curr_row.hide("slow", function () { + $(this).remove(); + // Now we have removed the row from the list, but maybe + // some row classes are wrong now. So we will itirate + // throught all rows and assign correct classes to them. + /** + * @var ct Count of processed rows. + */ + var ct = 0; + $table.find('tr').has('td').each(function() { + rowclass = (ct % 2 == 0) ? 'even' : 'odd'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + }); + } + // Show the query that we just executed + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage($('#js_query_display'), data.sql_query); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error); + } + }) // end $.get() + }) // end $.PMA_confirm() + }); // end $.live() +}); //end $(document).ready() for Drop functionality of Routines, Triggers and Events. + +/** * Attach Ajax event handlers for Drop Table. * * @uses $.PMA_confirm() diff --git a/js/messages.php b/js/messages.php index 6863532..18cb752 100644 --- a/js/messages.php +++ b/js/messages.php @@ -31,8 +31,6 @@ $js_messages['strDoYouReally'] = __('Do you really want to '); $js_messages['strDropDatabaseStrongWarning'] = __('You are about to DESTROY a complete database!'); $js_messages['strDropTableStrongWarning'] = __('You are about to DESTROY a complete table!'); $js_messages['strTruncateTableStrongWarning'] = __('You are about to TRUNCATE a complete table!'); -$js_messages['strDroppingEvent'] = __('Dropping Event'); -$js_messages['strDroppingProcedure'] = __('Dropping Procedure'); $js_messages['strDeleteTrackingData'] = __('Delete tracking data for this table'); $js_messages['strDeletingTrackingData'] = __('Deleting tracking data'); $js_messages['strDroppingPrimaryKeyIndex'] = __('Dropping Primary Key/Index'); @@ -120,6 +118,10 @@ $js_messages['strShowSearchResults'] = __('Show search results'); $js_messages['strBrowsing'] = __('Browsing'); $js_messages['strDeleting'] = __('Deleting');
+/* For db_routines.js */ +$js_messages['MissingReturn'] = __('The definition of a stored function must contain a RETURN statement!'); +$js_messages['strValueTooLong'] = __('Value too long in the form!'); + /* For import.js */ $js_messages['strImportCSV'] = __('Note: If the file contains multiple tables, they will be combined into one');
diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 5be5c76..a0b8628 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -371,6 +371,7 @@ $goto_whitelist = array( 'db_operations.php', 'db_printview.php', 'db_search.php', + 'db_routines.php', //'Documentation.html', 'export.php', 'import.php', diff --git a/libraries/common.lib.php b/libraries/common.lib.php index d2c8249..a9b87f9 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -840,7 +840,6 @@ function PMA_backquote($a_name, $do_it = true) } } // end of the 'PMA_backquote()' function
- /** * Defines the <CR><LF> value depending on the user OS. * @@ -2959,6 +2958,275 @@ function PMA_buildActionTitles() { $titles['Empty'] = PMA_getIcon('b_empty.png', __('Empty'), true); $titles['NoEmpty'] = PMA_getIcon('bd_empty.png', __('Empty'), true); $titles['Edit'] = PMA_getIcon('b_edit.png', __('Edit'), true); + $titles['NoEdit'] = PMA_getIcon('bd_edit.png', __('Edit'), true); + $titles['Export'] = PMA_getIcon('b_export.png', __('Export'), true); + $titles['NoExport'] = PMA_getIcon('bd_export.png', __('Export'), true); + $titles['Execute'] = PMA_getIcon('b_nextpage.png', __('Execute'), true); + $titles['NoExecute'] = PMA_getIcon('bd_nextpage.png', __('Execute'), true); return $titles; } + +/** + * This function processes the datatypes supported by the DB, as specified in + * $cfg['ColumnTypes'] and either returns an array (useful for quickly checking + * if a datatype is supported) or an HTML snippet that creates a drop-down list. + * + * @param bool $html Whether to generate an html snippet or an array + * @param string $selected The value to mark as selected in HTML mode + * + * @return mixed An HTML snippet or an array of datatypes. + * + * @uses htmlspecialchars() + * @uses in_array() + */ +function PMA_getSupportedDatatypes($html = false, $selected = '') +{ + global $cfg; + + if ($html) { + // NOTE: the SELECT tag in not included in this snippet. + $retval = ''; + foreach ($cfg['ColumnTypes'] as $key => $value) { + if (is_array($value)) { + $retval .= "<optgroup label='" . htmlspecialchars($key) . "'>"; + foreach ($value as $subkey => $subvalue) { + if ($subvalue == $selected) { + $retval .= "<option selected='selected'>"; + $retval .= $subvalue; + $retval .= "</option>"; + } else if ($subvalue === '-') { + $retval .= "<option disabled='disabled'>"; + $retval .= $subvalue; + $retval .= "</option>"; + } else { + $retval .= "<option>$subvalue</option>"; + } + } + $retval .= '</optgroup>'; + } else { + if ($selected == $value) { + $retval .= "<option selected='selected'>$value</option>"; + } else { + $retval .= "<option>$value</option>"; + } + } + } + } else { + $retval = array(); + foreach ($cfg['ColumnTypes'] as $key => $value) { + if (is_array($value)) { + foreach ($value as $subkey => $subvalue) { + if ($subvalue !== '-') { + $retval[] = $subvalue; + } + } + } else { + if ($value !== '-') { + $retval[] = $value; + } + } + } + } + + return $retval; +} // end PMA_getSupportedDatatypes() + +/** + * Returns a list of datatypes that are not (yet) handled by PMA. + * Used by: tbl_change.php and libraries/db_routines.inc.php + * + * @return array list of datatypes + */ + +function PMA_unsupportedDatatypes() { + // These GIS data types are not yet supported. + $no_support_types = array('geometry', + 'point', + 'linestring', + 'polygon', + 'multipoint', + 'multilinestring', + 'multipolygon', + 'geometrycollection' + ); + + return $no_support_types; +} + +/** + * Creates a dropdown box with MySQL functions for a particular column. + * + * @param array $field Data about the column for which + * to generate the dropdown + * @param bool $insert_mode Whether the operation is 'insert' + * + * @global array $cfg PMA configuration + * @global array $analyzed_sql Analyzed SQL query + * @global mixed $data (null/string) FIXME: what is this for? + * + * @return string An HTML snippet of a dropdown list with function + * names appropriate for the requested column. + */ +function PMA_getFunctionsForField($field, $insert_mode) +{ + global $cfg, $analyzed_sql, $data; + + $selected = ''; + // Find the current type in the RestrictColumnTypes. Will result in 'FUNC_CHAR' + // or something similar. Then directly look up the entry in the RestrictFunctions array, + // which will then reveal the available dropdown options + if (isset($cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])]) + && isset($cfg['RestrictFunctions'][$cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])]])) { + $current_func_type = $cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])]; + $dropdown = $cfg['RestrictFunctions'][$current_func_type]; + $default_function = $cfg['DefaultFunctions'][$current_func_type]; + } else { + $dropdown = array(); + $default_function = ''; + } + $dropdown_built = array(); + $op_spacing_needed = false; + // what function defined as default? + // for the first timestamp we don't set the default function + // if there is a default value for the timestamp + // (not including CURRENT_TIMESTAMP) + // and the column does not have the + // ON UPDATE DEFAULT TIMESTAMP attribute. + if ($field['True_Type'] == 'timestamp' + && empty($field['Default']) + && empty($data) + && ! isset($analyzed_sql[0]['create_table_fields'][$field['Field']]['on_update_current_timestamp'])) { + $default_function = $cfg['DefaultFunctions']['first_timestamp']; + } + // For primary keys of type char(36) or varchar(36) UUID if the default function + // Only applies to insert mode, as it would silently trash data on updates. + if ($insert_mode + && $field['Key'] == 'PRI' + && ($field['Type'] == 'char(36)' || $field['Type'] == 'varchar(36)') + ) { + $default_function = $cfg['DefaultFunctions']['pk_char36']; + } + // this is set only when appropriate and is always true + if (isset($field['display_binary_as_hex'])) { + $default_function = 'UNHEX'; + } + + // Create the output + $retval = ' <option></option>' . "\n"; + // loop on the dropdown array and print all available options for that field. + foreach ($dropdown as $each_dropdown){ + $retval .= ' '; + $retval .= '<option'; + if ($default_function === $each_dropdown) { + $retval .= ' selected="selected"'; + } + $retval .= '>' . $each_dropdown . '</option>' . "\n"; + $dropdown_built[$each_dropdown] = 'true'; + $op_spacing_needed = true; + } + // For compatibility's sake, do not let out all other functions. Instead + // print a separator (blank) and then show ALL functions which weren't shown + // yet. + $cnt_functions = count($cfg['Functions']); + for ($j = 0; $j < $cnt_functions; $j++) { + if (! isset($dropdown_built[$cfg['Functions'][$j]]) || $dropdown_built[$cfg['Functions'][$j]] != 'true') { + // Is current function defined as default? + $selected = ($field['first_timestamp'] && $cfg['Functions'][$j] == $cfg['DefaultFunctions']['first_timestamp']) + || (!$field['first_timestamp'] && $cfg['Functions'][$j] == $default_function) + ? ' selected="selected"' + : ''; + if ($op_spacing_needed == true) { + $retval .= ' '; + $retval .= '<option value="">--------</option>' . "\n"; + $op_spacing_needed = false; + } + + $retval .= ' '; + $retval .= '<option' . $selected . '>' . $cfg['Functions'][$j] . '</option>' . "\n"; + } + } // end for + + return $retval; +} // end PMA_getFunctionsForField() + +/** + * Checks if the current user has a specific privilege and returns true if the + * user indeed has that privilege or false if (s)he doesn't. This function must + * only be used for features that are available since MySQL 5, because it + * relies on the INFORMATION_SCHEMA database to be present. + * + * Example: PMA_currentUserHasPrivilege('CREATE ROUTINE', 'mydb'); + * // Checks if the currently logged in user has the global + * // 'CREATE ROUTINE' privilege or, if not, checks if the + * // user has this privilege on database 'mydb'. + * + * @uses PMA_DBI_fetch_value() + * @uses explode() + * @uses str_replace() + * @uses sprintf() + * + * @param string $priv The privilege to check + * @param mixed $db null, to only check global privileges + * string, db name where to also check for privileges + * @param mixed $tbl null, to only check global privileges + * string, db name where to also check for privileges + */ +function PMA_currentUserHasPrivilege($priv, $db = null, $tbl = null) +{ + // Get the username for the current user in the format + // required to use in the information schema database. + $user = PMA_DBI_fetch_value("SELECT CURRENT_USER();"); + if ($user === false) { + return false; + } + $user = explode('@', $user); + $username = "''"; + $username .= str_replace("'", "''", $user[0]); + $username .= "''@''"; + $username .= str_replace("'", "''", $user[1]); + $username .= "''"; + // Prepage the query + $query = "SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`%s` " + . "WHERE GRANTEE='%s' AND PRIVILEGE_TYPE='%s'"; + // Check global privileges first. + if (PMA_DBI_fetch_value(sprintf($query, + 'USER_PRIVILEGES', + $username, + $priv))) { + return true; + } + // If a database name was provided and user does not have the + // required global privilege, try database-wise permissions. + if ($db !== null) { + $query .= " AND TABLE_SCHEMA='%s'"; + if (PMA_DBI_fetch_value(sprintf($query, + 'SCHEMA_PRIVILEGES', + $username, + $priv, + PMA_sqlAddslashes($db)))) { + return true; + } + } else { + // There was no database name provided and the user + // does not have the correct global privilege. + return false; + } + // If a table name was also provided and we still didn't + // find any valid privileges, try table-wise privileges. + if ($tbl !== null) { + $query .= " AND TABLE_NAME='%s'"; + if ($retval = PMA_DBI_fetch_value(sprintf($query, + 'TABLE_PRIVILEGES', + $username, + $priv, + PMA_sqlAddslashes($db), + PMA_sqlAddslashes($tbl)))) { + return true; + } + } + // If we reached this point, the user does not + // have even valid table-wise privileges. + return false; +} + ?> diff --git a/libraries/database_interface.lib.php b/libraries/database_interface.lib.php index d8d48df..5e61ef8 100644 --- a/libraries/database_interface.lib.php +++ b/libraries/database_interface.lib.php @@ -1424,7 +1424,7 @@ function PMA_DBI_get_definition($db, $which, $name, $link = null) }
/** - * returns details about the TRIGGERs of a specific table + * returns details about the TRIGGERs for a specific table or database * * @uses PMA_DBI_fetch_result() * @param string $db db name @@ -1433,20 +1433,25 @@ function PMA_DBI_get_definition($db, $which, $name, $link = null) * * @return array information about triggers (may be empty) */ -function PMA_DBI_get_triggers($db, $table, $delimiter = '//') +function PMA_DBI_get_triggers($db, $table = '', $delimiter = '//') { $result = array(); - if (! $GLOBALS['cfg']['Server']['DisableIS']) { - // Note: in http://dev.mysql.com/doc/refman/5.0/en/faqs-triggers.html - // their example uses WHERE TRIGGER_SCHEMA='dbname' so let's use this - // instead of WHERE EVENT_OBJECT_SCHEMA='dbname' - $triggers = PMA_DBI_fetch_result("SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA= '" . PMA_sqlAddslashes($db,true) . "' and EVENT_OBJECT_TABLE = '" . PMA_sqlAddslashes($table, true) . "';"); + // Note: in http://dev.mysql.com/doc/refman/5.0/en/faqs-triggers.html + // their example uses WHERE TRIGGER_SCHEMA='dbname' so let's use this + // instead of WHERE EVENT_OBJECT_SCHEMA='dbname' + $query = "SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA= '" . PMA_sqlAddslashes($db,true) . "';"; + if (! empty($table)) { + $query .= " AND EVENT_OBJECT_TABLE = '" . PMA_sqlAddslashes($table, true) . "';"; + } } else { - $triggers = PMA_DBI_fetch_result("SHOW TRIGGERS FROM " . PMA_backquote(PMA_sqlAddslashes($db,true)) . " LIKE '" . PMA_sqlAddslashes($table, true) . "';"); + $query = "SHOW TRIGGERS FROM " . PMA_backquote(PMA_sqlAddslashes($db,true)); + if (! empty($table)) { + $query .= " LIKE '" . PMA_sqlAddslashes($table, true) . "';"; + } }
- if ($triggers) { + if ($triggers = PMA_DBI_fetch_result($query)) { foreach ($triggers as $trigger) { if ($GLOBALS['cfg']['Server']['DisableIS']) { $trigger['TRIGGER_NAME'] = $trigger['Trigger']; @@ -1457,6 +1462,7 @@ function PMA_DBI_get_triggers($db, $table, $delimiter = '//') } $one_result = array(); $one_result['name'] = $trigger['TRIGGER_NAME']; + $one_result['table'] = $trigger['EVENT_OBJECT_TABLE']; $one_result['action_timing'] = $trigger['ACTION_TIMING']; $one_result['event_manipulation'] = $trigger['EVENT_MANIPULATION'];
diff --git a/libraries/db_events.inc.php b/libraries/db_events.inc.php index 6e93299..f924026 100644 --- a/libraries/db_events.inc.php +++ b/libraries/db_events.inc.php @@ -10,52 +10,139 @@ if (! defined('PHPMYADMIN')) {
$events = PMA_DBI_fetch_result('SELECT EVENT_NAME, EVENT_TYPE FROM information_schema.EVENTS WHERE EVENT_SCHEMA= '' . PMA_sqlAddslashes($db,true) . '';');
-if ($events) { - PMA_generate_slider_effect('events', __('Events')); - echo '<fieldset>' . "\n"; - echo ' <legend>' . __('Events') . '</legend>' . "\n"; - echo '<table border="0">'; +$conditional_class_add = ''; +$conditional_class_drop = ''; +$conditional_class_export = ''; +if ($GLOBALS['cfg']['AjaxEnable']) { + $conditional_class_add = 'class="add_event_anchor"'; + $conditional_class_drop = 'class="drop_event_anchor"'; + $conditional_class_export = 'class="export_event_anchor"'; +} + +/** + * Display the export for a event. This is for when JS is disabled. + */ +if (! empty($_GET['exportevent']) && ! empty($_GET['eventname'])) { + $event_name = htmlspecialchars(PMA_backquote($_GET['eventname'])); + if ($create_event = PMA_DBI_get_definition($db, 'EVENT', $_GET['eventname'])) { + $create_event = '<textarea cols="40" rows="15" style="width: 100%;">' . $create_event . '</textarea>'; + if (! empty($_REQUEST['ajax_request'])) { + $extra_data = array('title' => sprintf(__('Export of event %s'), $event_name)); + PMA_ajaxResponse($create_event, true, $extra_data); + } else { + echo '<fieldset>' . "\n" + . ' <legend>' . sprintf(__('Export of event "%s"'), $event_name) . '</legend>' . "\n" + . $create_event + . '</fieldset>'; + } + } else { + $response = __('Error in Processing Request') . ' : ' + . sprintf(__('No event with name %s found in database %s'), + $event_name, htmlspecialchars(PMA_backquote($db))); + $response = PMA_message::error($response); + if (! empty($_REQUEST['ajax_request'])) { + PMA_ajaxResponse($response, false); + } else { + $response->display(); + } + } +} + +/** + * Display a list of available events + */ +echo "\n\n<span id='js_query_display'></span>\n\n"; +echo '<fieldset>' . "\n"; +echo ' <legend>' . __('Events') . '</legend>' . "\n"; +if (! $events) { + echo __('There are no events to display.'); +} else { + echo '<div class="hide" id="nothing2display">' . __('There are no events to display.') . '</div>'; + echo '<table class="data">'; echo sprintf('<tr> <th>%s</th> - <th> </th> - <th> </th> + <th colspan="3">%s</th> <th>%s</th> </tr>', __('Name'), + __('Action'), __('Type')); $ct=0; $delimiter = '//'; - if ($GLOBALS['cfg']['AjaxEnable']) { - $conditional_class = 'class="drop_event_anchor"'; - } else { - $conditional_class = ''; - } foreach ($events as $event) {
// information_schema (at least in MySQL 5.1.22) does not return // the full CREATE EVENT statement in a way that could be useful for us // so we rely on PMA_DBI_get_definition() which uses SHOW CREATE EVENT
- $definition = 'DROP EVENT ' . PMA_backquote($event['EVENT_NAME']) . $delimiter . "\n" - . PMA_DBI_get_definition($db, 'EVENT', $event['EVENT_NAME']) - . "\n"; + $create_event = PMA_DBI_get_definition($db, 'EVENT', $event['EVENT_NAME']); + $definition = 'DROP EVENT IF EXISTS ' . PMA_backquote($event['EVENT_NAME']) + . $delimiter . "\n" . $create_event . "\n";
$sqlDrop = 'DROP EVENT ' . PMA_backquote($event['EVENT_NAME']); echo sprintf('<tr class="%s"> - <td><strong>%s</strong></td> + <td><span class="drop_sql" style="display:none;">%s</span><strong>%s</strong></td> <td>%s</td> + <td><div class="create_sql" style="display: none;">%s</div>%s</td> <td>%s</td> <td>%s</td> </tr>', ($ct%2 == 0) ? 'even' : 'odd', + $sqlDrop, $event['EVENT_NAME'], - ! empty($definition) ? PMA_linkOrButton('db_sql.php?' . $url_query . '&sql_query=' . urlencode($definition) . '&show_query=1&db_query_force=1&delimiter=' . urlencode($delimiter), $titles['Structure']) : ' ', - '<a ' . $conditional_class . ' href="sql.php?' . $url_query . '&sql_query=' . urlencode($sqlDrop) . '" >' . $titles['Drop'] . '</a>', + ! empty($definition) ? PMA_linkOrButton('db_sql.php?' . $url_query . '&sql_query=' . urlencode($definition) . '&show_query=1&db_query_force=1&delimiter=' . urlencode($delimiter), $titles['Edit']) : ' ', + $create_event, + '<a ' . $conditional_class_export . ' href="db_events.php?' . $url_query + . '&exportevent=1' + . '&eventname=' . urlencode($event['EVENT_NAME']) + . '">' . $titles['Export'] . '</a>', + '<a ' . $conditional_class_drop . ' href="sql.php?' . $url_query . '&sql_query=' . urlencode($sqlDrop) . '" >' . $titles['Drop'] . '</a>', $event['EVENT_TYPE']); $ct++; } echo '</table>'; - echo '</fieldset>' . "\n"; - echo '</div>' . "\n"; } +echo '</fieldset>' . "\n"; + +/** + * If there has been a request to change the state + * of the event scheduler, process it now. + */ +if (! empty($_GET['toggle_scheduler'])) { + $new_scheduler_state = $_GET['toggle_scheduler']; + if ($new_scheduler_state === 'ON' || $new_scheduler_state === 'OFF') { + PMA_DBI_query("SET GLOBAL event_scheduler='$new_scheduler_state'"); + } +} + +/** + * Prepare to show the event scheduler fieldset, if necessary + */ +$tableStart = ''; +$schedulerFieldset = ''; +$es_state = PMA_DBI_fetch_value("SHOW GLOBAL VARIABLES LIKE 'event_scheduler'", 0, 1); +if ($es_state === 'ON' || $es_state === 'OFF') { + $es_change = ($es_state == 'ON') ? 'OFF' : 'ON'; + $tableStart = '<table style="width: 100%;"><tr><td style="width: 50%;">'; + $schedulerFieldset = '</td><td><fieldset style="margin: 1em 0;">' . "\n" + . PMA_getIcon('b_events.png') . __('The event scheduler is ') . $es_state . ':' + . ' <a href="db_events.php?' . $url_query . '&toggle_scheduler=' . $es_change . '">' + . __('Turn') . " $es_change\n" . '</a>' . "\n" + . '</fieldset></td></tr></table>' . "\n"; +} + +/** + * Display the form for adding a new event + */ +echo $tableStart . '<fieldset style="margin: 1em 0;">' . "\n" + . ' <a href="db_events.php?' . $url_query . '&addevent=1" ' . $conditional_class_add . '>' . "\n" + . PMA_getIcon('b_event_add.png') . __('Add a new Event') . '</a>' . "\n" + . '</fieldset>' . "\n"; + +/** + * Display the state of the event scheduler + * and offer an option to toggle it. + */ +echo $schedulerFieldset; + ?> diff --git a/libraries/db_links.inc.php b/libraries/db_links.inc.php index 7eaf343..cb276d5 100644 --- a/libraries/db_links.inc.php +++ b/libraries/db_links.inc.php @@ -93,6 +93,17 @@ if (! $db_is_information_schema) { $tab_privileges['text'] = __('Privileges'); $tab_privileges['icon'] = 's_rights.png'; } + $tab_routines['link'] = 'db_routines.php'; + $tab_routines['text'] = __('Routines'); + $tab_routines['icon'] = 'b_routines.png'; + + $tab_events['link'] = 'db_events.php'; + $tab_events['text'] = __('Events'); + $tab_events['icon'] = 'b_events.png'; + + $tab_triggers['link'] = 'db_triggers.php'; + $tab_triggers['text'] = __('Triggers'); + $tab_triggers['icon'] = 'b_triggers.png'; }
/** @@ -110,6 +121,15 @@ if (! $db_is_information_schema) { if ($is_superuser) { $tabs[] =& $tab_privileges; } + if (PMA_MYSQL_INT_VERSION >= 50002 && ! PMA_DRIZZLE) { + $tabs[] =& $tab_routines; + } + if (PMA_MYSQL_INT_VERSION >= 50106 && ! PMA_DRIZZLE) { + $tabs[] =& $tab_events; + } + if (PMA_MYSQL_INT_VERSION >= 50002 && ! PMA_DRIZZLE) { + $tabs[] =& $tab_triggers; + } } if (PMA_Tracker::isActive()) { $tabs[] =& $tab_tracking; diff --git a/libraries/db_routines.inc.php b/libraries/db_routines.inc.php deleted file mode 100644 index d6a5b07..0000000 --- a/libraries/db_routines.inc.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * - * @todo Support seeing the "results" of the called procedure or - * function. This needs further reseach because a procedure - * does not necessarily contain a SELECT statement that - * produces something to see. But it seems we could at least - * get the number of rows affected. We would have to - * use the CLIENT_MULTI_RESULTS flag to get the result set - * and also the call status. All this does not fit well with - * our current sql.php. - * Of course the interface would need a way to pass calling parameters. - * Also, support DEFINER (like we do in export). - * @package phpMyAdmin - */ -if (! defined('PHPMYADMIN')) { - exit; -} - -$routines = PMA_DBI_fetch_result('SELECT SPECIFIC_NAME,ROUTINE_NAME,ROUTINE_TYPE,DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA= \'' . PMA_sqlAddslashes($db,true) . '\';'); - -if ($routines) { - PMA_generate_slider_effect('routines', __('Routines')); - echo '<fieldset>' . "\n"; - echo ' <legend>' . __('Routines') . '</legend>' . "\n"; - echo '<table border="0">'; - echo sprintf('<tr> - <th>%s</th> - <th> </th> - <th> </th> - <th>%s</th> - <th>%s</th> - </tr>', - __('Name'), - __('Type'), - __('Return type')); - $ct=0; - $delimiter = '//'; - if ($GLOBALS['cfg']['AjaxEnable']) { - $conditional_class = 'class="drop_procedure_anchor"'; - } else { - $conditional_class = ''; - } - - foreach ($routines as $routine) { - - // information_schema (at least in MySQL 5.0.45) - // does not return the routine parameters - // so we rely on PMA_DBI_get_definition() which - // uses SHOW CREATE - - $definition = 'DROP ' . $routine['ROUTINE_TYPE'] . ' ' . PMA_backquote($routine['SPECIFIC_NAME']) . $delimiter . "\n" - . PMA_DBI_get_definition($db, $routine['ROUTINE_TYPE'], $routine['SPECIFIC_NAME']) - . "\n"; - - //if ($routine['ROUTINE_TYPE'] == 'PROCEDURE') { - // $sqlUseProc = 'CALL ' . $routine['SPECIFIC_NAME'] . '()'; - //} else { - // $sqlUseProc = 'SELECT ' . $routine['SPECIFIC_NAME'] . '()'; - /* this won't get us far: to really use the function - i'd need to know how many parameters the function needs and then create - something to ask for them. As i don't see this directly in - the table i am afraid that requires parsing the ROUTINE_DEFINITION - and i don't really need that now so i simply don't offer - a method for running the function*/ - //} - if ($routine['ROUTINE_TYPE'] == 'PROCEDURE') { - $sqlDropProc = 'DROP PROCEDURE ' . PMA_backquote($routine['SPECIFIC_NAME']); - } else { - $sqlDropProc = 'DROP FUNCTION ' . PMA_backquote($routine['SPECIFIC_NAME']); - } - - echo sprintf('<tr class="%s"> - <td><input type="hidden" class="drop_procedure_sql" value="%s" /><strong>%s</strong></td> - <td>%s</td> - <td>%s</td> - <td>%s</td> - <td>%s</td> - </tr>', - ($ct%2 == 0) ? 'even' : 'odd', - $sqlDropProc, - $routine['ROUTINE_NAME'], - ! empty($definition) ? PMA_linkOrButton('db_sql.php?' . $url_query . '&sql_query=' . urlencode($definition) . '&show_query=1&db_query_force=1&delimiter=' . urlencode($delimiter), $titles['Edit']) : ' ', - '<a ' . $conditional_class . ' href="sql.php?' . $url_query . '&sql_query=' . urlencode($sqlDropProc) . '" >' . $titles['Drop'] . '</a>', - $routine['ROUTINE_TYPE'], - $routine['DTD_IDENTIFIER']); - $ct++; - } - echo '</table>'; - echo '</fieldset>' . "\n"; - echo '</div>' . "\n"; -} -?> diff --git a/libraries/db_routines.lib.php b/libraries/db_routines.lib.php new file mode 100644 index 0000000..13859cf --- /dev/null +++ b/libraries/db_routines.lib.php @@ -0,0 +1,1265 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @package phpMyAdmin + */ +if (! defined('PHPMYADMIN')) { + exit; +} + +/** + * This function parses a string containing one parameter of a routine, + * as returned by PMA_RTN_parseAllParameters() and returns an array containing + * the information about this parameter. + * + * @param string $value A string containing one parameter of a routine + * + * @return array Parsed information about the input parameter + * + * @uses PMA_SQP_parse() + * @uses PMA_unquote() + * @uses in_array() + * @uses strtoupper() + * @uses strtolower() + * @uses sort() + * @uses implode() + */ +function PMA_RTN_parseOneParameter($value) +{ + global $param_directions; + + $retval = array(0 => '', + 1 => '', + 2 => '', + 3 => '', + 4 => ''); + $parsed_param = PMA_SQP_parse($value); + $pos = 0; + if (in_array(strtoupper($parsed_param[$pos]['data']), $param_directions)) { + $retval[0] = strtoupper($parsed_param[0]['data']); + $pos++; + } + if ($parsed_param[$pos]['type'] == 'alpha_identifier' || $parsed_param[$pos]['type'] == 'quote_backtick') { + $retval[1] = PMA_unQuote($parsed_param[$pos]['data']); + $pos++; + } + $depth = 0; + $param_length = ''; + $param_opts = array(); + for ($i=$pos; $i<$parsed_param['len']; $i++) { + if (($parsed_param[$i]['type'] == 'alpha_columnType' + || $parsed_param[$i]['type'] == 'alpha_functionName') // "CHAR" seems to be mistaken for a function by the parser + && $depth == 0) { + $retval[2] = strtoupper($parsed_param[$i]['data']); + } else if ($parsed_param[$i]['type'] == 'punct_bracket_open_round' && $depth == 0) { + $depth = 1; + } else if ($parsed_param[$i]['type'] == 'punct_bracket_close_round' && $depth == 1) { + $depth = 0; + } else if ($depth == 1) { + $param_length .= $parsed_param[$i]['data']; + } else if ($parsed_param[$i]['type'] == 'alpha_reservedWord' && strtoupper($parsed_param[$i]['data']) == 'CHARSET' && $depth == 0) { + if ($parsed_param[$i+1]['type'] == 'alpha_charset' || $parsed_param[$i+1]['type'] == 'alpha_identifier') { + $param_opts[] = strtolower($parsed_param[$i+1]['data']); + } + } else if ($parsed_param[$i]['type'] == 'alpha_columnAttrib' && $depth == 0) { + $param_opts[] = strtoupper($parsed_param[$i]['data']); + } + } + $retval[3] = $param_length; + sort($param_opts); + $retval[4] = implode(' ', $param_opts); + + return $retval; +} // end PMA_RTN_parseOneParameter() + + +/** + * This function looks through the contents of a parsed + * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts + * information about the routine's parameters. + * + * @param array $parsed_query Parsed query, returned by by PMA_SQP_parse() + * @param string $routine_type Routine type: 'PROCEDURE' or 'FUNCTION' + * + * @return array Information about the parameteres of a routine. + * + * @uses PMA_RTN_parseOneParameter() + */ +function PMA_RTN_parseAllParameters($parsed_query, $routine_type) +{ + global $param_directions; + + $retval = array(); + $retval['num'] = 0; + + // First get the list of parameters from the query + $buffer = ''; + $params = array(); + $fetching = false; + $depth = 0; + for ($i=0; $i<$parsed_query['len']; $i++) { + if ($parsed_query[$i]['type'] == 'alpha_reservedWord' && $parsed_query[$i]['data'] == $routine_type) { + $fetching = true; + } else if ($fetching == true && $parsed_query[$i]['type'] == 'punct_bracket_open_round') { + $depth++; + if ($depth > 1) { + $buffer .= $parsed_query[$i]['data'] . ' '; + } + } else if ($fetching == true && $parsed_query[$i]['type'] == 'punct_bracket_close_round') { + $depth--; + if ($depth > 0) { + $buffer .= $parsed_query[$i]['data'] . ' '; + } else { + break; + } + } else if ($parsed_query[$i]['type'] == 'punct_listsep' && $depth == 1) { + $params[] = $buffer; + $retval['num']++; + $buffer = ''; + } else if ($fetching == true && $depth > 0) { + $buffer .= $parsed_query[$i]['data'] . ' '; + } + } + if (! empty($buffer)) { + $params[] = $buffer; + $retval['num']++; + } + // Now parse each parameter individually + foreach ($params as $key => $value) { + list($retval['dir'][], + $retval['name'][], + $retval['type'][], + $retval['length'][], + $retval['opts'][]) = PMA_RTN_parseOneParameter($value); + } + // Since some indices of $retval may be still undefined, we fill + // them each with an empty array to avoid E_ALL errors in PHP. + foreach (array('dir', 'name', 'type', 'length', 'opts') as $key => $index) { + if (! isset($retval[$index])) { + $retval[$index] = array(); + } + } + + return $retval; +} // end PMA_RTN_parseAllParameters() + +/** + * This function looks through the contents of a parsed + * SHOW CREATE [PROCEDURE | FUNCTION] query and extracts + * information about the routine's definer. + * + * @param array $parsed_query Parsed query, returned by PMA_SQP_parse() + * + * @return string The definer of a routine. + * + * @uses substr() + * @uses PMA_unQuote() + */ +function PMA_RTN_parseRoutineDefiner($parsed_query) +{ + $retval = ''; + $fetching = false; + for ($i=0; $i<$parsed_query['len']; $i++) { + if ($parsed_query[$i]['type'] == 'alpha_reservedWord' && $parsed_query[$i]['data'] == 'DEFINER') { + $fetching = true; + } else if ($fetching == true && + ($parsed_query[$i]['type'] != 'quote_backtick' && substr($parsed_query[$i]['type'], 0, 5) != 'punct')) { + break; + } else if ($fetching == true && $parsed_query[$i]['type'] == 'quote_backtick') { + $retval .= PMA_unQuote($parsed_query[$i]['data']); + } else if ($fetching == true && $parsed_query[$i]['type'] == 'punct_user') { + $retval .= $parsed_query[$i]['data']; + } + } + return $retval; +} // end PMA_RTN_parseRoutineDefiner() + +/** + * This function will generate the values that are required to complete + * the "Edit routine" form given the name of a routine. + * + * @param string $db The database that the routine belogs to. + * @param string $name The name of the routine. + * @param bool $all Whether to return all data or just + * the info about parameters. + * + * @return array Data necessary to create the routine editor. + * + * @uses PMA_sqlAddslashes() + * @uses PMA_DBI_fetch_single_row() + * @uses PMA_SQP_parse() + * @uses PMA_DBI_get_definition() + * @uses PMA_RTN_parseAllParameters() + * @uses PMA_RTN_parseRoutineDefiner() + * @uses PMA_RTN_parseOneParameter() + */ +function PMA_RTN_getRoutineDataFromName($db, $name, $all = true) +{ + global $param_directions, $param_sqldataaccess; + + $retval = array(); + + // Build and execute the query + $fields = "SPECIFIC_NAME, ROUTINE_TYPE, DTD_IDENTIFIER, " + . "ROUTINE_DEFINITION, IS_DETERMINISTIC, SQL_DATA_ACCESS, " + . "ROUTINE_COMMENT, SECURITY_TYPE"; + $where = "ROUTINE_SCHEMA='" . PMA_sqlAddslashes($db) . "' " + . "AND SPECIFIC_NAME='" . PMA_sqlAddslashes($name) . "'"; + $query = "SELECT $fields FROM INFORMATION_SCHEMA.ROUTINES WHERE $where;"; + + $routine = PMA_DBI_fetch_single_row($query); + + if (! $routine) { + return false; + } + + // Get required data + $retval['name'] = $routine['SPECIFIC_NAME']; + $retval['type'] = $routine['ROUTINE_TYPE']; + $parsed_query = PMA_SQP_parse( + PMA_DBI_get_definition( + $db, + $routine['ROUTINE_TYPE'], + $routine['SPECIFIC_NAME'] + ) + ); + $params = PMA_RTN_parseAllParameters($parsed_query, $routine['ROUTINE_TYPE']); + $retval['num_params'] = $params['num']; + $retval['param_dir'] = $params['dir']; + $retval['param_name'] = $params['name']; + $retval['param_type'] = $params['type']; + $retval['param_length'] = $params['length']; + $retval['param_opts_num'] = $params['opts']; + $retval['param_opts_text'] = $params['opts']; + + // Get extra data + if ($all) { + if ($retval['type'] == 'FUNCTION') { + $retval['type_toggle'] = 'PROCEDURE'; + } else { + $retval['type_toggle'] = 'FUNCTION'; + } + $retval['returntype'] = ''; + $retval['returnlength'] = ''; + $retval['returnopts_num'] = ''; + $retval['returnopts_text'] = ''; + if (! empty($routine['DTD_IDENTIFIER'])) { + if (strlen($routine['DTD_IDENTIFIER']) > 63) { + // If the DTD_IDENTIFIER string from INFORMATION_SCHEMA is + // at least 64 characters, then it may actually have been + // chopped because that column is a varchar(64), so we will + // parse the output of SHOW CREATE query to get accurate + // information about the return variable. + $dtd = ''; + $fetching = false; + for ($i=0; $i<$parsed_query['len']; $i++) { + if ($parsed_query[$i]['type'] == 'alpha_reservedWord' + && strtoupper($parsed_query[$i]['data']) == 'RETURNS') { + $fetching = true; + } else if ($fetching == true + && $parsed_query[$i]['type'] == 'alpha_reservedWord') { + // We will not be looking for options such as UNSIGNED + // or ZEROFILL because there is no way that a numeric + // field's DTD_IDENTIFIER can be longer than 64 + // characters. We can safely assume that the return + // datatype is either ENUM or SET, so we only look + // for CHARSET. + $word = strtoupper($parsed_query[$i]['data']); + if ($word == 'CHARSET' + && ($parsed_query[$i+1]['type'] == 'alpha_charset' + || $parsed_query[$i+1]['type'] == 'alpha_identifier')) { + $dtd .= $word . ' ' . $parsed_query[$i+1]['data']; + } + break; + } else if ($fetching == true) { + $dtd .= $parsed_query[$i]['data'] . ' '; + } + } + $routine['DTD_IDENTIFIER'] = $dtd; + } + $returnparam = PMA_RTN_parseOneParameter($routine['DTD_IDENTIFIER']); + $retval['returntype'] = $returnparam[2]; + $retval['returnlength'] = $returnparam[3]; + $retval['returnopts_num'] = $returnparam[4]; + $retval['returnopts_text'] = $returnparam[4]; + } + $retval['definer'] = PMA_RTN_parseRoutineDefiner($parsed_query); + $retval['definition'] = $routine['ROUTINE_DEFINITION']; + $retval['isdeterministic'] = ''; + if ($routine['IS_DETERMINISTIC'] == 'YES') { + $retval['isdeterministic'] = " checked='checked'"; + } + $retval['securitytype_definer'] = ''; + $retval['securitytype_invoker'] = ''; + if ($routine['SECURITY_TYPE'] == 'DEFINER') { + $retval['securitytype_definer'] = " selected='selected'"; + } else if ($routine['SECURITY_TYPE'] == 'INVOKER') { + $retval['securitytype_invoker'] = " selected='selected'"; + } + $retval['sqldataaccess'] = $routine['SQL_DATA_ACCESS']; + $retval['comment'] = $routine['ROUTINE_COMMENT']; + } + + return $retval; +} // PMA_RTN_getRoutineDataFromName() + +/** + * This function will generate the values that are required to complete the "Add new routine" form + * It is especially necessary to handle the 'Add another parameter', 'Remove last parameter' + * and 'Change routine type' functionalities when JS is disabled. + * + * @return array Data necessary to create the routine editor. + * + * @uses isset() + * @uses is_array() + * @uses in_array() + * @uses strtolower() + * @uses PMA_getSupportedDatatypes() + */ +function PMA_RTN_getRoutineDataFromRequest() +{ + global $_REQUEST, $param_directions, $param_sqldataaccess; + + $retval = array(); + $retval['name'] = ''; + if (isset($_REQUEST['routine_name'])) { + $retval['name'] = $_REQUEST['routine_name']; + } + $retval['original_name'] = ''; + if (isset($_REQUEST['routine_original_name'])) { + $retval['original_name'] = $_REQUEST['routine_original_name']; + } + $retval['type'] = 'PROCEDURE'; + $retval['type_toggle'] = 'FUNCTION'; + if (isset($_REQUEST['routine_type']) && $_REQUEST['routine_type'] == 'FUNCTION') { + $retval['type'] = 'FUNCTION'; + $retval['type_toggle'] = 'PROCEDURE'; + } + $retval['original_type'] = 'PROCEDURE'; + if (isset($_REQUEST['routine_original_type']) && $_REQUEST['routine_original_type'] == 'FUNCTION') { + $retval['original_type'] = 'FUNCTION'; + } + $retval['num_params'] = 0; + $retval['param_dir'] = array(); + $retval['param_name'] = array(); + $retval['param_type'] = array(); + $retval['param_length'] = array(); + $retval['param_opts_num'] = array(); + $retval['param_opts_text'] = array(); + if (isset($_REQUEST['routine_param_name']) + && isset($_REQUEST['routine_param_type']) + && isset($_REQUEST['routine_param_length']) + && isset($_REQUEST['routine_param_opts_num']) + && isset($_REQUEST['routine_param_opts_text']) + && is_array($_REQUEST['routine_param_name']) + && is_array($_REQUEST['routine_param_type']) + && is_array($_REQUEST['routine_param_length']) + && is_array($_REQUEST['routine_param_opts_num']) + && is_array($_REQUEST['routine_param_opts_text'])) { + + if ($_REQUEST['routine_type'] == 'PROCEDURE') { + $temp_num_params = 0; + $retval['param_dir'] = $_REQUEST['routine_param_dir']; + foreach ($retval['param_dir'] as $key => $value) { + if (! in_array($value, $param_directions, true)) { + $retval['param_dir'][$key] = ''; + } + $retval['num_params']++; + } + if ($temp_num_params > $retval['num_params']) { + $retval['num_params'] = $temp_num_params; + } + } + $temp_num_params = 0; + $retval['param_name'] = $_REQUEST['routine_param_name']; + foreach ($retval['param_name'] as $key => $value) { + $retval['param_name'][$key] = $value; + $temp_num_params++; + } + if ($temp_num_params > $retval['num_params']) { + $retval['num_params'] = $temp_num_params; + } + $temp_num_params = 0; + $retval['param_type'] = $_REQUEST['routine_param_type']; + foreach ($retval['param_type'] as $key => $value) { + if (! in_array($value, PMA_getSupportedDatatypes(), true)) { + $retval['param_type'][$key] = ''; + } + $temp_num_params++; + } + if ($temp_num_params > $retval['num_params']) { + $retval['num_params'] = $temp_num_params; + } + $temp_num_params = 0; + $retval['param_length'] = $_REQUEST['routine_param_length']; + foreach ($retval['param_length'] as $key => $value) { + $retval['param_length'][$key] = $value; + $temp_num_params++; + } + if ($temp_num_params > $retval['num_params']) { + $retval['num_params'] = $temp_num_params; + } + $temp_num_params = 0; + $retval['param_opts_num'] = $_REQUEST['routine_param_opts_num']; + foreach ($retval['param_opts_num'] as $key => $value) { + $retval['param_opts_num'][$key] = $value; + $temp_num_params++; + } + if ($temp_num_params > $retval['num_params']) { + $retval['num_params'] = $temp_num_params; + } + $temp_num_params = 0; + $retval['param_opts_text'] = $_REQUEST['routine_param_opts_text']; + foreach ($retval['param_opts_text'] as $key => $value) { + $retval['param_opts_text'][$key] = $value; + $temp_num_params++; + } + if ($temp_num_params > $retval['num_params']) { + $retval['num_params'] = $temp_num_params; + } + } + $retval['returntype'] = ''; + if (isset($_REQUEST['routine_returntype']) && in_array($_REQUEST['routine_returntype'], PMA_getSupportedDatatypes(), true)) { + $retval['returntype'] = $_REQUEST['routine_returntype']; + } + $retval['returnlength'] = ''; + if (isset($_REQUEST['routine_returnlength'])) { + $retval['returnlength'] = $_REQUEST['routine_returnlength']; + } + $retval['returnopts_num'] = ''; + if (isset($_REQUEST['routine_returnopts_num'])) { + $retval['returnopts_num'] = $_REQUEST['routine_returnopts_num']; + } + $retval['returnopts_text'] = ''; + if (isset($_REQUEST['routine_returnopts_text'])) { + $retval['returnopts_text'] = $_REQUEST['routine_returnopts_text']; + } + $retval['definition'] = ''; + if (isset($_REQUEST['routine_definition'])) { + $retval['definition'] = $_REQUEST['routine_definition']; + } + $retval['isdeterministic'] = ''; + if (isset($_REQUEST['routine_isdeterministic']) && strtolower($_REQUEST['routine_isdeterministic']) == 'on') { + $retval['isdeterministic'] = " checked='checked'"; + } + $retval['definer'] = ''; + if (isset($_REQUEST['routine_definer'])) { + $retval['definer'] = $_REQUEST['routine_definer']; + } + $retval['securitytype_definer'] = ''; + $retval['securitytype_invoker'] = ''; + if (isset($_REQUEST['routine_securitytype'])) { + if ($_REQUEST['routine_securitytype'] === 'DEFINER') { + $retval['securitytype_definer'] = " selected='selected'"; + } else if ($_REQUEST['routine_securitytype'] === 'INVOKER') { + $retval['securitytype_invoker'] = " selected='selected'"; + } + } + $retval['sqldataaccess'] = ''; + if (isset($_REQUEST['routine_sqldataaccess']) && in_array($_REQUEST['routine_sqldataaccess'], $param_sqldataaccess, true)) { + $retval['sqldataaccess'] = $_REQUEST['routine_sqldataaccess']; + } + $retval['comment'] = ''; + if (isset($_REQUEST['routine_comment'])) { + $retval['comment'] = $_REQUEST['routine_comment']; + } + + return $retval; +} // end function PMA_RTN_getRoutineDataFromRequest() + +/** + * Creates one row for the parameter table used in the routine editor. + * + * @param array $routine Data for the routine returned by + * PMA_RTN_getRoutineDataFromRequest() or + * PMA_RTN_getRoutineDataFromName() + * @param mixed $index Either a numeric index of the row being processed + * or NULL to create a template row for AJAX request + * @param string $class Class used to hide the direction column, if the + * row is for a stored function. + * + * @return string HTML code of one row of parameter table for the routine editor. + * + * @uses PMA_getSupportedDatatypes() + * @uses PMA_getSupportedCharsets() + */ +function PMA_RTN_getParameterRow($routine = array(), $index = null, $class = '') +{ + global $param_directions, $param_opts_num, $titles; + + if ($index === null) { + // template row for AJAX request + $i = 0; + $index = '%s'; + $drop_class = ''; + $routine = array( + 'param_dir' => array(0 => ''), + 'param_name' => array(0 => ''), + 'param_type' => array(0 => ''), + 'param_length' => array(0 => ''), + 'param_opts_num' => array(0 => ''), + 'param_opts_text' => array(0 => '') + ); + } else if (! empty($routine)) { + // regular row for routine editor + $drop_class = ' hide'; + $i = $index; + } else { + // No input data. This shouldn't happen, + // but better be safe than sorry. + return ''; + } + + // Create the output + $retval = ""; + $retval .= " <tr>\n"; + $retval .= " <td class='routine_direction_cell$class'><select name='routine_param_dir[$index]'>\n"; + foreach ($param_directions as $key => $value) { + $selected = ""; + if (! empty($routine['param_dir'][$i]) && $routine['param_dir'][$i] == $value) { + $selected = " selected='selected'"; + } + $retval .= " <option$selected>$value</option>\n"; + } + $retval .= " </select></td>\n"; + $retval .= " <td><input name='routine_param_name[$index]' type='text'\n"; + $retval .= " value='{$routine['param_name'][$i]}' /></td>\n"; + $retval .= " <td><select name='routine_param_type[$index]'>"; + $retval .= PMA_getSupportedDatatypes(true, $routine['param_type'][$i]) . "\n"; + $retval .= " </select></td>\n"; + $retval .= " <td><input name='routine_param_length[$index]' type='text'\n"; + $retval .= " value='{$routine['param_length'][$i]}' /></td>\n"; + $retval .= " <td class='routine_param_opts_text'>\n"; + $retval .= PMA_generateCharsetDropdownBox(PMA_CSDROPDOWN_CHARSET, + "routine_param_opts_text[$index]", + null, + $routine['param_opts_text'][$i]); + $retval .= " </td>\n"; + $retval .= " <td class='routine_param_opts_num'><select name='routine_param_opts_num[$index]'>\n"; + $retval .= " <option value=''></option>"; + foreach ($param_opts_num as $key => $value) { + $selected = ""; + if (! empty($routine['param_opts_num'][$i]) && $routine['param_opts_num'][$i] == $value) { + $selected = " selected='selected'"; + } + $retval .= "<option$selected>$value</option>"; + } + $retval .= "\n </select></td>\n"; + $retval .= " <td class='routine_param_remove$drop_class' style='vertical-align: middle;'>\n"; + $retval .= " <a href='#' class='routine_param_remove_anchor'>\n"; + $retval .= " {$titles['Drop']}\n"; + $retval .= " </a>\n"; + $retval .= " </td>\n"; + $retval .= " </tr>\n"; + + return $retval; +} // end PMA_RTN_getParameterRow() + +/** + * Displays a form used to add/edit a routine + * + * @param string $mode If the editor will be used edit a routine + * or add a new one: 'edit' or 'add'. + * @param string $operation If the editor was previously invoked with + * JS turned off, this will hold the name of + * the current operation: 'add', remove', 'change' + * @param array $routine Data for the routine returned by + * PMA_RTN_getRoutineDataFromRequest() or + * PMA_RTN_getRoutineDataFromName() + * @param array $errors If the editor was already invoked and there + * has been an error while processing the request + * this array will hold the errors. + * @param bool $is_ajax True, if called from an ajax request + * + * @return string HTML code for the routine editor. + * + * @uses htmlentities() + * @uses PMA_generate_common_hidden_inputs() + * @uses strtoupper() + * @uses PMA_getSupportedDatatypes() + * @uses PMA_getSupportedCharsets() + */ +function PMA_RTN_getEditorForm($mode, $operation, $routine, $errors, $is_ajax) { + global $db, $titles, $param_directions, $param_sqldataaccess, $param_opts_num; + + // Escape special characters + $need_escape = array( + 'original_name', + 'name', + 'returnlength', + 'definition', + 'definer', + 'comment' + ); + foreach($need_escape as $key => $index) { + $routine[$index] = htmlentities($routine[$index], ENT_QUOTES); + } + for ($i=0; $i<$routine['num_params']; $i++) { + $routine['param_name'][$i] = htmlentities($routine['param_name'][$i], ENT_QUOTES); + $routine['param_length'][$i] = htmlentities($routine['param_length'][$i], ENT_QUOTES); + } + + // Handle some logic first + if ($operation == 'change') { + if ($routine['type'] == 'PROCEDURE') { + $routine['type'] = 'FUNCTION'; + $routine['type_toggle'] = 'PROCEDURE'; + } else { + $routine['type'] = 'PROCEDURE'; + $routine['type_toggle'] = 'FUNCTION'; + } + } else if ($operation == 'add' || ($routine['num_params'] == 0 && $mode == 'add' && ! $errors)) { + $routine['param_dir'][] = ''; + $routine['param_name'][] = ''; + $routine['param_type'][] = ''; + $routine['param_length'][] = ''; + $routine['param_opts_num'][] = ''; + $routine['param_opts_text'][] = ''; + $routine['num_params']++; + } else if ($operation == 'remove') { + unset($routine['param_dir'][$routine['num_params']-1]); + unset($routine['param_name'][$routine['num_params']-1]); + unset($routine['param_type'][$routine['num_params']-1]); + unset($routine['param_length'][$routine['num_params']-1]); + unset($routine['param_opts_num'][$routine['num_params']-1]); + unset($routine['param_opts_text'][$routine['num_params']-1]); + $routine['num_params']--; + } + $disable_remove_parameter = ''; + if (! $routine['num_params']) { + $disable_remove_parameter = " color: gray;' disabled='disabled"; + } + $original_routine = ''; + if ($mode == 'edit') { + $original_routine = "<input name='routine_original_name' " + . "type='hidden' value='{$routine['original_name']}'/>\n" + . "<input name='routine_original_type' " + . "type='hidden' value='{$routine['original_type']}'/>\n"; + } + $isfunction_class = ''; + $isprocedure_class = ''; + $isfunction_select = ''; + $isprocedure_select = ''; + if ($routine['type'] == 'PROCEDURE') { + $isfunction_class = ' hide'; + $isprocedure_select = " selected='selected'"; + } else { + $isprocedure_class = ' hide'; + $isfunction_select = " selected='selected'"; + } + + // Create the output + $retval = ""; + $retval .= "<!-- START " . strtoupper($mode) . " ROUTINE FORM -->\n\n"; + $retval .= "<form class='rte_form' action='db_routines.php' method='post'>\n"; + $retval .= "<input name='{$mode}routine' type='hidden' value='1' />\n"; + $retval .= $original_routine; + $retval .= PMA_generate_common_hidden_inputs($db) . "\n"; + $retval .= "<fieldset>\n"; + $retval .= "<legend>" . __('Details') . "</legend>\n"; + $retval .= "<table class='rte_table' style='width: 100%'>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Routine name') . "</td>\n"; + $retval .= " <td><input type='text' name='routine_name' value='{$routine['name']}' /></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Type') . "</td>\n"; + $retval .= " <td>\n"; + if ($is_ajax) { + $retval .= " <select name='routine_type'>\n"; + $retval .= " <option value='PROCEDURE'$isprocedure_select>PROCEDURE</option>\n"; + $retval .= " <option value='FUNCTION'$isfunction_select>FUNCTION</option>\n"; + $retval .= " </select>\n"; + } else { + $retval .= " <input name='routine_type' type='hidden' value='{$routine['type']}' />\n"; + $retval .= " <div style='width: 49%; float: left; text-align: center; font-weight: bold;'>\n"; + $retval .= " {$routine['type']}\n"; + $retval .= " </div>\n"; + $retval .= " <input style='width: 49%;' type='submit' name='routine_changetype'\n"; + $retval .= " value='".sprintf(__('Change to %s'), $routine['type_toggle'])."' />\n"; + } + $retval .= " </td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Parameters') . "</td>\n"; + $retval .= " <td>\n"; + // parameter handling start + $retval .= " <table class='routine_params_table' style='width: 100%;'>\n"; + $retval .= " <tr>\n"; + $retval .= " <th class='routine_direction_cell$isprocedure_class'>" . __('Direction') . "</th>\n"; + $retval .= " <th>" . __('Name') . "</th>\n"; + $retval .= " <th>" . __('Type') . "</th>\n"; + $retval .= " <th>" . __('Length/Values') . "</th>\n"; + $retval .= " <th colspan='2'>" . __('Options') . "</th>\n"; + $retval .= " <th class='routine_param_remove hide'> </th>\n"; + $retval .= " </tr>"; + for ($i=0; $i<$routine['num_params']; $i++) { // each parameter + $retval .= PMA_RTN_getParameterRow($routine, $i, $isprocedure_class); + } + $retval .= " </table>\n"; + $retval .= " </td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td> </td>\n"; + $retval .= " <td>\n"; + $retval .= " <input style='width: 49%;' type='submit' \n"; + $retval .= " name='routine_addparameter'\n"; + $retval .= " value='" . __('Add parameter') . "' />\n"; + $retval .= " <input style='width: 49%;$disable_remove_parameter' type='submit' \n"; + $retval .= " name='routine_removeparameter'\n"; + $retval .= " value='" . __('Remove last parameter') . "' />\n"; + $retval .= " </td>\n"; + $retval .= "</tr>\n"; + // parameter handling end + $retval .= "<tr class='routine_return_row$isfunction_class'>\n"; + $retval .= " <td>" . __('Return type') . "</td>\n"; + $retval .= " <td><select name='routine_returntype'>\n"; + $retval .= PMA_getSupportedDatatypes(true, $routine['returntype']) . "\n"; + $retval .= " </select></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr class='routine_return_row$isfunction_class'>\n"; + $retval .= " <td>" . __('Return length/values') . "</td>\n"; + $retval .= " <td><input type='text' name='routine_returnlength'\n"; + $retval .= " value='{$routine['returnlength']}' /></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr class='routine_return_row$isfunction_class'>\n"; + $retval .= " <td>" . __('Return options') . "</td>\n"; + $retval .= " <td><div>\n"; + $retval .= PMA_generateCharsetDropdownBox(PMA_CSDROPDOWN_CHARSET, + "routine_returnopts_text", + null, + $routine['returnopts_text']) . "\n"; + $retval .= " </div>\n"; + $retval .= " <div><select name='routine_returnopts_num'>\n"; + $retval .= " <option value=''></option>"; + foreach ($param_opts_num as $key => $value) { + $selected = ""; + if (! empty($routine['returnopts_num']) && $routine['returnopts_num'] == $value) { + $selected = " selected='selected'"; + } + $retval .= "<option$selected>$value</option>"; + } + $retval .= "\n </select></div></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Definition') . "</td>\n"; + $retval .= " <td><textarea name='routine_definition' rows='15' cols='40'>{$routine['definition']}</textarea></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Is deterministic') . "</td>\n"; + $retval .= " <td><input type='checkbox' name='routine_isdeterministic'{$routine['isdeterministic']} /></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Definer') . "</td>\n"; + $retval .= " <td><input type='text' name='routine_definer'\n"; + $retval .= " value='{$routine['definer']}' /></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Security type') . "</td>\n"; + $retval .= " <td><select name='routine_securitytype'>\n"; + $retval .= " <option value='DEFINER'{$routine['securitytype_definer']}>DEFINER</option>\n"; + $retval .= " <option value='INVOKER'{$routine['securitytype_invoker']}>INVOKER</option>\n"; + $retval .= " </select></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('SQL data access') . "</td>\n"; + $retval .= " <td><select name='routine_sqldataaccess'>\n"; + foreach ($param_sqldataaccess as $key => $value) { + $selected = ""; + if ($routine['sqldataaccess'] == $value) { + $selected = " selected='selected'"; + } + $retval .= " <option$selected>$value</option>\n"; + } + $retval .= " </select></td>\n"; + $retval .= "</tr>\n"; + $retval .= "<tr>\n"; + $retval .= " <td>" . __('Comment') . "</td>\n"; + $retval .= " <td><input type='text' name='routine_comment'\n"; + $retval .= " value='{$routine['comment']}' /></td>\n"; + $retval .= "</tr>\n"; + $retval .= "</table>\n"; + $retval .= "</fieldset>\n"; + if ($is_ajax) { + $retval .= "<input type='hidden' name='routine_process_{$mode}routine' value='true' />\n"; + $retval .= "<input type='hidden' name='ajax_request' value='true' />\n"; + } else { + $retval .= "<fieldset class='tblFooters routineEditorSubmit'>\n"; + $retval .= " <input type='submit' name='routine_process_{$mode}routine'\n"; + $retval .= " value='" . __('Go') . "' />\n"; + $retval .= "</fieldset>\n"; + } + $retval .= "</form>\n\n"; + $retval .= "<!-- END " . strtoupper($mode) . " ROUTINE FORM -->\n\n"; + + return $retval; +} // end PMA_RTN_getEditorForm() + +/** + * Creates the HTML code that shows the routine execution dialog. + * + * @param array $routine Data for the routine returned by + * PMA_RTN_getRoutineDataFromName() + * @param bool $is_ajax True, if called from an ajax request + * + * @return string HTML code for the routine execution dialog. + * + * @uses PMA_generate_common_hidden_inputs() + * @uses PMA_unsupportedDatatypes() + * @uses stristr() + * @uses in_array() + * @uses strtolower() + * @uses strtoupper() + * @uses isset() + * @uses PMA_SQP_parse() + * @uses htmlentities() + * @uses PMA_unquote() + */ +function PMA_RTN_getExecuteForm($routine, $is_ajax) +{ + global $db, $cfg; + + // Escape special characters + $routine['name'] = htmlentities($routine['name'], ENT_QUOTES); + for ($i=0; $i<$routine['num_params']; $i++) { + $routine['param_name'][$i] = htmlentities($routine['param_name'][$i], ENT_QUOTES); + } + + // Create the output + $retval = ""; + $retval .= "<!-- START ROUTINE EXECUTE FORM -->\n\n"; + $retval .= "<form action='db_routines.php' method='post' class='rte_form'>\n"; + $retval .= "<input type='hidden' name='routine_name' value='{$routine['name']}' />\n"; + $retval .= PMA_generate_common_hidden_inputs($db) . "\n"; + $retval .= "<fieldset>\n"; + if ($is_ajax != true) { + $retval .= "<legend>{$routine['name']}</legend>\n"; + $retval .= "<table class='rte_table'>\n"; + $retval .= "<caption class='tblHeaders'>\n"; + $retval .= __('Routine parameters'); + $retval .= "</caption>\n"; + } else { + $retval .= "<legend>" . __('Routine parameters') . "</legend>\n"; + $retval .= "<table class='rte_table' style='width: 100%;'>\n"; + } + $retval .= "<tr>\n"; + $retval .= "<th>" . __('Name') . "</th>\n"; + $retval .= "<th>" . __('Type') . "</th>\n"; + if ($cfg['ShowFunctionFields']) { + $retval .= "<th>" . __('Function') . "</th>\n"; + } + $retval .= "<th>" . __('Value') . "</th>\n"; + $retval .= "</tr>\n"; + for ($i=0; $i<$routine['num_params']; $i++) { // Each parameter + if ($routine['type'] == 'PROCEDURE' && $routine['param_dir'][$i] == 'OUT') { + continue; + } + $rowclass = ($i % 2 == 0) ? 'even' : 'odd'; + $retval .= "\n<tr class='$rowclass'>\n"; + $retval .= "<td><strong>{$routine['param_name'][$i]}</strong></td>\n"; + $retval .= "<td>{$routine['param_type'][$i]}</td>\n"; + if ($cfg['ShowFunctionFields']) { + $retval .= "<td>\n"; + // Get a list of data types that are not yet supported. + $no_support_types = PMA_unsupportedDatatypes(); + if (stristr($routine['param_type'][$i], 'enum') + || stristr($routine['param_type'][$i], 'set') + || in_array(strtolower($routine['param_type'][$i]), $no_support_types)) { + $retval .= "--\n"; + } else { + $field = array( + 'True_Type' => strtolower($routine['param_type'][$i]), + 'Type' => '', + 'Key' => '', + 'Field' => '', + 'Default' => '', + 'first_timestamp' => false + ); + $retval .= "<select name='funcs[{$routine['param_name'][$i]}]'>"; + $retval .= PMA_getFunctionsForField($field, false); + $retval .= "</select>"; + } + $retval .= "</td>\n"; + } + // Append a class to date/time fields so that + // jQuery can attach a datepicker to them + $class = ''; + if (in_array($routine['param_type'][$i], array('DATETIME', 'TIMESTAMP'))) { + $class = 'datetimefield'; + } else if ($routine['param_type'][$i] == 'DATE') { + $class = 'datefield'; + } + $retval .= "<td style='white-space: nowrap;'>\n"; + if (in_array($routine['param_type'][$i], array('ENUM', 'SET'))) { + $tokens = PMA_SQP_parse($routine['param_length'][$i]); + if ($routine['param_type'][$i] == 'ENUM') { + $input_type = 'radio'; + } else { + $input_type = 'checkbox'; + } + for ($j=0; $j<$tokens['len']; $j++) { + if ($tokens[$j]['type'] != 'punct_listsep') { + $tokens[$j]['data'] = htmlentities(PMA_unquote($tokens[$j]['data']), ENT_QUOTES); + $retval .= "<input name='params[{$routine['param_name'][$i]}][]' " + . "value='{$tokens[$j]['data']}' type='$input_type' />" + . "{$tokens[$j]['data']}<br />\n"; + } + } + } else if (in_array(strtolower($routine['param_type'][$i]), $no_support_types)) { + $retval .= "\n"; + } else { + $retval .= "<input class='$class' type='text' name='params[{$routine['param_name'][$i]}]' />\n"; + } + $retval .= "</td>\n"; + $retval .= "</tr>\n"; + } + $retval .= "\n</table>\n"; + if ($is_ajax != true) { + $retval .= "</fieldset>\n\n"; + $retval .= "<fieldset class='tblFooters'>\n"; + $retval .= " <input type='submit' name='execute_routine'\n"; + $retval .= " value='" . __('Go') . "' />\n"; + $retval .= "</fieldset>\n"; + } else { + $retval .= "<input type='hidden' name='execute_routine' value='true' />"; + $retval .= "<input type='hidden' name='ajax_request' value='true' />"; + } + $retval .= "</form>\n\n"; + $retval .= "<!-- END ROUTINE EXECUTE FORM -->\n\n"; + + return $retval; +} // end PMA_RTN_getExecuteForm() + +/** + * Composes the query necessary to create a routine from an HTTP request. + * + * @return string The CREATE [ROUTINE | PROCEDURE] query. + * + * @uses explode() + * @uses strpos() + * @uses PMA_backquote() + * @uses sprintf() + * @uses htmlspecialchars() + * @uses is_array() + * @uses preg_match() + * @uses count() + * @uses strtoupper() + * @uses strtolower() + */ +function PMA_RTN_getQueryFromRequest() { + global $_REQUEST, $cfg, $routine_errors, $param_sqldataaccess; + + $query = 'CREATE '; + if (! empty($_REQUEST['routine_definer']) && strpos($_REQUEST['routine_definer'], '@') !== false) { + $arr = explode('@', $_REQUEST['routine_definer']); + $query .= 'DEFINER=' . PMA_backquote($arr[0]) . '@' . PMA_backquote($arr[1]) . ' '; + } + if ($_REQUEST['routine_type'] == 'FUNCTION' || $_REQUEST['routine_type'] == 'PROCEDURE') { + $query .= $_REQUEST['routine_type'] . ' '; + } else { + $routine_errors[] = sprintf(__('Invalid routine type: "%s"'), htmlspecialchars($_REQUEST['routine_type'])); + } + if (! empty($_REQUEST['routine_name'])) { + $query .= PMA_backquote($_REQUEST['routine_name']) . ' '; + } else { + $routine_errors[] = __('You must provide a routine name'); + } + $params = ''; + $warned_about_dir = false; + $warned_about_name = false; + $warned_about_length = false; + if ( ! empty($_REQUEST['routine_param_name']) && ! empty($_REQUEST['routine_param_type']) + && ! empty($_REQUEST['routine_param_length']) && is_array($_REQUEST['routine_param_name']) + && is_array($_REQUEST['routine_param_type']) && is_array($_REQUEST['routine_param_length'])) { + + for ($i=0; $i<count($_REQUEST['routine_param_name']); $i++) { + if (! empty($_REQUEST['routine_param_name'][$i]) && ! empty($_REQUEST['routine_param_type'][$i])) { + if ($_REQUEST['routine_type'] == 'PROCEDURE' && ! empty($_REQUEST['routine_param_dir'][$i])) { + $params .= $_REQUEST['routine_param_dir'][$i] . " " . PMA_backquote($_REQUEST['routine_param_name'][$i]) . " " + . $_REQUEST['routine_param_type'][$i]; + } else if ($_REQUEST['routine_type'] == 'FUNCTION') { + $params .= PMA_backquote($_REQUEST['routine_param_name'][$i]) . " " . $_REQUEST['routine_param_type'][$i]; + } else if (! $warned_about_dir) { + $warned_about_dir = true; + $routine_errors[] = sprintf(__('Invalid direction "%s" given for parameter.'), + htmlspecialchars($_REQUEST['routine_param_dir'][$i])); + } + if ($_REQUEST['routine_param_length'][$i] != '' + && !preg_match('@^(DATE|DATETIME|TIME|TINYBLOB|TINYTEXT|BLOB|TEXT|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT)$@i', + $_REQUEST['routine_param_type'][$i])) { + $params .= "(" . $_REQUEST['routine_param_length'][$i] . ")"; + } else if ($_REQUEST['routine_param_length'][$i] == '' + && preg_match('@^(ENUM|SET|VARCHAR|VARBINARY)$@i', $_REQUEST['routine_param_type'][$i])) { + if (! $warned_about_length) { + $warned_about_length = true; + $routine_errors[] = __('You must provide length/values for routine ' + . 'parameters of type ENUM, SET, VARCHAR and VARBINARY.'); + } + } + if (! empty($_REQUEST['routine_param_opts_text'][$i])) { + if (isset($cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_param_type'][$i])])) { + $group = $cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_param_type'][$i])]; + if ($group == 'FUNC_CHAR') { + $params .= ' CHARSET ' . strtolower($_REQUEST['routine_param_opts_text'][$i]); + } + } + } + if (! empty($_REQUEST['routine_param_opts_num'][$i])) { + if (isset($cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_param_type'][$i])])) { + $group = $cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_param_type'][$i])]; + if ($group == 'FUNC_NUMBER') { + $params .= ' ' . strtoupper($_REQUEST['routine_param_opts_num'][$i]); + } + } + } + if ($i != count($_REQUEST['routine_param_name'])-1) { + $params .= ", "; + } + } else if (! $warned_about_name) { + $warned_about_name = true; + $routine_errors[] = __('You must provide a name and a type for each routine parameter.'); + break; + } + } + } + $query .= " (" . $params . ") "; + if ($_REQUEST['routine_type'] == 'FUNCTION') { + $query .= "RETURNS {$_REQUEST['routine_returntype']}"; + if (! empty($_REQUEST['routine_returnlength']) + && !preg_match('@^(DATE|DATETIME|TIME|TINYBLOB|TINYTEXT|BLOB|TEXT|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT)$@i', + $_REQUEST['routine_returntype'])) { + $query .= "(" . $_REQUEST['routine_returnlength'] . ")"; + } else if (empty($_REQUEST['routine_returnlength']) + && preg_match('@^(ENUM|SET|VARCHAR|VARBINARY)$@i', $_REQUEST['routine_returntype'])) { + if (! $warned_about_length) { + $warned_about_length = true; + $routine_errors[] = __('You must provide length/values for routine ' + . 'parameters of type ENUM, SET, VARCHAR and VARBINARY.'); + } + } + if (! empty($_REQUEST['routine_returnopts_text'])) { + if (isset($cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_returntype'])])) { + $group = $cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_returntype'])]; + if ($group == 'FUNC_CHAR') { + $query .= ' CHARSET ' . strtolower($_REQUEST['routine_returnopts_text']); + } + } + } + if (! empty($_REQUEST['routine_returnopts_num'])) { + if (isset($cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_returntype'])])) { + $group = $cfg['RestrictColumnTypes'][strtoupper($_REQUEST['routine_returntype'])]; + if ($group == 'FUNC_NUMBER') { + $query .= ' ' . strtoupper($_REQUEST['routine_returnopts_num']); + } + } + } + $query .= ' '; + } + if (! empty($_REQUEST['routine_comment'])) { + $query .= "COMMENT '{$_REQUEST['routine_comment']}' "; + } + if (isset($_REQUEST['routine_isdeterministic'])) { + $query .= 'DETERMINISTIC '; + } else { + $query .= 'NOT DETERMINISTIC '; + } + if (! empty($_REQUEST['routine_sqldataaccess']) && in_array($_REQUEST['routine_sqldataaccess'], $param_sqldataaccess, true)) { + $query .= $_REQUEST['routine_sqldataaccess'] . ' '; + } + if (! empty($_REQUEST['routine_securitytype'])) { + if ($_REQUEST['routine_securitytype'] == 'DEFINER' || $_REQUEST['routine_securitytype'] == 'INVOKER') { + $query .= 'SQL SECURITY ' . $_REQUEST['routine_securitytype'] . ' '; + } + } + if (! empty($_REQUEST['routine_definition'])) { + $query .= $_REQUEST['routine_definition']; + } else { + $routine_errors[] = __('You must provide a routine definition.'); + } + return $query; +} // end PMA_RTN_getQueryFromRequest() + +/** + * Creates the HTML for a row of the routines list. + * + * @param array $routine Data about the routine returned by a query + * from the INFORMATION_SCHEMA db. + * @param int $ct Row count + * @param bool $is_ajax Whether this function was called + * from within an AJAX request + * + * @return string An HTML snippet containing a row for the routines list. + * + * @uses sprintf() + * @uses PMA_currentUserHasPrivilege() + * @uses PMA_backquote + * @uses PMA_RTN_getRoutineDataFromName() + * @uses htmlspecialchars() + * @uses urlencode() + */ +function PMA_RTN_getRowForRoutinesList($routine, $ct = 0, $is_ajax = false) { + global $titles, $db, $url_query, $ajax_class; + + // Do the logic first + $rowclass = ($ct % 2 == 0) ? 'even' : 'odd'; + if ($is_ajax) { + $rowclass .= ' ajaxInsert hide'; + } + $editlink = $titles['NoEdit']; + $execlink = $titles['NoExecute']; + $exprlink = $titles['NoExport']; + $droplink = $titles['NoDrop']; + $sql_drop = sprintf('DROP %s IF EXISTS %s', + $routine['ROUTINE_TYPE'], + PMA_backquote($routine['SPECIFIC_NAME'])); + if ($routine['ROUTINE_DEFINITION'] !== NULL + && PMA_currentUserHasPrivilege('ALTER ROUTINE', $db) + && PMA_currentUserHasPrivilege('CREATE ROUTINE', $db)) { + $editlink = '<a ' . $ajax_class['edit'] . ' href="db_routines.php?' . $url_query + . '&editroutine=1' + . '&routine_name=' . urlencode($routine['SPECIFIC_NAME']) + . '">' . $titles['Edit'] . '</a>'; + } + if ($routine['ROUTINE_DEFINITION'] !== NULL && PMA_currentUserHasPrivilege('EXECUTE', $db)) { + // Check if he routine has any input parameters. If it does, + // we will show a dialog to get values for these parameters, + // otherwise we can execute it directly. + $routine_details = PMA_RTN_getRoutineDataFromName($db, $routine['SPECIFIC_NAME'], false); + if ($routine !== false) { + $execute_action = 'execute_routine'; + for ($i=0; $i<$routine_details['num_params']; $i++) { + if ($routine_details['type'] == 'PROCEDURE' && $routine_details['param_dir'][$i] == 'OUT') { + continue; + } + $execute_action = 'execute_dialog'; + break; + } + $execlink = '<a ' . $ajax_class['exec']. ' href="db_routines.php?' . $url_query + . '&' . $execute_action . '=1' + . '&routine_name=' . urlencode($routine['SPECIFIC_NAME']) + . '">' . $titles['Execute'] . '</a>'; + } + } + if ($routine['ROUTINE_DEFINITION'] !== NULL) { + $exprlink = '<a ' . $ajax_class['export'] . ' href="db_routines.php?' . $url_query + . '&exportroutine=1' + . '&routine_name=' . urlencode($routine['SPECIFIC_NAME']) + . '">' . $titles['Export'] . '</a>'; + } + if (PMA_currentUserHasPrivilege('ALTER ROUTINE', $db)) { + $droplink = '<a ' . $ajax_class['drop']. ' href="sql.php?' . $url_query + . '&sql_query=' . urlencode($sql_drop) + . '&goto=db_routines.php' . urlencode("?db=$db") + . '" >' . $titles['Drop'] . '</a>'; + } + // Display a row of data + $retval = " <tr class='$rowclass'>\n"; + $retval .= " <td>\n"; + $retval .= " <span class='drop_sql hide'>$sql_drop</span>\n"; + $retval .= " <strong>" . htmlspecialchars($routine['ROUTINE_NAME']) . "</strong>\n"; + $retval .= " </td>\n"; + $retval .= " <td>$editlink</td>\n"; + $retval .= " <td>$execlink</td>\n"; + $retval .= " <td>$exprlink</td>\n"; + $retval .= " <td>$droplink</td>\n"; + $retval .= " <td>{$routine['ROUTINE_TYPE']}</td>\n"; + $retval .= " <td>" . htmlspecialchars($routine['DTD_IDENTIFIER']) . "</td>\n"; + $retval .= " </tr>\n"; + return $retval; +} // end PMA_RTN_getRowForRoutinesList() + +/** + * Creates a list of available routines for the specified database + * + * @return string An HTML snippet with the list of routines. + * + * @uses PMA_sqlAddslashes() + * @uses PMA_DBI_fetch_result() + * @uses PMA_RTN_getRowForRoutinesList() + */ +function PMA_RTN_getRoutinesList() +{ + global $db; + + /** + * Get the routines + */ + $columns = "`SPECIFIC_NAME`, `ROUTINE_NAME`, `ROUTINE_TYPE`, `DTD_IDENTIFIER`, `ROUTINE_DEFINITION`"; + $where = "ROUTINE_SCHEMA='" . PMA_sqlAddslashes($db) . "'"; + $routines = PMA_DBI_fetch_result("SELECT $columns FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE $where;"); + /** + * Conditional classes switch the list on or off + */ + $class1 = 'hide'; + $class2 = ''; + if (! $routines) { + $class1 = ''; + $class2 = ' hide'; + } + + /** + * Generate output + */ + $retval = ""; + $retval .= "\n\n<span id='js_query_display'></span>\n\n"; + $retval .= "<!-- LIST OF ROUTINES START -->\n"; + $retval .= "<fieldset>\n"; + $retval .= " <legend>" . __('Routines') . "</legend>\n"; + $retval .= " <div class='$class1' id='nothing2display'>\n"; + $retval .= " " . __('There are no routines to display.') . "\n"; + $retval .= " </div>\n"; + $retval .= " <table class='data$class2'>\n"; + $retval .= " <!-- TABLE HEADERS -->\n"; + $retval .= " <tr>\n"; + $retval .= " <th>" . __('Name') . "</th>\n"; + $retval .= " <th colspan='4'>" . __('Action') . "</th>\n"; + $retval .= " <th>" . __('Type') . "</th>\n"; + $retval .= " <th>" . __('Return type') . "</th>\n"; + $retval .= " </tr>\n"; + $retval .= " <!-- TABLE DATA -->\n"; + $ct = 0; + // Display each routine + foreach ($routines as $routine) { + $retval .= PMA_RTN_getRowForRoutinesList($routine, $ct); + $ct++; + } + $retval .= " </table>\n"; + $retval .= "</fieldset>\n"; + $retval .= "<!-- LIST OF ROUTINES END -->\n\n"; + + return $retval; +} // end PMA_RTN_getRoutinesList() + +/** + * Creates a fieldset for adding a new routine, if the user has the privileges. + * + * @return string An HTML snippet with the link to add a new routine. + * + * @uses PMA_currentUserHasPrivilege() + * @uses PMA_getIcon() + * @uses PMA_showMySQLDocu() + */ +function PMA_RTN_getAddRoutineLink() +{ + global $db, $url_query, $ajax_class; + + $retval = ""; + $retval .= "<!-- ADD ROUTINE FORM START -->\n"; + $retval .= "<fieldset>\n"; + if (PMA_currentUserHasPrivilege('CREATE ROUTINE', $db)) { + $retval .= "<a {$ajax_class['add']} href='db_routines.php"; + $retval .= "?$url_query&addroutine=1'>\n"; + $retval .= PMA_getIcon('b_routine_add.png') . "\n"; + $retval .= __('Add routine') . "</a>\n"; + } else { + $retval .= PMA_getIcon('b_routine_add.png') . "\n"; + $retval .= __('You do not have the necessary privileges to create a new routine') . "\n"; + } + $retval .= PMA_showMySQLDocu('SQL-Syntax', 'CREATE_PROCEDURE') . "\n"; + $retval .= "</fieldset>\n"; + $retval .= "<!-- ADD ROUTINE FORM END -->\n\n"; + + return $retval; +} // end PMA_RTN_getAddRoutineLink() + +?> diff --git a/libraries/dbi/mysql.dbi.lib.php b/libraries/dbi/mysql.dbi.lib.php index e84e6b0..5cbb4fa 100644 --- a/libraries/dbi/mysql.dbi.lib.php +++ b/libraries/dbi/mysql.dbi.lib.php @@ -208,6 +208,32 @@ function PMA_DBI_free_result() }
/** + * Check if there are any more query results from a multi query + * + * @return boolean false + */ +function PMA_DBI_more_results() { + // N.B.: PHP's 'mysql' extension does not support + // multi_queries so this function will always + // return false. Use the 'mysqli' extension, if + // you need support for multi_queries. + return false; +} + +/** + * Prepare next result from multi_query + * + * @return boolean false + */ +function PMA_DBI_next_result() { + // N.B.: PHP's 'mysql' extension does not support + // multi_queries so this function will always + // return false. Use the 'mysqli' extension, if + // you need support for multi_queries. + return false; +} + +/** * Returns a string representing the type of connection used * @uses mysql_get_host_info() * @uses $GLOBALS['userlink'] as default for $link diff --git a/libraries/dbi/mysqli.dbi.lib.php b/libraries/dbi/mysqli.dbi.lib.php index 2418fd2..bee7430 100644 --- a/libraries/dbi/mysqli.dbi.lib.php +++ b/libraries/dbi/mysqli.dbi.lib.php @@ -255,6 +255,44 @@ function PMA_DBI_free_result() }
/** + * Check if there are any more query results from a multi query + * + * @uses $GLOBALS['userlink'] + * @uses mysqli_more_results() + * @param object mysqli $link the mysqli object + * @return boolean true or false + */ +function PMA_DBI_more_results($link = null) { + if (empty($link)) { + if (isset($GLOBALS['userlink'])) { + $link = $GLOBALS['userlink']; + } else { + return false; + } + } + return mysqli_more_results($link); +} + +/** + * Prepare next result from multi_query + * + * @uses $GLOBALS['userlink'] + * @uses mysqli_next_result() + * @param object mysqli $link the mysqli object + * @return boolean true or false + */ +function PMA_DBI_next_result($link = null) { + if (empty($link)) { + if (isset($GLOBALS['userlink'])) { + $link = $GLOBALS['userlink']; + } else { + return false; + } + } + return mysqli_next_result($link); +} + +/** * Returns a string representing the type of connection used * @uses mysqli_get_host_info() * @uses $GLOBALS['userlink'] as default for $link diff --git a/libraries/display_triggers.inc.php b/libraries/display_triggers.inc.php new file mode 100644 index 0000000..aa4583e --- /dev/null +++ b/libraries/display_triggers.inc.php @@ -0,0 +1,123 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @package phpMyAdmin + */ +if (! defined('PHPMYADMIN')) { + exit; +} + +$url_query .= '&goto=tbl_triggers.php'; + +$triggers = PMA_DBI_get_triggers($db, $table); + +$conditional_class_add = ''; +$conditional_class_drop = ''; +$conditional_class_export = ''; +if ($GLOBALS['cfg']['AjaxEnable']) { + $conditional_class_add = 'class="add_trigger_anchor"'; + $conditional_class_drop = 'class="drop_trigger_anchor"'; + $conditional_class_export = 'class="export_trigger_anchor"'; +} + +/** + * Display the export for a trigger. This is for when JS is disabled. + */ +if (! empty($_GET['exporttrigger']) && ! empty($_GET['triggername'])) { + $success = false; + foreach ($triggers as $trigger) { + if ($trigger['name'] === $_GET['triggername']) { + $success = true; + $trigger_name = htmlspecialchars(PMA_backquote($_GET['triggername'])); + $create_trig = '<textarea cols="40" rows="15" style="width: 100%;">' . $trigger['create'] . '</textarea>'; + if (! empty($_REQUEST['ajax_request'])) { + $extra_data = array('title' => sprintf(__('Export of trigger %s'), $trigger_name)); + PMA_ajaxResponse($create_trig, true, $extra_data); + } else { + echo '<fieldset>' . "\n" + . ' <legend>' . sprintf(__('Export of trigger "%s"'), $trigger_name) . '</legend>' . "\n" + . $create_trig + . '</fieldset>'; + } + } + } + if (! $success) { + $response = __('Error in Processing Request') . ' : ' + . sprintf(__('No trigger with name %s found'), $event_name); + $response = PMA_message::error($response); + if (! empty($_REQUEST['ajax_request'])) { + PMA_ajaxResponse($response, false); + } else { + $response->display(); + } + } +} + +/** + * Display a list of available triggers + */ +echo "\n\n<span id='js_query_display'></span>\n\n"; +echo '<fieldset>' . "\n"; +echo ' <legend>' . __('Triggers') . '</legend>' . "\n"; +if (! $triggers) { + echo __('There are no triggers to display.'); +} else { + echo '<div class="hide" id="nothing2display">' . __('There are no triggers to display.') . '</div>'; + echo '<table class="data">' . "\n"; + + // Print table header + echo "<tr>\n<th>" . __('Name') . "</th>\n"; + if (empty($table)) { + // if we don't have a table name, we will be showing the per-database list. + // so we must specify which table each trigger belongs to + echo "<th>" . __('Table') . "</th>\n"; + } + echo "<th colspan='3'>" . __('Action') . "</th>\n"; + echo "<th>" . __('Time') . "</th>\n"; + echo "<th>" . __('Event') . "</th>\n"; + echo "</tr>"; + + $ct=0; + $delimiter = '//'; + // Print table contents + foreach ($triggers as $trigger) { + $drop_and_create = $trigger['drop'] . $delimiter . "\n" . $trigger['create'] . "\n"; + $row = ($ct%2 == 0) ? 'even' : 'odd'; + $editlink = PMA_linkOrButton('tbl_sql.php?' . $url_query . '&sql_query=' + . urlencode($drop_and_create) . '&show_query=1&delimiter=' . urlencode($delimiter), $titles['Edit']); + $exprlink = '<a ' . $conditional_class_export . ' href="db_triggers.php?' . $url_query + . '&exporttrigger=1' + . '&triggername=' . urlencode($trigger['name']) + . '">' . $titles['Export'] . '</a>'; + $droplink = '<a ' . $conditional_class_drop . ' href="sql.php?' . $url_query . '&sql_query=' + . urlencode($trigger['drop']) . '" >' . $titles['Drop'] . '</a>'; + + echo "<tr class='noclick $row'>\n"; + echo "<td><span class='drop_sql' style='display:none;'>{$trigger['drop']}</span>"; + echo "<strong>{$trigger['name']}</strong></td>\n"; + if (empty($table)) { + echo "<td><a href='tbl_triggers.php?db=$db&table={$trigger['table']}'>"; + echo $trigger['table'] . "</a></td>\n"; + } + echo "<td>$editlink</td>\n"; + echo "<td><div class='create_sql' style='display: none;'>{$trigger['create']}</div>$exprlink</td>\n"; + echo "<td>$droplink</td>\n"; + echo "<td>{$trigger['action_timing']}</td>\n"; + echo "<td>{$trigger['event_manipulation']}</td>\n"; + echo "</tr>\n"; + $ct++; + } + echo '</table>'; +} +echo '</fieldset>'; + +/** + * Display the form for adding a new trigger + */ +echo '<fieldset>' . "\n" + . ' <a href="tbl_triggers.php?' . $url_query . '&addtrigger=1" class="' . $conditional_class_add . '">' . "\n" + . PMA_getIcon('b_trigger_add.png') . __('Add a new Trigger') . '</a>' . "\n" + . '</fieldset>' . "\n"; + +?> diff --git a/libraries/tbl_links.inc.php b/libraries/tbl_links.inc.php index e31dd53..66df327 100644 --- a/libraries/tbl_links.inc.php +++ b/libraries/tbl_links.inc.php @@ -40,6 +40,13 @@ $err_url = $cfg['DefaultTabTable'] . PMA_generate_common_url($url_params); require_once './libraries/header.inc.php';
/** + * Ensure that $db_is_information_schema is not null + */ +if (! isset($db_is_information_schema)) { + $db_is_information_schema = false; +} + +/** * Displays links */ $tabs = array(); @@ -61,7 +68,7 @@ $tabs['search']['icon'] = 'b_search.png'; $tabs['search']['text'] = __('Search'); $tabs['search']['link'] = 'tbl_select.php';
-if (! (isset($db_is_information_schema) && $db_is_information_schema)) { +if (!$db_is_information_schema) { $tabs['insert']['icon'] = 'b_insrow.png'; $tabs['insert']['link'] = 'tbl_change.php'; $tabs['insert']['text'] = __('Insert'); @@ -76,7 +83,7 @@ $tabs['export']['text'] = __('Export'); * Don't display "Import" and "Operations" * for views and information_schema */ -if (! $tbl_is_view && ! (isset($db_is_information_schema) && $db_is_information_schema)) { +if (! $tbl_is_view && !$db_is_information_schema) { $tabs['import']['icon'] = 'b_tblimport.png'; $tabs['import']['link'] = 'tbl_import.php'; $tabs['import']['text'] = __('Import'); @@ -90,13 +97,16 @@ if(PMA_Tracker::isActive()) { $tabs['tracking']['text'] = __('Tracking'); $tabs['tracking']['link'] = 'tbl_tracking.php'; } -if (! $tbl_is_view && ! (isset($db_is_information_schema) && $db_is_information_schema)) { +if (! $db_is_information_schema && PMA_MYSQL_INT_VERSION >= 50002 && ! PMA_DRIZZLE) { + $tabs['triggers']['link'] = 'tbl_triggers.php'; + $tabs['triggers']['text'] = __('Triggers'); + $tabs['triggers']['icon'] = 'b_triggers.png'; }
/** * Views support a limited number of operations */ -if ($tbl_is_view && ! (isset($db_is_information_schema) && $db_is_information_schema)) { +if ($tbl_is_view && !$db_is_information_schema) { $tabs['operation']['icon'] = 'b_tblops.png'; $tabs['operation']['link'] = 'view_operations.php'; $tabs['operation']['text'] = __('Operations'); diff --git a/libraries/tbl_properties.inc.php b/libraries/tbl_properties.inc.php index 4f1b647..8edc3ea 100644 --- a/libraries/tbl_properties.inc.php +++ b/libraries/tbl_properties.inc.php @@ -14,6 +14,7 @@ if (! defined('PHPMYADMIN')) { * Check parameters */ require_once './libraries/common.inc.php'; +require_once './libraries/common.lib.php'; PMA_checkParameters(array('db', 'table', 'action', 'num_fields'));
@@ -322,27 +323,7 @@ for ($i = 0; $i < $num_fields; $i++) { $type = rtrim($type); $type_upper = strtoupper($type);
- foreach ($cfg['ColumnTypes'] as $col_goup => $column_type) { - if (is_array($column_type)) { - $content_cells[$i][$ci] .= '<optgroup label="' . htmlspecialchars($col_goup) . '">'; - foreach ($column_type as $col_group_type) { - $content_cells[$i][$ci] .= '<option value="'. $col_group_type . '"'; - if ($type_upper == strtoupper($col_group_type)) { - $content_cells[$i][$ci] .= ' selected="selected"'; - } - $content_cells[$i][$ci] .= '>' . $col_group_type . '</option>'; - } - $content_cells[$i][$ci] .= '</optgroup>'; - continue; - } - - $content_cells[$i][$ci] .= '<option value="'. $column_type . '"'; - if ($type_upper == strtoupper($column_type)) { - $content_cells[$i][$ci] .= ' selected="selected"'; - } - $content_cells[$i][$ci] .= '>' . $column_type . '</option>'; - } // end for - + $content_cells[$i][$ci] .= PMA_getSupportedDatatypes(true, $type_upper); $content_cells[$i][$ci] .= ' </select>'; $ci++;
diff --git a/libraries/tbl_triggers.inc.php b/libraries/tbl_triggers.inc.php deleted file mode 100644 index 0663ef4..0000000 --- a/libraries/tbl_triggers.inc.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * - * @package phpMyAdmin - */ -if (! defined('PHPMYADMIN')) { - exit; -} - -$url_query .= '&goto=tbl_structure.php'; - -$triggers = PMA_DBI_get_triggers($db, $table); - -if ($triggers) { - echo '<div id="tabletriggers">' . "\n"; - echo '<table class="data">' . "\n"; - echo ' <caption class="tblHeaders">' . __('Triggers') . '</caption>' . "\n"; - echo sprintf('<tr> - <th>%s</th> - <th> </th> - <th> </th> - <th>%s</th> - <th>%s</th> - </tr>', - __('Name'), - __('Time'), - __('Event')); - $ct=0; - $delimiter = '//'; - if ($GLOBALS['cfg']['AjaxEnable']) { - $conditional_class = 'class="drop_trigger_anchor"'; - } else { - $conditional_class = ''; - } - - foreach ($triggers as $trigger) { - $drop_and_create = $trigger['drop'] . $delimiter . "\n" . $trigger['create'] . "\n"; - - echo sprintf('<tr class="noclick %s"> - <td><strong>%s</strong></td> - <td>%s</td> - <td>%s</td> - <td>%s</td> - <td>%s</td> - </tr>', - ($ct%2 == 0) ? 'even' : 'odd', - $trigger['name'], - PMA_linkOrButton('tbl_sql.php?' . $url_query . '&sql_query=' . urlencode($drop_and_create) . '&show_query=1&delimiter=' . urlencode($delimiter), $titles['Change']), - '<a ' . $conditional_class . ' href="sql.php?' . $url_query . '&sql_query=' . urlencode($trigger['drop']) . '" >' . $titles['Drop'] . '</a>', - $trigger['action_timing'], - $trigger['event_manipulation']); - $ct++; - } - echo '</table>'; - echo '</div>' . "\n"; -} -?> diff --git a/sql.php b/sql.php index f4ea949..7da775a 100644 --- a/sql.php +++ b/sql.php @@ -449,6 +449,15 @@ if (isset($GLOBALS['show_as_php']) || !empty($GLOBALS['validatequery'])) {
$result = @PMA_DBI_try_query($full_sql_query, null, PMA_DBI_QUERY_STORE);
+ // If a stored procedure was called, there may be more results that are + // queued up and waiting to be flushed from the buffer. So let's do that. + while (true) { + if(! PMA_DBI_more_results()) { + break; + } + PMA_DBI_next_result(); + } + $querytime_after = array_sum(explode(' ', microtime()));
$GLOBALS['querytime'] = $querytime_after - $querytime_before; diff --git a/tbl_change.php b/tbl_change.php index 4adaf40..94c7da0 100644 --- a/tbl_change.php +++ b/tbl_change.php @@ -12,6 +12,7 @@ * Gets the variables sent or posted to this script and displays the header */ require_once './libraries/common.inc.php'; +require_once './libraries/common.lib.php';
/** * Ensures db and table are valid, else moves to the "parent" script @@ -537,8 +538,8 @@ foreach ($rows as $row_id => $vrow) { $idindex = ($o_rows * $fields_cnt) + $i + 1; $tabindex = $idindex;
- // These GIS data types are not yet supported. - $no_support_types = array('geometry', 'point', 'linestring', 'polygon', 'multipoint', 'multilinestring', 'multipolygon', 'geometrycollection'); + // Get a list of data types that are not yet supported. + $no_support_types = PMA_unsupportedDatatypes();
// The function column // ------------------- @@ -556,88 +557,9 @@ foreach ($rows as $row_id => $vrow) { ?> <td> <select name="funcs<?php echo $field_name_appendix; ?>" <?php echo $unnullify_trigger; ?> tabindex="<?php echo ($tabindex + $tabindex_for_function); ?>" id="field_<?php echo $idindex; ?>_1"> - <option></option> - <?php - $selected = ''; - - // Find the current type in the RestrictColumnTypes. Will result in 'FUNC_CHAR' - // or something similar. Then directly look up the entry in the RestrictFunctions array, - // which will then reveal the available dropdown options - if (isset($cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])]) - && isset($cfg['RestrictFunctions'][$cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])]])) { - $current_func_type = $cfg['RestrictColumnTypes'][strtoupper($field['True_Type'])]; - $dropdown = $cfg['RestrictFunctions'][$current_func_type]; - $default_function = $cfg['DefaultFunctions'][$current_func_type]; - } else { - $dropdown = array(); - $default_function = ''; - } - - $dropdown_built = array(); - $op_spacing_needed = false; - - // what function defined as default? - // for the first timestamp we don't set the default function - // if there is a default value for the timestamp - // (not including CURRENT_TIMESTAMP) - // and the column does not have the - // ON UPDATE DEFAULT TIMESTAMP attribute. - - if ($field['True_Type'] == 'timestamp' - && empty($field['Default']) - && empty($data) - && ! isset($analyzed_sql[0]['create_table_fields'][$field['Field']]['on_update_current_timestamp'])) { - $default_function = $cfg['DefaultFunctions']['first_timestamp']; - } - - // For primary keys of type char(36) or varchar(36) UUID if the default function - // Only applies to insert mode, as it would silently trash data on updates. - if ($insert_mode - && $field['Key'] == 'PRI' - && ($field['Type'] == 'char(36)' || $field['Type'] == 'varchar(36)') - ) { - $default_function = $cfg['DefaultFunctions']['pk_char36']; - } - - // this is set only when appropriate and is always true - if (isset($field['display_binary_as_hex'])) { - $default_function = 'UNHEX'; - } - - // loop on the dropdown array and print all available options for that field. - foreach ($dropdown as $each_dropdown){ - echo '<option'; - if ($default_function === $each_dropdown) { - echo ' selected="selected"'; - } - echo '>' . $each_dropdown . '</option>' . "\n"; - $dropdown_built[$each_dropdown] = 'true'; - $op_spacing_needed = true; - } - - // For compatibility's sake, do not let out all other functions. Instead - // print a separator (blank) and then show ALL functions which weren't shown - // yet. - $cnt_functions = count($cfg['Functions']); - for ($j = 0; $j < $cnt_functions; $j++) { - if (! isset($dropdown_built[$cfg['Functions'][$j]]) || $dropdown_built[$cfg['Functions'][$j]] != 'true') { - // Is current function defined as default? - $selected = ($field['first_timestamp'] && $cfg['Functions'][$j] == $cfg['DefaultFunctions']['first_timestamp']) - || (!$field['first_timestamp'] && $cfg['Functions'][$j] == $default_function) - ? ' selected="selected"' - : ''; - if ($op_spacing_needed == true) { - echo ' '; - echo '<option value="">--------</option>' . "\n"; - $op_spacing_needed = false; - } - - echo ' '; - echo '<option' . $selected . '>' . $cfg['Functions'][$j] . '</option>' . "\n"; - } - } // end for - unset($selected); - ?> +<?php + echo PMA_getFunctionsForField($field, $insert_mode); +?> </select> </td> <?php diff --git a/tbl_structure.php b/tbl_structure.php index 21fc51e..41e5b9d 100644 --- a/tbl_structure.php +++ b/tbl_structure.php @@ -932,8 +932,6 @@ if ($cfg['ShowStats']) { } // END - Calc Table Space
-require './libraries/tbl_triggers.inc.php'; - echo '<div class="clearfloat"></div>' . "\n";
/** diff --git a/tbl_triggers.php b/tbl_triggers.php new file mode 100644 index 0000000..bf9cbbc --- /dev/null +++ b/tbl_triggers.php @@ -0,0 +1,35 @@ +<?php + +/** + * + */ +require_once './libraries/common.inc.php'; +require_once './libraries/common.lib.php'; + +$GLOBALS['js_include'][] = 'jquery/jquery-ui-1.8.custom.js'; +$GLOBALS['js_include'][] = 'display_triggers.js'; + +require_once './libraries/tbl_common.php'; + +/** + * Create labels for the list + */ +$titles = PMA_buildActionTitles(); + +/** + * Displays the header and tabs + */ +require_once './libraries/tbl_links.inc.php'; + +/** + * Displays the list of triggers + */ +require_once './libraries/display_triggers.inc.php'; + +/** + * Displays the footer + */ +require './libraries/footer.inc.php'; + + +?> diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index 960f63f..5ec7c1e 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -1858,6 +1858,19 @@ fieldset .disabled-field td { margin-bottom: 0.5em; }
+.rte_table td { + vertical-align: middle; +} + +.rte_table input, .rte_table select, .rte_table textarea { + width: 100%; + margin: 0; + box-sizing: border-box; + -ms-box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + #table_columns input, #table_columns select { width: 14em; box-sizing: border-box; diff --git a/themes/original/img/b_event_add.png b/themes/original/img/b_event_add.png new file mode 100644 index 0000000..6940d74 Binary files /dev/null and b/themes/original/img/b_event_add.png differ diff --git a/themes/original/img/b_events.png b/themes/original/img/b_events.png new file mode 100644 index 0000000..4564284 Binary files /dev/null and b/themes/original/img/b_events.png differ diff --git a/themes/original/img/b_routine_add.png b/themes/original/img/b_routine_add.png new file mode 100644 index 0000000..95b9719 Binary files /dev/null and b/themes/original/img/b_routine_add.png differ diff --git a/themes/original/img/b_routines.png b/themes/original/img/b_routines.png new file mode 100644 index 0000000..428b0db Binary files /dev/null and b/themes/original/img/b_routines.png differ diff --git a/themes/original/img/b_trigger_add.png b/themes/original/img/b_trigger_add.png new file mode 100644 index 0000000..5b91c50 Binary files /dev/null and b/themes/original/img/b_trigger_add.png differ diff --git a/themes/original/img/b_triggers.png b/themes/original/img/b_triggers.png new file mode 100644 index 0000000..e902511 Binary files /dev/null and b/themes/original/img/b_triggers.png differ diff --git a/themes/original/img/bd_edit.png b/themes/original/img/bd_edit.png new file mode 100644 index 0000000..8894dcf Binary files /dev/null and b/themes/original/img/bd_edit.png differ diff --git a/themes/original/img/bd_export.png b/themes/original/img/bd_export.png new file mode 100644 index 0000000..07e4c67 Binary files /dev/null and b/themes/original/img/bd_export.png differ diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index fcaba3d..27008b9 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -2209,6 +2209,19 @@ fieldset .disabled-field td { margin-bottom: 0.5em; }
+.rte_table td { + vertical-align: middle; +} + +.rte_table input, .rte_table select, .rte_table textarea { + width: 100%; + margin: 0; + box-sizing: border-box; + -ms-box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + #table_columns input, #table_columns select { width: 14em; box-sizing: border-box; diff --git a/themes/pmahomme/img/b_event_add.png b/themes/pmahomme/img/b_event_add.png new file mode 100644 index 0000000..6940d74 Binary files /dev/null and b/themes/pmahomme/img/b_event_add.png differ diff --git a/themes/pmahomme/img/b_events.png b/themes/pmahomme/img/b_events.png new file mode 100644 index 0000000..4564284 Binary files /dev/null and b/themes/pmahomme/img/b_events.png differ diff --git a/themes/pmahomme/img/b_routine_add.png b/themes/pmahomme/img/b_routine_add.png new file mode 100644 index 0000000..95b9719 Binary files /dev/null and b/themes/pmahomme/img/b_routine_add.png differ diff --git a/themes/pmahomme/img/b_routines.png b/themes/pmahomme/img/b_routines.png new file mode 100644 index 0000000..428b0db Binary files /dev/null and b/themes/pmahomme/img/b_routines.png differ diff --git a/themes/pmahomme/img/b_trigger_add.png b/themes/pmahomme/img/b_trigger_add.png new file mode 100644 index 0000000..5b91c50 Binary files /dev/null and b/themes/pmahomme/img/b_trigger_add.png differ diff --git a/themes/pmahomme/img/b_triggers.png b/themes/pmahomme/img/b_triggers.png new file mode 100644 index 0000000..e902511 Binary files /dev/null and b/themes/pmahomme/img/b_triggers.png differ diff --git a/themes/pmahomme/img/bd_edit.png b/themes/pmahomme/img/bd_edit.png new file mode 100644 index 0000000..6aa2a18 Binary files /dev/null and b/themes/pmahomme/img/bd_edit.png differ diff --git a/themes/pmahomme/img/bd_export.png b/themes/pmahomme/img/bd_export.png new file mode 100644 index 0000000..841c758 Binary files /dev/null and b/themes/pmahomme/img/bd_export.png differ
hooks/post-receive