PageRenderTime 50ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/SemanticNotifyMe/includes/SMW_NMDBHelper.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 303 lines | 234 code | 15 blank | 54 comment | 67 complexity | 9b2dd59e0bfe719b655c83049b28a7f6 MD5 | raw file
  1. <?php
  2. /*
  3. * Created on 19.10.2008
  4. *
  5. * Author: ning
  6. */
  7. class SNMDBHelper {
  8. /**
  9. * Make sure the table of the given name has the given fields, provided
  10. * as an array with entries fieldname => typeparams. typeparams should be
  11. * in a normalised form and order to match to existing values.
  12. *
  13. * The function returns an array that includes all columns that have been
  14. * changed. For each such column, the array contains an entry
  15. * columnname => action, where action is one of 'up', 'new', or 'del'
  16. * If the table was already fine or was created completely anew, an empty
  17. * array is returned (assuming that both cases require no action).
  18. *
  19. * NOTE: the function partly ignores the order in which fields are set up.
  20. * Only if the type of some field changes will its order be adjusted explicitly.
  21. *
  22. * @param string $primaryKeys
  23. * This optional string specifies the primary keys if there is more
  24. * than one. This is a comma separated list of column names. The primary
  25. * keys are not altered, if the table already exists.
  26. */
  27. public static function setupTable( $table, $fields, $db, $verbose, $primaryKeys = "" ) {
  28. global $wgDBname;
  29. SNMDBHelper::reportProgress( "Setting up table $table ...\n", $verbose );
  30. if ( $db->tableExists( $table ) === false ) { // create new table
  31. $sql = 'CREATE TABLE ' . $wgDBname . '.' . $table . ' (';
  32. $first = true;
  33. foreach ( $fields as $name => $type ) {
  34. if ( $first ) {
  35. $first = false;
  36. } else {
  37. $sql .= ',';
  38. }
  39. $sql .= $name . ' ' . $type;
  40. }
  41. if ( !empty( $primaryKeys ) ) {
  42. $sql .= ", PRIMARY KEY(" . $primaryKeys . ")";
  43. }
  44. $sql .= ') TYPE=myisam';
  45. $db->query( $sql, 'SNMDBHelper::setupTable' );
  46. SNMDBHelper::reportProgress( " ... new table created\n", $verbose );
  47. return array();
  48. } else { // check table signature
  49. SNMDBHelper::reportProgress( " ... table exists already, checking structure ...\n", $verbose );
  50. $res = $db->query( 'DESCRIBE ' . $table, 'SNMDBHelper::setupTable' );
  51. $curfields = array();
  52. $result = array();
  53. while ( $row = $db->fetchObject( $res ) ) {
  54. $type = strtoupper( $row->Type );
  55. if ( substr( $type, 0, 8 ) == 'VARCHAR(' ) {
  56. $type .= ' binary'; // just assume this to be the case for VARCHAR, avoid collation checks
  57. }
  58. if ( $row->Null != 'YES' ) {
  59. $type .= ' NOT NULL';
  60. }
  61. if ( $row->Key == 'PRI' ) { // / FIXME: updating "KEY" is not possible, the below query will fail in this case.
  62. $type .= ' KEY';
  63. }
  64. if ( $row->Extra == 'auto_increment' ) {
  65. $type .= ' AUTO_INCREMENT';
  66. }
  67. if ( $row->Default != '' ) {
  68. $type .= ' default \'' . $row->Default . '\'';
  69. }
  70. $curfields[$row->Field] = $type;
  71. }
  72. $position = 'FIRST';
  73. foreach ( $fields as $name => $type ) {
  74. if ( !array_key_exists( $name, $curfields ) ) {
  75. SNMDBHelper::reportProgress( " ... creating column $name ... ", $verbose );
  76. $db->query( "ALTER TABLE $table ADD `$name` $type $position", 'SNMDBHelper::setupTable' );
  77. $result[$name] = 'new';
  78. SNMDBHelper::reportProgress( "done \n", $verbose );
  79. } elseif ( $curfields[$name] != $type ) {// && stripos("auto_increment", $type) == -1) {
  80. SNMDBHelper::reportProgress( " ... changing type of column $name from '$curfields[$name]' to '$type' ... ", $verbose );
  81. $db->query( "ALTER TABLE $table CHANGE `$name` `$name` $type $position", 'SNMDBHelper::setupTable' );
  82. $result[$name] = 'up';
  83. $curfields[$name] = false;
  84. SNMDBHelper::reportProgress( "done.\n", $verbose );
  85. } else {
  86. SNMDBHelper::reportProgress( " ... column $name is fine\n", $verbose );
  87. $curfields[$name] = false;
  88. }
  89. $position = "AFTER $name";
  90. }
  91. foreach ( $curfields as $name => $value ) {
  92. if ( $value !== false ) { // not encountered yet --> delete
  93. SNMDBHelper::reportProgress( " ... deleting obsolete column $name ... ", $verbose );
  94. $db->query( "ALTER TABLE $table DROP COLUMN `$name`", 'SNMDBHelper::setupTable' );
  95. $result[$name] = 'del';
  96. SNMDBHelper::reportProgress( "done.\n", $verbose );
  97. }
  98. }
  99. SNMDBHelper::reportProgress( " ... table $table set up successfully.\n", $verbose );
  100. return $result;
  101. }
  102. }
  103. /**
  104. * Make sure that each of the column descriptions in the given array is indexed by *one* index
  105. * in the given DB table.
  106. */
  107. public static function setupIndex( $table, $columns, $db ) {
  108. $table = $db->tableName( $table );
  109. $res = $db->query( 'SHOW INDEX FROM ' . $table , 'SMW::SetupIndex' );
  110. if ( !$res ) {
  111. return false;
  112. }
  113. $indexes = array();
  114. while ( $row = $db->fetchObject( $res ) ) {
  115. if ( !array_key_exists( $row->Key_name, $indexes ) ) {
  116. $indexes[$row->Key_name] = array();
  117. }
  118. $indexes[$row->Key_name][$row->Seq_in_index] = $row->Column_name;
  119. }
  120. foreach ( $indexes as $key => $index ) { // clean up existing indexes
  121. $id = array_search( implode( ',', $index ), $columns );
  122. if ( $id !== false ) {
  123. $columns[$id] = false;
  124. } else { // duplicate or unrequired index
  125. if ( $key != 'PRIMARY' ) {
  126. $db->query( 'DROP INDEX ' . $key . ' ON ' . $table, 'SMW::SetupIndex' );
  127. }
  128. }
  129. }
  130. foreach ( $columns as $column ) { // add remaining indexes
  131. if ( $column != false ) {
  132. $db->query( "ALTER TABLE $table ADD INDEX ( $column )", 'SMW::SetupIndex' );
  133. }
  134. }
  135. return true;
  136. }
  137. /**
  138. * Print some output to indicate progress. The output message is given by
  139. * $msg, while $verbose indicates whether or not output is desired at all.
  140. */
  141. public static function reportProgress( $msg, $verbose ) {
  142. if ( !$verbose ) {
  143. return;
  144. }
  145. if ( ob_get_level() == 0 ) { // be sure to have some buffer, otherwise some PHPs complain
  146. ob_start();
  147. }
  148. print $msg;
  149. ob_flush();
  150. flush();
  151. }
  152. /**
  153. * Transform input parameters into a suitable array of SQL options.
  154. * The parameter $valuecol defines the string name of the column to which
  155. * sorting requests etc. are to be applied.
  156. */
  157. public static function getSQLOptions( $requestoptions, $valuecol = NULL ) {
  158. $sql_options = array();
  159. if ( $requestoptions !== NULL ) {
  160. if ( is_numeric( $requestoptions->limit ) && $requestoptions->limit >= 0 ) {
  161. $sql_options['LIMIT'] = $requestoptions->limit;
  162. }
  163. if ( is_numeric( $requestoptions->offset ) && $requestoptions->offset > 0 ) {
  164. $sql_options['OFFSET'] = $requestoptions->offset;
  165. }
  166. if ( ( $valuecol !== NULL ) && ( $requestoptions->sort ) ) {
  167. if ( is_array( $valuecol ) ) {
  168. $sql_options['ORDER BY'] = $requestoptions->ascending ? mysql_real_escape_string( implode( ",", $valuecol ) ) : mysql_real_escape_string( implode( ",", $valuecol ) ) . ' DESC';
  169. } else {
  170. $sql_options['ORDER BY'] = $requestoptions->ascending ? mysql_real_escape_string( $valuecol ) : mysql_real_escape_string( $valuecol ) . ' DESC';
  171. }
  172. }
  173. }
  174. return $sql_options;
  175. }
  176. public static function getSQLOptionsAsString( $requestoptions, $valuecol = NULL ) {
  177. $options = SNMDBHelper::getSQLOptions( $requestoptions, $valuecol );
  178. $limit = array_key_exists( 'LIMIT', $options ) && is_numeric( $options['LIMIT'] ) ? 'LIMIT ' . $options['LIMIT'] : '';
  179. $offset = array_key_exists( 'OFFSET', $options ) && is_numeric( $options['OFFSET'] ) ? 'OFFSET ' . $options['OFFSET'] : '';
  180. $orderby = array_key_exists( 'ORDER BY', $options ) ? 'ORDER BY ' . $options['ORDER BY'] : '';
  181. return $orderby . ' ' . $limit . ' ' . $offset;
  182. }
  183. /**
  184. * Transform input parameters into a suitable string of additional SQL conditions.
  185. * The parameter $valuecol defines the string name of the column to which
  186. * value restrictions etc. are to be applied.
  187. * @param $requestoptions object with options
  188. * @param $valuecol name of SQL column to which conditions apply
  189. * @param $labelcol name of SQL column to which string conditions apply, if any
  190. */
  191. public static function getSQLConditions( $requestoptions, $valuecol, $labelcol = NULL ) {
  192. $sql_conds = '';
  193. if ( $requestoptions !== NULL ) {
  194. $db = wfGetDB( DB_SLAVE ); // TODO: use slave?
  195. if ( $requestoptions->boundary !== NULL ) { // apply value boundary
  196. if ( $requestoptions->ascending ) {
  197. if ( $requestoptions->include_boundary ) {
  198. $op = ' >= ';
  199. } else {
  200. $op = ' > ';
  201. }
  202. } else {
  203. if ( $requestoptions->include_boundary ) {
  204. $op = ' <= ';
  205. } else {
  206. $op = ' < ';
  207. }
  208. }
  209. $sql_conds .= ' AND ' . mysql_real_escape_string( $valuecol ) . $op . $db->addQuotes( $requestoptions->boundary );
  210. }
  211. $operator = isset( $requestoptions->disjunctiveStrings ) && $requestoptions->disjunctiveStrings === true ? ' OR ' : ' AND ';
  212. $neutral = isset( $requestoptions->disjunctiveStrings ) && $requestoptions->disjunctiveStrings === true ? ' FALSE ' : ' TRUE ';
  213. if ( $labelcol !== NULL ) { // apply string conditions
  214. $sql_conds .= ' AND ( ';
  215. foreach ( $requestoptions->getStringConditions() as $strcond ) {
  216. $string = str_replace( array( '_', ' ' ), array( '\_', '\_' ), $strcond->string );
  217. switch ( $strcond->condition ) {
  218. case SMWStringCondition::STRCOND_PRE:
  219. $string .= '%';
  220. break;
  221. case SMWStringCondition::STRCOND_POST:
  222. $string = '%' . $string;
  223. break;
  224. case SMWStringCondition::STRCOND_MID:
  225. $string = '%' . $string . '%';
  226. break;
  227. }
  228. if ( $requestoptions->isCaseSensitive ) {
  229. $sql_conds .= mysql_real_escape_string( $labelcol ) . ' LIKE ' . $db->addQuotes( $string ) . $operator;
  230. } else {
  231. $sql_conds .= ' UPPER(' . mysql_real_escape_string( $labelcol ) . ') LIKE UPPER(' . $db->addQuotes( $string ) . ') ' . $operator;
  232. }
  233. }
  234. $sql_conds .= ' ' . $neutral . ' ) ';
  235. }
  236. }
  237. return $sql_conds;
  238. }
  239. /**
  240. * Returns sql conditions of $requestoptions in an Array.
  241. * Warning! Does not support SMWAdvRequestOptions
  242. *
  243. * @param SMWRequestOptions $requestoptions
  244. * @param string $valuecol
  245. * @param string $labelcol
  246. * @return array
  247. */
  248. public static function getSQLConditionsAsArray( $requestoptions, $valuecol, $labelcol = NULL ) {
  249. $sql_conds = array();
  250. if ( $requestoptions !== NULL ) {
  251. $db = wfGetDB( DB_SLAVE );
  252. if ( $requestoptions->boundary !== NULL ) { // apply value boundary
  253. if ( $requestoptions->ascending ) {
  254. if ( $requestoptions->include_boundary ) {
  255. $op = ' >= ';
  256. } else {
  257. $op = ' > ';
  258. }
  259. } else {
  260. if ( $requestoptions->include_boundary ) {
  261. $op = ' <= ';
  262. } else {
  263. $op = ' < ';
  264. }
  265. }
  266. $sql_conds[] = mysql_real_escape_string( $valuecol ) . $op . $db->addQuotes( $requestoptions->boundary );
  267. }
  268. if ( $labelcol !== NULL ) { // apply string conditions
  269. foreach ( $requestoptions->getStringConditions() as $strcond ) {
  270. $string = str_replace( array( '_', ' ' ), array( '\_', '\_' ), $strcond->string );
  271. switch ( $strcond->condition ) {
  272. case SMWStringCondition::STRCOND_PRE:
  273. $string .= '%';
  274. break;
  275. case SMWStringCondition::STRCOND_POST:
  276. $string = '%' . $string;
  277. break;
  278. case SMWStringCondition::STRCOND_MID:
  279. $string = '%' . $string . '%';
  280. break;
  281. }
  282. $sql_conds[] = 'UPPER(' . mysql_real_escape_string( $labelcol ) . ') LIKE UPPER(' . $db->addQuotes( $string ) . ')';
  283. }
  284. }
  285. }
  286. return $sql_conds;
  287. }
  288. }