Replaced calls to exit() with wfAbruptExit().
[lhc/web/wiklou.git] / includes / DatabaseFunctions.php
1 <?
2 include_once( "FulltextStoplist.php" );
3 include_once( "CacheManager.php" );
4
5 define( "DB_READ", -1 );
6 define( "DB_WRITE", -2 );
7 define( "DB_LAST", -3 );
8
9 $wgLastDatabaseQuery = "";
10
11 /* private */ $wgBufferSQLResults = true;
12
13 function wfGetDB( $altuser = "", $altpassword = "", $altserver = "", $altdb = "" )
14 {
15 global $wgDBserver, $wgDBuser, $wgDBpassword;
16 global $wgDBname, $wgDBconnection, $wgEmergencyContact;
17
18 $noconn = wfMsgNoDB( "noconnect", $wgDBserver );
19 $nodb = wfMsgNoDB( "nodb", $wgDBname );
20
21 $helpme = "\n<p>If this error persists after reloading and clearing " .
22 "your browser cache, please notify the <a href=\"mailto:" .
23 $wgEmergencyContact . "\">Wikipedia developers</a>.</p>";
24
25 if ( $altuser != "" ) {
26 $serve = ($altserver ? $altserver : $wgDBserver );
27 $db = ($altdb ? $altdb : $wgDBname );
28 $wgDBconnection = mysql_connect( $serve, $altuser, $altpassword )
29 or die( "bad sql user" );
30 mysql_select_db( $db, $wgDBconnection ) or die(
31 htmlspecialchars(mysql_error()) );
32 }
33
34 if ( ! $wgDBconnection ) {
35 @$wgDBconnection = mysql_pconnect( $wgDBserver, $wgDBuser, $wgDBpassword )
36 or wfEmergencyAbort();
37
38 if( !mysql_select_db( $wgDBname, $wgDBconnection ) ) {
39 /* Persistent connections may become stuck in an unusable state */
40 wfDebug( "Persistent connection is broken?\n", true );
41
42 @$wgDBconnection = mysql_connect( $wgDBserver, $wgDBuser, $wgDBpassword )
43 or wfEmergencyAbort();
44
45 @mysql_select_db( $wgDBname, $wgDBconnection )
46 or wfEmergencyAbort();
47 }
48 }
49 # mysql_ping( $wgDBconnection );
50 return $wgDBconnection;
51 }
52
53 /* Call this function if we couldn't contact the database...
54 We'll try to use the cache to display something in the meantime */
55 function wfEmergencyAbort( $msg = "" ) {
56 global $wgTitle, $wgUseFileCache, $title, $wgOutputEncoding;
57
58 header( "Content-type: text/html; charset=$wgOutputEncoding" );
59 if($msg == "") $msg = wfMsgNoDB( "noconnect" );
60 $text = $msg;
61
62 if($wgUseFileCache) {
63 if($wgTitle) {
64 $t =& $wgTitle;
65 } else {
66 if($title) {
67 $t = Title::newFromURL( $title );
68 } else {
69 $t = Title::newFromText( wfMsgNoDB( "mainpage" ) );
70 }
71 }
72
73 $cache = new CacheManager( $t );
74 if( $cache->isFileCached() ) {
75 $msg = "<p style='color: red'><b>$msg<br>\n" .
76 wfMsgNoDB( "cachederror" ) . "</b></p>\n";
77
78 $tag = "<div id='article'>";
79 $text = str_replace(
80 $tag,
81 $tag . $msg,
82 $cache->fetchPageText() );
83 }
84 }
85
86 /* Don't cache error pages! They cause no end of trouble... */
87 header( "Cache-control: none" );
88 header( "Pragma: nocache" );
89 echo $text;
90 wfAbruptExit();
91 }
92
93 # $db: DB_READ = -1 read from slave (or only server)
94 # DB_WRITE = -2 write to master (or only server)
95 # 0,1,2,... query a database with a specific index
96 # Replication is not actually implemented just yet
97 function wfQuery( $sql, $db, $fname = "" )
98 {
99 global $wgLastDatabaseQuery, $wgOut, $wgDebugDumpSql, $wgBufferSQLResults;
100 global $wgProfiling;
101 if ( $wgProfiling ) {
102 # wfGeneralizeSQL will probably cut down the query to reasonable
103 # logging size most of the time. The substr is really just a sanity check.
104 $profName = "wfQuery: " . substr( wfGeneralizeSQL( $sql ), 0, 255 );
105 wfProfileIn( $profName );
106 }
107
108 if ( !is_numeric( $db ) ) {
109 # Someone has tried to call this the old way
110 $wgOut->fatalError( wfMsgNoDB( "wrong_wfQuery_params", $db, $sql ) );
111 }
112
113 $wgLastDatabaseQuery = $sql;
114
115 if( $wgDebugDumpSql ) {
116 $sqlx = substr( $sql, 0, 500 );
117 $sqlx = wordwrap(strtr($sqlx,"\t\n"," "));
118 wfDebug( "SQL: $sqlx\n" );
119 }
120
121 $conn = wfGetDB();
122 if( $wgBufferSQLResults ) {
123 $ret = mysql_query( $sql, $conn );
124 } else {
125 $ret = mysql_unbuffered_query( $sql, $conn );
126 }
127
128 if ( false === $ret ) {
129 $wgOut->databaseError( $fname );
130 wfAbruptExit();
131 }
132
133 if ( $wgProfiling ) {
134 wfProfileOut( $profName );
135 }
136 return $ret;
137 }
138
139 function wfUnbufferedQuery( $sql, $db, $fname = "" ){
140 global $wgBufferSQLResults;
141 $oldstate = $wgBufferSQLResults;
142
143 $wgBufferSQLResults = true;
144 $res = wfQuery($sql, $db, $fname);
145
146 $wgBufferSQLResults = $oldstate;
147 return $res;
148 }
149
150 function wfFreeResult( $res ) { mysql_free_result( $res ); }
151 function wfFetchObject( $res ) { return mysql_fetch_object( $res ); }
152 function wfNumRows( $res ) { return mysql_num_rows( $res ); }
153 function wfNumFields( $res ) { return mysql_num_fields( $res ); }
154 function wfFieldName( $res, $n ) { return mysql_field_name( $res, $n ); }
155 function wfInsertId() { return mysql_insert_id( wfGetDB() ); }
156 function wfDataSeek( $res, $row ) { return mysql_data_seek( $res, $row ); }
157 function wfLastErrno() { return mysql_errno(); }
158 function wfLastError() { return mysql_error(); }
159 function wfAffectedRows() { return mysql_affected_rows( wfGetDB() ); }
160
161 function wfLastDBquery()
162 {
163 global $wgLastDatabaseQuery;
164 return $wgLastDatabaseQuery;
165 }
166
167 function wfSetSQL( $table, $var, $value, $cond )
168 {
169 $sql = "UPDATE $table SET $var = '" .
170 wfStrencode( $value ) . "' WHERE ($cond)";
171 wfQuery( $sql, DB_WRITE, "wfSetSQL" );
172 }
173
174 function wfGetSQL( $table, $var, $cond )
175 {
176 $sql = "SELECT $var FROM $table WHERE ($cond)";
177 $result = wfQuery( $sql, DB_READ, "wfGetSQL" );
178
179 $ret = "";
180 if ( mysql_num_rows( $result ) > 0 ) {
181 $s = mysql_fetch_object( $result );
182 $ret = $s->$var;
183 mysql_free_result( $result );
184 }
185 return $ret;
186 }
187
188 function wfStrencode( $s )
189 {
190 return addslashes( $s );
191 }
192
193 # Ideally we'd be using actual time fields in the db
194 function wfTimestamp2Unix( $ts ) {
195 return gmmktime( ( (int)substr( $ts, 8, 2) ),
196 (int)substr( $ts, 10, 2 ), (int)substr( $ts, 12, 2 ),
197 (int)substr( $ts, 4, 2 ), (int)substr( $ts, 6, 2 ),
198 (int)substr( $ts, 0, 4 ) );
199 }
200
201 function wfUnix2Timestamp( $unixtime ) {
202 return gmdate( "YmdHis", $unixtime );
203 }
204
205 function wfTimestampNow() {
206 # return NOW
207 return gmdate( "YmdHis" );
208 }
209
210 # Sorting hack for MySQL 3, which doesn't use index sorts for DESC
211 function wfInvertTimestamp( $ts ) {
212 return strtr(
213 $ts,
214 "0123456789",
215 "9876543210"
216 );
217 }
218
219 # Removes most variables from an SQL query and replaces them with X or N for numbers.
220 # It's only slightly flawed. Don't use for anything important.
221 function wfGeneralizeSQL( $sql )
222 {
223 # This does the same as the regexp below would do, but in such a way
224 # as to avoid crashing php on some large strings.
225 # $sql = preg_replace ( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql);
226
227 $sql = str_replace ( "\\\\", "", $sql);
228 $sql = str_replace ( "\\'", "", $sql);
229 $sql = str_replace ( "\\\"", "", $sql);
230 $sql = preg_replace ("/'.*'/s", "'X'", $sql);
231 $sql = preg_replace ('/".*"/s', "'X'", $sql);
232
233 # All newlines, tabs, etc replaced by single space
234 $sql = preg_replace ( "/\s+/", " ", $sql);
235
236 # All numbers => N
237 $sql = preg_replace ('/-?[0-9]+/s', "N", $sql);
238
239 return $sql;
240 }
241
242 function wfFieldExists( $table, $field )
243 {
244 $fname = "wfFieldExists";
245 $res = wfQuery( "DESCRIBE $table", DB_READ, $fname );
246 $found = false;
247
248 while ( $row = wfFetchObject( $res ) ) {
249 if ( $row->Field == $field ) {
250 $found = true;
251 break;
252 }
253 }
254 return $found;
255 }
256
257 function wfIndexExists( $table, $index )
258 {
259 global $wgDBname;
260 $fname = "wfIndexExists";
261 $sql = "SHOW INDEXES FROM $table";
262 $res = wfQuery( $sql, DB_READ, $fname );
263 $found = false;
264 while ( $row = wfFetchObject( $res ) ) {
265 if ( $row->Key_name == $index ) {
266 $found = true;
267 break;
268 }
269 }
270 return $found;
271 }
272 ?>