database.pgsql.inc

  1. drupal
    1. 4.6 includes/database.pgsql.inc
    2. 4.7 includes/database.pgsql.inc
    3. 5 includes/database.pgsql.inc
    4. 6 includes/database.pgsql.inc

Database interface code for PostgreSQL database servers.

Functions & methods

NameDescription
db_affected_rowsDetermine the number of rows changed by the preceding query.
db_check_setupVerify if the database is set up correctly.
db_connectInitialize a database connection.
db_decode_blobReturns text from a Binary Large OBject value. In case of PostgreSQL decodes data after select from bytea field.
db_distinct_fieldWraps the given table.field entry with a DISTINCT(). The wrapper is added to the SELECT list entry of the given query and the resulting query is returned. This function only applies the wrapper if a DISTINCT doesn't already exist in the query.
db_encode_blobReturns a properly formatted Binary Large OBject value. In case of PostgreSQL encodes data for insert into bytea field.
db_errorDetermine whether the previous query caused an error.
db_escape_stringPrepare user input for use in a database query, preventing SQL injection attacks. Note: This function requires PostgreSQL 7.2 or later.
db_fetch_arrayFetch one result row from the previous query as an array.
db_fetch_objectFetch one result row from the previous query as an object.
db_lock_tableLock a table. This function automatically starts a transaction.
db_next_idReturn a new unique ID in the given sequence.
db_num_rowsDetermine how many result rows were found by the preceding query.
db_query_rangeRuns a limited-range query in the active database.
db_query_temporaryRuns a SELECT query and stores its results in a temporary table.
db_resultReturn an individual result field from the previous query.
db_unlock_tablesUnlock all locked tables. This function automatically commits a transaction.
_db_queryHelper function for db_query().

File

includes/database.pgsql.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Database interface code for PostgreSQL database servers.
  5. */
  6. /**
  7. * @ingroup database
  8. * @{
  9. */
  10. /**
  11. * Initialize a database connection.
  12. *
  13. * Note that you can change the pg_connect() call to pg_pconnect() if you
  14. * want to use persistent connections. This is not recommended on shared hosts,
  15. * and might require additional database/webserver tuning. It can increase
  16. * performance, however, when the overhead to connect to your database is high
  17. * (e.g. your database and web server live on different machines).
  18. */
  19. function db_connect($url) {
  20. // Check if MySQL support is present in PHP
  21. if (!function_exists('pg_connect')) {
  22. drupal_maintenance_theme();
  23. drupal_set_title('PHP PostgreSQL support not enabled');
  24. print theme('maintenance_page', '<p>We were unable to use the PostgreSQL database because the PostgreSQL extension for PHP is not installed. Check your <code>PHP.ini</code> to see how you can enable it.</p>
  25. <p>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>');
  26. exit;
  27. }
  28. $url = parse_url($url);
  29. $conn_string = '';
  30. // Decode url-encoded information in the db connection string
  31. if (isset($url['user'])) {
  32. $conn_string .= ' user=' . urldecode($url['user']);
  33. }
  34. if (isset($url['pass'])) {
  35. $conn_string .= ' password=' . urldecode($url['pass']);
  36. }
  37. if (isset($url['host'])) {
  38. $conn_string .= ' host=' . urldecode($url['host']);
  39. }
  40. if (isset($url['path'])) {
  41. $conn_string .= ' dbname=' . substr(urldecode($url['path']), 1);
  42. }
  43. if (isset($url['port'])) {
  44. $conn_string .= ' port=' . urldecode($url['port']);
  45. }
  46. // pg_last_error() does not return a useful error message for database
  47. // connection errors. We must turn on error tracking to get at a good error
  48. // message, which will be stored in $php_errormsg.
  49. $track_errors_previous = ini_get('track_errors');
  50. ini_set('track_errors', 1);
  51. $connection = @pg_connect($conn_string);
  52. if (!$connection) {
  53. drupal_maintenance_theme();
  54. drupal_set_header('HTTP/1.1 503 Service Unavailable');
  55. drupal_set_title('Unable to connect to database');
  56. print theme('maintenance_page', '<p>This either means that the database information in your <code>settings.php</code> file is incorrect or we can\'t contact the PostgreSQL database server. This could mean your hosting provider\'s database server is down.</p>
  57. <p>The PostgreSQL error was: '. theme('placeholder', decode_entities($php_errormsg)) .'</p>
  58. <p>Currently, the database is '. theme('placeholder', substr($url['path'], 1)) .', the username is '. theme('placeholder', $url['user']) .', and the database server is '. theme('placeholder', $url['host']) .'.</p>
  59. <ul>
  60. <li>Are you sure you have the correct username and password?</li>
  61. <li>Are you sure that you have typed the correct hostname?</li>
  62. <li>Are you sure you have the correct database name?</li>
  63. <li>Are you sure that the database server is running?</li>
  64. </ul>
  65. <p>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>');
  66. exit;
  67. }
  68. // Restore error tracking setting
  69. ini_set('track_errors', $track_errors_previous);
  70. return $connection;
  71. }
  72. /**
  73. * Helper function for db_query().
  74. */
  75. function _db_query($query, $debug = 0) {
  76. global $active_db, $last_result, $queries;
  77. if (variable_get('dev_query', 0)) {
  78. list($usec, $sec) = explode(' ', microtime());
  79. $timer = (float)$usec + (float)$sec;
  80. }
  81. $last_result = pg_query($active_db, $query);
  82. if (variable_get('dev_query', 0)) {
  83. $bt = debug_backtrace();
  84. $query = $bt[2]['function'] . "\n" . $query;
  85. list($usec, $sec) = explode(' ', microtime());
  86. $stop = (float)$usec + (float)$sec;
  87. $diff = $stop - $timer;
  88. $queries[] = array($query, $diff);
  89. }
  90. if ($debug) {
  91. print '<p>query: '. $query .'<br />error:'. pg_last_error($active_db) .'</p>';
  92. }
  93. if ($last_result !== FALSE) {
  94. return $last_result;
  95. }
  96. else {
  97. trigger_error(check_plain(pg_last_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
  98. return FALSE;
  99. }
  100. }
  101. /**
  102. * Fetch one result row from the previous query as an object.
  103. *
  104. * @param $result
  105. * A database query result resource, as returned from db_query().
  106. * @return
  107. * An object representing the next row of the result. The attributes of this
  108. * object are the table fields selected by the query.
  109. */
  110. function db_fetch_object($result) {
  111. if ($result) {
  112. return pg_fetch_object($result);
  113. }
  114. }
  115. /**
  116. * Fetch one result row from the previous query as an array.
  117. *
  118. * @param $result
  119. * A database query result resource, as returned from db_query().
  120. * @return
  121. * An associative array representing the next row of the result. The keys of
  122. * this object are the names of the table fields selected by the query, and
  123. * the values are the field values for this result row.
  124. */
  125. function db_fetch_array($result) {
  126. if ($result) {
  127. return pg_fetch_assoc($result);
  128. }
  129. }
  130. /**
  131. * Determine how many result rows were found by the preceding query.
  132. *
  133. * @param $result
  134. * A database query result resource, as returned from db_query().
  135. * @return
  136. * The number of result rows.
  137. */
  138. function db_num_rows($result) {
  139. if ($result) {
  140. return pg_num_rows($result);
  141. }
  142. }
  143. /**
  144. * Return an individual result field from the previous query.
  145. *
  146. * Only use this function if exactly one field is being selected; otherwise,
  147. * use db_fetch_object() or db_fetch_array().
  148. *
  149. * @param $result
  150. * A database query result resource, as returned from db_query().
  151. * @param $row
  152. * The index of the row whose result is needed.
  153. * @return
  154. * The resulting field.
  155. */
  156. function db_result($result, $row = 0) {
  157. if ($result && pg_num_rows($result) > $row) {
  158. $res = pg_fetch_row($result, $row);
  159. return $res[0];
  160. }
  161. }
  162. /**
  163. * Determine whether the previous query caused an error.
  164. */
  165. function db_error() {
  166. global $active_db;
  167. return pg_last_error($active_db);
  168. }
  169. /**
  170. * Return a new unique ID in the given sequence.
  171. *
  172. * For compatibility reasons, Drupal does not use auto-numbered fields in its
  173. * database tables. Instead, this function is used to return a new unique ID
  174. * of the type requested. If necessary, a new sequence with the given name
  175. * will be created.
  176. */
  177. function db_next_id($name) {
  178. $id = db_result(db_query("SELECT nextval('%s_seq')", db_prefix_tables($name)));
  179. return $id;
  180. }
  181. /**
  182. * Determine the number of rows changed by the preceding query.
  183. */
  184. function db_affected_rows() {
  185. global $last_result;
  186. return pg_affected_rows($last_result);
  187. }
  188. /**
  189. * Runs a limited-range query in the active database.
  190. *
  191. * Use this as a substitute for db_query() when a subset of the query
  192. * is to be returned.
  193. * User-supplied arguments to the query should be passed in as separate
  194. * parameters so that they can be properly escaped to avoid SQL injection
  195. * attacks.
  196. *
  197. * @param $query
  198. * A string containing an SQL query.
  199. * @param ...
  200. * A variable number of arguments which are substituted into the query
  201. * using printf() syntax. Instead of a variable number of query arguments,
  202. * you may also pass a single array containing the query arguments.
  203. * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
  204. * in '') and %%.
  205. *
  206. * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  207. * and TRUE values to decimal 1.
  208. *
  209. * @param $from
  210. * The first result row to return.
  211. * @param $count
  212. * The maximum number of result rows to return.
  213. * @return
  214. * A database query result resource, or FALSE if the query was not executed
  215. * correctly.
  216. */
  217. function db_query_range($query) {
  218. $args = func_get_args();
  219. $count = array_pop($args);
  220. $from = array_pop($args);
  221. array_shift($args);
  222. $query = db_prefix_tables($query);
  223. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  224. $args = $args[0];
  225. }
  226. _db_query_callback($args, TRUE);
  227. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  228. $query .= ' LIMIT '. (int)$count .' OFFSET '. (int)$from;
  229. return _db_query($query);
  230. }
  231. /**
  232. * Runs a SELECT query and stores its results in a temporary table.
  233. *
  234. * Use this as a substitute for db_query() when the results need to stored
  235. * in a temporary table. Temporary tables exist for the duration of the page
  236. * request.
  237. * User-supplied arguments to the query should be passed in as separate parameters
  238. * so that they can be properly escaped to avoid SQL injection attacks.
  239. *
  240. * Note that if you need to know how many results were returned, you should do
  241. * a SELECT COUNT(*) on the temporary table afterwards. db_num_rows() and
  242. * db_affected_rows() do not give consistent result across different database
  243. * types in this case.
  244. *
  245. * @param $query
  246. * A string containing a normal SELECT SQL query.
  247. * @param ...
  248. * A variable number of arguments which are substituted into the query
  249. * using printf() syntax. The query arguments can be enclosed in one
  250. * array instead.
  251. * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
  252. * in '') and %%.
  253. *
  254. * NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  255. * and TRUE values to decimal 1.
  256. *
  257. * @param $table
  258. * The name of the temporary table to select into. This name will not be
  259. * prefixed as there is no risk of collision.
  260. * @return
  261. * A database query result resource, or FALSE if the query was not executed
  262. * correctly.
  263. */
  264. function db_query_temporary($query) {
  265. $args = func_get_args();
  266. $tablename = array_pop($args);
  267. array_shift($args);
  268. $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' AS SELECT', db_prefix_tables($query));
  269. if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
  270. $args = $args[0];
  271. }
  272. _db_query_callback($args, TRUE);
  273. $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
  274. return _db_query($query);
  275. }
  276. /**
  277. * Returns a properly formatted Binary Large OBject value.
  278. * In case of PostgreSQL encodes data for insert into bytea field.
  279. *
  280. * @param $data
  281. * Data to encode.
  282. * @return
  283. * Encoded data.
  284. */
  285. function db_encode_blob($data) {
  286. return "'". pg_escape_bytea($data) ."'";
  287. }
  288. /**
  289. * Returns text from a Binary Large OBject value.
  290. * In case of PostgreSQL decodes data after select from bytea field.
  291. *
  292. * @param $data
  293. * Data to decode.
  294. * @return
  295. * Decoded data.
  296. */
  297. function db_decode_blob($data) {
  298. return pg_unescape_bytea($data);
  299. }
  300. /**
  301. * Prepare user input for use in a database query, preventing SQL injection attacks.
  302. * Note: This function requires PostgreSQL 7.2 or later.
  303. */
  304. function db_escape_string($text) {
  305. return pg_escape_string($text);
  306. }
  307. /**
  308. * Lock a table.
  309. * This function automatically starts a transaction.
  310. */
  311. function db_lock_table($table) {
  312. db_query('BEGIN; LOCK TABLE {'. db_escape_table($table) .'} IN EXCLUSIVE MODE');
  313. }
  314. /**
  315. * Unlock all locked tables.
  316. * This function automatically commits a transaction.
  317. */
  318. function db_unlock_tables() {
  319. db_query('COMMIT');
  320. }
  321. /**
  322. * Verify if the database is set up correctly.
  323. */
  324. function db_check_setup() {
  325. $encoding = db_result(db_query('SHOW server_encoding'));
  326. if (!in_array(strtolower($encoding), array('unicode', 'utf8'))) {
  327. drupal_set_message(t('Your PostgreSQL database is set up with the wrong character encoding (%encoding). It is possible it will not work as expected. It is advised to recreate it with UTF-8/Unicode encoding. More information can be found in the <a href="%url">PostgreSQL documentation</a>.', array('%encoding' => $encoding, '%url' => 'http://www.postgresql.org/docs/7.4/interactive/multibyte.html')), 'status');
  328. }
  329. }
  330. /**
  331. * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to
  332. * the SELECT list entry of the given query and the resulting query is returned.
  333. * This function only applies the wrapper if a DISTINCT doesn't already exist in
  334. * the query.
  335. *
  336. * @param $table Table containing the field to set as DISTINCT
  337. * @param $field Field to set as DISTINCT
  338. * @param $query Query to apply the wrapper to
  339. * @return SQL query with the DISTINCT wrapper surrounding the given table.field.
  340. */
  341. function db_distinct_field($table, $field, $query) {
  342. $field_to_select = 'DISTINCT ON ('. $table .'.'. $field .") $table.$field";
  343. // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
  344. $query = preg_replace('/(SELECT.*)('. $table .'\.)?(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1'. $field_to_select .'\3', $query);
  345. $query = preg_replace('/(ORDER BY )(?!'.$table.'\.'.$field.')/', '\1'."$table.$field, ", $query);
  346. return $query;
  347. }
  348. /**
  349. * @} End of "ingroup database".
  350. */
Login or register to post comments