Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F772178
db_connection.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Feb 1, 5:34 AM
Size
16 KB
Mime Type
text/x-php
Expires
Mon, Feb 3, 5:34 AM (3 h, 39 m)
Engine
blob
Format
Raw Data
Handle
555722
Attached To
rINP In-Portal
db_connection.php
View Options
<?php
/**
* @version $Id: db_connection.php 13529 2010-05-11 08:47:37Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined
(
'FULL_PATH'
)
or
die
(
'restricted access!'
);
/**
* Multi database connection class
*
*/
class
kDBConnection
{
/**
* Holds reference to global KernelApplication instance
* @access public
* @var kApplication
*/
var
$Application
;
/**
* Current database type
*
* @var string
* @access private
*/
var
$dbType
=
'mysql'
;
/**
* Created connection handle
*
* @var resource
* @access private
*/
var
$connectionID
=
null
;
/**
* Handle of currenty processed recordset
*
* @var resource
* @access private
*/
var
$queryID
=
null
;
/**
* DB type specific function mappings
*
* @var Array
* @access private
*/
var
$metaFunctions
=
Array
();
/**
* Function to handle sql errors
*
* @var string
* @access private
*/
var
$errorHandler
=
''
;
/**
* Error code
*
* @var int
* @access private
*/
var
$errorCode
=
0
;
/**
* Error message
*
* @var string
* @access private
*/
var
$errorMessage
=
''
;
/**
* Defines if database connection
* operations should generate debug
* information
*
* @var bool
*/
var
$debugMode
=
false
;
/**
* Save query execution statistics
*
* @var bool
*/
var
$_captureStatistics
=
false
;
/**
* Last query to database
*
* @var string
*/
var
$lastQuery
=
''
;
/**
* Total processed queries count
*
* @var int
*/
var
$_queryCount
=
0
;
/**
* Total time, used for serving queries
*
* @var Array
*/
var
$_queryTime
=
0
;
/**
* Initializes connection class with
* db type to used in future
*
* @param string $dbType
* @return DBConnection
* @access public
*/
function
kDBConnection
(
$dbType
,
$errorHandler
=
''
)
{
$this
->
dbType
=
$dbType
;
// $this->initMetaFunctions();
if
(!
$errorHandler
)
{
$this
->
errorHandler
=
Array
(&
$this
,
'handleError'
);
}
else
{
$this
->
errorHandler
=
$errorHandler
;
}
$this
->
_captureStatistics
=
defined
(
'DBG_CAPTURE_STATISTICS'
)
&&
DBG_CAPTURE_STATISTICS
&&
!(
defined
(
'ADMIN'
)
&&
ADMIN
);
if
(
class_exists
(
'kApplication'
))
{
// prevents "Fatal Error" on 2nd installation step (when database is empty)
$this
->
Application
=&
kApplication
::
Instance
();
}
}
/**
* Set's custom error
*
* @param int $code
* @param string $msg
* @access public
*/
function
setError
(
$code
,
$msg
)
{
$this
->
errorCode
=
$code
;
$this
->
errorMessage
=
$msg
;
}
/**
* Checks if previous query execution
* raised an error.
*
* @return bool
* @access public
*/
function
hasError
()
{
return
!(
$this
->
errorCode
==
0
);
}
/**
* Caches function specific to requested
* db type
*
* @access private
*/
function
initMetaFunctions
()
{
$ret
=
Array
();
switch
(
$this
->
dbType
)
{
case
'mysql'
:
$ret
=
Array
();
// only define functions, that name differs from "dbType_<meta_name>"
break
;
}
$this
->
metaFunctions
=
$ret
;
}
/**
* Get's function for specific db type
* based on it's meta name
*
* @param string $name
* @return string
* @access private
*/
function
getMetaFunction
(
$name
)
{
/*if (!isset($this->metaFunctions[$name])) {
$this->metaFunctions[$name] = $name;
}*/
return
$this
->
dbType
.
'_'
.
$name
;
}
/**
* Try to connect to database server
* using specified parameters and set
* database to $db if connection made
*
* @param string $host
* @param string $user
* @param string $pass
* @param string $db
* @access public
*/
function
Connect
(
$host
,
$user
,
$pass
,
$db
,
$force_new
=
false
)
{
$func
=
$this
->
getMetaFunction
(
'connect'
);
$this
->
connectionID
=
$func
(
$host
,
$user
,
$pass
,
$force_new
)
or
trigger_error
(
"Database connection failed, please check your connection settings"
,
defined
(
'IS_INSTALL'
)
&&
IS_INSTALL
?
E_USER_WARNING
:
E_USER_ERROR
);
if
(
$this
->
connectionID
)
{
if
(
defined
(
'DBG_SQL_MODE'
))
{
$this
->
Query
(
'SET sql_mode =
\'
'
.
DBG_SQL_MODE
.
'
\'
'
);
}
if
(
defined
(
'SQL_COLLATION'
)
&&
defined
(
'SQL_CHARSET'
))
{
$this
->
Query
(
'SET NAMES
\'
'
.
SQL_CHARSET
.
'
\'
COLLATE
\'
'
.
SQL_COLLATION
.
'
\'
'
);
}
$this
->
setDB
(
$db
);
$this
->
showError
();
}
else
{
// simulate error, becase php mysql client doesn't provide such information
$this
->
errorCode
=
2003
;
$this
->
errorMessage
=
"Can't connect to MySQL server on '$host' (113)"
;
}
}
function
ReConnect
(
$host
,
$user
,
$pass
,
$db
,
$force_new
=
false
)
{
$func
=
$this
->
getMetaFunction
(
'close'
);
$func
(
$this
->
connectionID
);
$this
->
Connect
(
$host
,
$user
,
$pass
,
$db
,
$force_new
);
}
/**
* Shows error message from previous operation
* if it failed
*
* @access private
*/
function
showError
(
$sql
=
''
)
{
$this
->
setError
(
0
,
''
);
// reset error
if
(
$this
->
connectionID
)
{
$func
=
$this
->
getMetaFunction
(
'errno'
);
$this
->
errorCode
=
$func
(
$this
->
connectionID
);
if
(
$this
->
hasError
())
{
$func
=
$this
->
getMetaFunction
(
'error'
);
$this
->
errorMessage
=
$func
(
$this
->
connectionID
);
if
(
is_array
(
$this
->
errorHandler
))
{
$func
=
$this
->
errorHandler
[
1
];
$ret
=
$this
->
errorHandler
[
0
]->
$func
(
$this
->
errorCode
,
$this
->
errorMessage
,
$sql
);
}
else
{
$func
=
$this
->
errorHandler
;
$ret
=
$func
(
$this
->
errorCode
,
$this
->
errorMessage
,
$sql
);
}
if
(!
$ret
)
exit
;
}
}
}
/**
* Default error handler for sql errors
*
* @param int $code
* @param string $msg
* @param string $sql
* @return bool
* @access private
*/
function
handleError
(
$code
,
$msg
,
$sql
)
{
echo
'<b>Processing SQL</b>: '
.
$sql
.
'<br>'
;
echo
'<b>Error ('
.
$code
.
'):</b> '
.
$msg
.
'<br>'
;
return
false
;
}
/**
* Set's database name for connection
* to $new_name
*
* @param string $new_name
* @return bool
* @access public
*/
function
setDB
(
$new_name
)
{
if
(!
$this
->
connectionID
)
return
false
;
$func
=
$this
->
getMetaFunction
(
'select_db'
);
return
$func
(
$new_name
,
$this
->
connectionID
);
}
/**
* Returns first field of first line
* of recordset if query ok or false
* otherwise
*
* @param string $sql
* @param int $offset
* @return string
* @access public
*/
function
GetOne
(
$sql
,
$offset
=
0
)
{
$row
=
$this
->
GetRow
(
$sql
,
$offset
);
if
(!
$row
)
return
false
;
return
array_shift
(
$row
);
}
/**
* Returns first row of recordset
* if query ok, false otherwise
*
* @param stirng $sql
* @param int $offset
* @return Array
* @access public
*/
function
GetRow
(
$sql
,
$offset
=
0
)
{
$sql
.=
' '
.
$this
->
getLimitClause
(
$offset
,
1
);
$ret
=
$this
->
Query
(
$sql
);
if
(!
$ret
)
return
false
;
return
array_shift
(
$ret
);
}
/**
* Returns 1st column of recordset as
* one-dimensional array or false otherwise
* Optional parameter $key_field can be used
* to set field name to be used as resulting
* array key
*
* @param string $sql
* @param string $key_field
* @return Array
* @access public
*/
function
GetCol
(
$sql
,
$key_field
=
null
)
{
$rows
=
$this
->
Query
(
$sql
);
if
(!
$rows
)
return
$rows
;
$i
=
0
;
$row_count
=
count
(
$rows
);
$ret
=
Array
();
if
(
isset
(
$key_field
))
{
while
(
$i
<
$row_count
)
{
$ret
[
$rows
[
$i
][
$key_field
]]
=
array_shift
(
$rows
[
$i
]);
$i
++;
}
}
else
{
while
(
$i
<
$row_count
)
{
$ret
[]
=
array_shift
(
$rows
[
$i
]);
$i
++;
}
}
return
$ret
;
}
/**
* Queries db with $sql query supplied
* and returns rows selected if any, false
* otherwise. Optional parameter $key_field
* allows to set one of the query fields
* value as key in string array.
*
* @param string $sql
* @param string $key_field
* @return Array
*/
function
Query
(
$sql
,
$key_field
=
null
,
$no_debug
=
false
)
{
$this
->
lastQuery
=
$sql
;
if
(!
$no_debug
)
{
$this
->
_queryCount
++;
}
if
(
$this
->
debugMode
&&
!
$no_debug
)
{
return
$this
->
debugQuery
(
$sql
,
$key_field
);
}
$query_func
=
$this
->
getMetaFunction
(
'query'
);
// set 1st checkpoint: begin
if
(
$this
->
_captureStatistics
)
{
$start_time
=
getmicrotime
();
}
// set 1st checkpoint: end
$this
->
queryID
=
$query_func
(
$sql
,
$this
->
connectionID
);
if
(
is_resource
(
$this
->
queryID
))
{
$ret
=
Array
();
$fetch_func
=
$this
->
getMetaFunction
(
'fetch_assoc'
);
if
(
isset
(
$key_field
))
{
while
((
$row
=
$fetch_func
(
$this
->
queryID
)))
{
$ret
[
$row
[
$key_field
]]
=
$row
;
}
}
else
{
while
((
$row
=
$fetch_func
(
$this
->
queryID
)))
{
$ret
[]
=
$row
;
}
}
// set 2nd checkpoint: begin
if
(
$this
->
_captureStatistics
)
{
$query_time
=
getmicrotime
()
-
$start_time
;
if
(
$query_time
>
DBG_MAX_SQL_TIME
&&
!
$no_debug
)
{
$this
->
Application
->
logSlowQuery
(
$sql
,
$query_time
);
}
$this
->
_queryTime
+=
$query_time
;
}
// set 2nd checkpoint: end
$this
->
Destroy
();
return
$ret
;
}
else
{
// set 2nd checkpoint: begin
if
(
$this
->
_captureStatistics
)
{
$this
->
_queryTime
+=
getmicrotime
()
-
$start_time
;
}
// set 2nd checkpoint: end
}
$this
->
showError
(
$sql
);
return
false
;
}
function
ChangeQuery
(
$sql
)
{
$this
->
Query
(
$sql
);
return
$this
->
errorCode
==
0
?
true
:
false
;
}
function
debugQuery
(
$sql
,
$key_field
=
null
)
{
global
$debugger
;
$query_func
=
$this
->
getMetaFunction
(
'query'
);
// set 1st checkpoint: begin
$profileSQLs
=
defined
(
'DBG_SQL_PROFILE'
)
&&
DBG_SQL_PROFILE
;
if
(
$profileSQLs
)
{
$queryID
=
$debugger
->
generateID
();
$debugger
->
profileStart
(
'sql_'
.
$queryID
,
$debugger
->
formatSQL
(
$sql
));
}
// set 1st checkpoint: end
$this
->
queryID
=
$query_func
(
$sql
,
$this
->
connectionID
);
if
(
is_resource
(
$this
->
queryID
)
)
{
$ret
=
Array
();
$fetch_func
=
$this
->
getMetaFunction
(
'fetch_assoc'
);
if
(
isset
(
$key_field
)
)
{
while
(
(
$row
=
$fetch_func
(
$this
->
queryID
))
)
{
$ret
[
$row
[
$key_field
]]
=
$row
;
}
}
else
{
while
(
(
$row
=
$fetch_func
(
$this
->
queryID
))
)
{
$ret
[]
=
$row
;
}
}
// set 2nd checkpoint: begin
if
(
$profileSQLs
)
{
$first_cell
=
count
(
$ret
)
==
1
&&
count
(
current
(
$ret
))
==
1
?
current
(
current
(
$ret
))
:
null
;
if
(
strlen
(
$first_cell
)
>
200
)
{
$first_cell
=
substr
(
$first_cell
,
0
,
50
)
.
' ...'
;
}
$debugger
->
profileFinish
(
'sql_'
.
$queryID
,
null
,
null
,
$this
->
getAffectedRows
(),
$first_cell
,
$this
->
_queryCount
);
$debugger
->
profilerAddTotal
(
'sql'
,
'sql_'
.
$queryID
);
}
// set 2nd checkpoint: end
$this
->
Destroy
();
return
$ret
;
}
else
{
// set 2nd checkpoint: begin
if
(
$profileSQLs
)
{
$debugger
->
profileFinish
(
'sql_'
.
$queryID
,
null
,
null
,
$this
->
getAffectedRows
(),
null
,
$this
->
_queryCount
);
$debugger
->
profilerAddTotal
(
'sql'
,
'sql_'
.
$queryID
);
}
// set 2nd checkpoint: end
}
$this
->
showError
(
$sql
);
return
false
;
}
/**
* Free memory used to hold recordset handle
*
* @access private
*/
function
Destroy
()
{
if
(
$this
->
queryID
)
{
$free_func
=
$this
->
getMetaFunction
(
'free_result'
);
$free_func
(
$this
->
queryID
);
$this
->
queryID
=
null
;
}
}
/**
* Returns auto increment field value from
* insert like operation if any, zero otherwise
*
* @return int
* @access public
*/
function
getInsertID
()
{
$func
=
$this
->
getMetaFunction
(
'insert_id'
);
return
$func
(
$this
->
connectionID
);
}
/**
* Returns row count affected by last query
*
* @return int
* @access public
*/
function
getAffectedRows
()
{
$func
=
$this
->
getMetaFunction
(
'affected_rows'
);
return
$func
(
$this
->
connectionID
);
}
/**
* Returns LIMIT sql clause part for specific db
*
* @param int $offset
* @param int $rows
* @return string
* @access private
*/
function
getLimitClause
(
$offset
,
$rows
)
{
if
(!(
$rows
>
0
))
return
''
;
switch
(
$this
->
dbType
)
{
default
:
return
'LIMIT '
.
$offset
.
','
.
$rows
;
break
;
}
}
/**
* If it's a string, adds quotes and backslashes (only work since PHP 4.3.0)
* Otherwise returns as-is
*
* @param mixed $string
*
* @return string
*/
function
qstr
(
$string
)
{
if
(
is_null
(
$string
)
)
{
return
'NULL'
;
}
# This will also quote numeric values. This should be harmless,
# and protects against weird problems that occur when they really
# _are_ strings such as article titles and string->number->string
# conversion is not 1:1.
return
"'"
.
mysql_real_escape_string
(
$string
,
$this
->
connectionID
)
.
"'"
;
}
/**
* Escapes strings (only work since PHP 4.3.0)
*
* @param mixed $string
*
* @return string
*/
function
escape
(
$string
)
{
if
(
is_null
(
$string
)
)
{
return
'NULL'
;
}
$string
=
mysql_real_escape_string
(
$string
,
$this
->
connectionID
);
// prevent double-escaping of MySQL wildcard symbols ("%" and "_") in case if they were already escaped
return
str_replace
(
Array
(
'
\\\\
%'
,
'
\\\\
_'
),
Array
(
'
\\
%'
,
'
\\
_'
),
$string
);
}
/**
* Returns last error code occured
*
* @return int
*/
function
getErrorCode
()
{
return
$this
->
errorCode
;
}
/**
* Returns last error message
*
* @return string
* @access public
*/
function
getErrorMsg
()
{
return
$this
->
errorMessage
;
}
/**
* Performs insert of given data (useful with small number of queries)
* or stores it to perform multiple insert later (useful with large number of queries)
*
* @param Array $fields_hash
* @param string $table
* @param string $type
* @param bool $insert_now
* @return bool
*/
function
doInsert
(
$fields_hash
,
$table
,
$type
=
'INSERT'
,
$insert_now
=
true
)
{
static
$value_sqls
=
Array
();
if
(
$insert_now
)
{
$fields_sql
=
'`'
.
implode
(
'`,`'
,
array_keys
(
$fields_hash
))
.
'`'
;
}
$values_sql
=
''
;
foreach
(
$fields_hash
as
$field_name
=>
$field_value
)
{
$values_sql
.=
$this
->
qstr
(
$field_value
)
.
','
;
}
// don't use preg here, as it may fail when string is too long
$value_sqls
[]
=
rtrim
(
$values_sql
,
','
);
$insert_result
=
true
;
if
(
$insert_now
)
{
$insert_count
=
count
(
$value_sqls
);
if
((
$insert_count
>
1
)
&&
(
$value_sqls
[
$insert_count
-
1
]
==
$value_sqls
[
$insert_count
-
2
]))
{
// last two records are the same
array_pop
(
$value_sqls
);
}
$sql
=
strtoupper
(
$type
)
.
' INTO `'
.
$table
.
'` ('
.
$fields_sql
.
') VALUES ('
.
implode
(
'),('
,
$value_sqls
)
.
')'
;
$insert_result
=
$this
->
ChangeQuery
(
$sql
);
$value_sqls
=
Array
();
}
return
$insert_result
;
}
function
doUpdate
(
$fields_hash
,
$table
,
$key_clause
)
{
if
(!
$fields_hash
)
return
true
;
$fields_sql
=
''
;
foreach
(
$fields_hash
as
$field_name
=>
$field_value
)
{
$fields_sql
.=
'`'
.
$field_name
.
'` = '
.
$this
->
qstr
(
$field_value
)
.
','
;
}
// don't use preg here, as it may fail when string is too long
$fields_sql
=
rtrim
(
$fields_sql
,
','
);
$sql
=
'UPDATE `'
.
$table
.
'` SET '
.
$fields_sql
.
' WHERE '
.
$key_clause
;
return
$this
->
ChangeQuery
(
$sql
);
}
/**
* Allows to detect table's presense in database
*
* @param string $table_name
* @return bool
*/
function
TableFound
(
$table_name
)
{
static
$table_found
=
Array
();
if
(!
preg_match
(
'/^'
.
preg_quote
(
TABLE_PREFIX
,
'/'
).
'(.*)/'
,
$table_name
))
{
$table_name
=
TABLE_PREFIX
.
$table_name
;
}
if
(!
isset
(
$table_found
[
$table_name
]))
{
$table_found
[
$table_name
]
=
$this
->
Query
(
'SHOW TABLES LIKE "'
.
$table_name
.
'"'
);
}
return
$table_found
[
$table_name
];
}
/**
* Returns query processing statistics
*
* @return Array
*/
function
getQueryStatistics
()
{
return
Array
(
'time'
=>
$this
->
_queryTime
,
'count'
=>
$this
->
_queryCount
);
}
}
Event Timeline
Log In to Comment