| 1 33 34 package com.sqlmagic.tinysql; 35 36 import java.util.*; 37 import java.lang.*; 38 import java.io.*; 39 import java.sql.SQLException ; 40 import java.sql.Types ; 41 42 51 public abstract class tinySQL { 52 53 boolean debug=false,groupBreak=true,keepRecord=true; 54 boolean exDebug=false,performDebug=false; 55 Hashtable groupFunctions; 56 String newLine = System.getProperty("line.separator"); 57 String zeroCount=(String )null; 58 static tinySQLTable insertTable=(tinySQLTable)null; 59 tinySQLWhere wc; 60 private InputStream SQLStream; 63 64 private tinySQLStatement sqlstatement = null; 68 73 public tinySQL() { 74 75 } 76 77 84 public tsResultSet sqlexec() throws tinySQLException { 85 86 SQLStream = (InputStream) System.in; 87 System.err.println("Reading SQL Statements from STDIN..."); 88 System.err.println("CRASHING AFTER THIS POINT IS SURE..."); 89 System.err.println("Have no Statement, no connection and no clue how to continue ..."); 90 return sql(null); 91 92 } 93 94 101 public tsResultSet sqlexec(tinySQLStatement s) throws tinySQLException 102 { 103 return sql(s); 104 } 105 public tsResultSet sqlexec(tinySQLPreparedStatement s) 106 throws tinySQLException 107 { 108 return sql(s); 109 } 110 111 121 protected tsResultSet sql(Object s) throws tinySQLException 122 { 123 126 tsResultSet rs = null; 127 tinySQLTable jtbl; 128 tinySQLPreparedStatement pstmt=(tinySQLPreparedStatement)null; 129 boolean useTinyParser = true; 130 Vector actions,columns,columnDefs,values,columnContexts,columnAliases, 131 tbls; 132 String actionType,orderType,tableName,statementType,byteString; 133 Hashtable h; 134 byte[] bStream; 135 ByteArrayInputStream st; 136 int i; 137 String actionString; 138 groupBreak=true; 139 keepRecord=true; 140 zeroCount = (String )null; 141 statementType = s.getClass().getName(); 142 try 143 { 144 149 actions = (Vector)null; 150 if ( statementType.endsWith("tinySQLPreparedStatement") ) 151 { 152 pstmt = (tinySQLPreparedStatement)s; 153 pstmt.updateActions(actions); 154 actions = pstmt.getActions(); 155 byteString = pstmt.getSQLString(); 156 bStream = (byte[])null; 157 if ( pstmt.getSQLString() != (String )null ) 158 bStream = pstmt.getSQLString().getBytes(); 159 } else if ( statementType.endsWith("tinySQLStatement") ) { 160 bStream = ((tinySQLStatement)s).getSQLString().getBytes(); 161 } else { 162 throw new tinySQLException("Unknown statement type" 163 + statementType); 164 } 165 if ( actions == (Vector)null ) 166 { 167 st = new ByteArrayInputStream(bStream); 168 SQLStream = (InputStream) st; 169 tinySQLParser tinyp = new tinySQLParser(SQLStream); 170 actions = tinyp.getActions(); 171 if ( statementType.endsWith("tinySQLPreparedStatement") ) 172 pstmt.updateActions(actions); 173 } 174 212 for (i = 0; i < actions.size(); i++) 213 { 214 h = (Hashtable)actions.elementAt(i); 215 actionType = (String )h.get("TYPE"); 216 220 tableName = (String ) h.get("TABLE"); 221 wc = (tinySQLWhere) h.get("WHERE"); 222 if ( tableName != (String )null & !actionType.equals("DROP_TABLE") & 223 !actionType.equals("CREATE_TABLE") & !actionType.equals("INSERT") ) 224 { 225 jtbl = getTable(tableName); 226 231 if ( statementType.endsWith("tinySQLPreparedStatement") ) 232 pstmt.addTable(jtbl); 233 if ( wc != (tinySQLWhere)null ) wc.setColumnTypes(jtbl); 234 } 235 actionString = UtilString.actionToString(h); 236 if ( debug ) System.out.println("ACTION: " + actionString); 237 if ( actionType.equals("UPDATE") ) 238 { 239 242 columns = (Vector) h.get("COLUMNS"); 243 values = (Vector) h.get("VALUES"); 244 UpdateStatement (tableName, columns, values, wc); 245 } else if ( actionType.equals("DELETE") ) { 246 249 DeleteStatement (tableName, wc); 250 } else if ( actionType.equals("SELECT") ) { 251 254 tbls = (Vector) h.get("TABLES"); 255 columns = (Vector) h.get("COLUMNS"); 256 columnContexts = (Vector) h.get("CONTEXT"); 257 columnAliases = (Vector) h.get("COLUMN_ALIASES"); 258 orderType = (String )h.get("ORDER_TYPE"); 259 rs = SelectStatement(tbls,columns,columnContexts, 260 columnAliases,wc,orderType,s); 261 } else if ( actionType.equals("INSERT") ) { 262 265 columns = (Vector) h.get("COLUMNS"); 266 values = (Vector) h.get("VALUES"); 267 InsertStatement (statementType, tableName, columns, values); 268 } else if ( actionType.equals("CREATE_TABLE") ) { 269 279 columnDefs = (Vector) h.get("COLUMN_DEF"); 280 CreateTable (tableName, columnDefs); 281 } else if ( actionType.equals("ALTER_ADD") ) { 282 285 columnDefs = (Vector) h.get("COLUMN_DEF"); 286 AlterTableAddCol (tableName, columnDefs); 287 } else if ( actionType.equals("ALTER_DROP") ) { 288 291 columns = (Vector) h.get("COLUMNS"); 292 AlterTableDropCol (tableName, columns); 293 } else if ( actionType.equals("ALTER_RENAME") ) { 294 297 String oldColname = (String ) h.get("OLD_COLUMN"); 298 String newColname = (String ) h.get("NEW_COLUMN"); 299 AlterTableRenameCol(tableName, oldColname, newColname); 300 } else if ( actionType.equals("DROP_TABLE") ) { 301 304 DropTable( tableName ); 305 } else { 306 System.out.println("Unrecognized action " + actionType); 307 } 308 } 309 } catch (Exception e) { 310 if ( exDebug ) e.printStackTrace(System.out); 311 throw new tinySQLException(e.getMessage()); 312 } 313 return rs; 314 } 315 318 protected tsResultSet SelectStatement (Vector t,Vector c,Vector x, 319 Vector a, tinySQLWhere w,String ot,Object stmt) throws tinySQLException 320 { 321 Hashtable tables,columns; 322 Vector groupByColumns,orderByColumns; 323 String tableName,tableAlias,columnList,selectColumn, 324 columnName,functionName,upperColumn,columnContext,functionArgs, 325 columnAlias; 326 StringBuffer functionBuffer; 327 FieldTokenizer ft,ftArgs; 328 tsResultSet jrs; 329 tsColumn columnObject,testCol; 330 Vector cols,groupFunction; 331 int i,j,insertAt,rowCount,foundDot,columnSize,columnType; 332 int[] rowCounts; 333 tinySQLTable jtbl; 334 Enumeration col_keys; 335 338 jrs = new tsResultSet(t, c, w, this); 339 groupFunctions = new Hashtable(); 340 groupByColumns = new Vector(); 341 orderByColumns = new Vector(); 342 try 343 { 344 jrs.setFetchSize(((tinySQLStatement)stmt).getFetchSize()); 345 jrs.setType(((tinySQLStatement)stmt).getResultSetType()); 346 } catch (SQLException sqle) { 347 Utils.log ("Caught SQLException while setting Fetchsize and ResultSetType"); 348 Utils.log (" This event is (should be) impossible!"); 349 } 350 355 tables = new Hashtable(); 356 tables.put("TABLE_SELECT_ORDER",t); 357 rowCounts = new int[t.size()]; 358 for (i = 0; i < t.size(); i++) 359 { 360 tableName = (String )t.elementAt(i); 361 jtbl = getTable(tableName); 362 tables.put(tableName,jtbl); 363 jtbl.GoTop(); 364 368 rowCount = jtbl.GetRowCount(); 369 rowCounts[i] = rowCount; 370 if ( i == 0 ) continue; 371 insertAt = 0; 372 for ( j = i - 1; j >= 0; j-- ) 373 { 374 if ( rowCounts[j] <= rowCounts[i] ) 375 { 376 insertAt = j + 1; 377 break; 378 } 379 } 380 if ( insertAt != i ) 381 { 382 385 rowCount = rowCounts[insertAt]; 386 rowCounts[insertAt] = rowCounts[i]; 387 rowCounts[i] = rowCount; 388 t.removeElementAt(i); 389 t.insertElementAt(tableName,insertAt); 390 } 391 if ( debug | performDebug ) 392 { 393 System.out.println("Table selection order"); 394 for ( j = 0; j <= i; j++ ) 395 System.out.println(t.elementAt(j) + " " + rowCounts[j]); 396 } 397 } 398 if ( w != (tinySQLWhere)null ) w.setColumnTypes(tables); 399 402 for (i = 0; i < c.size(); i++) 403 { 404 columnName = (String )c.elementAt(i); 405 columnContext = (String )x.elementAt(i); 406 if ( !columnName.equals("*") ) continue; 407 412 for ( j = 0; j < c.size(); j++ ) 413 { 414 columnContext = (String )x.elementAt(j); 415 if ( columnContext.equals("SELECT") ) 416 { 417 c.removeElementAt(j); 418 x.removeElementAt(j); 419 a.removeElementAt(j); 420 } 421 } 422 for ( j = 0; j < t.size(); j++ ) 423 { 424 jtbl = (tinySQLTable)tables.get((String )t.elementAt(j)); 425 col_keys = jtbl.column_info.keys(); 426 429 while (col_keys.hasMoreElements()) 430 { 431 columnName = (String )col_keys.nextElement(); 432 c.addElement(jtbl.table + "->" + jtbl.tableAlias 433 + "." + columnName); 434 a.addElement(columnName); 435 x.addElement("SELECT"); 436 } 437 } 438 break; 439 } 440 443 for (i = 0; i < c.size(); i++) 444 { 445 columnName = (String )c.elementAt(i); 446 columnContext = (String )x.elementAt(i); 447 columnAlias = (String )null; 448 if ( i < a.size() ) 449 columnAlias = (String )a.elementAt(i); 450 columnObject = new tsColumn(columnName,tables); 451 columnObject.alias = UtilString.removeQuotes(columnAlias); 452 456 if ( columnContext.equals("GROUP") ) 457 { 458 groupByColumns.addElement(columnObject); 459 } else if ( columnContext.equals("ORDER") ) { 460 orderByColumns.addElement(columnObject); 461 } else { 462 jrs.addColumn (columnObject); 463 } 464 if ( debug ) System.out.println("Adding " + columnContext 465 + " column " + newLine + columnObject.toString() + newLine); 466 } 467 jrs.setState (1,tables,groupByColumns,orderByColumns,ot); 468 contSelectStatement (jrs); 469 return jrs; 470 } 471 476 protected void contSelectStatement (tsResultSet jrs) 477 throws tinySQLException 478 { 479 483 String columnName,columnString,whereStatus; 484 boolean addOK; 485 int i,rowCount; 486 int level = jrs.getLevel (); 487 tinySQLTable jtbl; 488 tsColumn updateColumn; 489 Hashtable tables = jrs.getTableState (); 490 Vector ob = jrs.getOrderByColumns(); 491 tinySQLWhere wc = jrs.getWhereClause(); 492 String orderType = jrs.getOrderType(); 493 497 Hashtable tbl_list = new Hashtable(); 498 Vector groupFunction; 499 Vector t = (Vector)tables.get("TABLE_SELECT_ORDER"); 500 String current = (String ) t.elementAt(0); 501 String firstColumn = "*"; 502 tbl_list.put( current, new Integer (1) ); 503 506 tsRow record = new tsRow(); 507 if ( ob.size() > 0 ) record.setOrderBy(ob); 508 Vector resultSet = new Vector(); 509 512 while ( level > 0 ) 513 { 514 boolean levelFound = false; 515 519 Enumeration keys = tbl_list.keys(); 520 while (keys.hasMoreElements()) 521 { 522 527 String hashkey = (String ) keys.nextElement(); 528 int currLevel = ((Integer ) tbl_list.get(hashkey)).intValue(); 529 534 if (currLevel == level) 535 { 536 current = hashkey; levelFound = true; break; 537 } 538 } 539 boolean eof = false; boolean haveRecord = false; 545 if (levelFound) 546 { 547 550 jtbl = (tinySQLTable) tables.get(current); 551 if ( performDebug ) System.out.println("Selecting records from " 552 + jtbl.table); 553 557 boolean found = false; 558 while (jtbl.NextRecord()) 559 { 560 if (!jtbl.isDeleted()) 561 { 562 567 Enumeration cols = jtbl.column_info.keys(); 568 found = true; 569 whereStatus = "TRUE"; 570 while (cols.hasMoreElements()) 571 { 572 columnName = jtbl.table + "->" + jtbl.tableAlias 573 + "." + (String )cols.nextElement(); 574 columnString = jtbl.GetCol(columnName); 575 if ( wc != (tinySQLWhere)null ) 576 { 577 whereStatus = wc.evaluate(columnName,columnString); 578 if ( whereStatus.equals("FALSE") ) 579 { 580 584 wc.clearValues(jtbl.table + "->" + jtbl.tableAlias); 585 found = false; 586 break; 587 } 588 } 589 592 jrs.updateColumns(columnName,columnString); 593 } 594 if ( found ) break; 595 } 596 } 597 if (found) 598 { 599 for ( i = 0; i < jrs.numcols(); i++ ) 600 { 601 updateColumn = jrs.columnAtIndex(i); 602 columnString = updateColumn.getString(); 603 if ( updateColumn.isNotNull ) 604 record.put(updateColumn.name,columnString); 605 else 606 record.remove(updateColumn.name); 607 } 608 if ( performDebug ) 609 System.out.println("Record is " + record.toString()); 610 614 eof = false; 615 619 if (level < t.size()) 620 { 621 624 level++; 625 629 String next_tbl = (String ) t.elementAt( level - 1); 630 tbl_list.put( next_tbl, new Integer (level) ); 631 } else { 632 646 haveRecord = true; 647 } 648 } else { 649 654 if ( wc != (tinySQLWhere)null ) wc.clearValues(jtbl.table); 655 level--; 656 eof = true; 657 jtbl.GoTop(); 658 } 659 } else { 660 664 level--; 665 } 666 669 if (haveRecord) 670 { 671 676 if ( jrs.isGrouped() ) 677 { 678 if ( groupBreak ) 679 { 680 zeroCount = (String )null; 681 addOK = jrs.addRow((tsRow)record.clone(),orderType); 682 if (addOK == false) 683 { 684 jrs.setLevel (level); 685 return; 686 } 687 groupBreak = false; 688 } else { 689 jrs.updateRow( (tsRow) record.clone()); 690 } 691 } else { 692 695 addOK = jrs.addRow((tsRow)record.clone(),orderType); 696 if (addOK == false) 697 { 698 jrs.setLevel (level); 699 return; 700 } 701 } 702 firstColumn = "*"; 703 } 704 } 705 708 for ( i = 0; i < t.size(); i++ ) 709 { 710 jtbl = (tinySQLTable)tables.get((String )t.elementAt(i)); 711 jtbl.close(); 712 } 713 if ( zeroCount != (String )null ) 714 { 715 record.put(zeroCount,"0"); 716 addOK = jrs.addRow((tsRow)record.clone()); 717 zeroCount = (String )null; 718 } 719 722 jrs.setLevel (0); 723 } 724 727 private void DeleteStatement (String tableName, tinySQLWhere wc) 728 throws tinySQLException 729 { 730 tinySQLTable jtbl; 731 Hashtable tables; 732 String columnName,columnString,whereStatus; 733 Enumeration cols; 734 737 jtbl = getTable(tableName); 738 tables = new Hashtable(); 739 tables.put(tableName, jtbl); 740 743 jtbl.GoTop(); 744 while (jtbl.NextRecord()) 745 { 746 if (!jtbl.isDeleted()) 747 { 748 cols = jtbl.column_info.keys(); 749 whereStatus = "TRUE"; 750 while (cols.hasMoreElements()) 751 { 752 columnName = jtbl.table + "->" + jtbl.tableAlias + "." 753 + (String )cols.nextElement(); 754 columnString = jtbl.GetCol(columnName); 755 758 if ( wc != (tinySQLWhere)null ) 759 whereStatus = wc.evaluate(columnName,columnString); 760 if ( whereStatus.equals("FALSE") ) break; 761 } 762 if ( whereStatus.equals("TRUE") ) jtbl.DeleteRow(); 763 if ( wc != (tinySQLWhere)null ) 764 wc.clearValues(jtbl.table + "->" + jtbl.tableAlias); 765 } 766 } 767 jtbl.close(); 768 } 769 772 private void UpdateStatement(String tableName, Vector c, Vector v, tinySQLWhere wc) 773 throws tinySQLException 774 { 775 778 tinySQLTable jtbl = getTable(tableName); 779 Hashtable tables = new Hashtable(); 780 tables.put(tableName, jtbl); 781 String columnName,columnString,whereStatus; 782 785 jtbl.GoTop(); 786 while (jtbl.NextRecord()) 787 { 788 if (!jtbl.isDeleted()) 789 { 790 Enumeration cols = jtbl.column_info.keys(); 791 whereStatus = "TRUE"; 792 while (cols.hasMoreElements()) 793 { 794 797 columnName = jtbl.table + "->" + jtbl.table 798 + "." + (String ) cols.nextElement(); 799 columnString = jtbl.GetCol(columnName); 800 803 if ( wc != (tinySQLWhere)null ) 804 whereStatus = wc.evaluate(columnName,columnString); 805 if ( whereStatus.equals("FALSE") ) break; 806 } 807 if ( whereStatus.equals("TRUE") ) jtbl.UpdateCurrentRow(c, v); 808 if ( wc != (tinySQLWhere)null ) 809 wc.clearValues(jtbl.table + "->" + jtbl.tableAlias); 810 } 811 } 812 jtbl.close(); 813 } 814 818 private void InsertStatement (String statementType, String tableName, 819 Vector c, Vector v) 820 throws tinySQLException 821 { 822 String columnName,valueString; 823 int i,columnType,columnSize; 824 tinySQLTable jtbl=(tinySQLTable)null; 825 double value; 826 insertTable = getTable(tableName); 827 830 for ( i = 0; i < c.size(); i++ ) 831 { 832 columnName = (String )c.elementAt(i); 833 valueString = (String )v.elementAt(i); 834 if ( valueString == (String )null ) continue; 835 valueString = UtilString.removeQuotes(valueString); 836 valueString = UtilString.replaceAll(valueString,"''","'"); 837 columnType = insertTable.ColType(columnName); 838 if ( Utils.isNumberColumn(columnType) ) 839 { 840 try 841 { 842 value = Double.parseDouble(valueString); 843 } catch (Exception e) { 844 throw new tinySQLException("Insert failed: column " 845 + columnName + " is numeric - found " + valueString); 846 } 847 } 848 columnSize = insertTable.ColSize(columnName); 849 if ( valueString.length() > columnSize ) 850 { 851 throw new tinySQLException("Insert failed: string too long for " 852 + " column " + columnName + " " 853 + Integer.toString(valueString.length()) 854 + " > " + Integer.toString(columnSize) + "<" + valueString +">"); 855 } 856 } 857 insertTable.InsertRow(c, v); 858 863 if ( !statementType.endsWith("tinySQLPreparedStatement") ) 864 insertTable.close(); 865 } 866 872 abstract void CreateTable (String tableName, Vector v) 873 throws IOException, tinySQLException; 874 880 abstract void AlterTableAddCol (String tableName, Vector v) 881 throws IOException, tinySQLException; 882 883 889 abstract void AlterTableDropCol (String tableName, Vector v) 890 throws IOException, tinySQLException; 891 896 void AlterTableRenameCol (String tableName, String oldColname, String newColname) 897 throws IOException, tinySQLException 898 { 899 throw new tinySQLException("ALTER TABLE RENAME '" + oldColname + " TO " + newColname + "' is not supported"); 900 } 901 904 abstract void DropTable (String tableName) throws tinySQLException; 905 908 abstract tinySQLTable getTable(String tableName) throws tinySQLException; 909 910 } 911 | Popular Tags |