1 |
ravilov |
1.1 |
<?PHP // -*-Mode: C++;-*- |
2 |
|
|
/* |
3 |
|
|
Bill Adams (bill<at>evil<dot>inetarena<dot>com) |
4 |
|
|
DBI.php3 -- A perl DBI like class. |
5 |
|
|
See: http://evil.inetarena.com/php/DBI.php for more info. |
6 |
|
|
|
7 |
|
|
Licence: LGPL (http://www.gnu.org/). |
8 |
|
|
|
9 |
|
|
This software is provided "AS IS" with no warrenty either implicit, |
10 |
|
|
explicit or otherwise. Use at your own risk. |
11 |
|
|
|
12 |
|
|
... |
13 |
|
|
|
14 |
|
|
Notes: |
15 |
|
|
|
16 |
|
|
o 'do' is called 'dbh_do' in this because 'do' is a reserved word. |
17 |
|
|
|
18 |
|
|
o Not every function is implemented. |
19 |
|
|
|
20 |
|
|
|
21 |
|
|
28 Mar 2000 baa Fixed the sth function to call the right constructor so |
22 |
|
|
. one can have multiple database connections. |
23 |
|
|
|
24 |
|
|
*/ |
25 |
|
|
|
26 |
|
|
class DBI { |
27 |
|
|
|
28 |
|
|
var $db_type = ''; |
29 |
|
|
var $dbh = ''; |
30 |
|
|
var $DBD; |
31 |
|
|
var $errorstr = ''; |
32 |
|
|
var $is_persistent; |
33 |
|
|
var $exit_on_fail = 0; |
34 |
|
|
|
35 |
|
|
function parse_dbi_string( $dbi_connect_str ){ |
36 |
|
|
|
37 |
|
|
if( ereg( "(p)?dbi:(.+):(.+)[;:](host=)?(.+)", $dbi_connect_str, $regs ) || |
38 |
|
|
ereg( "(p)?dbi:(.+):(.+)", $dbi_connect_str, $regs )){ |
39 |
|
|
$dbi[db_type] = $regs[2]; |
40 |
|
|
$dbi[db_name] = $regs[3]; |
41 |
|
|
$dbi[db_host] = ( $regs[5] ? $regs[5] : '' ); |
42 |
|
|
$dbi[is_persistent] = ( $regs[1] ? 1 : 0 ); |
43 |
|
|
//echo "Connecting: [ ", |
44 |
|
|
//$dbi[db_type],"][", |
45 |
|
|
//$dbi[db_name],"][", |
46 |
|
|
//$dbi[dbh_user], "][", |
47 |
|
|
//$dbi[db_host], "]<br>\n"; |
48 |
|
|
return( $dbi ); |
49 |
|
|
|
50 |
|
|
} else { |
51 |
|
|
echo "DBI: Invalid Connect String '$dbi_connect_str'.<br>\n"; |
52 |
|
|
return; |
53 |
|
|
} |
54 |
|
|
|
55 |
|
|
} |
56 |
|
|
|
57 |
|
|
function DBI( $dbi_connect_str, $db_user = '', $db_passwd = '' ){ |
58 |
|
|
|
59 |
|
|
$this->is_persistent = 0; |
60 |
|
|
$dbi_info = $this->parse_dbi_string( $dbi_connect_str ); |
61 |
|
|
if( ! $dbi_info ){ return; } |
62 |
|
|
$this->is_persistent = $db_info[is_persistent]; |
63 |
|
|
|
64 |
|
|
|
65 |
|
|
if( $dbi_info[db_type] != '' ){ |
66 |
|
|
$this->connect( $dbi_info[db_type], $dbi_info[db_name], |
67 |
|
|
$dbi_info[db_host], |
68 |
|
|
$db_user, $db_passwd, |
69 |
|
|
$dbi_info[is_persistent] ); |
70 |
|
|
} |
71 |
|
|
return $this; |
72 |
|
|
//Arrg! There is no way to return a false object on the new. |
73 |
|
|
// so that means the user will have to check $this->dbh to see if |
74 |
|
|
// the connection was made. |
75 |
|
|
}//end constructor |
76 |
|
|
|
77 |
|
|
|
78 |
|
|
function connect( $db_type, $db_name, $db_host = '', |
79 |
|
|
$db_user = '', $db_passwd = '', |
80 |
|
|
$is_persistent = 0 ){ |
81 |
|
|
|
82 |
|
|
//See if we need to parse the db_type... |
83 |
|
|
if( ereg( "(p)?dbi:(.+):(.+)[;:](.+)", $db_type, $regs ) || |
84 |
|
|
ereg( "(p)?dbi:(.+):(.+)[;:]?(.+)?", $db_type, $regs )){ |
85 |
|
|
$db_user = $db_name; |
86 |
|
|
$db_passwd = $db_host; |
87 |
|
|
$db_type = $regs[2]; |
88 |
|
|
$db_name = $regs[3]; |
89 |
|
|
$db_host = ( $regs[4] ? $regs[4] : 'localhost' ); |
90 |
|
|
$is_persistent = ( $regs[1] ? 1 : 0 ); |
91 |
|
|
//echo "Connecting: [ $db_name ][ $dbh_user ][ $db_host ]<br>\n"; |
92 |
|
|
} |
93 |
|
|
|
94 |
|
|
$this->is_persistent = $is_persistent; |
95 |
|
|
|
96 |
|
|
//Select the database type. |
97 |
|
|
if( eregi( "^mysql$", $db_type )){ |
98 |
|
|
$db_type = 'mysql'; //perl string for this database. |
99 |
|
|
} else if( eregi( "informix", $db_type )){ |
100 |
|
|
$db_type = 'Informix'; |
101 |
|
|
} else if( eregi( "sybase", $db_type )){ |
102 |
|
|
$db_type = 'sybase'; |
103 |
|
|
} else if (eregi( "Pg", $db_type )){ |
104 |
|
|
$db_type = 'Pg'; |
105 |
|
|
} |
106 |
|
|
$this->db_type = $db_type; |
107 |
|
|
|
108 |
|
|
|
109 |
|
|
//Include the file only if we have not already read it. |
110 |
|
|
if( ! $GLOBALS['classDBD'.$db_type."_read"] ){ |
111 |
|
|
include( 'class.DBD::'.$db_type ); |
112 |
|
|
} |
113 |
|
|
|
114 |
|
|
//Check to see if we could read it... |
115 |
|
|
if( ! $GLOBALS['classDBD'.$db_type."_read"] ){ |
116 |
|
|
echo "Error: No DBD for $db_type.<br>\n"; |
117 |
|
|
$this->errstr = "Error: No DBD driver for '$db_type'."; |
118 |
|
|
return; |
119 |
|
|
} |
120 |
|
|
|
121 |
|
|
//Track the connections. The reason for doing this is that |
122 |
|
|
// if the user tries (at least with MySQL_* functions) to |
123 |
|
|
// connecto to a mysql database with the same arguments |
124 |
|
|
// then mysql_connect will return the same connection handle. |
125 |
|
|
// This is a problem when the user tries to select two different |
126 |
|
|
// MySQL databases using the same host, user, and password. |
127 |
|
|
//$GLOBALS[classDBI_connectiontrack] = array( ); |
128 |
|
|
if( $GLOBALS[classDBI_connectiontrack] |
129 |
|
|
[$db_type][$db_host][$db_user][$db_passwd] |
130 |
|
|
&& |
131 |
|
|
$GLOBALS[classDBI_connectiontrack] |
132 |
|
|
[$db_type][$db_host][$db_user][$db_passwd] != $db_name ){ |
133 |
|
|
echo "<B>DBI Warning:</B> You are trying to connect to two different ", |
134 |
|
|
$db_type," databases with the same host, user, and password. ", |
135 |
|
|
"This will probably give you unexpected results. ", |
136 |
|
|
"Expect problems.", |
137 |
|
|
"<br>\n"; |
138 |
|
|
} |
139 |
|
|
|
140 |
|
|
$DBD_class = 'DBD_'.$db_type; |
141 |
|
|
$this->DBD = new $DBD_class; |
142 |
|
|
|
143 |
|
|
//Originally, I was going to have the sub class set the variables |
144 |
|
|
// in this class but when you do something like $class1 = $class2, |
145 |
|
|
// PHP makes a copy of the class so changes to class2 will not |
146 |
|
|
// be shown in class1. For this reason, functions will need to be |
147 |
|
|
// fully parameterized and the value of DBD->errstr will have to be |
148 |
|
|
// copied after the call. |
149 |
|
|
|
150 |
|
|
//Note that the arg list for the DBD connect is different than that |
151 |
|
|
// of this connect. |
152 |
|
|
$conn = $this->DBD->DBD_connect( $db_name, $db_host, |
153 |
|
|
$db_user, $db_passwd, |
154 |
|
|
$this->is_persistent ); |
155 |
|
|
|
156 |
|
|
if( !$conn ){ |
157 |
|
|
$this->errstr = $this->DBD->errstr; |
158 |
|
|
return; |
159 |
|
|
} |
160 |
|
|
|
161 |
|
|
$GLOBALS[classDBI_connectiontrack] |
162 |
|
|
[$db_type][$db_host][$db_user][$db_passwd] = $db_name; |
163 |
|
|
|
164 |
|
|
$this->dbh = $conn; |
165 |
|
|
return( $this ); |
166 |
|
|
}//end connect function |
167 |
|
|
|
168 |
|
|
|
169 |
|
|
function disconnect( ){ |
170 |
|
|
if( $this->DBD ){ |
171 |
|
|
$this->DBD->disconnect( ); |
172 |
|
|
} |
173 |
|
|
}//end disconnect function |
174 |
|
|
|
175 |
|
|
|
176 |
|
|
function exit_on_fail( $yesno = '' ){ |
177 |
|
|
//Should the program stop if a query fails? |
178 |
|
|
// This is partially implemented. |
179 |
|
|
if( $yesno != '' ){ |
180 |
|
|
$this->DBD->exit_on_fail = $yesno; |
181 |
|
|
} |
182 |
|
|
return( $this->DBD->exit_on_fail ); |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
|
186 |
|
|
function prepare( $query ){ |
187 |
|
|
//Does nothing but save the query. Be sure we call the |
188 |
|
|
// prepare of the DBD object. Otherwise |
189 |
|
|
// we get conflicts if we try to have more than one |
190 |
|
|
// database handle. |
191 |
|
|
if( ! $this->dbh ){ return; } |
192 |
|
|
$sth = $this->DBD->prepare( $query ); |
193 |
|
|
$this->errstr = $this->DBD->errstr; |
194 |
|
|
return( $sth ); |
195 |
|
|
}//end dbh prepare fn |
196 |
|
|
|
197 |
|
|
|
198 |
|
|
//do is a reserved word so I have to name this something else. |
199 |
|
|
function dbh_do( $query ){ |
200 |
|
|
//run the query and return the number of affected rows. |
201 |
|
|
$rows = $this->DBD->dbh_do( $query ); |
202 |
|
|
$this->errstr = $this->DBD->errstr; |
203 |
|
|
if( $rows == 0 ){ $rows = '0E0'; } |
204 |
|
|
return( $rows ); |
205 |
|
|
}//end fn do |
206 |
|
|
|
207 |
|
|
|
208 |
|
|
function insert_id( ){ |
209 |
|
|
//Get the last serial number from an insert. |
210 |
|
|
return( $this->DBD->insert_id( )); |
211 |
|
|
}//end fn insert_id |
212 |
|
|
|
213 |
|
|
function quote( $string ){ |
214 |
|
|
return( $this->DBD->quote( $string )); |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
}//end DBI class |
218 |
|
|
|
219 |
|
|
//Print out warnings if the user gets duplicate connections. |
220 |
|
|
$GLOBALS[classDBI_connectiontrack] = array( ); |