18if ( !defined(
'E_USER_ERROR') ) define(
'E_USER_ERROR',256);
59 const HttpDateFormat =
"'Dy, DD Mon IYYY HH24:MI:SS \"GMT\"'";
64 const SqlDateFormat =
"'YYYYMMDD\"T\"HH24MISS'";
70 const SqlUTCFormat =
"'YYYYMMDD\"T\"HH24MISS\"Z\"'";
76 const SqlDurationFormat =
"'\"PT\"HH24\"H\"MI\"M\"'";
90 function __construct( $connection_string, $dbuser=
null, $dbpass=
null, $options=
null ) {
91 if ( preg_match(
'/^(pgsql):/', $connection_string, $matches ) ) {
92 $this->dialect = $matches[1];
95 error_log(
"Unable to connect to database: ". $e->getMessage() );
96 trigger_error(
"Unsupported database connection '".$connection_string.
"'",E_USER_ERROR);
99 $this->db =
new PDO( $connection_string, $dbuser, $dbpass, $options );
100 }
catch (PDOException $e) {
101 error_log(
"Unable to connect to database: ". $e->getMessage() );
102 if ( function_exists(
'trigger_error') )
103 trigger_error(
"PDO connection error '".$connection_string.
"': ".$e->getMessage(),E_USER_ERROR);
113 function SetSearchPath( $search_path =
null ) {
114 if ( !isset($this->dialect) ) {
115 trigger_error(
"Unsupported database dialect",E_USER_ERROR);
118 switch ( $this->dialect ) {
120 if ( $search_path ==
null ) $search_path =
'public';
121 $sql =
"SET search_path TO " . $search_path;
122 $sth = $this->db->query($sql);
132 function GetVersion( ) {
133 if ( isset($this->version) )
return $this->version;
134 if ( !isset($this->dialect) ) {
135 trigger_error(
"Unsupported database dialect", E_USER_ERROR);
138 $version = $this->dialect.
':';
140 switch ( $this->dialect ) {
142 $sql =
"SELECT version()";
143 if ( $sth = $this->db->query($sql) ) {
144 $row = $sth->fetch(PDO::FETCH_NUM);
145 $version .= preg_replace(
'/^PostgreSQL (\d+\.\d+)\..*$/i',
'$1', $row[0]);
151 $this->version = $version;
161 function GetFields( $tablename_string ) {
162 if ( !isset($this->dialect) ) {
163 trigger_error(
"Unsupported database dialect", E_USER_ERROR);
166 switch ( $this->dialect ) {
170 if ( strpos($tablename_string,
'.') ) {
171 list( $schema, $table ) = explode(
'.', $tablename_string, 2);
173 $table = $tablename_string;
176 $sql =
'SELECT f.attname AS fieldname, t.typname AS typename, f.atttypmod AS precision FROM pg_attribute f';
177 $sql .=
' JOIN pg_class c ON ( f.attrelid = c.oid )';
178 $sql .=
' JOIN pg_type t ON ( f.atttypid = t.oid )';
179 $sql .=
' JOIN pg_namespace ns ON ( c.relnamespace = ns.oid )';
180 $sql .=
' WHERE relname = '.$this->Quote($table,PDO::PARAM_STR).
' AND attnum >= 0 ';
181 if ( isset($schema) ) $sql .=
' AND ns.nspname = '.$this->Quote($schema,PDO::PARAM_STR);
182 $sql .=
' ORDER BY f.attnum';
183 dbg_error_log(
'AwlDBDialect', $sql);
202 function TranslateSQL( $sql_string ) {
216 function Quote( $value, $value_type =
null ) {
217 if ( isset($value_type) && $value_type ==
'identifier' ) {
218 if ( $this->dialect ==
'mysql' ) {
220 $rv =
'`' . str_replace(
'`',
'\\`', $value ) .
'`';
223 $rv =
'"' . str_replace(
'"',
'\\"', $value ) .
'"';
228 if ( !isset($value_type) ) {
229 if ( !isset($value) ) $value_type = PDO::PARAM_NULL;
230 elseif ( is_bool($value) ) $value_type = PDO::PARAM_BOOL;
231 elseif ( is_float($value) ) $value_type = PDO::PARAM_INT;
232 elseif ( is_numeric($value)) {
233 if ( preg_match(
'{^(19|20)\d\d(0[1-9]|1[012])([012]\d|30|31)$}', $value) )
234 $value_type = PDO::PARAM_STR;
235 elseif ( preg_match(
'{^0x}i', $value) )
236 $value_type = PDO::PARAM_STR;
237 elseif ( preg_match(
'{^[0-9+-]+e[0-9+-]+$}i', $value) )
238 $value_type = PDO::PARAM_STR;
239 elseif ( preg_match(
'/^[01]{6,}$/i', $value) )
240 $value_type = PDO::PARAM_STR;
242 $value_type = PDO::PARAM_INT;
245 $value_type = PDO::PARAM_STR;
248 if ( is_string($value_type) ) {
249 switch( $value_type ) {
251 $value_type = PDO::PARAM_NULL;
255 $value_type = PDO::PARAM_INT;
258 $value_type = PDO::PARAM_BOOL;
261 $value_type = PDO::PARAM_STR;
266 switch ( $value_type ) {
267 case PDO::PARAM_NULL:
273 case PDO::PARAM_BOOL:
274 $rv = ($value ?
'TRUE' :
'FALSE');
284 $rv =
"'".str_replace(
"'",
"''", str_replace(
':',
'\\x3a', str_replace(
'\\',
'\\x5c', $value))).
"'";
286 if ( $this->dialect ==
'pgsql' && strpos( $rv,
'\\' ) !==
false ) {
291 $rv =
'E'.str_replace(
'?',
'\\x3f', $rv);
318 function ReplaceParameters() {
319 $argc = func_num_args();
320 $args = func_get_args();
322 if ( is_array($args[0]) ) {
327 $argc = count($args);
329 $qry = array_shift($args);
331 if ( is_array($args[0]) ) {
333 $argc = count($args);
336 if ( ! isset($args[0]) )
return $this->ReplaceNamedParameters($qry,$args);
342 $parts = explode(
'?', $qry, $argc + 1 );
343 $querystring = $parts[0];
346 for( $i = 0; $i < $argc; $i++ ) {
348 $querystring .= $this->Quote($arg);
350 if ( isset($parts[$z]) ) $querystring .= $parts[$z];
374 function ReplaceNamedParameters() {
375 $argc = func_num_args();
376 $args = func_get_args();
378 if ( is_array($args[0]) ) {
383 $argc = count($args);
385 $querystring = array_shift($args);
387 if ( is_array($args[0]) ) {
389 $argc = count($args);
392 foreach( $args AS $name => $value ) {
393 if ( substr($name, 0, 1) !=
':' ) {
394 dbg_error_log(
"ERROR",
"AwlDBDialect: Named parameter '%s' does not begin with a colon.", $name);
396 $replacement = str_replace(
'$',
'\\$', $this->Quote($value));
397 $querystring = preg_replace(
'{\Q'.$name.
'\E\b}s', $replacement, $querystring );