You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PgSqlDataAccess.php 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <?php
  2. namespace Luticate\Utils\DataAccess;
  3. use Luticate\Utils\Business\LuStringUtils;
  4. /**
  5. * Created by PhpStorm.
  6. * User: robin
  7. * Date: 6/10/16
  8. * Time: 11:05 AM
  9. */
  10. class PgSqlDataAccess extends AbstractDbDataAccess
  11. {
  12. public static $types = ["SERIAL" => "integer",
  13. "BIGSERIAL" => "integer",
  14. "abstime" => "datetime",
  15. "aclitem" => "",
  16. "any" => "",
  17. "anyarray" => "",
  18. "anyelement" => "",
  19. "anyenum" => "",
  20. "anynonarray" => "",
  21. "anyrange" => "",
  22. "bigint" => "integer",
  23. "bit" => "",
  24. "bit varying" => "",
  25. "boolean" => "boolean",
  26. "box" => "",
  27. "bytea" => "string",
  28. "char" => "string",
  29. "character" => "string",
  30. "character varying" => "string",
  31. "cid" => "",
  32. "cidr" => "",
  33. "circle" => "",
  34. "cstring" => "",
  35. "date" => "datetime",
  36. "daterange" => "",
  37. "decimal" => "float",
  38. "double precision" => "float",
  39. "event_trigger" => "",
  40. "fdw_handler" => "",
  41. "gtsvector" => "",
  42. "inet" => "",
  43. "information_schema.cardinal_number" => "",
  44. "information_schema.character_data" => "",
  45. "information_schema.sql_identifier" => "",
  46. "information_schema.time_stamp" => "",
  47. "information_schema.yes_or_no" => "",
  48. "int2vector" => "",
  49. "int4range" => "",
  50. "int8range" => "",
  51. "integer" => "integer",
  52. "internal" => "",
  53. "interval" => "",
  54. "json" => "",
  55. "jsonb" => "",
  56. "language_handler" => "",
  57. "line" => "",
  58. "lseg" => "",
  59. "macaddr" => "",
  60. "money" => "string",
  61. "name" => "",
  62. "numeric" => "float",
  63. "numrange" => "",
  64. "oid" => "",
  65. "oidvector" => "",
  66. "opaque" => "",
  67. "path" => "",
  68. "pg_lsn" => "",
  69. "pg_node_tree" => "",
  70. "point" => "",
  71. "polygon" => "",
  72. "real" => "float",
  73. "record" => "",
  74. "refcursor" => "",
  75. "regclass" => "",
  76. "regconfig" => "",
  77. "regdictionary" => "",
  78. "regoper" => "",
  79. "regoperator" => "",
  80. "regproc" => "",
  81. "regprocedure" => "",
  82. "regtype" => "",
  83. "reltime" => "",
  84. "smallint" => "integer",
  85. "smallserial" => "integer",
  86. "smgr" => "",
  87. "text" => "string",
  88. "tid" => "",
  89. "timestamp without time zone" => "datetime",
  90. "timestamp with time zone" => "datetime",
  91. "time without time zone" => "datetime",
  92. "time with time zone" => "datetime",
  93. "tinterval" => "",
  94. "trigger" => "",
  95. "tsquery" => "",
  96. "tsrange" => "",
  97. "tstzrange" => "",
  98. "tsvector" => "",
  99. "txid_snapshot" => "",
  100. "unknown" => "",
  101. "uuid" => "",
  102. "void" => "",
  103. "xid" => "",
  104. "xml" => ""];
  105. /**
  106. * @param string $sqlType
  107. * @return string
  108. */
  109. public function sqlTypeToPhpType($sqlType)
  110. {
  111. $isArray = false;
  112. if (LuStringUtils::endsWith($sqlType, "[]")) {
  113. $isArray = true;
  114. $sqlType = substr($sqlType, 0, strlen($sqlType) - 2);
  115. }
  116. if (!isset(static::$types) || static::$types[$sqlType] == "") {
  117. return "mixed";
  118. }
  119. return static::$types[$sqlType] . ($isArray ? "[]" : "");
  120. }
  121. /**
  122. * @param \PDO $pdo
  123. * @return array|null
  124. */
  125. public function getTablesFull($pdo)
  126. {
  127. $tables_names = $this->getTables($pdo);
  128. if (is_null($tables_names)) {
  129. return null;
  130. }
  131. $tables = [];
  132. foreach ($tables_names as $table_name) {
  133. $columns = $this->getColumns($pdo, $table_name);
  134. if (is_null($columns)) {
  135. return null;
  136. }
  137. $tables[$table_name] = $columns;
  138. }
  139. return $tables;
  140. }
  141. /**
  142. * @param $pdo \PDO
  143. * @return string[]|null
  144. */
  145. public function getTables($pdo)
  146. {
  147. $tablesQuery = $pdo->prepare("SELECT table_name AS name
  148. FROM information_schema.tables
  149. WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')");
  150. if ($tablesQuery->execute(array())) {
  151. $tables = $tablesQuery->fetchAll();
  152. $tables = array_map(function($table)
  153. {
  154. return $table["name"];
  155. }, $tables);
  156. return $tables;
  157. }
  158. else
  159. return null;
  160. }
  161. /**
  162. * @param $pdo \PDO
  163. * @param $table_name string
  164. * @return array|null
  165. */
  166. public function getColumns($pdo, $table_name)
  167. {
  168. $columnsQuery = $pdo->prepare("SELECT column_name as name, data_type as data_type, is_nullable as nullable FROM information_schema.columns WHERE table_name = :table_name");
  169. if ($columnsQuery->execute(array(":table_name" => $table_name)))
  170. {
  171. $columns = $columnsQuery->fetchAll();
  172. return $columns;
  173. }
  174. else
  175. return null;
  176. }
  177. /**
  178. * @param \PDO $pdo
  179. * @return array|null
  180. */
  181. public function getStoredProceduresFull($pdo)
  182. {
  183. $sps = $this->getStoredProcedures($pdo);
  184. if (is_null($sps)) {
  185. return null;
  186. }
  187. foreach ($sps as $sp_name => $sp) {
  188. $args = $this->getStoredProceduresArguments($pdo, $sp);
  189. if (is_null($args)) {
  190. return null;
  191. }
  192. $sps[$sp_name]["args"] = $args;
  193. }
  194. return $sps;
  195. }
  196. /**
  197. * @param $pdo \PDO
  198. * @return array|null
  199. */
  200. public function getStoredProcedures($pdo)
  201. {
  202. $spQuery = $pdo->prepare("SELECT r.routine_name AS sp_name, r.data_type AS data_type, proc.proretset AS proretset, proc.prosrc AS prosrc
  203. FROM information_schema.routines r
  204. LEFT JOIN pg_catalog.pg_proc proc ON proc.proname = r.routine_name
  205. WHERE r.specific_schema='public'");
  206. if ($spQuery->execute())
  207. {
  208. $sps = $spQuery->fetchAll();
  209. $data = [];
  210. foreach ($sps as $sp) {
  211. $data[$sp["sp_name"]] = ["sp" => $sp];
  212. }
  213. return $data;
  214. }
  215. else
  216. return null;
  217. }
  218. /**
  219. * @param $pdo \PDO
  220. * @param $sp string
  221. * @return array|null
  222. */
  223. public function getStoredProceduresArguments($pdo, $sp)
  224. {
  225. $sp_name = $sp["sp"]["sp_name"];
  226. $spQuery = $pdo->prepare("SELECT parameters.parameter_name as name, parameters.data_type, parameters.parameter_mode
  227. FROM information_schema.routines
  228. JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
  229. WHERE routines.specific_schema='public' AND routines.routine_name = :sp_name
  230. ORDER BY parameters.ordinal_position;");
  231. if ($spQuery->execute(array("sp_name" => $sp_name)))
  232. {
  233. $sp_ = $spQuery->fetchAll();
  234. $sps = array("in" => array(), "out" => array());
  235. foreach ($sp_ as $p) {
  236. $type = strtolower($p["parameter_mode"]);
  237. if (empty($p["name"])) {
  238. $p["name"] = "arg" . count($sps[$type]);
  239. }
  240. $sps[$type][] = $p;
  241. }
  242. $out_count = count($sps['out']);
  243. if ($out_count == 0)
  244. {
  245. $sps['out'][] = array(
  246. "name" => empty($sp_name) ? "arg" . count($sps['out']) : $sp_name,
  247. "data_type" => $sp["data_type"],
  248. "parameter_mode" => "OUT"
  249. );
  250. $out_count = 1;
  251. }
  252. return $sps;
  253. }
  254. else
  255. return null;
  256. }
  257. }