1 9 package com.ziclix.python.sql; 10 11 import org.python.core.Py; 12 import org.python.core.PyException; 13 import org.python.core.PyInteger; 14 import org.python.core.PyList; 15 import org.python.core.PyObject; 16 import org.python.core.PyTuple; 17 import org.python.core.__builtin__; 18 19 import java.sql.CallableStatement ; 20 import java.sql.DatabaseMetaData ; 21 import java.sql.ResultSet ; 22 import java.sql.ResultSetMetaData ; 23 import java.sql.SQLException ; 24 import java.sql.SQLWarning ; 25 import java.sql.Types ; 26 import java.util.ArrayList ; 27 import java.util.LinkedList ; 28 import java.util.List ; 29 import java.util.Set ; 30 31 54 abstract public class Fetch { 55 56 63 protected int rowcount; 64 65 68 protected int rownumber; 69 70 73 private DataHandler datahandler; 74 75 78 protected PyObject description; 79 80 83 private List listeners; 84 85 90 protected Fetch(DataHandler datahandler) { 91 92 this.rowcount = -1; 93 this.rownumber = -1; 94 this.description = Py.None; 95 this.datahandler = datahandler; 96 this.listeners = new ArrayList (3); 97 } 98 99 106 public static Fetch newFetch(DataHandler datahandler, boolean dynamic) { 107 108 if (dynamic) { 109 return new DynamicFetch(datahandler); 110 } else { 111 return new StaticFetch(datahandler); 112 } 113 } 114 115 118 public int getRowCount() { 119 return this.rowcount; 120 } 121 122 126 public PyObject getDescription() { 127 return this.description; 128 } 129 130 135 abstract public void add(ResultSet resultSet); 136 137 146 abstract public void add(ResultSet resultSet, Set skipCols); 147 148 155 abstract public void add(CallableStatement callableStatement, Procedure procedure, PyObject params); 156 157 166 public PyObject fetchone() { 167 168 PyObject sequence = fetchmany(1); 169 170 if (sequence.__len__() == 1) { 171 return sequence.__getitem__(0); 172 } else { 173 return Py.None; 174 } 175 } 176 177 187 public abstract PyObject fetchall(); 188 189 210 public abstract PyObject fetchmany(int size); 211 212 217 public abstract PyObject nextset(); 218 219 240 public abstract void scroll(int value, String mode); 241 242 245 public void close() throws SQLException { 246 this.listeners.clear(); 247 } 248 249 256 protected PyObject createDescription(ResultSetMetaData meta) throws SQLException { 257 258 PyObject metadata = new PyList(); 259 260 for (int i = 1; i <= meta.getColumnCount(); i++) { 261 PyObject[] a = new PyObject[7]; 262 263 a[0] = Py.newString(meta.getColumnName(i)); 264 a[1] = Py.newInteger(meta.getColumnType(i)); 265 a[2] = Py.newInteger(meta.getColumnDisplaySize(i)); 266 a[3] = Py.None; 267 268 switch (meta.getColumnType(i)) { 269 270 case Types.BIGINT: 271 case Types.BIT: 272 case Types.DECIMAL: 273 case Types.DOUBLE: 274 case Types.FLOAT: 275 case Types.INTEGER: 276 case Types.SMALLINT: 277 a[4] = Py.newInteger(meta.getPrecision(i)); 278 a[5] = Py.newInteger(meta.getScale(i)); 279 break; 280 281 default : 282 a[4] = Py.None; 283 a[5] = Py.None; 284 break; 285 } 286 287 a[6] = Py.newInteger(meta.isNullable(i)); 288 289 ((PyList) metadata).append(new PyTuple(a)); 290 } 291 292 return metadata; 293 } 294 295 302 protected PyObject createDescription(Procedure procedure) throws SQLException { 303 304 PyObject metadata = new PyList(); 305 306 for (int i = 0, len = procedure.columns.__len__(); i < len; i++) { 307 PyObject column = procedure.columns.__getitem__(i); 308 int colType = ((PyInteger)column.__getitem__(Procedure.COLUMN_TYPE).__int__()).getValue(); 309 310 switch (colType) { 311 312 case DatabaseMetaData.procedureColumnReturn: 313 PyObject[] a = new PyObject[7]; 314 315 a[0] = column.__getitem__(Procedure.NAME); 316 a[1] = column.__getitem__(Procedure.DATA_TYPE); 317 a[2] = Py.newInteger(-1); 318 a[3] = column.__getitem__(Procedure.LENGTH); 319 320 switch (((PyInteger)a[1].__int__()).getValue()) { 321 322 case Types.BIGINT: 323 case Types.BIT: 324 case Types.DECIMAL: 325 case Types.DOUBLE: 326 case Types.FLOAT: 327 case Types.INTEGER: 328 case Types.SMALLINT: 329 a[4] = column.__getitem__(Procedure.PRECISION); 330 a[5] = column.__getitem__(Procedure.SCALE); 331 break; 332 333 default : 334 a[4] = Py.None; 335 a[5] = Py.None; 336 break; 337 } 338 339 int nullable = ((PyInteger)column.__getitem__(Procedure.NULLABLE).__int__()).getValue(); 340 341 a[6] = (nullable == DatabaseMetaData.procedureNullable) ? Py.One : Py.Zero; 342 343 ((PyList) metadata).append(new PyTuple(a)); 344 break; 345 } 346 } 347 348 return metadata; 349 } 350 351 360 protected PyObject createResults(CallableStatement callableStatement, Procedure procedure, PyObject params) throws SQLException { 361 362 PyList results = new PyList(); 363 364 for (int i = 0, j = 0, len = procedure.columns.__len__(); i < len; i++) { 365 PyObject obj = Py.None; 366 PyObject column = procedure.columns.__getitem__(i); 367 int colType = ((PyInteger)column.__getitem__(Procedure.COLUMN_TYPE).__int__()).getValue(); 368 int dataType = ((PyInteger)column.__getitem__(Procedure.DATA_TYPE).__int__()).getValue(); 369 370 switch (colType) { 371 372 case DatabaseMetaData.procedureColumnIn: 373 j++; 374 break; 375 376 case DatabaseMetaData.procedureColumnOut: 377 case DatabaseMetaData.procedureColumnInOut: 378 obj = datahandler.getPyObject(callableStatement, i + 1, dataType); 379 380 params.__setitem__(j++, obj); 381 break; 382 383 case DatabaseMetaData.procedureColumnReturn: 384 obj = datahandler.getPyObject(callableStatement, i + 1, dataType); 385 386 Object rs = obj.__tojava__(ResultSet .class); 388 389 if (rs == Py.NoConversion) { 390 results.append(obj); 391 } else { 392 add((ResultSet ) rs); 393 } 394 break; 395 } 396 } 397 398 if (results.__len__() == 0) { 399 return results; 400 } 401 402 PyList ret = new PyList(); 403 404 ret.append(__builtin__.tuple(results)); 405 406 return ret; 407 } 408 409 417 protected PyList createResults(ResultSet set, Set skipCols, PyObject metaData) throws SQLException { 418 419 PyList res = new PyList(); 420 421 while (set.next()) { 422 PyObject tuple = createResult(set, skipCols, metaData); 423 424 res.append(tuple); 425 } 426 427 return res; 428 } 429 430 438 protected PyTuple createResult(ResultSet set, Set skipCols, PyObject metaData) throws SQLException { 439 440 int descriptionLength = metaData.__len__(); 441 PyObject[] row = new PyObject[descriptionLength]; 442 443 for (int i = 0; i < descriptionLength; i++) { 444 if ((skipCols != null) && skipCols.contains(new Integer (i + 1))) { 445 row[i] = Py.None; 446 } else { 447 int type = ((PyInteger) metaData.__getitem__(i).__getitem__(1)).getValue(); 448 449 row[i] = datahandler.getPyObject(set, i + 1, type); 450 } 451 } 452 453 SQLWarning warning = set.getWarnings(); 454 455 if (warning != null) { 456 fireWarning(warning); 457 } 458 459 PyTuple tuple = new PyTuple(row); 460 461 return tuple; 462 } 463 464 protected void fireWarning(SQLWarning warning) { 465 466 WarningEvent event = new WarningEvent(this, warning); 467 468 for (int i = listeners.size() - 1; i >= 0; i--) { 469 try { 470 ((WarningListener) listeners.get(i)).warning(event); 471 } catch (Throwable t) { 472 } 473 } 474 } 475 476 public void addWarningListener(WarningListener listener) { 477 this.listeners.add(listener); 478 } 479 480 public boolean removeWarningListener(WarningListener listener) { 481 return this.listeners.remove(listener); 482 } 483 } 484 485 492 class StaticFetch extends Fetch { 493 494 497 protected List results; 498 499 502 protected List descriptions; 503 504 508 public StaticFetch(DataHandler datahandler) { 509 510 super(datahandler); 511 512 this.results = new LinkedList (); 513 this.descriptions = new LinkedList (); 514 } 515 516 521 public void add(ResultSet resultSet) { 522 this.add(resultSet, null); 523 } 524 525 531 public void add(ResultSet resultSet, Set skipCols) { 532 533 try { 534 if ((resultSet != null) && (resultSet.getMetaData() != null)) { 535 PyObject metadata = this.createDescription(resultSet.getMetaData()); 536 PyObject result = this.createResults(resultSet, skipCols, metadata); 537 538 this.results.add(result); 539 this.descriptions.add(metadata); 540 541 this.rowcount = ((PyObject) this.results.get(0)).__len__(); 543 544 this.description = ((PyObject) this.descriptions.get(0)); 546 547 this.rownumber = 0; 549 } 550 } catch (PyException e) { 551 throw e; 552 } catch (Throwable e) { 553 throw zxJDBC.makeException(e); 554 } finally { 555 try { 556 resultSet.close(); 557 } catch (Throwable e) { 558 } 559 } 560 } 561 562 569 public void add(CallableStatement callableStatement, Procedure procedure, PyObject params) { 570 571 try { 572 PyObject result = this.createResults(callableStatement, procedure, params); 573 574 if (result.__len__() > 0) { 575 this.results.add(result); 576 this.descriptions.add(this.createDescription(procedure)); 577 578 this.rowcount = ((PyObject) this.results.get(0)).__len__(); 580 581 this.description = ((PyObject) this.descriptions.get(0)); 583 584 this.rownumber = 0; 586 } 587 } catch (PyException e) { 588 throw e; 589 } catch (Throwable e) { 590 throw zxJDBC.makeException(e); 591 } 592 } 593 594 605 public PyObject fetchall() { 606 return fetchmany(this.rowcount); 607 } 608 609 631 public PyObject fetchmany(int size) { 632 633 if ((results == null) || (results.size() == 0)) { 634 throw zxJDBC.makeException(zxJDBC.DatabaseError, "no results"); 635 } 636 637 PyObject res = new PyList(); 638 PyObject current = (PyObject) results.get(0); 639 640 if (size <= 0) { 641 size = this.rowcount; 642 } 643 644 if (this.rownumber < this.rowcount) { 645 res = current.__getslice__(Py.newInteger(this.rownumber), Py.newInteger(this.rownumber + size), Py.One); 646 this.rownumber += size; 647 } 648 649 return res; 650 } 651 652 658 public void scroll(int value, String mode) { 659 660 int pos; 661 662 if ("relative".equals(mode)) { 663 pos = this.rownumber + value; 664 } else if ("absolute".equals(mode)) { 665 pos = value; 666 } else { 667 throw zxJDBC.makeException(zxJDBC.ProgrammingError, "invalid cursor scroll mode [" + mode + "]"); 668 } 669 670 if ((pos >= 0) && (pos < this.rowcount)) { 671 this.rownumber = pos; 672 } else { 673 throw zxJDBC.makeException(Py.IndexError, "cursor index [" + pos + "] out of range"); 674 } 675 } 676 677 682 public PyObject nextset() { 683 684 PyObject next = Py.None; 685 686 if ((results != null) && (results.size() > 1)) { 687 this.results.remove(0); 688 this.descriptions.remove(0); 689 690 next = (PyObject) this.results.get(0); 691 this.description = (PyObject) this.descriptions.get(0); 692 this.rowcount = next.__len__(); 693 this.rownumber = 0; 694 } 695 696 return (next == Py.None) ? Py.None : Py.One; 697 } 698 699 702 public void close() throws SQLException { 703 704 super.close(); 705 706 this.rownumber = -1; 707 708 this.results.clear(); 709 } 710 } 711 712 719 class DynamicFetch extends Fetch { 720 721 724 protected Set skipCols; 725 726 729 protected ResultSet resultSet; 730 731 734 public DynamicFetch(DataHandler datahandler) { 735 super(datahandler); 736 } 737 738 745 public void add(ResultSet resultSet) { 746 add(resultSet, null); 747 } 748 749 756 public void add(ResultSet resultSet, Set skipCols) { 757 758 if (this.resultSet != null) { 759 throw zxJDBC.makeException(zxJDBC.getString("onlyOneResultSet")); 760 } 761 762 try { 763 if ((resultSet != null) && (resultSet.getMetaData() != null)) { 764 if (this.description == Py.None) { 765 this.description = this.createDescription(resultSet.getMetaData()); 766 } 767 768 this.resultSet = resultSet; 769 this.skipCols = skipCols; 770 771 this.rowcount = 0; 775 this.rownumber = 0; 776 } 777 } catch (PyException e) { 778 throw e; 779 } catch (Throwable e) { 780 throw zxJDBC.makeException(e); 781 } 782 } 783 784 791 public void add(CallableStatement callableStatement, Procedure procedure, PyObject params) { 792 throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("nocallprocsupport")); 793 } 794 795 798 public PyObject fetchall() { 799 return fetch(0, true); 800 } 801 802 805 public PyObject fetchmany(int size) { 806 return fetch(size, false); 807 } 808 809 815 private PyObject fetch(int size, boolean all) { 816 817 PyList res = new PyList(); 818 819 if (this.resultSet == null) { 820 throw zxJDBC.makeException(zxJDBC.DatabaseError, "no results"); 821 } 822 823 try { 824 all = (size < 0) ? true : all; 825 826 while (((size-- > 0) || all) && this.resultSet.next()) { 827 PyTuple tuple = createResult(this.resultSet, this.skipCols, this.description); 828 res.append(tuple); 829 this.rowcount++; 830 this.rownumber = this.resultSet.getRow(); 831 } 832 } catch (AbstractMethodError e) { 833 throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("nodynamiccursors")); 834 } catch (PyException e) { 835 throw e; 836 } catch (Throwable e) { 837 throw zxJDBC.makeException(e); 838 } 839 840 return res; 841 } 842 843 846 public PyObject nextset() { 847 return Py.None; 848 } 849 850 856 public void scroll(int value, String mode) { 857 858 try { 859 int type = this.resultSet.getType(); 860 861 if ((type != ResultSet.TYPE_FORWARD_ONLY) || (value > 0)) { 862 if ("relative".equals(mode)) { 863 if (value < 0) { 864 value = Math.abs(this.rownumber + value); 865 } else if (value > 0) { 866 value = this.rownumber + value + 1; 867 } 868 } else if ("absolute".equals(mode)) { 869 if (value < 0) { 870 throw zxJDBC.makeException(Py.IndexError, "cursor index [" + value + "] out of range"); 871 } 872 } else { 873 throw zxJDBC.makeException(zxJDBC.ProgrammingError, "invalid cursor scroll mode [" + mode + "]"); 874 } 875 876 if (value == 0) { 877 this.resultSet.beforeFirst(); 878 } else { 879 if (!this.resultSet.absolute(value)) { 880 throw zxJDBC.makeException(Py.IndexError, "cursor index [" + value + "] out of range"); 881 } 882 } 883 884 this.rownumber = this.resultSet.getRow(); 886 } else { 887 String msg = "dynamic result set of type [" + type + "] does not support scrolling"; 888 889 throw zxJDBC.makeException(zxJDBC.NotSupportedError, msg); 890 } 891 } catch (AbstractMethodError e) { 892 throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("nodynamiccursors")); 893 } catch (SQLException e) { 894 throw zxJDBC.makeException(e); 895 } catch (Throwable t) { 896 throw zxJDBC.makeException(t); 897 } 898 } 899 900 903 public void close() throws SQLException { 904 905 super.close(); 906 907 if (this.resultSet == null) { 908 return; 909 } 910 911 this.rownumber = -1; 912 913 try { 914 this.resultSet.close(); 915 } finally { 916 this.resultSet = null; 917 } 918 } 919 } 920 | Popular Tags |