1 19 package com.mysql.jdbc; 20 21 import java.io.UnsupportedEncodingException ; 22 23 import java.math.BigDecimal ; 24 25 import java.sql.SQLException ; 26 27 import java.util.ArrayList ; 28 import java.util.HashMap ; 29 import java.util.List ; 30 31 32 37 public class UpdatableResultSet extends ResultSet { 38 39 private final static byte[] STREAM_DATA_MARKER = "** STREAM DATA **" 40 .getBytes(); 41 42 43 private List primaryKeyIndicies = null; 44 45 46 private com.mysql.jdbc.PreparedStatement deleter = null; 47 48 49 private com.mysql.jdbc.PreparedStatement inserter = null; 50 51 52 private com.mysql.jdbc.PreparedStatement refresher; 53 54 55 private com.mysql.jdbc.PreparedStatement updater = null; 56 private SingleByteCharsetConverter charConverter; 57 private String charEncoding; 58 private String deleteSQL = null; 59 private String insertSQL = null; 60 private String quotedIdChar = null; 61 private String refreshSQL = null; 62 private String tableName; 63 64 65 private String updateSQL = null; 66 67 68 private byte[][] defaultColumnValue; 69 70 71 private byte[][] savedCurrentRow; 72 73 74 private boolean isUpdatable = false; 75 76 82 public UpdatableResultSet(long updateCount, long updateID) { 83 super(updateCount, updateID); 84 } 85 86 92 104 public UpdatableResultSet(String catalog, Field[] fields, RowData rows, 105 com.mysql.jdbc.Connection conn) throws SQLException { 106 super(catalog, fields, rows, conn); 107 isUpdatable = checkUpdatability(); 108 } 109 110 118 public UpdatableResultSet(Field[] fields, RowData rows) 119 throws SQLException { 120 super(fields, rows); 121 isUpdatable = checkUpdatability(); 122 } 123 124 136 public synchronized boolean isAfterLast() throws SQLException { 137 return super.isAfterLast(); 138 } 139 140 152 public synchronized boolean isBeforeFirst() throws SQLException { 153 return super.isBeforeFirst(); 154 } 155 156 164 public int getConcurrency() throws SQLException { 165 return (isUpdatable ? CONCUR_UPDATABLE : CONCUR_READ_ONLY); 166 } 167 168 179 public synchronized boolean isFirst() throws SQLException { 180 return super.isFirst(); 181 } 182 183 197 public synchronized boolean isLast() throws SQLException { 198 return super.isLast(); 199 } 200 201 239 public synchronized boolean absolute(int row) throws SQLException { 240 return super.absolute(row); 241 } 242 243 254 public synchronized void afterLast() throws SQLException { 255 super.afterLast(); 256 } 257 258 269 public synchronized void beforeFirst() throws SQLException { 270 super.beforeFirst(); 271 } 272 273 282 public synchronized void cancelRowUpdates() throws SQLException { 283 if (doingUpdates) { 284 doingUpdates = false; 285 updater.clearParameters(); 286 } 287 } 288 289 295 public synchronized void clearWarnings() throws java.sql.SQLException { 296 warningChain = null; 297 } 298 299 315 public synchronized void close() throws java.sql.SQLException { 316 super.close(); 317 } 318 319 328 public synchronized void deleteRow() throws SQLException { 329 if (!isUpdatable) { 330 throw new NotUpdatable(); 331 } 332 333 if (onInsertRow) { 334 throw new SQLException ( 335 "Can not call deleteRow() when on insert row"); 336 } else if (rowData.size() == 0) { 337 throw new SQLException ("Can't deleteRow() on empty result set"); 338 } else if (isBeforeFirst()) { 339 throw new SQLException ( 340 "Before start of result set. Can not call deleteRow()."); 341 } else if (isAfterLast()) { 342 throw new SQLException ( 343 "After end of result set. Can not call deleteRow()."); 344 } 345 346 if (deleter == null) { 347 if (deleteSQL == null) { 348 generateStatements(); 349 } 350 351 deleter = (com.mysql.jdbc.PreparedStatement) connection 352 .prepareStatement(deleteSQL); 353 354 if (deleter.getMaxRows() != 0) { 355 deleter.setMaxRows(0); 356 } 357 } 358 359 deleter.clearParameters(); 360 361 String characterEncoding = null; 362 363 if (connection.useUnicode()) { 364 characterEncoding = connection.getEncoding(); 365 } 366 367 try { 371 int numKeys = primaryKeyIndicies.size(); 372 373 if (numKeys == 1) { 374 int index = ((Integer ) primaryKeyIndicies.get(0)).intValue(); 375 String currentVal = ((characterEncoding == null) 376 ? new String (thisRow[index]) 377 : new String (thisRow[index], characterEncoding)); 378 deleter.setString(1, currentVal); 379 } else { 380 for (int i = 0; i < numKeys; i++) { 381 int index = ((Integer ) primaryKeyIndicies.get(i)).intValue(); 382 String currentVal = ((characterEncoding == null) 383 ? new String (thisRow[index]) 384 : new String (thisRow[index], characterEncoding)); 385 deleter.setString(i + 1, currentVal); 386 } 387 } 388 389 deleter.executeUpdate(); 390 rowData.removeRow(rowData.getCurrentRowNumber()); 391 } catch (java.io.UnsupportedEncodingException encodingEx) { 392 throw new SQLException ("Unsupported character encoding '" 393 + connection.getEncoding() + "'"); 394 } 395 } 396 397 409 public synchronized boolean first() throws SQLException { 410 return super.first(); 411 } 412 413 421 public synchronized void insertRow() throws SQLException { 422 if (!onInsertRow) { 423 throw new SQLException ("Not on insert row"); 424 } else { 425 inserter.executeUpdate(); 426 427 int numPrimaryKeys = 0; 428 429 if (primaryKeyIndicies != null) { 430 numPrimaryKeys = primaryKeyIndicies.size(); 431 } 432 433 long autoIncrementId = inserter.getLastInsertID(); 434 int numFields = fields.length; 435 byte[][] newRow = new byte[numFields][]; 436 437 for (int i = 0; i < numFields; i++) { 438 if (inserter.isNull(i)) { 439 newRow[i] = null; 440 } else { 441 newRow[i] = inserter.getBytes(i); 442 } 443 444 if ((numPrimaryKeys == 1) && fields[i].isPrimaryKey() 445 && (autoIncrementId > 0)) { 446 newRow[i] = String.valueOf(autoIncrementId).getBytes(); 447 } 448 } 449 450 rowData.addRow(newRow); 451 resetInserter(); 452 } 453 } 454 455 467 public synchronized boolean last() throws SQLException { 468 return super.last(); 469 } 470 471 480 public synchronized void moveToCurrentRow() throws SQLException { 481 if (!isUpdatable) { 482 throw new NotUpdatable(); 483 } 484 485 if (this.onInsertRow) { 486 onInsertRow = false; 487 this.thisRow = this.savedCurrentRow; 488 } 489 } 490 491 507 public synchronized void moveToInsertRow() throws SQLException { 508 if (!this.isUpdatable) { 509 throw new NotUpdatable(); 510 } 511 512 if (this.inserter == null) { 513 generateStatements(); 514 this.inserter = (com.mysql.jdbc.PreparedStatement) connection 515 .prepareStatement(this.insertSQL); 516 517 if (this.inserter.getMaxRows() != 0) { 518 this.inserter.setMaxRows(0); 519 } 520 521 extractDefaultValues(); 522 resetInserter(); 523 } else { 524 resetInserter(); 525 } 526 527 int numFields = this.fields.length; 528 529 this.onInsertRow = true; 530 this.doingUpdates = false; 531 this.savedCurrentRow = this.thisRow; 532 this.thisRow = new byte[numFields][]; 533 534 for (int i = 0; i < numFields; i++) { 535 if (this.defaultColumnValue[i] != null) { 536 this.inserter.setBytes(i + 1, this.defaultColumnValue[i]); 537 538 byte[] defaultValueCopy = new byte[this.defaultColumnValue[i].length]; 541 System.arraycopy(defaultColumnValue[i], 0, defaultValueCopy, 0, defaultValueCopy.length); 542 this.thisRow[i] = defaultValueCopy; 543 } else { 544 this.inserter.setNull(i + 1, java.sql.Types.NULL); 545 this.thisRow[i] = null; 546 } 547 } 548 } 549 550 566 public synchronized boolean next() throws java.sql.SQLException { 567 return super.next(); 568 } 569 570 586 public synchronized boolean prev() throws java.sql.SQLException { 587 return super.prev(); 588 } 589 590 607 public synchronized boolean previous() throws SQLException { 608 return super.previous(); 609 } 610 611 629 public synchronized void refreshRow() throws SQLException { 630 if (!isUpdatable) { 631 throw new NotUpdatable(); 632 } 633 634 if (onInsertRow) { 635 throw new SQLException ( 636 "Can not call refreshRow() when on insert row"); 637 } else if (rowData.size() == 0) { 638 throw new SQLException ("Can't refreshRow() on empty result set"); 639 } else if (isBeforeFirst()) { 640 throw new SQLException ( 641 "Before start of result set. Can not call refreshRow()."); 642 } else if (isAfterLast()) { 643 throw new SQLException ( 644 "After end of result set. Can not call refreshRow()."); 645 } 646 647 if (refresher == null) { 648 if (refreshSQL == null) { 649 generateStatements(); 650 } 651 652 refresher = (com.mysql.jdbc.PreparedStatement) connection 653 .prepareStatement(refreshSQL); 654 655 if (refresher.getMaxRows() != 0) { 656 refresher.setMaxRows(0); 657 } 658 } 659 660 refresher.clearParameters(); 661 662 int numKeys = primaryKeyIndicies.size(); 663 664 if (numKeys == 1) { 665 byte[] dataFrom = null; 666 int index = ((Integer ) primaryKeyIndicies.get(0)).intValue(); 667 668 if (!doingUpdates) { 669 dataFrom = thisRow[index]; 670 } else { 671 dataFrom = updater.getBytes(index); 672 673 if (updater.isNull(index) || (dataFrom.length == 0)) { 675 dataFrom = thisRow[index]; 676 } 677 } 678 679 refresher.setBytesNoEscape(1, dataFrom); 680 } else { 681 for (int i = 0; i < numKeys; i++) { 682 byte[] dataFrom = null; 683 int index = ((Integer ) primaryKeyIndicies.get(i)).intValue(); 684 685 if (!doingUpdates) { 686 dataFrom = thisRow[index]; 687 } else { 688 dataFrom = updater.getBytes(index); 689 690 if (updater.isNull(index) || (dataFrom.length == 0)) { 692 dataFrom = thisRow[index]; 693 } 694 } 695 696 refresher.setBytesNoEscape(i + 1, dataFrom); 697 } 698 } 699 700 java.sql.ResultSet rs = null; 701 702 try { 703 rs = refresher.executeQuery(); 704 705 int numCols = rs.getMetaData().getColumnCount(); 706 707 if (rs.next()) { 708 for (int i = 0; i < numCols; i++) { 709 byte[] val = rs.getBytes(i + 1); 710 711 if ((val == null) || rs.wasNull()) { 712 thisRow[i] = null; 713 } else { 714 thisRow[i] = rs.getBytes(i + 1); 715 } 716 } 717 } else { 718 throw new SQLException ("refreshRow() called on row that has been deleted or had primary key changed", 719 SQLError.SQL_STATE_GENERAL_ERROR); 720 } 721 } finally { 722 if (rs != null) { 723 try { 724 rs.close(); 725 } catch (SQLException ex) { 726 ; } 728 } 729 } 730 } 731 732 756 public synchronized boolean relative(int rows) throws SQLException { 757 return super.relative(rows); 758 } 759 760 773 public synchronized boolean rowDeleted() throws SQLException { 774 throw new NotImplemented(); 775 } 776 777 789 public synchronized boolean rowInserted() throws SQLException { 790 throw new NotImplemented(); 791 } 792 793 797 809 public synchronized boolean rowUpdated() throws SQLException { 810 throw new NotImplemented(); 811 } 812 813 826 public synchronized void updateAsciiStream(int columnIndex, 827 java.io.InputStream x, int length) throws SQLException { 828 if (!onInsertRow) { 829 if (!doingUpdates) { 830 doingUpdates = true; 831 syncUpdate(); 832 } 833 834 updater.setAsciiStream(columnIndex, x, length); 835 } else { 836 inserter.setAsciiStream(columnIndex, x, length); 837 this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; 838 } 839 } 840 841 854 public synchronized void updateAsciiStream(String columnName, 855 java.io.InputStream x, int length) throws SQLException { 856 updateAsciiStream(findColumn(columnName), x, length); 857 } 858 859 871 public synchronized void updateBigDecimal(int columnIndex, BigDecimal x) 872 throws SQLException { 873 if (!onInsertRow) { 874 if (!doingUpdates) { 875 doingUpdates = true; 876 syncUpdate(); 877 } 878 879 updater.setBigDecimal(columnIndex, x); 880 } else { 881 inserter.setBigDecimal(columnIndex, x); 882 883 if (x == null) { 884 this.thisRow[columnIndex - 1] = null; 885 } else { 886 this.thisRow[columnIndex - 1] = x.toString().getBytes(); 887 } 888 } 889 } 890 891 903 public synchronized void updateBigDecimal(String columnName, BigDecimal x) 904 throws SQLException { 905 updateBigDecimal(findColumn(columnName), x); 906 } 907 908 921 public synchronized void updateBinaryStream(int columnIndex, 922 java.io.InputStream x, int length) throws SQLException { 923 if (!onInsertRow) { 924 if (!doingUpdates) { 925 doingUpdates = true; 926 syncUpdate(); 927 } 928 929 updater.setBinaryStream(columnIndex, x, length); 930 } else { 931 inserter.setBinaryStream(columnIndex, x, length); 932 933 if (x == null) { 934 this.thisRow[columnIndex - 1] = null; 935 } else { 936 this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; 937 } 938 } 939 } 940 941 954 public synchronized void updateBinaryStream(String columnName, 955 java.io.InputStream x, int length) throws SQLException { 956 updateBinaryStream(findColumn(columnName), x, length); 957 } 958 959 962 public void updateBlob(int columnIndex, java.sql.Blob blob) 963 throws SQLException { 964 if (!onInsertRow) { 965 if (!doingUpdates) { 966 doingUpdates = true; 967 syncUpdate(); 968 } 969 970 updater.setBlob(columnIndex, blob); 971 } else { 972 inserter.setBlob(columnIndex, blob); 973 974 if (blob == null) { 975 this.thisRow[columnIndex - 1] = null; 976 } else { 977 this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; 978 } 979 } 980 } 981 982 985 public void updateBlob(String columnName, java.sql.Blob blob) 986 throws SQLException { 987 updateBlob(findColumn(columnName), blob); 988 } 989 990 1002 public synchronized void updateBoolean(int columnIndex, boolean x) 1003 throws SQLException { 1004 if (!onInsertRow) { 1005 if (!doingUpdates) { 1006 doingUpdates = true; 1007 syncUpdate(); 1008 } 1009 1010 updater.setBoolean(columnIndex, x); 1011 } else { 1012 inserter.setBoolean(columnIndex, x); 1013 1014 this.thisRow[columnIndex - 1] = inserter.getBytes(1); 1015 } 1016 } 1017 1018 1030 public synchronized void updateBoolean(String columnName, boolean x) 1031 throws SQLException { 1032 updateBoolean(findColumn(columnName), x); 1033 } 1034 1035 1046 public synchronized void updateByte(int columnIndex, byte x) 1047 throws SQLException { 1048 if (!onInsertRow) { 1049 if (!doingUpdates) { 1050 doingUpdates = true; 1051 syncUpdate(); 1052 } 1053 1054 updater.setByte(columnIndex, x); 1055 } else { 1056 inserter.setByte(columnIndex, x); 1057 1058 this.thisRow[columnIndex - 1] = inserter.getBytes(columnIndex); 1059 } 1060 } 1061 1062 1073 public synchronized void updateByte(String columnName, byte x) 1074 throws SQLException { 1075 updateByte(findColumn(columnName), x); 1076 } 1077 1078 1090 public synchronized void updateBytes(int columnIndex, byte[] x) 1091 throws SQLException { 1092 if (!onInsertRow) { 1093 if (!doingUpdates) { 1094 doingUpdates = true; 1095 syncUpdate(); 1096 } 1097 1098 updater.setBytes(columnIndex, x); 1099 } else { 1100 inserter.setBytes(columnIndex, x); 1101 1102 this.thisRow[columnIndex - 1] = x; 1103 } 1104 } 1105 1106 1118 public synchronized void updateBytes(String columnName, byte[] x) 1119 throws SQLException { 1120 updateBytes(findColumn(columnName), x); 1121 } 1122 1123 1136 public synchronized void updateCharacterStream(int columnIndex, 1137 java.io.Reader x, int length) throws SQLException { 1138 if (!onInsertRow) { 1139 if (!doingUpdates) { 1140 doingUpdates = true; 1141 syncUpdate(); 1142 } 1143 1144 updater.setCharacterStream(columnIndex, x, length); 1145 } else { 1146 inserter.setCharacterStream(columnIndex, x, length); 1147 1148 if (x == null) { 1149 this.thisRow[columnIndex - 1] = null; 1150 } else { 1151 this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER; 1152 } 1153 } 1154 } 1155 1156 1169 public synchronized void updateCharacterStream(String columnName, 1170 java.io.Reader reader, int length) throws SQLException { 1171 updateCharacterStream(findColumn(columnName), reader, length); 1172 } 1173 1174 1177 public void updateClob(int columnIndex, java.sql.Clob clob) throws SQLException { 1178 if (clob == null) { 1179 updateNull(columnIndex); 1180 } else { 1181 updateCharacterStream(columnIndex, clob.getCharacterStream(), (int) clob.length()); 1182 } 1183 } 1184 1185 1196 public synchronized void updateDate(int columnIndex, java.sql.Date x) 1197 throws SQLException { 1198 if (!onInsertRow) { 1199 if (!doingUpdates) { 1200 doingUpdates = true; 1201 syncUpdate(); 1202 } 1203 1204 updater.setDate(columnIndex, x); 1205 } else { 1206 inserter.setDate(columnIndex, x); 1207 1208 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1209 - 1); 1210 } 1211 } 1212 1213 1224 public synchronized void updateDate(String columnName, java.sql.Date x) 1225 throws SQLException { 1226 updateDate(findColumn(columnName), x); 1227 } 1228 1229 1241 public synchronized void updateDouble(int columnIndex, double x) 1242 throws SQLException { 1243 if (!onInsertRow) { 1244 if (!doingUpdates) { 1245 doingUpdates = true; 1246 syncUpdate(); 1247 } 1248 1249 updater.setDouble(columnIndex, x); 1250 } else { 1251 inserter.setDouble(columnIndex, x); 1252 1253 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1254 - 1); 1255 } 1256 } 1257 1258 1270 public synchronized void updateDouble(String columnName, double x) 1271 throws SQLException { 1272 updateDouble(findColumn(columnName), x); 1273 } 1274 1275 1287 public synchronized void updateFloat(int columnIndex, float x) 1288 throws SQLException { 1289 if (!onInsertRow) { 1290 if (!doingUpdates) { 1291 doingUpdates = true; 1292 syncUpdate(); 1293 } 1294 1295 updater.setFloat(columnIndex, x); 1296 } else { 1297 inserter.setFloat(columnIndex, x); 1298 1299 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1300 - 1); 1301 } 1302 } 1303 1304 1316 public synchronized void updateFloat(String columnName, float x) 1317 throws SQLException { 1318 updateFloat(findColumn(columnName), x); 1319 } 1320 1321 1333 public synchronized void updateInt(int columnIndex, int x) 1334 throws SQLException { 1335 if (!onInsertRow) { 1336 if (!doingUpdates) { 1337 doingUpdates = true; 1338 syncUpdate(); 1339 } 1340 1341 updater.setInt(columnIndex, x); 1342 } else { 1343 inserter.setInt(columnIndex, x); 1344 1345 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1346 - 1); 1347 } 1348 } 1349 1350 1362 public synchronized void updateInt(String columnName, int x) 1363 throws SQLException { 1364 updateInt(findColumn(columnName), x); 1365 } 1366 1367 1378 public synchronized void updateLong(int columnIndex, long x) 1379 throws SQLException { 1380 if (!onInsertRow) { 1381 if (!doingUpdates) { 1382 doingUpdates = true; 1383 syncUpdate(); 1384 } 1385 1386 updater.setLong(columnIndex, x); 1387 } else { 1388 inserter.setLong(columnIndex, x); 1389 1390 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1391 - 1); 1392 } 1393 } 1394 1395 1406 public synchronized void updateLong(String columnName, long x) 1407 throws SQLException { 1408 updateLong(findColumn(columnName), x); 1409 } 1410 1411 1422 public synchronized void updateNull(int columnIndex) 1423 throws SQLException { 1424 if (!onInsertRow) { 1425 if (!doingUpdates) { 1426 doingUpdates = true; 1427 syncUpdate(); 1428 } 1429 1430 updater.setNull(columnIndex, 0); 1431 } else { 1432 inserter.setNull(columnIndex, 0); 1433 1434 this.thisRow[columnIndex - 1] = null; 1435 } 1436 } 1437 1438 1448 public synchronized void updateNull(String columnName) 1449 throws SQLException { 1450 updateNull(findColumn(columnName)); 1451 } 1452 1453 1468 public synchronized void updateObject(int columnIndex, Object x, int scale) 1469 throws SQLException { 1470 if (!onInsertRow) { 1471 if (!doingUpdates) { 1472 doingUpdates = true; 1473 syncUpdate(); 1474 } 1475 1476 updater.setObject(columnIndex, x); 1477 } else { 1478 inserter.setObject(columnIndex, x); 1479 1480 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1481 - 1); 1482 } 1483 } 1484 1485 1497 public synchronized void updateObject(int columnIndex, Object x) 1498 throws SQLException { 1499 if (!onInsertRow) { 1500 if (!doingUpdates) { 1501 doingUpdates = true; 1502 syncUpdate(); 1503 } 1504 1505 updater.setObject(columnIndex, x); 1506 } else { 1507 inserter.setObject(columnIndex, x); 1508 1509 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1510 - 1); 1511 } 1512 } 1513 1514 1529 public synchronized void updateObject(String columnName, Object x, int scale) 1530 throws SQLException { 1531 updateObject(findColumn(columnName), x); 1532 } 1533 1534 1546 public synchronized void updateObject(String columnName, Object x) 1547 throws SQLException { 1548 updateObject(findColumn(columnName), x); 1549 } 1550 1551 1559 public synchronized void updateRow() throws SQLException { 1560 if (!isUpdatable) { 1561 throw new NotUpdatable(); 1562 } 1563 1564 if (doingUpdates) { 1565 updater.executeUpdate(); 1566 refreshRow(); 1567 doingUpdates = false; 1568 } 1569 1570 syncUpdate(); 1574 } 1575 1576 1588 public synchronized void updateShort(int columnIndex, short x) 1589 throws SQLException { 1590 if (!onInsertRow) { 1591 if (!doingUpdates) { 1592 doingUpdates = true; 1593 syncUpdate(); 1594 } 1595 1596 updater.setShort(columnIndex, x); 1597 } else { 1598 inserter.setShort(columnIndex, x); 1599 1600 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1601 - 1); 1602 } 1603 } 1604 1605 1617 public synchronized void updateShort(String columnName, short x) 1618 throws SQLException { 1619 updateShort(findColumn(columnName), x); 1620 } 1621 1622 1634 public synchronized void updateString(int columnIndex, String x) 1635 throws SQLException { 1636 if (!onInsertRow) { 1637 if (!doingUpdates) { 1638 doingUpdates = true; 1639 syncUpdate(); 1640 } 1641 1642 updater.setString(columnIndex, x); 1643 } else { 1644 inserter.setString(columnIndex, x); 1645 1646 if (x == null) { 1647 this.thisRow[columnIndex - 1] = null; 1648 } else { 1649 if (getCharConverter() != null) { 1650 try { 1651 this.thisRow[columnIndex - 1] = StringUtils.getBytes(x, 1652 this.charConverter, this.charEncoding); 1653 } catch (UnsupportedEncodingException uEE) { 1654 throw new SQLException ( 1655 "Unsupported character encoding '" 1656 + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 1657 } 1658 } else { 1659 this.thisRow[columnIndex - 1] = x.getBytes(); 1660 } 1661 } 1662 } 1663 } 1664 1665 1677 public synchronized void updateString(String columnName, String x) 1678 throws SQLException { 1679 updateString(findColumn(columnName), x); 1680 } 1681 1682 1693 public synchronized void updateTime(int columnIndex, java.sql.Time x) 1694 throws SQLException { 1695 if (!onInsertRow) { 1696 if (!doingUpdates) { 1697 doingUpdates = true; 1698 syncUpdate(); 1699 } 1700 1701 updater.setTime(columnIndex, x); 1702 } else { 1703 inserter.setTime(columnIndex, x); 1704 1705 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1706 - 1); 1707 } 1708 } 1709 1710 1721 public synchronized void updateTime(String columnName, java.sql.Time x) 1722 throws SQLException { 1723 updateTime(findColumn(columnName), x); 1724 } 1725 1726 1738 public synchronized void updateTimestamp(int columnIndex, 1739 java.sql.Timestamp x) throws SQLException { 1740 if (!onInsertRow) { 1741 if (!doingUpdates) { 1742 doingUpdates = true; 1743 syncUpdate(); 1744 } 1745 1746 updater.setTimestamp(columnIndex, x); 1747 } else { 1748 inserter.setTimestamp(columnIndex, x); 1749 1750 this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex 1751 - 1); 1752 } 1753 } 1754 1755 1767 public synchronized void updateTimestamp(String columnName, 1768 java.sql.Timestamp x) throws SQLException { 1769 updateTimestamp(findColumn(columnName), x); 1770 } 1771 1772 1778 protected void setResultSetConcurrency(int concurrencyFlag) { 1779 super.setResultSetConcurrency(concurrencyFlag); 1780 1781 } 1790 1791 protected void checkRowPos() throws SQLException { 1792 if (!this.onInsertRow) { 1796 super.checkRowPos(); 1797 } 1798 } 1799 1800 1807 protected void generateStatements() throws SQLException { 1808 if (!isUpdatable) { 1809 this.doingUpdates = false; 1810 this.onInsertRow = false; 1811 1812 throw new NotUpdatable(); 1813 } 1814 1815 String quotedId = getQuotedIdChar(); 1816 1817 this.tableName = null; 1818 1819 if (fields[0].getOriginalTableName() != null) { 1820 StringBuffer tableNameBuffer = new StringBuffer (); 1821 1822 String databaseName = fields[0].getDatabaseName(); 1823 1824 if ((databaseName != null) && (databaseName.length() > 0)) { 1825 tableNameBuffer.append(quotedId); 1826 tableNameBuffer.append(databaseName); 1827 tableNameBuffer.append(quotedId); 1828 tableNameBuffer.append('.'); 1829 } 1830 1831 tableNameBuffer.append(quotedId); 1832 tableNameBuffer.append(fields[0].getOriginalTableName()); 1833 tableNameBuffer.append(quotedId); 1834 1835 this.tableName = tableNameBuffer.toString(); 1836 } else { 1837 StringBuffer tableNameBuffer = new StringBuffer (); 1838 1839 tableNameBuffer.append(quotedId); 1840 tableNameBuffer.append(fields[0].getTableName()); 1841 tableNameBuffer.append(quotedId); 1842 1843 this.tableName = tableNameBuffer.toString(); 1844 } 1845 1846 primaryKeyIndicies = new ArrayList (); 1847 1848 StringBuffer fieldValues = new StringBuffer (); 1849 StringBuffer keyValues = new StringBuffer (); 1850 StringBuffer columnNames = new StringBuffer (); 1851 StringBuffer insertPlaceHolders = new StringBuffer (); 1852 boolean firstTime = true; 1853 boolean keysFirstTime = true; 1854 1855 for (int i = 0; i < fields.length; i++) { 1856 String originalColumnName = fields[i].getOriginalName(); 1857 String columnName = null; 1858 1859 if (this.connection.getIO().hasLongColumnInfo() 1860 && (originalColumnName != null) 1861 && (originalColumnName.length() > 0)) { 1862 columnName = originalColumnName; 1863 } else { 1864 columnName = fields[i].getName(); 1865 } 1866 1867 if (fields[i].isPrimaryKey()) { 1868 primaryKeyIndicies.add(new Integer (i)); 1869 1870 if (!keysFirstTime) { 1871 keyValues.append(" AND "); 1872 } else { 1873 keysFirstTime = false; 1874 } 1875 1876 keyValues.append(quotedId); 1877 keyValues.append(columnName); 1878 keyValues.append(quotedId); 1879 keyValues.append("=?"); 1880 } 1881 1882 if (firstTime) { 1883 firstTime = false; 1884 fieldValues.append("SET "); 1885 } else { 1886 fieldValues.append(","); 1887 columnNames.append(","); 1888 insertPlaceHolders.append(","); 1889 } 1890 1891 insertPlaceHolders.append("?"); 1892 1893 columnNames.append(quotedId); 1894 columnNames.append(columnName); 1895 columnNames.append(quotedId); 1896 1897 fieldValues.append(quotedId); 1898 fieldValues.append(columnName); 1899 fieldValues.append(quotedId); 1900 fieldValues.append("=?"); 1901 } 1902 1903 updateSQL = "UPDATE " + this.tableName + " " + fieldValues.toString() 1904 + " WHERE " + keyValues.toString(); 1905 insertSQL = "INSERT INTO " + this.tableName + " (" 1906 + columnNames.toString() + ") VALUES (" 1907 + insertPlaceHolders.toString() + ")"; 1908 refreshSQL = "SELECT " + columnNames.toString() + " FROM " + tableName 1909 + " WHERE " + keyValues.toString(); 1910 deleteSQL = "DELETE FROM " + this.tableName + " WHERE " 1911 + keyValues.toString(); 1912 } 1913 1914 boolean isUpdatable() { 1915 return this.isUpdatable; 1916 } 1917 1918 1924 void syncUpdate() throws SQLException { 1925 if (updater == null) { 1926 if (updateSQL == null) { 1927 generateStatements(); 1928 } 1929 1930 updater = (com.mysql.jdbc.PreparedStatement) connection 1931 .prepareStatement(updateSQL); 1932 1933 if (updater.getMaxRows() != 0) { 1934 updater.setMaxRows(0); 1935 } 1936 } 1937 1938 int numFields = fields.length; 1939 updater.clearParameters(); 1940 1941 for (int i = 0; i < numFields; i++) { 1942 if (thisRow[i] != null) { 1943 updater.setBytes(i + 1, thisRow[i]); 1944 } else { 1945 updater.setNull(i + 1, 0); 1946 } 1947 } 1948 1949 int numKeys = primaryKeyIndicies.size(); 1950 1951 if (numKeys == 1) { 1952 int index = ((Integer ) primaryKeyIndicies.get(0)).intValue(); 1953 byte[] keyData = thisRow[index]; 1954 updater.setBytes(numFields + 1, keyData); 1955 } else { 1956 for (int i = 0; i < numKeys; i++) { 1957 byte[] currentVal = thisRow[((Integer ) primaryKeyIndicies.get(i)) 1958 .intValue()]; 1959 1960 if (currentVal != null) { 1961 updater.setBytes(numFields + i + 1, currentVal); 1962 } else { 1963 updater.setNull(numFields + i + 1, 0); 1964 } 1965 } 1966 } 1967 } 1968 1969 private boolean initializedCharConverter = false; 1970 1971 private synchronized SingleByteCharsetConverter getCharConverter() 1972 throws SQLException { 1973 if (!this.initializedCharConverter) { 1974 this.initializedCharConverter = true; 1975 1976 if (this.connection.useUnicode()) { 1977 this.charEncoding = connection.getEncoding(); 1978 this.charConverter = this.connection.getCharsetConverter(this.charEncoding); 1979 } 1980 } 1981 1982 return this.charConverter; 1983 } 1984 1985 private synchronized String getQuotedIdChar() throws SQLException { 1986 if (this.quotedIdChar == null) { 1987 boolean useQuotedIdentifiers = connection.supportsQuotedIdentifiers(); 1988 1989 if (useQuotedIdentifiers) { 1990 java.sql.DatabaseMetaData dbmd = connection.getMetaData(); 1991 this.quotedIdChar = dbmd.getIdentifierQuoteString(); 1992 } else { 1993 this.quotedIdChar = ""; 1994 } 1995 } 1996 1997 return this.quotedIdChar; 1998 } 1999 2000 2007 private String getTableName(Field field) { 2008 String originalTableName = field.getOriginalTableName(); 2009 2010 if ((originalTableName != null) && (originalTableName.length() > 0)) { 2011 return originalTableName; 2012 } else { 2013 return field.getTableName(); 2014 } 2015 } 2016 2017 2024 private boolean checkUpdatability() throws SQLException { 2025 String tableName = null; 2026 String catalogName = null; 2027 2028 int primaryKeyCount = 0; 2029 2030 if (fields.length > 0) { 2031 2032 tableName = fields[0].getOriginalTableName(); 2033 catalogName = fields[0].getDatabaseName(); 2034 2035 if (tableName == null) { 2036 tableName = fields[0].getTableName(); 2037 catalogName = this.catalog; 2038 } 2039 2040 if (fields[0].isPrimaryKey()) { 2041 primaryKeyCount++; 2042 } 2043 2044 for (int i = 1; i < fields.length; i++) { 2048 String otherTableName = fields[i].getOriginalTableName(); 2049 2050 String otherCatalogName = fields[i].getDatabaseName(); 2051 2052 if (otherTableName == null) { 2053 otherTableName = fields[i].getTableName(); 2054 otherCatalogName = this.catalog; 2055 } 2056 2057 if ((tableName == null) 2059 || !otherTableName.equals(tableName)) { 2060 return false; 2061 } 2062 2063 if ((catalogName == null) || !otherCatalogName.equals(catalogName)) { 2065 return false; 2066 } 2067 2068 if (fields[i].isPrimaryKey()) { 2069 primaryKeyCount++; 2070 } 2071 } 2072 2073 if ((tableName == null) || (tableName.length() == 0)) { 2074 return false; 2075 } 2076 } else { 2077 return false; 2078 } 2079 2080 if (primaryKeyCount == 0) { 2084 return false; 2085 } 2086 2087 if ((this.catalog == null) || (this.catalog.length() == 0)) { 2093 this.catalog = fields[0].getDatabaseName(); 2094 2095 if ((this.catalog == null) || (this.catalog.length() == 0)) { 2096 throw new SQLException ( 2097 "Can not create updatable result sets when there is no currently selected database" 2098 + " and MySQL server version < 4.1", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); 2099 } 2100 } 2101 2102 if (this.connection.useStrictUpdates()) { 2103 java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); 2104 2105 java.sql.ResultSet rs = null; 2106 HashMap primaryKeyNames = new HashMap (); 2107 2108 try { 2109 rs = dbmd.getPrimaryKeys(catalogName, null, tableName); 2110 2111 while (rs.next()) { 2112 String keyName = rs.getString(4); 2113 keyName = keyName.toUpperCase(); 2114 primaryKeyNames.put(keyName, keyName); 2115 } 2116 } finally { 2117 if (rs != null) { 2118 try { 2119 rs.close(); 2120 } catch (Exception ex) { 2121 AssertionFailedException.shouldNotHappen(ex); 2122 } 2123 2124 rs = null; 2125 } 2126 } 2127 2128 if (primaryKeyNames.size() == 0) { 2129 return false; } 2131 2132 for (int i = 0; i < fields.length; i++) { 2136 if (fields[i].isPrimaryKey()) { 2137 String columnNameUC = fields[i].getName().toUpperCase(); 2138 2139 if (primaryKeyNames.remove(columnNameUC) == null) { 2140 String originalName = fields[i].getOriginalName(); 2142 2143 if (originalName != null) { 2144 if (primaryKeyNames.remove( 2145 originalName.toUpperCase()) == null) { 2146 return false; 2148 } 2149 } 2150 } 2151 } 2152 } 2153 2154 return primaryKeyNames.isEmpty(); 2155 } 2156 2157 return true; 2158 } 2159 2160 private synchronized void extractDefaultValues() throws SQLException { 2161 java.sql.DatabaseMetaData dbmd = this.connection.getMetaData(); 2162 2163 java.sql.ResultSet columnsResultSet = null; 2164 2165 try { 2166 String unquotedTableName = this.tableName; 2167 2168 if (unquotedTableName.startsWith(this.quotedIdChar)) { 2169 unquotedTableName = unquotedTableName.substring(1); 2170 } 2171 2172 if (unquotedTableName.endsWith(this.quotedIdChar)) { 2173 unquotedTableName = unquotedTableName.substring(0, 2174 unquotedTableName.length() - 1); 2175 } 2176 2177 columnsResultSet = dbmd.getColumns(this.catalog, null, 2178 unquotedTableName, "%"); 2179 2180 HashMap columnNameToDefaultValueMap = new HashMap (this.fields.length ); 2181 2182 while (columnsResultSet.next()) { 2183 String columnName = columnsResultSet.getString("COLUMN_NAME"); 2184 byte[] defaultValue = columnsResultSet.getBytes("COLUMN_DEF"); 2185 2186 columnNameToDefaultValueMap.put(columnName, defaultValue); 2187 } 2188 2189 int numFields = this.fields.length; 2190 2191 this.defaultColumnValue = new byte[numFields][]; 2192 2193 for (int i = 0; i < numFields; i++) { 2194 String tableName = this.fields[i].getOriginalName(); 2195 2196 if ((tableName == null) || (tableName.length() == 0)) { 2197 tableName = this.fields[i].getName(); 2198 } 2199 2200 if (tableName != null) { 2201 byte[] defaultVal = (byte[]) columnNameToDefaultValueMap 2202 .get(tableName); 2203 2204 this.defaultColumnValue[i] = defaultVal; 2205 } 2206 } 2207 } finally { 2208 if (columnsResultSet != null) { 2209 columnsResultSet.close(); 2210 2211 columnsResultSet = null; 2212 } 2213 } 2214 } 2215 2216 private void resetInserter() throws SQLException { 2217 inserter.clearParameters(); 2218 2219 for (int i = 0; i < fields.length; i++) { 2220 inserter.setNull(i + 1, 0); 2221 } 2222 } 2223} 2224 | Popular Tags |