Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 106 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
| IacSqlInfo | |
0.00% |
0 / 106 |
|
0.00% |
0 / 5 |
2352 | |
0.00% |
0 / 1 |
| result2fields | |
0.00% |
0 / 80 |
|
0.00% |
0 / 1 |
1260 | |||
| charsetnr2chars | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
| type2Text | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| flags2Array | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| constantsFill | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
30 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * IacSqlInfo |
| 4 | * Provides meta data and information on sql statements and database |
| 5 | * |
| 6 | * @package sql |
| 7 | * @author Informatica Asociada |
| 8 | * @copyright 2015 |
| 9 | * @version 1.0.0 |
| 10 | * @require php 5.3 |
| 11 | */ |
| 12 | /* |
| 13 | |
| 14 | create table vacia( |
| 15 | abigint1 bigint, |
| 16 | abigint1u bigint unsigned, |
| 17 | aint1 int, |
| 18 | aint1u int unsigned not null, |
| 19 | amediumint1 mediumint, |
| 20 | amediumint1u mediumint unsigned, |
| 21 | asmallint1 smallint, |
| 22 | asmallint1u smallint unsigned not null, |
| 23 | atinyint1 tinyint, |
| 24 | atinyint1u tinyint unsigned not null, |
| 25 | ayear4 year(4) COMMENT '1901 to 2155 o 0000 for invalid', |
| 26 | |
| 27 | |
| 28 | adecimal5_2 DECIMAL(5,2) not null default '0.00' COMMENT ' -999.99 to 999.99', |
| 29 | adecimal5_2u DECIMAL(5,2) unsigned not null default '0.00', |
| 30 | anumeric5_2 NUMERIC(5,2) not null default '0.00', |
| 31 | anumeric5_2u NUMERIC(5,2) unsigned not null default '0.00', |
| 32 | |
| 33 | anumeric3_0 NUMERIC(3,0) not null default '0', |
| 34 | anumeric3_0u NUMERIC(3,0) unsigned not null default '0', |
| 35 | anumeric3 NUMERIC(3) not null default '0', |
| 36 | anumeric3u NUMERIC(3) unsigned not null default '0', |
| 37 | |
| 38 | afloat7_4 FLOAT(7,4) not null default '0.00' COMMENT 'ie -999.9999', |
| 39 | afloat7_4u FLOAT(7,4) unsigned not null default '0.00', |
| 40 | |
| 41 | adouble7_4 DOUBLE(7,4) not null default '0.00' COMMENT 'ie -999.9999', |
| 42 | adouble7_4u DOUBLE(7,4) unsigned not null default '0.00', |
| 43 | |
| 44 | areal7_4 REAL(7,4) not null default '0.00' COMMENT 'ie -999.9999', |
| 45 | areal7_4u REAL(7,4) unsigned not null default '0.00', |
| 46 | |
| 47 | adouble3_0 DOUBLE(3,0) not null default '0' COMMENT ' no decs', |
| 48 | adouble3_0u DOUBLE(3,0) unsigned not null default '0', |
| 49 | |
| 50 | |
| 51 | abti1 bit(1), |
| 52 | abti16 bit(16), |
| 53 | |
| 54 | adate date COMMENT '1000-01-01 to 9999-12-31 ', |
| 55 | adatetime datetime COMMENT '1000-01-01 to 9999-12-31 fractional seconds part in up to microseconds (6 digits) as of MySQL 5.6.4 prev ignored', |
| 56 | atimestamp timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '1970-01-01 00:00:01 UTC to 2038-01-19 03:14:07 UTC fractional seconds part in up to microseconds (6 digits) as of MySQL 5.6.4 prev ignored', |
| 57 | |
| 58 | |
| 59 | achar4 char(4), |
| 60 | avarchar129 varchar(129), |
| 61 | abinary12 binary(12), |
| 62 | avarbinary12 varbinary(12), |
| 63 | |
| 64 | atinytext tinytext, |
| 65 | atext text, |
| 66 | amediumtext mediumtext, |
| 67 | alongtext longtext, |
| 68 | |
| 69 | atinyblob tinyblob, |
| 70 | ablob blob, |
| 71 | amediumblob mediumblob, |
| 72 | alongblob longblob, |
| 73 | |
| 74 | geo geometry, pt point, ln linestring, poly polygon, |
| 75 | |
| 76 | geo_coll geometrycollection, pt_multi multipoint, ln_multi multilinestring, poly_multi multipolygon |
| 77 | |
| 78 | --ayear2 year(2) COMMENT '1 to 99, depreciated, creates year4!', |
| 79 | |
| 80 | ) |
| 81 | |
| 82 | */ |
| 83 | |
| 84 | namespace Iac\inc\sql; |
| 85 | |
| 86 | /** |
| 87 | * IacSqlInfo |
| 88 | * |
| 89 | * @author Informatica Asociada |
| 90 | * @copyright 2015 |
| 91 | * @version 1.0.0 |
| 92 | * @require php 5.3 |
| 93 | */ |
| 94 | class IacSqlInfo { |
| 95 | protected $flags; |
| 96 | protected $types; |
| 97 | |
| 98 | protected $apiType2mysql = array( |
| 99 | 'bigint'=> 'longlong', |
| 100 | 'int'=> 'long', |
| 101 | 'mediumint'=> 'int24', |
| 102 | 'smallint'=> 'short', |
| 103 | 'tinyint'=> 'tinyint', |
| 104 | 'year'=> 'year', |
| 105 | 'numeric'=> 'decimal', |
| 106 | |
| 107 | ); |
| 108 | |
| 109 | // https://dev.mysql.com/doc/refman/5.5/en/integer-types.html |
| 110 | protected $dataTypesUnsigned = array( |
| 111 | 'tinyint'=>array('max'=>255), |
| 112 | 'smallint'=>array('max'=>65535), |
| 113 | 'mediumint'=>array('max'=>16777215), |
| 114 | 'int'=>array('max'=>4294967295), |
| 115 | 'bigint'=>array('max'=>'18446744073709551615'), |
| 116 | 'year' => array('max'=>2155,'min'=>1901), |
| 117 | ); |
| 118 | |
| 119 | |
| 120 | protected $dataTypesTrans = array( |
| 121 | 'tinyint'=>array('type'=>'tinyint', 'numeric'=>true,'bytes'=>1, 'min'=>-128, 'max'=>127,), |
| 122 | |
| 123 | 'decimal' => array( 'type'=>'decimal', 'numeric'=>true, 'floatingPoint'=>true, |
| 124 | ), |
| 125 | 'char' => array( 'type'=>'char', |
| 126 | ), |
| 127 | 'short' => array( 'type'=>'smallint', 'numeric'=>true,'bytes'=>2, 'min'=>-32768, 'max'=>32767, |
| 128 | ), |
| 129 | 'long' => array( 'type'=>'int', 'numeric'=>true,'bytes'=>4, 'min'=>-2147483648, 'max'=>2147483647, |
| 130 | ), |
| 131 | 'float' => array( 'type'=>'float', 'numeric'=>true, 'floatingPoint'=>true, |
| 132 | ), |
| 133 | 'double' => array( 'type'=>'double', 'numeric'=>true, 'floatingPoint'=>true, |
| 134 | ), |
| 135 | 'null' => array( 'type'=>'null', |
| 136 | ), |
| 137 | 'timestamp' => array( 'type'=>'timestamp', |
| 138 | ), |
| 139 | 'longlong' => array( 'type'=>'bigint', 'numeric'=>true,'bytes'=>8, 'min'=>'-9223372036854775808', 'max'=>'9223372036854775807', |
| 140 | ), |
| 141 | 'int24' => array( 'type'=>'mediumint', 'numeric'=>true,'bytes'=>3, 'min'=>-8388608, 'max'=>8388607, |
| 142 | ), |
| 143 | 'date' => array( 'type'=>'date', |
| 144 | ), |
| 145 | 'time' => array( 'type'=>'time', |
| 146 | ), |
| 147 | 'datetime' => array( 'type'=>'datetime', |
| 148 | ), |
| 149 | 'year' => array( 'type'=>'year', 'numeric'=>true, |
| 150 | ), |
| 151 | 'newdate' => array( 'type'=>'date', |
| 152 | ), |
| 153 | 'interval' => array( 'type'=>'interval', |
| 154 | ), |
| 155 | 'set' => array( 'type'=>'set', |
| 156 | ), |
| 157 | 'tiny_blob' => array( 'type'=>'tinytext', 'blob'=>true, |
| 158 | ), |
| 159 | 'medium_blob' => array( 'type'=>'mediumtext', 'blob'=>true, |
| 160 | ), |
| 161 | 'long_blob' => array( 'type'=>'longtext', 'blob'=>true, |
| 162 | ), |
| 163 | 'blob' => array( 'type'=>'text', 'blob'=>true, |
| 164 | ), |
| 165 | 'var_string' => array( 'type'=>'varchar', |
| 166 | ), |
| 167 | 'string' => array( 'type'=>'binary', |
| 168 | ), |
| 169 | 'geometry' => array( 'type'=>'geometry', |
| 170 | ), |
| 171 | 'newdecimal' => array( 'type'=>'decimal', 'numeric'=>true, 'floatingPoint'=>true, |
| 172 | ), |
| 173 | 'bit' => array( 'type'=>'bit', |
| 174 | ), |
| 175 | ); |
| 176 | // Art 60 risr deduccion casa habitacion por uso o goce, depositos efvo regla 3.5.11 |
| 177 | /** |
| 178 | * IacSqlInfo::result2fields() |
| 179 | * |
| 180 | * @param object $result mysqli resultset |
| 181 | * @return array associative array indexed by field with field's metadata |
| 182 | */ |
| 183 | public function result2fields($result) { |
| 184 | $primary_keys = 0; |
| 185 | $fields = array(); |
| 186 | $finfo = $result->fetch_fields(); |
| 187 | foreach ($finfo as $f) { |
| 188 | $binary = ($f->flags & MYSQLI_BINARY_FLAG) === MYSQLI_BINARY_FLAG; |
| 189 | |
| 190 | $asMysqli = $type = $this->type2Text($f->type,$f->flags); |
| 191 | // mysqli type to mysql data type |
| 192 | |
| 193 | //if(($f->flags & MYSQLI_GROUP_FLAG) && $asMysqli === 'CHAR') |
| 194 | if($f->charsetnr === 63 && $asMysqli === 'CHAR') |
| 195 | $type = 'TINYINT'; |
| 196 | elseif(($f->flags & MYSQLI_ENUM_FLAG) === MYSQLI_ENUM_FLAG) |
| 197 | $type = 'ENUM'; |
| 198 | elseif(($f->flags & MYSQLI_SET_FLAG) === MYSQLI_SET_FLAG) |
| 199 | $type = 'SET'; |
| 200 | elseif(!$binary && $asMysqli === 'STRING') |
| 201 | $type = 'CHAR'; |
| 202 | elseif($binary && $asMysqli === 'VAR_STRING') |
| 203 | $type = "VARBINARY"; |
| 204 | $type = strtolower($type); |
| 205 | if(array_key_exists($type, $this->apiType2mysql)) |
| 206 | $type = $this->apiType2mysql[$type]; |
| 207 | |
| 208 | $field = array( |
| 209 | 'type' => strtolower($type), |
| 210 | 'typeMysqli' => $asMysqli, |
| 211 | 'flags' => $this->flags2Array($f->flags), |
| 212 | 'metaData' => $f, |
| 213 | //'max_chars' => $f->length, // ? |
| 214 | ); |
| 215 | |
| 216 | if(($f->flags & MYSQLI_PRI_KEY_FLAG) === MYSQLI_PRI_KEY_FLAG) { |
| 217 | $primary_keys++; |
| 218 | $field['pri_key'] = true; |
| 219 | $field['pri_key_multiple'] = $primary_keys > 1; // on multi coolumn primar key the first column will be fixed after this loop |
| 220 | $field['auto_increment'] = ($f->flags & MYSQLI_AUTO_INCREMENT_FLAG) === MYSQLI_AUTO_INCREMENT_FLAG; |
| 221 | } |
| 222 | $field['null'] = !( ($f->flags & MYSQLI_NOT_NULL_FLAG) === MYSQLI_NOT_NULL_FLAG ); |
| 223 | $field['required'] = !$field['null']; |
| 224 | |
| 225 | if(isset($this->dataTypesTrans[$type])) |
| 226 | $field = array_merge($field,$this->dataTypesTrans[$type]); |
| 227 | $type = $field['type']; |
| 228 | |
| 229 | if($type === 'char' || $type === 'varchar' || $type === 'binary' || $type === 'varbinary') { |
| 230 | $field['max_chars'] = $this->charsetnr2chars($f->length,$f->charsetnr); |
| 231 | $field['max_multibytes'] = $f->length; |
| 232 | } |
| 233 | elseif(isset($field['numeric'])) { |
| 234 | $unsigned = ($f->flags & MYSQLI_UNSIGNED_FLAG) === MYSQLI_UNSIGNED_FLAG; |
| 235 | $field['decimals'] = $f->decimals; |
| 236 | if(isset($field['floatingPoint'])) { |
| 237 | if($f->decimals == 0) { |
| 238 | $decs = ''; |
| 239 | if($type==='decimal') { |
| 240 | if($unsigned) { |
| 241 | $integers = $field['integers'] = $f->length - $f->decimals; |
| 242 | } else { |
| 243 | $integers = $field['integers'] = $f->length - $f->decimals -1; |
| 244 | } |
| 245 | } else { |
| 246 | $integers = $field['integers'] = $f->length - $f->decimals; |
| 247 | } |
| 248 | } else { |
| 249 | $decs = '.'.str_repeat('9',$f->decimals); |
| 250 | if($type==='decimal') { |
| 251 | if($unsigned) { |
| 252 | $integers = $field['integers'] = $f->length - $f->decimals -1; |
| 253 | } else { |
| 254 | $integers = $field['integers'] = $f->length - $f->decimals -2; |
| 255 | } |
| 256 | } else { |
| 257 | $integers = $field['integers'] = $f->length - $f->decimals; |
| 258 | } |
| 259 | } |
| 260 | $field['min'] = '-'.str_repeat('9',$integers).$decs; |
| 261 | $field['max'] = str_repeat('9',$integers).$decs; |
| 262 | } else { |
| 263 | if($unsigned) { |
| 264 | $field['integers'] = $f->length - $f->decimals; |
| 265 | } else { |
| 266 | $field['integers'] = $f->length - $f->decimals - 1; |
| 267 | } |
| 268 | } |
| 269 | if($unsigned) { |
| 270 | $field['min'] = 0; |
| 271 | if(isset($this->dataTypesUnsigned[$type])) |
| 272 | $field = array_merge($field,$this->dataTypesUnsigned[$type]); |
| 273 | $field['max_chars'] = strlen($field['max']); |
| 274 | } else { |
| 275 | $field['max_chars'] = strlen($field['min']); |
| 276 | } |
| 277 | } |
| 278 | elseif(isset($field['blob'])) { |
| 279 | if($binary) |
| 280 | $field['type'] = str_replace('text','blob',$field['type']); |
| 281 | if($f->length > 0) { |
| 282 | $field['max_multibytes'] = $f->length; |
| 283 | if(!$binary) |
| 284 | $field['max_chars'] = $this->charsetnr2chars($f->length,$f->charsetnr); |
| 285 | } |
| 286 | } |
| 287 | elseif($type === 'bit') { |
| 288 | $field['min'] = 0; |
| 289 | $field['max'] = $f->length; //FIXME |
| 290 | $field['max_chars'] = $f->length; |
| 291 | } |
| 292 | $fields[$f->name] = $field; |
| 293 | } |
| 294 | // on multiple column primary key, mark the first column as multiple |
| 295 | if($primary_keys > 1) |
| 296 | foreach($fields as &$field) |
| 297 | if(isset($field['pri_key'])) { |
| 298 | $field['pri_key_multiple'] = true; |
| 299 | break; |
| 300 | } |
| 301 | return $fields; |
| 302 | } |
| 303 | |
| 304 | /** |
| 305 | * IacSqlInfo::charsetnr2chars() |
| 306 | * Returns length in characters given the length in bytes, for the given $charsetnr |
| 307 | * |
| 308 | * @param int $lengthInBytes length in bytes |
| 309 | * @param int $charsetnr mysql characterset code |
| 310 | * @return int |
| 311 | */ |
| 312 | protected function charsetnr2chars($lengthInBytes,$charsetnr) { |
| 313 | if($charsetnr == 33) // utf8 |
| 314 | return $lengthInBytes/3; |
| 315 | if($charsetnr == 8) // latin1 |
| 316 | return $lengthInBytes; |
| 317 | //TODO SELECT * FROM information_schema.collations; |
| 318 | return $lengthInBytes; |
| 319 | } |
| 320 | |
| 321 | /** |
| 322 | * iacMysqli::type2Text() |
| 323 | * return mysqli type for the field |
| 324 | * |
| 325 | * @param integer $type_id from $result->fetch_field()->type or $result->fetch_field_direct($i)->type |
| 326 | * @return string mysql type for id |
| 327 | */ |
| 328 | public function type2Text($type_id,$flags_num) { |
| 329 | // fill constants if not done yet |
| 330 | $this->constantsFill(); |
| 331 | // unkown type |
| 332 | if(!array_key_exists($type_id, $this->types)) |
| 333 | return null; |
| 334 | return $this->types[$type_id]; |
| 335 | } |
| 336 | |
| 337 | /** |
| 338 | * iacMysqli::flags2Array() |
| 339 | * Get mysqli flags |
| 340 | * |
| 341 | * @param integer $flags_num from $result->fetch_field()->flags or $result->fetch_field_direct($i)->flags |
| 342 | * @return array associative array with flag names indexed by mysqli constant |
| 343 | */ |
| 344 | public function flags2Array($flags_num) { |
| 345 | // fill constants if not done yet |
| 346 | //if(!isset($this->flags)) |
| 347 | $this->constantsFill(); |
| 348 | $result = array(); |
| 349 | foreach($this->flags as $n => $t) |
| 350 | if(($flags_num & $n) === $n) { |
| 351 | $result[$n] = $t; |
| 352 | } |
| 353 | return $result; |
| 354 | } |
| 355 | |
| 356 | /** |
| 357 | * IacSqlInfo::constantsFill() |
| 358 | * Fills mysqli's type names into $this->types and flag names into $this>$flags |
| 359 | * |
| 360 | * @return void |
| 361 | * @see http://php.net/manual/en/mysqli-result.fetch-fields.php |
| 362 | * @see http://php.net/manual/en/mysqli.constants.php |
| 363 | */ |
| 364 | protected function constantsFill() { |
| 365 | if(isset($this->types)) { |
| 366 | return; // constants have been filled |
| 367 | } |
| 368 | $flags = array(); |
| 369 | $types = array(); |
| 370 | $constants = get_defined_constants(true); // era true |
| 371 | foreach($constants['mysqli'] as $c => $n) |
| 372 | if(preg_match('/^MYSQLI_TYPE_(.*)/', $c, $m)) |
| 373 | $types[$n] = $m[1]; |
| 374 | elseif(preg_match('/MYSQLI_(.*)_FLAG$/', $c, $mFlag)) |
| 375 | $flags[$n] = $mFlag[1]; |
| 376 | $this->types = $types; |
| 377 | $this->flags = $flags; |
| 378 | } |
| 379 | |
| 380 | } |