PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/db/library/dbscript/postgresql.php

https://github.com/tjgillies/dbscript
PHP | 756 lines | 652 code | 56 blank | 48 comment | 157 complexity | 11d74a9d50014ad605caf6daf46b079d MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * dbscript -- restful openid framework
  4. * @version 0.6.0 -- 22-October-2008
  5. * @author Brian Hendrickson <brian@dbscript.net>
  6. * @link http://dbscript.net/
  7. * @copyright Copyright 2008 Brian Hendrickson
  8. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  9. * @package dbscript
  10. */
  11. /**
  12. * PostgreSQL
  13. *
  14. * adapter for the PostgreSQL database system
  15. *
  16. * Usage:
  17. * <code>
  18. * $db = new PostgreSQL ( 'hostname', 'database_name', 'username', 'password' );
  19. * </code>
  20. *
  21. * More info...
  22. * {@link http://dbscript.net/postgresql}
  23. *
  24. * @package dbscript
  25. * @author Brian Hendrickson <brian@dbscript.net>
  26. * @access public
  27. * @version 0.6.0 -- 22-October-2008
  28. * @todo support array datatypes
  29. */
  30. class PostgreSQL extends Database {
  31. var $connstr;
  32. var $oid;
  33. var $host;
  34. var $user;
  35. var $pass;
  36. var $dbname;
  37. function PostgreSQL() {
  38. $this->db_open = false;
  39. $this->models = array();
  40. $this->recordsets = array();
  41. $this->max_blob_length = 6144000; // default max blob file size is 6MB
  42. $this->max_string_length = 1024000; // default max string length is 1MB
  43. $this->datatype_map = array(
  44. 'real' => 'float',
  45. 'double precision' => 'float',
  46. 'int' => 'int',
  47. 'integer' => 'int',
  48. 'smallint' => 'int',
  49. 'bigint' => 'int',
  50. 'serial' => 'int',
  51. 'serial primary key' => 'int',
  52. 'bigserial' => 'int',
  53. 'numeric' => 'int',
  54. 'text' => 'text',
  55. 'char' => 'char',
  56. 'varchar' => 'char',
  57. 'character' => 'char',
  58. 'character varying' => 'char',
  59. 'timestamp' => 'time',
  60. 'timestamp without time zone' => 'time',
  61. 'timestamp with time zone' => 'time',
  62. 'time' => 'time',
  63. 'time without time zone' => 'time',
  64. 'time with time zone' => 'time',
  65. 'date' => 'date',
  66. 'boolean' => 'bool',
  67. 'oid' => 'blob'
  68. );
  69. $func_args = func_get_args();
  70. $argnames = array('host','dbname','user','password','port');
  71. $this->true_values = array('t','true','1',true);
  72. $this->alias_array = array();
  73. for ($i = 0; $i < count($argnames); $i++) {
  74. if (isset($func_args[$i]))
  75. $this->$argnames[$i] = $func_args[$i];
  76. else
  77. $this->$argnames[$i] = "";
  78. }
  79. for ($i = 0; $i < count($func_args); $i++) {
  80. if (strlen($func_args[$i]) > 0)
  81. $this->connstr .= $argnames[$i] . '=' . $func_args[$i] . ' ';
  82. }
  83. $this->connect();
  84. }
  85. function connect() { // establish a connection to the database
  86. trigger_before( 'connect', $this, $this );
  87. $this->conn = @pg_connect($this->connstr);
  88. if (!$this->conn) {
  89. $this->db_open = false;
  90. trigger_error("Sorry, the database connection failed. Please check your database connection settings.".@pg_last_error($this->conn), E_USER_ERROR );
  91. } else {
  92. $this->db_open = true;
  93. }
  94. return $this->db_open;
  95. }
  96. function escape_string($string) {
  97. trigger_before( 'escape_string', $this, $this );
  98. if (!(strlen($string) > 0)) { return ""; }
  99. $result = @pg_escape_string($string);
  100. if (!$result && !(is_numeric($string)))
  101. trigger_error("error in escape_string in postgresql.php".@pg_last_error($this->conn), E_USER_ERROR );
  102. return $result;
  103. }
  104. function get_result( $sql, $returnfalse = NULL ) { /* run an SQL query */
  105. trigger_before( 'get_result', $this, $this );
  106. global $request;
  107. if (isset($request->params)) {
  108. trigger_before( 'get_result', $request, $this );
  109. }
  110. $result = @pg_query( $this->conn, $sql );
  111. if (!$result && $returnfalse === NULL)
  112. trigger_error("error in get_result in postgresql.php".@pg_last_error($this->conn)." ".$sql, E_USER_ERROR );
  113. elseif (!$result && $returnfalse)
  114. return true;
  115. else
  116. return $result;
  117. }
  118. function next_primary_key( $table, $pkfield, $sequence_name=NULL ) {
  119. trigger_before( 'next_primary_key', $this, $this );
  120. if ($sequence_name == NULL) {
  121. $sql = "SELECT relname FROM pg_class WHERE relkind='S' and substr(relname,1,".strlen($table).")='$table'";
  122. $result = $this->get_result($sql);
  123. if ($this->num_rows($result) > 0) {
  124. $seq = $this->result_value($result,0,"relname");
  125. } else {
  126. return '';
  127. }
  128. } else {
  129. $seq = $sequence_name;
  130. }
  131. $pk_result = $this->get_result("SELECT nextval('$seq')");
  132. if ($this->num_rows($result) > 0)
  133. $pkvalue = $this->result_value( $pk_result, 0, "nextval" );
  134. else
  135. trigger_error("error selecting nexval in next_primary_key in postgresql.php".@pg_last_error($this->conn), E_USER_ERROR );
  136. return $pkvalue;
  137. }
  138. function last_insert_id(&$result,$pkfield,$table) { // returns the id of the most recently modified record
  139. trigger_before( 'last_insert_id', $this, $this );
  140. $oid = @pg_last_oid($result);
  141. if (!$oid)
  142. trigger_error(@pg_last_error($this->conn), E_USER_ERROR );
  143. $sql = "SELECT ". $pkfield . " FROM " . $table . " WHERE oid = " . $oid;
  144. $res = $this->get_result($sql);
  145. if (!$res)
  146. trigger_error("error in last_insert_id in postgresql.php".@pg_last_error($this->conn), E_USER_ERROR );
  147. else
  148. return $this->result_value($res,0,$pkfield);
  149. }
  150. function result_value(&$result,$resultindex,$field) { // get a single value from a result set
  151. trigger_before( 'result_value', $this, $this );
  152. $return = pg_fetch_result($result,$resultindex,$field);
  153. if (!$return && $return != 0)
  154. trigger_error("error in result_value in postgresql.php".@pg_last_error($this->conn), E_USER_ERROR );
  155. else
  156. return $return;
  157. }
  158. function close() {
  159. trigger_before( 'close', $this, $this );
  160. $args = func_get_args();
  161. pg_close( $this->conn );
  162. if ( isset( $args[0] ) ) {
  163. if ( strlen($args[0]) > 0 ) {
  164. header( "Location:" . $args[0] );
  165. exit;
  166. }
  167. }
  168. }
  169. function &get_table($table) {
  170. trigger_before( 'get_table', $this, $this );
  171. if ( isset( $this->models[$table] ) )
  172. if ($this->models[$table]->exists)
  173. return $this->models[$table];
  174. $custom_class = classify($table);
  175. if (!isset($this->models[$table]) && class_exists($custom_class)) {
  176. $this->models[$table] = new $custom_class();
  177. } elseif (!isset($this->models[$table])) {
  178. $this->models[$table] = new Model($table, $this);
  179. }
  180. if (!($this->models[$table]->exists))
  181. $this->models[$table]->register($table);
  182. return $this->models[$table];
  183. }
  184. function &model($model) {
  185. trigger_before( 'model', $this, $this );
  186. return $this->get_table(tableize($model));
  187. }
  188. function fetch_array( &$result, $row=NULL ) {
  189. trigger_before( 'fetch_array', $this, $this );
  190. if (is_numeric($row))
  191. $this->seek_row( $result, $row );
  192. return pg_fetch_array( $result, $row, PGSQL_ASSOC );
  193. }
  194. function fetch_row( &$result, $row=NULL ) {
  195. trigger_before( 'fetch_row', $this, $this );
  196. if ( ( is_numeric( $row ) ) )
  197. return pg_fetch_row( $result, $row );
  198. return pg_fetch_row( $result );
  199. }
  200. function seek_row(&$result,$row) {
  201. trigger_before( 'seek_row', $this, $this );
  202. return true;
  203. }
  204. function query_limit($limit,$offset) {
  205. trigger_before( 'query_limit', $this, $this );
  206. return " LIMIT " . $limit . " OFFSET " . $offset;
  207. }
  208. function blob_value( &$rec, $field, &$value ) {
  209. trigger_before( 'blob_value', $this, $this );
  210. return $value;
  211. }
  212. function sql_insert_for( &$rec ) {
  213. trigger_before( 'sql_insert_for', $this, $this );
  214. $sql = "INSERT INTO " . $rec->table . " (";
  215. $comma = '';
  216. $fields = '';
  217. $values = '';
  218. foreach (array_unique($rec->modified_fields) as $modified_field) {
  219. $datatype = $this->get_mapped_datatype($this->models[$rec->table]->field_array[$modified_field]);
  220. $this->pre_insert( $rec, $modified_field, $datatype );
  221. if ( !( $datatype == 'blob' && ( !(strlen( $rec->attributes[$modified_field] ) > 0 ) ) ) ) {
  222. $fields .= $comma . $modified_field;
  223. $values .= $comma . $this->quoted_insert_value( $rec, $modified_field );;
  224. $comma = ',';
  225. }
  226. }
  227. $sql .= $fields . ") VALUES (" . $values . ")";
  228. return $sql;
  229. }
  230. function sql_update_for( &$rec ) {
  231. trigger_before( 'sql_update_for', $this, $this );
  232. $sql = "UPDATE ";
  233. $sql .= $rec->table . ' SET ';
  234. $comma = '';
  235. foreach (array_unique($rec->modified_fields) as $modified_field) {
  236. $datatype = $this->get_mapped_datatype($this->models[$rec->table]->field_array[$modified_field]);
  237. $this->pre_update( $rec, $modified_field, $datatype );
  238. if ( !( $datatype == 'blob' && ( !(strlen( $rec->attributes[$modified_field] ) > 0 ) ) ) ) {
  239. $sql .= $comma . $this->quoted_update_value( $rec, $modified_field );
  240. $comma = ',';
  241. }
  242. }
  243. $sql .= " WHERE " . $rec->primary_key . "='" . $rec->attributes[$rec->primary_key] . "'";
  244. return $sql;
  245. }
  246. function sql_select_for( &$rec, $id ) {
  247. trigger_before( 'sql_select_for', $this, $this );
  248. return "SELECT ".$rec->selecttext." FROM ".$rec->table." WHERE ".$rec->primary_key." = '".$id."'";
  249. }
  250. function sql_delete_for( &$rec ) {
  251. trigger_before( 'sql_delete_for', $this, $this );
  252. $pkfield = $rec->primary_key;
  253. foreach ($rec->attributes as $key=>$value) {
  254. $datatype = $this->get_mapped_datatype($this->models[$rec->table]->field_array[$key]);
  255. if ($datatype == 'blob' && strlen($rec->attributes[$rec->primary_key]) > 0) {
  256. $oid_result = $this->get_result("select ".$key." from ".$rec->table." where ".$rec->primary_key." = '".$rec->attributes[$rec->primary_key]."'");
  257. $prev_oid = $this->fetch_array($oid_result,0,$key);
  258. if (isset($prev_oid[0]) && $prev_oid[0] > 0)
  259. $result = $this->large_object_delete($prev_oid[0]);
  260. }
  261. }
  262. $sql = 'DELETE FROM ' . $rec->table . ' WHERE ' . $pkfield . ' = ' . $rec->$pkfield;
  263. return $sql;
  264. }
  265. function select_distinct( $field, $table, $orderby ) {
  266. trigger_before( 'select_distinct', $this, $this );
  267. return "SELECT DISTINCT $field, " . $this->models[$table]->primary_key . " FROM $table ORDER BY $orderby DESC";
  268. }
  269. function quoted_update_value( &$rec, $modified_field ) {
  270. trigger_before( 'quoted_update_value', $this, $this );
  271. return $modified_field . "='" . $this->escape_string($rec->attributes[$modified_field]) . "'";
  272. }
  273. function quoted_insert_value( &$rec, $modified_field ) {
  274. trigger_before( 'quoted_insert_value', $this, $this );
  275. return "'" . $this->escape_string($rec->attributes[$modified_field]) . "'";
  276. }
  277. function pre_insert( &$rec, $modified_field, $datatype ) {
  278. trigger_before( 'pre_insert', $rec, $this );
  279. if (isset($this->models[$rec->table]->field_attrs[$modified_field]['required'])) {
  280. if (!(strlen( $rec->attributes[$modified_field] ) > 0))
  281. trigger_error( "$modified_field is a required field", E_USER_ERROR );
  282. }
  283. if (isset($this->models[$rec->table]->field_attrs[$modified_field]['unique'])) {
  284. $result = $this->get_result("select ".$modified_field." from ".$rec->table." where ".$modified_field." = '".$rec->attributes[$modified_field]."'");
  285. if ($result && $this->num_rows($result) > 0)
  286. trigger_error( "Sorry, that $modified_field has already been taken.", E_USER_ERROR );
  287. }
  288. if ($datatype == 'time' && !(strlen($rec->attributes[$modified_field]) > 0))
  289. $rec->attributes[$modified_field] = date("Y-m-d H:i:s",strtotime("now"));
  290. if ($datatype == 'blob' && strlen($rec->attributes[$modified_field]) > 0) {
  291. $coll = environment('collection_cache');
  292. if (isset($coll[$request->resource]) && $coll[$request->resource]['location'] == 'aws') {
  293. $this->file_upload = array($modified_field,$rec->attributes[$modified_field]);
  294. $rec->set_value($modified_field,'');
  295. } elseif (isset($coll[$request->resource]) && $coll[$request->resource]['location'] == 'uploads') {
  296. $this->file_upload = $rec->attributes[$modified_field];
  297. $rec->set_value($modified_field,'');
  298. } else {
  299. $oid = $this->large_object_create($rec->table,$rec->attributes[$modified_field]);
  300. if ($oid > 0)
  301. $rec->attributes[$modified_field] = $oid;
  302. }
  303. }
  304. if ($datatype == 'bool') {
  305. if ( in_array( $rec->attributes[$modified_field], $this->true_values, true ) )
  306. $rec->attributes[$modified_field] = "true";
  307. else
  308. $rec->attributes[$modified_field] = "false";
  309. }
  310. if ($modified_field == $rec->primary_key) {
  311. if ( in_array( $rec->attributes[$rec->primary_key], array( '', 0, '0' ), true ))
  312. $rec->attributes[$modified_field] = $this->next_primary_key( $rec->table, $modified_field);
  313. }
  314. }
  315. function pre_update( &$rec, $modified_field, $datatype ) {
  316. trigger_before( 'pre_update', $rec, $this );
  317. if (isset($this->models[$rec->table]->field_attrs[$modified_field]['required'])) {
  318. if (!(strlen( $rec->attributes[$modified_field] ) > 0))
  319. trigger_error( "Sorry, you must provide a value for $modified_field", E_USER_ERROR );
  320. }
  321. if (isset($this->models[$rec->table]->field_attrs[$modified_field]['unique'])) {
  322. $result = $this->get_result("select ".$modified_field." from ".$rec->table." where ".$modified_field." = '".$rec->attributes[$modified_field]."' and ".$rec->primary_key." != '".$rec->attributes[$rec->primary_key]."'");
  323. if ($this->num_rows($result) > 0)
  324. trigger_error( "Sorry, that $modified_field has already been taken.", E_USER_ERROR );
  325. }
  326. if ($datatype == 'blob' && (strlen( $rec->attributes[$modified_field] ) > 0 )) {
  327. global $request;
  328. $coll = environment('collection_cache');
  329. if (isset($coll[$request->resource]) && $coll[$request->resource]['location'] == 'aws') {
  330. $this->file_upload = array($modified_field,$rec->attributes[$modified_field]);
  331. $this->aws_delfile($rec,$rec->id);
  332. $this->aws_putfile($rec,$rec->id);
  333. $rec->set_value($modified_field,'');
  334. } elseif (isset($coll[$request->resource]) && $coll[$request->resource]['location'] == 'uploads') {
  335. update_uploadsfile($rec->table,$rec->id,$rec->attributes[$modified_field]);
  336. $rec->set_value($modified_field,'');
  337. } else {
  338. unlink_cachefile($rec->table,$rec->id,$coll);
  339. $oid_result = $this->get_result("select ".$modified_field." from ".$rec->table." where ".$rec->primary_key." = '".$rec->attributes[$rec->primary_key]."'");
  340. if ($this->num_rows($oid_result) > 0) {
  341. $prev_oid = $this->fetch_array($oid_result);
  342. if (isset($prev_oid[0]) && $prev_oid[0] > 0)
  343. $result = $this->large_object_delete($prev_oid);
  344. }
  345. $oid = $this->large_object_create($rec->table,$rec->attributes[$modified_field]);
  346. if ($oid > 0)
  347. $rec->attributes[$modified_field] = $oid;
  348. }
  349. }
  350. }
  351. function post_insert( &$rec, &$result ) {
  352. trigger_before( 'post_insert', $this, $this );
  353. if (is_array($this->file_upload))
  354. $this->aws_putfile($rec,$rec->id);
  355. elseif (!empty($this->file_upload))
  356. update_uploadsfile($rec->table,$rec->id,$this->file_upload);
  357. if (!$result) { trigger_error("Sorry, the record could not be saved due to a database error.", E_USER_ERROR ); }
  358. }
  359. function affected_rows(&$result) {
  360. trigger_before( 'affected_rows', $this, $this );
  361. return @pg_affected_rows($result);
  362. }
  363. function fetch_object(&$result) {
  364. trigger_before( 'fetch_object', $this, $this );
  365. return @pg_fetch_object($result);
  366. }
  367. function fetch_field(&$result,$i) {
  368. trigger_before( 'fetch_field', $this, $this );
  369. $field = new dbfield();
  370. $field->name = pg_field_name($result,$i);
  371. $field->type = pg_field_type($result,$i);
  372. $field->size = pg_field_size($result,$i);
  373. return $field;
  374. }
  375. function num_rows(&$result) {
  376. trigger_before( 'num_rows', $this, $this );
  377. return @pg_num_rows($result);
  378. }
  379. function num_fields(&$result) {
  380. trigger_before( 'num_fields', $this, $this );
  381. return @pg_num_fields($result);
  382. }
  383. function field_name(&$result, $index) {
  384. trigger_before( 'field_name', $this, $this );
  385. return @pg_field_name($result, $index);
  386. }
  387. function large_object_create($table,$file) {
  388. trigger_before( 'large_object_create', $this, $this );
  389. $return = false;
  390. if (!(file_exists($file)))
  391. return $return;
  392. $filename = basename($file);
  393. if (!$filename) { trigger_error("Error determining base name of large object file $filename", E_USER_ERROR ); }
  394. $handle = fopen($file,"r");
  395. if (!$handle) { trigger_error("Error opening large object file $file", E_USER_ERROR ); }
  396. $buffer = fread($handle,filesize($file));
  397. if (!$buffer) { trigger_error("Error reading large object file $file", E_USER_ERROR ); }
  398. $result = fclose($handle);
  399. $result = @pg_query($this->conn, "BEGIN");
  400. if (!$result) { trigger_error("error starting l_o_c transaction: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  401. $oid = @pg_lo_create($this->conn);
  402. if (!$oid) { trigger_error("error in pg_l_o_c: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  403. #$result = pg_query($this->conn,"UPDATE $table SET $field = $oid WHERE $pkfield = '$pkvalue'");
  404. #if (!$result) { trigger_error("Error updating file OID", E_USER_ERROR ); }
  405. $handle = @pg_lo_open($this->conn, $oid, "w");
  406. if (!$handle) { trigger_error("error in pg_l_o_o: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  407. $result = @pg_lo_write($handle, $buffer);
  408. if (!$result) { trigger_error("error in l_o_w: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  409. $result = @pg_lo_close($handle);
  410. if (!$result) { trigger_error("error in l_o_close: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  411. $result = @pg_query($this->conn, "COMMIT");
  412. if (!$result) { trigger_error("error committing l_o_c transaction: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  413. else {
  414. $return = $oid;
  415. }
  416. return $return;
  417. }
  418. function large_object_fetch($oid, $return = false) {
  419. trigger_before( 'large_object_fetch', $this, $this );
  420. //$result = pg_query($this->conn,"SELECT $field FROM $table WHERE $");
  421. //if (!$result) { trigger_error("Error in select file OID", E_USER_ERROR ); }
  422. //$oid = pg_result($result,0,$fieldname);
  423. //if (!$oid) { trigger_error("Error in file OID result", E_USER_ERROR ); }
  424. $result = @pg_query($this->conn,"BEGIN");
  425. if (!$result) { trigger_error("error starting l_o_f transaction: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  426. $handle = @pg_lo_open($this->conn, $oid, "r");
  427. if (!$handle) { trigger_error("error in l_o_f/l_o_o: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  428. if ($return === true)
  429. return @pg_lo_read($handle,$this->max_blob_length);
  430. else
  431. @pg_lo_read_all($handle);
  432. if (!$buffer) { trigger_error("error in l_o_read_all: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  433. $result = @pg_lo_close($handle);
  434. if (!$result) { trigger_error("error in l_o_close: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  435. $result = @pg_query($this->conn,"COMMIT");
  436. if (!$result) { trigger_error("error committing l_o_f transaction: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  437. return $return;
  438. }
  439. function large_object_delete($oid) {
  440. trigger_before( 'large_object_delete', $this, $this );
  441. $return = false;
  442. #$result = pg_query($this->conn,"SELECT $field FROM $table WHERE $pkfield = '$pkvalue'");
  443. #if (!$result) { trigger_error("Error in select file OID", E_USER_ERROR ); }
  444. #$oid = pg_result($result,0,$field);
  445. #if (!$oid) { trigger_error("Error in file OID result", E_USER_ERROR ); }
  446. $result = @pg_query($this->conn,"BEGIN");
  447. if (!$result) { trigger_error("error starting l_o_d transaction: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  448. $result = @pg_lo_unlink($this->conn, $oid);
  449. if (!$result) { trigger_error("error in l_o_unlink: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  450. $result = @pg_query($this->conn,"COMMIT");
  451. if (!$result) { trigger_error("error committing l_o_d transaction: ".@pg_last_error($this->conn), E_USER_ERROR ); }
  452. #$result = pg_query($this->conn,"DELETE FROM $table WHERE lo_oid = $oid");
  453. #if (!$result) { trigger_error("Error deleting file OID", E_USER_ERROR ); }
  454. else {
  455. $return = true;
  456. }
  457. return $return;
  458. }
  459. function add_table( $table, $field_array ) {
  460. trigger_before( 'add_table', $this, $this );
  461. if (!(count($field_array)>0)) trigger_error( "Error creating table. No fields are defined. Use \$model->auto_field and \$model->text_field etc.", E_USER_ERROR );
  462. $sql = "CREATE TABLE $table (";
  463. $comma = "";
  464. foreach ( $field_array as $field => $data_type ) {
  465. $sql .= "$comma $field $data_type";
  466. $comma = ",";
  467. }
  468. $sql .= ")";
  469. $result = $this->get_result($sql);
  470. if ($result)
  471. $this->tables[] = $table;
  472. }
  473. function add_field( $table, $field, $data_type ) {
  474. trigger_before( 'add_field', $this, $this );
  475. $sql = "ALTER TABLE $table ADD COLUMN $field $data_type";
  476. echo $sql."<BR>";
  477. $result = $this->get_result($sql);
  478. }
  479. function has_table($t) {
  480. trigger_before( 'has_table', $this, $this );
  481. return in_array( $t, $this->get_tables(), true );
  482. }
  483. function get_tables() {
  484. trigger_before( 'get_tables', $this, $this );
  485. $tables = array();
  486. #$sql = "SELECT a.relname AS Name FROM pg_class a, pg_user b ";
  487. #$sql .= "WHERE ( relkind = 'r') and relname !~ '^pg_' AND relname !~ '^sql_' ";
  488. #$sql .= "AND relname !~ '^xin[vx][0-9]+' AND b.usesysid = a.relowner ";
  489. #$sql .= "AND NOT (EXISTS (SELECT viewname FROM pg_views WHERE viewname=a.relname))";
  490. $sql = "SELECT tablename AS relname FROM pg_catalog.pg_tables";
  491. $sql .= " WHERE schemaname NOT IN ('pg_catalog', 'information_schema',";
  492. $sql .= " 'pg_toast') ORDER BY tablename";
  493. $result = $this->get_result($sql);
  494. while ($arr = $this->fetch_array($result)) {
  495. foreach($arr as $key=>$value) {
  496. if (!(in_array($value, array('db_sessions'))))
  497. $tables[] = $value;
  498. }
  499. }
  500. return $tables;
  501. }
  502. function get_fields($table) {
  503. trigger_before( 'get_fields', $this, $this );
  504. $datatypes = array();
  505. $fieldindex = array();
  506. $fieldindex[] = "";
  507. #$sql = "SELECT column_name, data_type FROM information_schema.columns ";
  508. #$sql .= "WHERE table_schema = 'public' AND table = '$table'";
  509. $sql = "SELECT a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod)";
  510. $sql .= " as type FROM pg_catalog.pg_attribute a LEFT JOIN";
  511. $sql .= " pg_catalog.pg_attrdef adef ON a.attrelid=adef.adrelid AND";
  512. $sql .= " a.attnum=adef.adnum LEFT JOIN pg_catalog.pg_type t ON";
  513. $sql .= " a.atttypid=t.oid WHERE a.attrelid = (SELECT oid FROM";
  514. $sql .= " pg_catalog.pg_class WHERE relname='$table')";
  515. $sql .= " and a.attname != 'tableoid' and a.attname != 'oid'";
  516. $sql .= " and a.attname != 'xmax' and a.attname != 'xmin'";
  517. $sql .= " and a.attname != 'cmax' and a.attname != 'cmin'";
  518. $sql .= " and a.attname != 'ctid' and a.attname != 'otre'";
  519. $sql .= " and a.attname not ilike '%..%' order by a.attnum ASC";
  520. $result = $this->get_result($sql,true);
  521. if (!$result) return $datatypes;
  522. while ($arr = $this->fetch_array($result)) {
  523. foreach($arr as $key=>$value) {
  524. if ($key == "attname") {
  525. $field = $value;
  526. $fieldindex[] = $value;
  527. } elseif ($key == "type") {
  528. $type = $value;
  529. }
  530. }
  531. $datatypes[$field] = $type;
  532. }
  533. $sql = "SELECT idx.indkey, idx.indisunique, idx.indisprimary";
  534. $sql .= " FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,";
  535. $sql .= " pg_catalog.pg_index idx";
  536. $sql .= " WHERE c.oid = idx.indrelid";
  537. $sql .= " AND idx.indexrelid = c2.oid";
  538. $sql .= " AND c.relname = '$table'";
  539. #$sql .= " AND idx.isprimary = true";
  540. $result = $this->get_result($sql);
  541. while ($row = pg_fetch_row($result)) {
  542. if (!(strstr($row[0], ' ')))
  543. $datatypes[$table."_primary_key"] = $fieldindex[$row[0]];
  544. }
  545. return $datatypes;
  546. }
  547. function create_openid_tables() {
  548. if (in_array('openid_identities',$this->tables))
  549. return;
  550. $result = $this->get_result("CREATE TABLE openid_identities ( uurl_id int NOT NULL, user_id int NOT NULL default '0', url text, hash char(32) )");
  551. $result = $this->get_result("CREATE TABLE oauth_consumers (consumer_key CHAR(255) PRIMARY KEY, secret CHAR(40), description CHAR(40))");
  552. $result = $this->get_result("CREATE TABLE oauth_tokens (consumer_key CHAR(255), token CHAR(40), secret CHAR(40), token_type CHAR(7), nonce CHAR(40), user_id INT DEFAULT 0, expires INT DEFAULT 0)");
  553. $result = $this->get_result("INSERT INTO oauth_consumers (consumer_key, secret, description) VALUES ('DUMMYKEY', '', 'Unidentified Consumer')");
  554. //;
  555. $result = $this->get_result("CREATE TABLE openid_nonces (server_url VARCHAR(255), timestamp INTEGER, ".
  556. "salt CHAR(40), UNIQUE (server_url, timestamp, salt))");
  557. $result = $this->get_result("CREATE TABLE openid_associations (server_url VARCHAR(255), handle VARCHAR(255), ".
  558. "secret BYTEA, issued INTEGER, lifetime INTEGER, ".
  559. "assoc_type VARCHAR(64), PRIMARY KEY (server_url, handle), ".
  560. "CONSTRAINT secret_length_constraint CHECK ".
  561. "(LENGTH(secret) <= 128))");
  562. }
  563. function auto_field( $field, &$model ) {
  564. $model->set_field( $field, "serial primary key" );
  565. $model->set_primary_key( $field );
  566. }
  567. function enum_field( $field, $values, &$model ) {
  568. $model->set_field( $field, $values );
  569. }
  570. function float_field( $field, &$model ) {
  571. $model->set_field( $field, "double precision" );
  572. }
  573. function bool_field( $field, &$model ) {
  574. $model->set_field( $field, "boolean" );
  575. }
  576. function char_field( $field, &$model, $options ) {
  577. if (!(isset($options['len'])))
  578. $options = array('len'=>255);
  579. $model->set_field( $field, "varchar(".$options['len'].")" );
  580. }
  581. function date_field( $field, &$model ) {
  582. $model->set_field( $field, "date" );
  583. }
  584. function file_field( $field, &$model ) {
  585. $model->set_field( $field, "oid" );
  586. }
  587. function int_field( $field, &$model ) {
  588. $model->set_field( $field, "int" );
  589. }
  590. function text_field( $field, &$model ) {
  591. $model->set_field( $field, "text" );
  592. }
  593. function time_field( $field, &$model ) {
  594. $model->set_field( $field, "timestamp with time zone" );
  595. }
  596. function get_query( $id=NULL, $find_by=NULL, &$model ) {
  597. if (isset($model->query)) {
  598. $q = $model->query;
  599. unset($model->query);
  600. return $q;
  601. }
  602. $model->set_param('id',$id);
  603. $model->set_param('find_by',$find_by);
  604. trigger_before( 'get_query', $model, $this );
  605. $pkfield = $model->primary_key;
  606. if ($model->find_by == NULL)
  607. $model->set_param('find_by', $model->primary_key);
  608. $relfields = array();
  609. $relfields = $model->relations;
  610. $table = $model->table;
  611. $fieldstring = '';
  612. $sql = "SELECT " . "\n";
  613. if (!array_key_exists($pkfield,$model->field_array))
  614. $sql .= "$table.$pkfield as \"$table.$pkfield\", " . "\n";
  615. foreach ($model->field_array as $fieldname=>$datatypename) {
  616. if (strpos($fieldname,".") === false)
  617. $fieldname = $table . "." . $fieldname;
  618. $fieldstring .= "$fieldname as \"$fieldname\", " . "\n";
  619. }
  620. $leftsql = "";
  621. $first = true;
  622. if (count($relfields) > 0) {
  623. foreach ($relfields as $key=>$val) {
  624. $spl = split("\.",$val["fkey"]);
  625. if (!($this->models[$spl[0]]->exists))
  626. $$spl[0] =& $this->get_table($spl[0]);
  627. $leftsql .= "(";
  628. }
  629. foreach ($relfields as $key=>$val) {
  630. $spl = split("\.",$val["fkey"]);
  631. if (($val["type"] == 'child-many')) {
  632. $join =& $this->get_table($model->join_table_for($table, $val['tab']));
  633. $spl[0] = $join->table;
  634. $val["fkey"] = $join->table.'.'.strtolower(classify($table))."_".$model->foreign_key_for( $table);
  635. }else{
  636. foreach ($this->models[$spl[0]]->field_array as $fieldname=>$datatypename) {
  637. $fieldstring .= $spl[0].".".$fieldname." as \"".$spl[0].".".$fieldname."\", " . "\n";
  638. }
  639. }
  640. if ($first)
  641. $leftsql .= $table;
  642. $leftsql .= " left join " . $spl[0] . " on ".$table.".".$val["col"]." = " . $val["fkey"];
  643. $leftsql .= ")";
  644. $first = false;
  645. }
  646. }
  647. $fieldstring = substr($fieldstring,0,-3) . " " . "\n";
  648. $sql .= $fieldstring;
  649. $sql .= "FROM ";
  650. $sql .= $leftsql;
  651. if (!(strlen($leftsql) > 1))
  652. $sql .= $table;
  653. if (is_array($model->find_by)) {
  654. $findfirst = true;
  655. $op = "AND";
  656. $eq = '=';
  657. foreach( $model->find_by as $col=>$val ) {
  658. if (is_array($val))
  659. list($col,$val) = each($val);
  660. if ($col == 'op') {
  661. $op = $val;
  662. } elseif ($col =='eq') {
  663. $eq = $val;
  664. } else {
  665. if (strpos($col,".") === false)
  666. $field = "$table.$col";
  667. else
  668. $field = $col;
  669. if ($findfirst) {
  670. $sql .= " WHERE $field $eq '$val' ";
  671. } else {
  672. $sql .= " $op $field $eq '$val' ";
  673. }
  674. $findfirst = false;
  675. }
  676. }
  677. } elseif ($model->id != NULL) {
  678. if (strpos($model->find_by,".") === false)
  679. $field = $table.".".$model->find_by;
  680. else
  681. $field = $model->find_by;
  682. $sql .= " WHERE $field = '".$model->id."' ";
  683. }
  684. if (!(isset($model->orderby)))
  685. $model->orderby = $table . "." . $pkfield;
  686. if (!(isset($model->order)))
  687. $model->order = "DESC";
  688. if (!(isset($model->offset)))
  689. $model->offset = 0;
  690. if (!(isset($model->limit)))
  691. $model->limit = 20;
  692. if (isset($model->groupby))
  693. $sql .= " GROUP BY " . $model->groupby . " ";
  694. $sql .= " ORDER BY " . $model->orderby . " ";
  695. $sql .= $model->order . $this->query_limit($model->limit,$model->offset);
  696. trigger_after( 'get_query', $model, $this );
  697. return $sql;
  698. }
  699. }
  700. ?>