PageRenderTime 120ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/interface/main/calendar/pnadodb/adodb-datadict.inc.php

https://bitbucket.org/DenizYldrm/openemr
PHP | 582 lines | 508 code | 29 blank | 45 comment | 44 complexity | 9924d1afebc1ef3716a681290754c526 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, MPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. V3.60 16 June 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.
  4. Released under both BSD license and Lesser GPL library license.
  5. Whenever there is any discrepancy between the two licenses,
  6. the BSD license will take precedence.
  7. Set tabs to 4 for best viewing.
  8. DOCUMENTATION:
  9. See adodb/tests/test-datadict.php for docs and examples.
  10. */
  11. /*
  12. Test script for parser
  13. */
  14. function Lens_ParseTest()
  15. {
  16. $str = "ACOL NUMBER(32,2) DEFAULT 'The \"cow\" (and Jim''s dog) jumps over the moon' PRIMARY, INTI INT AUTO DEFAULT 0";
  17. print "<p>$str</p>";
  18. $a= Lens_ParseArgs($str);
  19. print "<pre>";
  20. print_r($a);
  21. print "</pre>";
  22. }
  23. //Lens_ParseTest();
  24. /**
  25. Parse arguments, treat "text" (text) and 'text' as quotation marks.
  26. To escape, use "" or '' or ))
  27. @param endstmtchar Character that indicates end of statement
  28. @param tokenchars Include the following characters in tokens apart from A-Z and 0-9
  29. @returns 2 dimensional array containing parsed tokens.
  30. */
  31. function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
  32. {
  33. $pos = 0;
  34. $intoken = false;
  35. $stmtno = 0;
  36. $endquote = false;
  37. $tokens = array();
  38. $tokens[$stmtno] = array();
  39. $max = strlen($args);
  40. $quoted = false;
  41. while ($pos < $max) {
  42. $ch = substr($args,$pos,1);
  43. switch($ch) {
  44. case ' ':
  45. case "\t":
  46. case "\n":
  47. case "\r":
  48. if (!$quoted) {
  49. if ($intoken) {
  50. $intoken = false;
  51. $tokens[$stmtno][] = implode('',$tokarr);
  52. }
  53. break;
  54. }
  55. $tokarr[] = $ch;
  56. break;
  57. case '(':
  58. case ')':
  59. case '"':
  60. case "'":
  61. if ($intoken) {
  62. if (empty($endquote)) {
  63. $tokens[$stmtno][] = implode('',$tokarr);
  64. if ($ch == '(') $endquote = ')';
  65. else $endquote = $ch;
  66. $quoted = true;
  67. $intoken = true;
  68. $tokarr = array();
  69. } else if ($endquote == $ch) {
  70. $ch2 = substr($args,$pos+1,1);
  71. if ($ch2 == $endquote) {
  72. $pos += 1;
  73. $tokarr[] = $ch2;
  74. } else {
  75. $quoted = false;
  76. $intoken = false;
  77. $tokens[$stmtno][] = implode('',$tokarr);
  78. $endquote = '';
  79. }
  80. } else
  81. $tokarr[] = $ch;
  82. }else {
  83. if ($ch == '(') $endquote = ')';
  84. else $endquote = $ch;
  85. $quoted = true;
  86. $intoken = true;
  87. $tokarr = array();
  88. }
  89. break;
  90. default:
  91. if (!$intoken) {
  92. if ($ch == $endstmtchar) {
  93. $stmtno += 1;
  94. $tokens[$stmtno] = array();
  95. break;
  96. }
  97. $intoken = true;
  98. $quoted = false;
  99. $endquote = false;
  100. $tokarr = array();
  101. }
  102. if ($quoted) $tokarr[] = $ch;
  103. else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !== false) $tokarr[] = $ch;
  104. else {
  105. if ($ch == $endstmtchar) {
  106. $tokens[$stmtno][] = implode('',$tokarr);
  107. $stmtno += 1;
  108. $tokens[$stmtno] = array();
  109. $intoken = false;
  110. $tokarr = array();
  111. break;
  112. }
  113. $tokens[$stmtno][] = implode('',$tokarr);
  114. $tokens[$stmtno][] = $ch;
  115. $intoken = false;
  116. }
  117. }
  118. $pos += 1;
  119. }
  120. return $tokens;
  121. }
  122. class ADODB_DataDict {
  123. var $connection;
  124. var $debug = false;
  125. var $dropTable = "DROP TABLE %s";
  126. var $addCol = ' ADD';
  127. var $alterCol = ' ALTER COLUMN';
  128. var $dropCol = ' DROP COLUMN';
  129. var $schema = false;
  130. var $serverInfo = array();
  131. var $autoIncrement = false;
  132. var $dataProvider;
  133. var $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob
  134. /// in other words, we use a text area for editting.
  135. function GetCommentSQL($table,$col)
  136. {
  137. return false;
  138. }
  139. function SetCommentSQL($table,$col,$cmt)
  140. {
  141. return false;
  142. }
  143. function &MetaTables()
  144. {
  145. return $this->connection->MetaTables();
  146. }
  147. function &MetaColumns($tab)
  148. {
  149. return $this->connection->MetaColumns($tab);
  150. }
  151. function &MetaPrimaryKeys($tab,$owner=false,$intkey=false)
  152. {
  153. return $this->connection->MetaPrimaryKeys($tab.$owner,$intkey);
  154. }
  155. function MetaType($t,$len=-1,$fieldobj=false)
  156. {
  157. return ADORecordSet::MetaType($t,$len,$fieldobj);
  158. }
  159. // Executes the sql array returned by GetTableSQL and GetIndexSQL
  160. function ExecuteSQLArray($sql, $continueOnError = true)
  161. {
  162. $rez = 2;
  163. $conn = &$this->connection;
  164. $saved = $conn->debug;
  165. foreach($sql as $line) {
  166. if ($this->debug) $conn->debug = true;
  167. $ok = $conn->Execute($line);
  168. $conn->debug = $saved;
  169. if (!$ok) {
  170. if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
  171. if (!$continueOnError) return 0;
  172. $rez = 1;
  173. }
  174. }
  175. return 2;
  176. }
  177. /*
  178. Returns the actual type given a character code.
  179. C: varchar
  180. X: CLOB (character large object) or largest varchar size if CLOB is not supported
  181. C2: Multibyte varchar
  182. X2: Multibyte CLOB
  183. B: BLOB (binary large object)
  184. D: Date
  185. T: Date-time
  186. L: Integer field suitable for storing booleans (0 or 1)
  187. I: Integer
  188. F: Floating point number
  189. N: Numeric or decimal number
  190. */
  191. function ActualType($meta)
  192. {
  193. return $meta;
  194. }
  195. function CreateDatabase($dbname,$options=false)
  196. {
  197. $options = $this->_Options($options);
  198. $s = 'CREATE DATABASE '.$dbname;
  199. if (isset($options[$this->upperName])) $s .= ' '.$options[$this->upperName];
  200. $sql[] = $s;
  201. return $sql;
  202. }
  203. /*
  204. Generates the SQL to create index. Returns an array of sql strings.
  205. */
  206. function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
  207. {
  208. if ($this->schema) $tabname = $this->schema.'.'.$tabname;
  209. return $this->_IndexSQL($idxname, $tabname, $flds, $this->_Options($idxoptions));
  210. }
  211. function SetSchema($schema)
  212. {
  213. $this->schema = $schema;
  214. }
  215. function AddColumnSQL($tabname, $flds)
  216. {
  217. if ($this->schema) $tabname = $this->schema.'.'.$tabname;
  218. $sql = array();
  219. list($lines,$pkey) = $this->_GenFields($flds);
  220. foreach($lines as $v) {
  221. $sql[] = "ALTER TABLE $tabname $this->addCol $v";
  222. }
  223. return $sql;
  224. }
  225. function AlterColumnSQL($tabname, $flds)
  226. {
  227. if ($this->schema) $tabname = $this->schema.'.'.$tabname;
  228. $sql = array();
  229. list($lines,$pkey) = $this->_GenFields($flds);
  230. foreach($lines as $v) {
  231. $sql[] = "ALTER TABLE $tabname $this->alterCol $v";
  232. }
  233. return $sql;
  234. }
  235. function DropColumnSQL($tabname, $flds)
  236. {
  237. if ($this->schema) $tabname = $this->schema.'.'.$tabname;
  238. if (!is_array($flds)) $flds = explode(',',$flds);
  239. $sql = array();
  240. foreach($flds as $v) {
  241. $sql[] = "ALTER TABLE $tabname $this->dropCol $v";
  242. }
  243. return $sql;
  244. }
  245. function DropTableSQL($tabname)
  246. {
  247. if ($this->schema) $tabname = $this->schema.'.'.$tabname;
  248. $sql[] = sprintf($this->dropTable,$tabname);
  249. return $sql;
  250. }
  251. /*
  252. Generate the SQL to create table. Returns an array of sql strings.
  253. */
  254. function CreateTableSQL($tabname, $flds, $tableoptions=false)
  255. {
  256. if (!$tableoptions) $tableoptions = array();
  257. list($lines,$pkey) = $this->_GenFields($flds);
  258. $taboptions = $this->_Options($tableoptions);
  259. if ($this->schema) $tabname = $this->schema.'.'.$tabname;
  260. $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
  261. $tsql = $this->_Triggers($tabname,$taboptions);
  262. foreach($tsql as $s) $sql[] = $s;
  263. return $sql;
  264. }
  265. function _GenFields($flds)
  266. {
  267. if (is_string($flds)) {
  268. $padding = ' ';
  269. $txt = $flds.$padding;
  270. $flds = array();
  271. $flds0 = Lens_ParseArgs($txt,',');
  272. $hasparam = false;
  273. foreach($flds0 as $f0) {
  274. $f1 = array();
  275. foreach($f0 as $token) {
  276. switch (strtoupper($token)) {
  277. case 'CONSTRAINT':
  278. case 'DEFAULT':
  279. $hasparam = $token;
  280. break;
  281. default:
  282. if ($hasparam) $f1[$hasparam] = $token;
  283. else $f1[] = $token;
  284. $hasparam = false;
  285. break;
  286. }
  287. }
  288. $flds[] = $f1;
  289. }
  290. }
  291. $this->autoIncrement = false;
  292. $lines = array();
  293. $pkey = array();
  294. foreach($flds as $fld) {
  295. $fld = _array_change_key_case($fld);
  296. $fname = false;
  297. $fdefault = false;
  298. $fautoinc = false;
  299. $ftype = false;
  300. $fsize = false;
  301. $fprec = false;
  302. $fprimary = false;
  303. $fnoquote = false;
  304. $fdefts = false;
  305. $fdefdate = false;
  306. $fconstraint = false;
  307. $fnotnull = false;
  308. $funsigned = false;
  309. //-----------------
  310. // Parse attributes
  311. foreach($fld as $attr => $v) {
  312. if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
  313. else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
  314. switch($attr) {
  315. case '0':
  316. case 'NAME': $fname = $v; break;
  317. case '1':
  318. case 'TYPE': $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
  319. case 'SIZE': $dotat = strpos($v,'.');
  320. if ($dotat === false) $fsize = $v;
  321. else {
  322. $fsize = substr($v,0,$dotat);
  323. $fprec = substr($v,$dotat+1);
  324. }
  325. break;
  326. case 'UNSIGNED': $funsigned = true; break;
  327. case 'AUTOINCREMENT':
  328. case 'AUTO': $fautoinc = true; $fnotnull = true; break;
  329. case 'KEY':
  330. case 'PRIMARY': $fprimary = $v; $fnotnull = true; break;
  331. case 'DEF':
  332. case 'DEFAULT': $fdefault = $v; break;
  333. case 'NOTNULL': $fnotnull = $v; break;
  334. case 'NOQUOTE': $fnoquote = $v; break;
  335. case 'DEFDATE': $fdefdate = $v; break;
  336. case 'DEFTIMESTAMP': $fdefts = $v; break;
  337. case 'CONSTRAINT': $fconstraint = $v; break;
  338. } //switch
  339. } // foreach $fld
  340. //--------------------
  341. // VALIDATE FIELD INFO
  342. if (!strlen($fname)) {
  343. if ($this->debug) ADOConnection::outp("Undefined NAME");
  344. return false;
  345. }
  346. if (!strlen($ftype)) {
  347. if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
  348. return false;
  349. } else {
  350. $ftype = strtoupper($ftype);
  351. }
  352. $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
  353. if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
  354. if ($fprimary) $pkey[] = $fname;
  355. // some databases do not allow blobs to have defaults
  356. if ($ty == 'X') $fdefault = false;
  357. //--------------------
  358. // CONSTRUCT FIELD SQL
  359. if ($fdefts) {
  360. if (substr($this->connection->databaseType,0,5) == 'mysql') {
  361. $ftype = 'TIMESTAMP';
  362. } else {
  363. $fdefault = $this->connection->sysTimeStamp;
  364. }
  365. } else if ($fdefdate) {
  366. if (substr($this->connection->databaseType,0,5) == 'mysql') {
  367. $ftype = 'TIMESTAMP';
  368. } else {
  369. $fdefault = $this->connection->sysDate;
  370. }
  371. } else if (strlen($fdefault) && !$fnoquote)
  372. if ($ty == 'C' or $ty == 'X' or
  373. ( substr($fdefault,0,1) != "'" && !is_numeric($fdefault)))
  374. if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ')
  375. $fdefault = trim($fdefault);
  376. else if (strtolower($fdefault) != 'null')
  377. $fdefault = $this->connection->qstr($fdefault);
  378. $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
  379. $fname = str_pad($fname,16);
  380. $lines[] = "$fname $ftype$suffix";
  381. if ($fautoinc) $this->autoIncrement = true;
  382. } // foreach $flds
  383. return array($lines,$pkey);
  384. }
  385. /*
  386. GENERATE THE SIZE PART OF THE DATATYPE
  387. $ftype is the actual type
  388. $ty is the type defined originally in the DDL
  389. */
  390. function _GetSize($ftype, $ty, $fsize, $fprec)
  391. {
  392. if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
  393. $ftype .= "(".$fsize;
  394. if ($fprec) $ftype .= ",".$fprec;
  395. $ftype .= ')';
  396. }
  397. return $ftype;
  398. }
  399. // return string must begin with space
  400. function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
  401. {
  402. $suffix = '';
  403. if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
  404. if ($fnotnull) $suffix .= ' NOT NULL';
  405. if ($fconstraint) $suffix .= ' '.$fconstraint;
  406. return $suffix;
  407. }
  408. function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
  409. {
  410. if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX $idxname";
  411. if (isset($idxoptions['UNIQUE'])) $unique = ' UNIQUE';
  412. else $unique = '';
  413. if (is_array($flds)) $flds = implode(', ',$flds);
  414. $s = "CREATE$unique INDEX $idxname ON $tabname ";
  415. if (isset($idxoptions[$this->upperName])) $s .= $idxoptions[$this->upperName];
  416. $s .= "($flds)";
  417. $sql[] = $s;
  418. return $sql;
  419. }
  420. function _DropAutoIncrement($tabname)
  421. {
  422. return false;
  423. }
  424. function _TableSQL($tabname,$lines,$pkey,$tableoptions)
  425. {
  426. $sql = array();
  427. if (isset($tableoptions['REPLACE'])) {
  428. $sql[] = sprintf($this->dropTable,$tabname);
  429. if ($this->autoIncrement) {
  430. $sInc = $this->_DropAutoIncrement($tabname);
  431. if ($sInc) $sql[] = $sInc;
  432. }
  433. }
  434. $s = "CREATE TABLE $tabname (\n";
  435. $s .= implode(",\n", $lines);
  436. if (sizeof($pkey)>0) {
  437. $s .= ",\n PRIMARY KEY (";
  438. $s .= implode(", ",$pkey).")";
  439. }
  440. if (isset($tableoptions['CONSTRAINTS']))
  441. $s .= "\n".$tableoptions['CONSTRAINTS'];
  442. if (isset($tableoptions[$this->upperName.'_CONSTRAINTS']))
  443. $s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS'];
  444. $s .= "\n)";
  445. if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
  446. $sql[] = $s;
  447. return $sql;
  448. }
  449. /*
  450. GENERATE TRIGGERS IF NEEDED
  451. used when table has auto-incrementing field that is emulated using triggers
  452. */
  453. function _Triggers($tabname,$taboptions)
  454. {
  455. return array();
  456. }
  457. /*
  458. Sanitize options, so that array elements with no keys are promoted to keys
  459. */
  460. function _Options($opts)
  461. {
  462. if (!is_array($opts)) return array();
  463. $newopts = array();
  464. foreach($opts as $k => $v) {
  465. if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
  466. else $newopts[strtoupper($k)] = $v;
  467. }
  468. return $newopts;
  469. }
  470. /*
  471. "Florian Buzin [ easywe ]" <florian.buzin@easywe.de>
  472. This function changes/adds new fields to your table. You
  473. dont have to know if the col is new or not. It will check on its
  474. own.
  475. */
  476. function ChangeTableSQL($tablename, $flds)
  477. {
  478. if ($this->schema) $tabname = $this->schema.'.'.$tablename;
  479. else $tabname = $tablename;
  480. $conn = &$this->connection;
  481. if (!$conn) return false;
  482. $colarr = $conn->MetaColumns($tabname);
  483. if (!$colarr) return $this->CreateTableSQL($tablename,$flds);
  484. foreach($colarr as $col) $cols[strtoupper($col->name)] = " ALTER ";
  485. $sql = array();
  486. list($lines,$pkey) = $this->_GenFields($flds);
  487. foreach($lines as $v) {
  488. $f = explode(" ",$v);
  489. if(!empty($cols[strtoupper($f[0])])){
  490. $sql[] = "ALTER TABLE $tabname $this->alterCol $v";
  491. }else{
  492. $sql[] = "ALTER TABLE $tabname $this->addCol $v";
  493. }
  494. }
  495. return $sql;
  496. }
  497. } // class
  498. ?>