1 /* 2 * Copyright 2015-2018 HuntLabs.cn 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 module hunt.sql.stat.TableStat; 17 18 import hunt.sql.SQLUtils; 19 import hunt.sql.ast.SQLExpr; 20 import hunt.sql.ast.expr.SQLPropertyExpr; 21 import hunt.serialization.JsonSerializer; 22 import hunt.sql.util.FnvHash; 23 import hunt.sql.util.DBType; 24 import hunt.String; 25 import hunt.collection; 26 import hunt.String; 27 import std.string; 28 import hunt.text; 29 30 public class TableStat 31 { 32 33 int selectCount = 0; 34 int updateCount = 0; 35 int deleteCount = 0; 36 int insertCount = 0; 37 int dropCount = 0; 38 int mergeCount = 0; 39 int createCount = 0; 40 int alterCount = 0; 41 int createIndexCount = 0; 42 int dropIndexCount = 0; 43 int referencedCount = 0; 44 45 public int getReferencedCount() 46 { 47 return referencedCount; 48 } 49 50 public void incrementReferencedCount() 51 { 52 referencedCount++; 53 } 54 55 public int getDropIndexCount() 56 { 57 return dropIndexCount; 58 } 59 60 public void incrementDropIndexCount() 61 { 62 this.dropIndexCount++; 63 } 64 65 public int getCreateIndexCount() 66 { 67 return createIndexCount; 68 } 69 70 public void incrementCreateIndexCount() 71 { 72 createIndexCount++; 73 } 74 75 public int getAlterCount() 76 { 77 return alterCount; 78 } 79 80 public void incrementAlterCount() 81 { 82 this.alterCount++; 83 } 84 85 public int getCreateCount() 86 { 87 return createCount; 88 } 89 90 public void incrementCreateCount() 91 { 92 this.createCount++; 93 } 94 95 public int getMergeCount() 96 { 97 return mergeCount; 98 } 99 100 public void incrementMergeCount() 101 { 102 this.mergeCount++; 103 } 104 105 public int getDropCount() 106 { 107 return dropCount; 108 } 109 110 public void incrementDropCount() 111 { 112 dropCount++; 113 } 114 115 public void setDropCount(int dropCount) 116 { 117 this.dropCount = dropCount; 118 } 119 120 public int getSelectCount() 121 { 122 return selectCount; 123 } 124 125 public void incrementSelectCount() 126 { 127 selectCount++; 128 } 129 130 public void setSelectCount(int selectCount) 131 { 132 this.selectCount = selectCount; 133 } 134 135 public int getUpdateCount() 136 { 137 return updateCount; 138 } 139 140 public void incrementUpdateCount() 141 { 142 updateCount++; 143 } 144 145 public void setUpdateCount(int updateCount) 146 { 147 this.updateCount = updateCount; 148 } 149 150 public int getDeleteCount() 151 { 152 return deleteCount; 153 } 154 155 public void incrementDeleteCount() 156 { 157 this.deleteCount++; 158 } 159 160 public void setDeleteCount(int deleteCount) 161 { 162 this.deleteCount = deleteCount; 163 } 164 165 public void incrementInsertCount() 166 { 167 this.insertCount++; 168 } 169 170 public int getInsertCount() 171 { 172 return insertCount; 173 } 174 175 public void setInsertCount(int insertCount) 176 { 177 this.insertCount = insertCount; 178 } 179 180 override public string toString() 181 { 182 StringBuilder buf = new StringBuilder(4); 183 if (mergeCount > 0) 184 { 185 buf.append("Merge"); 186 } 187 if (insertCount > 0) 188 { 189 buf.append("Insert"); 190 } 191 if (updateCount > 0) 192 { 193 buf.append("Update"); 194 } 195 if (selectCount > 0) 196 { 197 buf.append("Select"); 198 } 199 if (deleteCount > 0) 200 { 201 buf.append("Delete"); 202 } 203 if (dropCount > 0) 204 { 205 buf.append("Drop"); 206 } 207 if (createCount > 0) 208 { 209 buf.append("Create"); 210 } 211 if (alterCount > 0) 212 { 213 buf.append("Alter"); 214 } 215 if (createIndexCount > 0) 216 { 217 buf.append("CreateIndex"); 218 } 219 if (dropIndexCount > 0) 220 { 221 buf.append("DropIndex"); 222 } 223 224 return buf.toString(); 225 } 226 227 public static class Name 228 { 229 private string name; 230 private long _hashCode64; 231 232 public this(string name) 233 { 234 this(name, FnvHash.hashCode64(name)); 235 } 236 237 public this(string name, long _hashCode64) 238 { 239 this.name = name; 240 this._hashCode64 = _hashCode64; 241 } 242 243 public string getName() 244 { 245 return this.name; 246 } 247 248 override public size_t toHash() @trusted nothrow 249 { 250 try{ 251 long value = hashCode64(); 252 return cast(size_t)(value ^ (value >>> 32)); 253 } 254 catch(Exception e){} 255 return 0; 256 } 257 258 public long hashCode64() 259 { 260 return _hashCode64; 261 } 262 263 override public bool opEquals(Object o) 264 { 265 if (!(cast(Name)(o) !is null)) 266 { 267 return false; 268 } 269 270 Name other = cast(Name) o; 271 return this._hashCode64 == other._hashCode64; 272 } 273 274 override public string toString() 275 { 276 return SQLUtils.normalize(this.name); 277 } 278 } 279 280 public static class Relationship 281 { 282 private Column left; 283 private Column right; 284 private string operator; 285 286 public this(Column left, Column right, string operator) 287 { 288 this.left = left; 289 this.right = right; 290 this.operator = operator; 291 } 292 293 public Column getLeft() 294 { 295 return left; 296 } 297 298 public Column getRight() 299 { 300 return right; 301 } 302 303 public string getOperator() 304 { 305 return operator; 306 } 307 308 override public size_t toHash() @trusted nothrow 309 { 310 int prime = 31; 311 size_t result = 1; 312 result = prime * result + ((left is null) ? 0 : (cast(Object)left).toHash()); 313 result = prime * result + ((operator is null) ? 0 : hashOf(operator)); 314 result = prime * result + ((right is null) ? 0 : (cast(Object)right).toHash()); 315 return result; 316 } 317 318 override public bool opEquals(Object obj) 319 { 320 if (this == obj) 321 { 322 return true; 323 } 324 if (obj is null) 325 { 326 return false; 327 } 328 if (typeid(this) != typeid(obj)) 329 { 330 return false; 331 } 332 Relationship other = cast(Relationship) obj; 333 if (left is null) 334 { 335 if (other.left !is null) 336 { 337 return false; 338 } 339 } 340 else if (!(cast(Object)(left)).opEquals(cast(Object)(other.left))) 341 { 342 return false; 343 } 344 if (operator is null) 345 { 346 if (other.operator !is null) 347 { 348 return false; 349 } 350 } 351 else if (!(operator == other.operator)) 352 { 353 return false; 354 } 355 if (right is null) 356 { 357 if (other.right !is null) 358 { 359 return false; 360 } 361 } 362 else if (!(cast(Object)(right)).opEquals(cast(Object)(other.right))) 363 { 364 return false; 365 } 366 return true; 367 } 368 369 override public string toString() 370 { 371 return left.toString ~ " " ~ operator ~ " " ~ right.toString; 372 } 373 374 } 375 376 public static class Condition 377 { 378 379 private Column column; 380 private string operator; 381 private List!(Object) values; 382 383 this() 384 { 385 values = new ArrayList!(Object)(); 386 } 387 388 public this(Column column, string operator) 389 { 390 this(); 391 this.column = column; 392 this.operator = operator; 393 } 394 395 public Column getColumn() 396 { 397 return column; 398 } 399 400 public string getOperator() 401 { 402 return operator; 403 } 404 405 public List!(Object) getValues() 406 { 407 return values; 408 } 409 410 public void addValue(Object value) 411 { 412 this.values.add(value); 413 } 414 415 override public size_t toHash() @trusted nothrow 416 { 417 int prime = 31; 418 size_t result = 1; 419 result = prime * result + ((column is null) ? 0 : (cast(Object)column).toHash()); 420 result = prime * result + ((operator is null) ? 0 : hashOf(operator)); 421 return result; 422 } 423 424 override public bool opEquals(Object obj) 425 { 426 if (this == obj) 427 { 428 return true; 429 } 430 if (obj is null) 431 { 432 return false; 433 } 434 if (typeid(this) != typeid(obj)) 435 { 436 return false; 437 } 438 Condition other = cast(Condition) obj; 439 if (column is null) 440 { 441 if (other.column !is null) 442 { 443 return false; 444 } 445 } 446 else if (!(cast(Object)(column)).opEquals(cast(Object)(other.column))) 447 { 448 return false; 449 } 450 if (operator is null) 451 { 452 if (other.operator !is null) 453 { 454 return false; 455 } 456 } 457 else if (!(operator == other.operator)) 458 { 459 return false; 460 } 461 return true; 462 } 463 464 override public string toString() 465 { 466 StringBuilder buf = new StringBuilder(); 467 buf.append((cast(Object)(this.column)).toString()); 468 buf.append(' '); 469 buf.append(this.operator); 470 471 if (values.size() == 1) 472 { 473 buf.append(' '); 474 buf.append(String.valueOf(this.values.get(0))); 475 } 476 else if (values.size() > 0) 477 { 478 buf.append(" ("); 479 for (int i = 0; i < values.size(); ++i) 480 { 481 if (i != 0) 482 { 483 buf.append(", "); 484 } 485 Object val = values.get(i); 486 if (cast(String)(val) !is null) 487 { 488 string jsonStr = toJson(val).toString; 489 buf.append(jsonStr); 490 } 491 else 492 { 493 buf.append(String.valueOf(val)); 494 } 495 } 496 buf.append(")"); 497 } 498 499 return buf.toString(); 500 } 501 } 502 503 public static class Column 504 { 505 506 private string table; 507 private string name; 508 protected long _hashCode64; 509 510 private bool where; 511 private bool select; 512 private bool groupBy; 513 private bool having; 514 private bool join; 515 516 private bool primaryKey; // for ddl 517 private bool unique; // 518 519 private Map!(string, Object) attributes; 520 521 private string fullName; 522 523 /** 524 * @since 1.0.20 525 */ 526 private string dataType; 527 528 this() 529 { 530 attributes = new HashMap!(string, Object)(); 531 } 532 533 public this(string table, string name) 534 { 535 this(); 536 this.table = table; 537 this.name = name; 538 539 int p = cast(int)(table.indexOf('.')); 540 if (p != - 1) 541 { 542 string dbType = null; 543 if (table.indexOf('`') != - 1) 544 { 545 dbType = DBType.MYSQL.name; 546 } 547 else if (table.indexOf('[') != - 1) 548 { 549 dbType = DBType.SQL_SERVER.name; 550 } 551 else if (table.indexOf('@') != - 1) 552 { 553 dbType = DBType.ORACLE.name; 554 } 555 SQLExpr owner = SQLUtils.toSQLExpr(table, dbType); 556 _hashCode64 = new SQLPropertyExpr(owner, name).hashCode64(); 557 } 558 else 559 { 560 _hashCode64 = FnvHash.hashCode64(table, name); 561 } 562 } 563 564 public this(string table, string name, long _hashCode64) 565 { 566 this(); 567 this.table = table; 568 this.name = name; 569 this._hashCode64 = _hashCode64; 570 } 571 572 public string getTable() 573 { 574 return table; 575 } 576 577 public string getFullName() 578 { 579 if (fullName is null) 580 { 581 if (table is null) 582 { 583 fullName = name; 584 } 585 else 586 { 587 fullName = table ~ '.' ~ name; 588 } 589 } 590 591 return fullName; 592 } 593 594 public long hashCode64() 595 { 596 return _hashCode64; 597 } 598 599 public bool isWhere() 600 { 601 return where; 602 } 603 604 public void setWhere(bool where) 605 { 606 this.where = where; 607 } 608 609 public bool isSelect() 610 { 611 return select; 612 } 613 614 public void setSelec(bool select) 615 { 616 this.select = select; 617 } 618 619 public bool isGroupBy() 620 { 621 return groupBy; 622 } 623 624 public void setGroupBy(bool groupBy) 625 { 626 this.groupBy = groupBy; 627 } 628 629 public bool isHaving() 630 { 631 return having; 632 } 633 634 public bool isJoin() 635 { 636 return join; 637 } 638 639 public void setJoin(bool join) 640 { 641 this.join = join; 642 } 643 644 public void setHaving(bool having) 645 { 646 this.having = having; 647 } 648 649 public bool isPrimaryKey() 650 { 651 return primaryKey; 652 } 653 654 public void setPrimaryKey(bool primaryKey) 655 { 656 this.primaryKey = primaryKey; 657 } 658 659 public bool isUnique() 660 { 661 return unique; 662 } 663 664 public void setUnique(bool unique) 665 { 666 this.unique = unique; 667 } 668 669 public string getName() 670 { 671 return name; 672 } 673 674 /** 675 * @since 1.0.20 676 */ 677 public string getDataType() 678 { 679 return dataType; 680 } 681 682 /** 683 * @since 1.0.20 684 */ 685 public void setDataType(string dataType) 686 { 687 this.dataType = dataType; 688 } 689 690 public Map!(string, Object) getAttributes() 691 { 692 return attributes; 693 } 694 695 public void setAttributes(Map!(string, Object) attributes) 696 { 697 this.attributes = attributes; 698 } 699 700 override public size_t toHash() @trusted nothrow 701 { 702 try{ 703 long hash = hashCode64(); 704 return cast(size_t)(hash ^ (hash >>> 32)); 705 }catch(Exception e){} 706 return 0; 707 } 708 709 override public string toString() 710 { 711 if (table !is null) 712 { 713 return SQLUtils.normalize(table) ~ "." ~ SQLUtils.normalize(name); 714 } 715 716 return SQLUtils.normalize(name); 717 } 718 719 override public bool opEquals(Object obj) 720 { 721 if (!( cast(Column)obj !is null )) 722 { 723 return false; 724 } 725 726 Column column = cast(Column) obj; 727 return _hashCode64 == column._hashCode64; 728 } 729 } 730 731 public static class Mode 732 { 733 __gshared Mode Insert; 734 __gshared Mode Update; 735 __gshared Mode Delete; 736 __gshared Mode Select; 737 __gshared Mode Merge; 738 __gshared Mode Truncate; 739 __gshared Mode Alter; 740 __gshared Mode Drop; 741 __gshared Mode DropIndex; 742 __gshared Mode CreateIndex; 743 __gshared Mode Replace; 744 745 shared static this() { 746 Insert = new Mode(1); // 747 Update = new Mode(2); // 748 Delete = new Mode(4); // 749 Select = new Mode(8); // 750 Merge = new Mode(16); // 751 Truncate = new Mode(32); 752 Alter = new Mode(64); // 753 Drop = new Mode(128); // 754 DropIndex = new Mode(256); 755 CreateIndex = new Mode(512); 756 Replace = new Mode(1024); 757 } 758 759 760 public int mark; 761 762 private this(int mark) 763 { 764 this.mark = mark; 765 } 766 767 bool opEquals(const Mode h) nothrow 768 { 769 return mark == h.mark; 770 } 771 772 bool opEquals(ref const Mode h) nothrow 773 { 774 return mark == h.mark; 775 } 776 } 777 }