1 2 10 package com.ziclix.python.sql; 11 12 import com.ziclix.python.sql.util.PyArgParser; 13 import org.python.core.ClassDictInit; 14 import org.python.core.Py; 15 import org.python.core.PyBuiltinFunctionSet; 16 import org.python.core.PyClass; 17 import org.python.core.PyDictionary; 18 import org.python.core.PyException; 19 import org.python.core.PyInteger; 20 import org.python.core.PyList; 21 import org.python.core.PyObject; 22 import org.python.core.PyString; 23 import org.python.core.PyTuple; 24 25 import java.sql.DatabaseMetaData ; 26 import java.sql.SQLException ; 27 import java.sql.SQLWarning ; 28 import java.sql.Statement ; 29 import java.util.List ; 30 31 39 public class PyCursor extends PyObject implements ClassDictInit, WarningListener { 40 41 42 protected Fetch fetch; 43 44 45 private boolean closed; 46 47 48 protected int arraysize; 49 50 51 protected int softspace; 52 53 54 protected PyObject rsType; 55 56 57 protected PyObject rsConcur; 58 59 60 protected PyObject warnings; 61 62 63 protected PyObject lastrowid; 64 65 66 protected PyObject updatecount; 67 68 69 protected boolean dynamicFetch; 70 71 72 protected PyConnection connection; 73 74 75 protected DataHandler datahandler; 76 77 78 protected PyStatement statement; 79 80 private static final DataHandler DATAHANDLER = DataHandler.getSystemDataHandler(); 82 83 88 PyCursor(PyConnection connection) { 89 this(connection, false); 90 } 91 92 99 PyCursor(PyConnection connection, boolean dynamicFetch) { 100 101 this.arraysize = 1; 102 this.softspace = 0; 103 this.closed = false; 104 this.rsType = Py.None; 105 this.rsConcur = Py.None; 106 this.connection = connection; 107 this.datahandler = DATAHANDLER; 108 this.dynamicFetch = dynamicFetch; 109 110 this.clear(); 112 } 113 114 124 PyCursor(PyConnection connection, boolean dynamicFetch, PyObject rsType, PyObject rsConcur) { 125 126 this(connection, dynamicFetch); 127 128 this.rsType = rsType; 129 this.rsConcur = rsConcur; 130 } 131 132 133 public static PyClass __class__; 134 135 141 protected PyClass getPyClass() { 142 return __class__; 143 } 144 145 146 protected static PyList __methods__; 147 148 149 protected static PyList __members__; 150 151 static { 152 PyObject[] m = new PyObject[9]; 153 154 m[0] = new PyString("close"); 155 m[1] = new PyString("execute"); 156 m[2] = new PyString("executemany"); 157 m[3] = new PyString("fetchone"); 158 m[4] = new PyString("fetchall"); 159 m[5] = new PyString("fetchmany"); 160 m[6] = new PyString("callproc"); 161 m[7] = new PyString("next"); 162 m[8] = new PyString("write"); 163 __methods__ = new PyList(m); 164 m = new PyObject[11]; 165 m[0] = new PyString("arraysize"); 166 m[1] = new PyString("rowcount"); 167 m[2] = new PyString("rownumber"); 168 m[3] = new PyString("description"); 169 m[4] = new PyString("datahandler"); 170 m[5] = new PyString("warnings"); 171 m[6] = new PyString("lastrowid"); 172 m[7] = new PyString("updatecount"); 173 m[8] = new PyString("softspace"); 174 m[9] = new PyString("closed"); 175 m[10] = new PyString("connection"); 176 __members__ = new PyList(m); 177 } 178 179 184 public String toString() { 185 return "<PyCursor object instance at " + Py.id(this) + ">"; 186 } 187 188 194 public void __setattr__(String name, PyObject value) { 195 196 if ("arraysize".equals(name)) { 197 this.arraysize = ((PyInteger)value.__int__()).getValue(); 198 } else if ("softspace".equals(name)) { 199 this.softspace = ((PyInteger)value.__int__()).getValue(); 200 } else if ("datahandler".equals(name)) { 201 this.datahandler = (DataHandler)value.__tojava__(DataHandler.class); 202 } else { 203 super.__setattr__(name, value); 204 } 205 } 206 207 213 public PyObject __findattr__(String name) { 214 215 if ("arraysize".equals(name)) { 216 return Py.newInteger(arraysize); 217 } else if ("softspace".equals(name)) { 218 return Py.newInteger(softspace); 219 } else if ("__methods__".equals(name)) { 220 return __methods__; 221 } else if ("__members__".equals(name)) { 222 return __members__; 223 } else if ("description".equals(name)) { 224 return this.fetch.description; 225 } else if ("rowcount".equals(name)) { 226 return Py.newInteger(this.fetch.rowcount); 227 } else if ("rownumber".equals(name)) { 228 int rn = this.fetch.rownumber; 229 return (rn < 0) ? Py.None : Py.newInteger(rn); 230 } else if ("warnings".equals(name)) { 231 return warnings; 232 } else if ("lastrowid".equals(name)) { 233 return lastrowid; 234 } else if ("updatecount".equals(name)) { 235 return updatecount; 236 } else if ("datahandler".equals(name)) { 237 return Py.java2py(this.datahandler); 238 } else if ("dynamic".equals(name)) { 239 return this.dynamicFetch ? Py.One : Py.Zero; 240 } else if ("connection".equals(name)) { 241 return this.connection; 242 } else if ("closed".equals(name)) { 243 return Py.newBoolean(closed); 244 } else if ("callproc".equals(name)) { 245 try { 246 if (!getMetaData().supportsStoredProcedures()) { 248 return null; 249 } 250 } catch (Throwable t) {} 251 } 252 253 return super.__findattr__(name); 254 } 255 256 261 static public void classDictInit(PyObject dict) { 262 263 dict.__setitem__("__version__", Py.newString("$Revision: 1.36 $").__getslice__(Py.newInteger(11), Py.newInteger(-2), null)); 264 dict.__setitem__("fetchmany", new CursorFunc("fetchmany", 0, 0, 1, "fetch specified number of rows")); 265 dict.__setitem__("close", new CursorFunc("close", 1, 0, "close the cursor")); 266 dict.__setitem__("fetchall", new CursorFunc("fetchall", 2, 0, "fetch all results")); 267 dict.__setitem__("fetchone", new CursorFunc("fetchone", 3, 0, "fetch the next result")); 268 dict.__setitem__("nextset", new CursorFunc("nextset", 4, 0, "return next set or None")); 269 dict.__setitem__("execute", new CursorFunc("execute", 5, 1, 4, "execute the sql expression")); 270 dict.__setitem__("setinputsizes", new CursorFunc("setinputsizes", 6, 1, "not implemented")); 271 dict.__setitem__("setoutputsize", new CursorFunc("setoutputsize", 7, 1, 2, "not implemented")); 272 dict.__setitem__("callproc", new CursorFunc("callproc", 8, 1, 4, "executes a stored procedure")); 273 dict.__setitem__("executemany", new CursorFunc("executemany", 9, 1, 3, "execute sql with the parameter list")); 274 dict.__setitem__("scroll", new CursorFunc("scroll", 10, 1, 2, "scroll the cursor in the result set to a new position according to mode")); 275 dict.__setitem__("write", new CursorFunc("write", 11, 1, "execute the sql written to this file-like object")); 276 dict.__setitem__("prepare", new CursorFunc("prepare", 12, 1, "prepare the sql statement for later execution")); 277 278 dict.__setitem__("classDictInit", null); 280 dict.__setitem__("toString", null); 281 dict.__setitem__("getDataHandler", null); 282 dict.__setitem__("warning", null); 283 dict.__setitem__("fetch", null); 284 dict.__setitem__("statement", null); 285 dict.__setitem__("dynamicFetch", null); 286 dict.__setitem__("getPyClass", null); 287 dict.__setitem__("rsConcur", null); 288 dict.__setitem__("rsType", null); 289 } 290 291 295 public void __del__() { 296 close(); 297 } 298 299 306 public void close() { 307 308 try { 309 this.clear(); 310 this.connection.remove(this); 311 } finally { 312 this.closed = true; 313 } 314 } 315 316 323 public PyObject __iter__() { 324 return this; 325 } 326 327 337 public PyObject next() { 338 PyObject row = __iternext__(); 339 if (row == null) { 340 throw Py.StopIteration(""); 341 } 342 return row; 343 } 344 345 353 public PyObject __iternext__() { 354 PyObject row = fetchone(); 355 return row.__nonzero__() ? row : null; 356 } 357 358 365 protected DatabaseMetaData getMetaData() throws SQLException { 366 return this.connection.connection.getMetaData(); 367 } 368 369 374 public DataHandler getDataHandler() { 375 return this.datahandler; 376 } 377 378 387 private PyStatement prepareStatement(PyObject sql, PyObject maxRows, boolean prepared) { 388 389 PyStatement stmt = null; 390 391 if (sql == Py.None) { 392 return null; 393 } 394 395 try { 396 if (sql instanceof PyStatement) { 397 stmt = (PyStatement)sql; 398 } else { 399 Statement sqlStatement = null; 400 String sqlString = sql.__str__().toString(); 401 402 if (sqlString.trim().length() == 0) { 403 return null; 404 } 405 406 boolean normal = ((this.rsType == Py.None) && (this.rsConcur == Py.None)); 407 408 if (normal) { 409 if (prepared) { 410 sqlStatement = this.connection.connection.prepareStatement(sqlString); 411 } else { 412 sqlStatement = this.connection.connection.createStatement(); 413 } 414 } else { 415 int t = ((PyInteger)this.rsType.__int__()).getValue(); 416 int c = ((PyInteger)this.rsConcur.__int__()).getValue(); 417 418 if (prepared) { 419 sqlStatement = this.connection.connection.prepareStatement(sqlString, t, c); 420 } else { 421 sqlStatement = this.connection.connection.createStatement(t, c); 422 } 423 } 424 425 int style = prepared ? PyStatement.STATEMENT_PREPARED : PyStatement.STATEMENT_STATIC; 426 427 stmt = new PyStatement(sqlStatement, sqlString, style); 428 } 429 430 if (maxRows != Py.None) { 431 stmt.statement.setMaxRows(((PyInteger)maxRows.__int__()).getValue()); 432 } 433 } catch (AbstractMethodError e) { 434 throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("nodynamiccursors")); 435 } catch (PyException e) { 436 throw e; 437 } catch (Throwable e) { 438 throw zxJDBC.makeException(e); 439 } 440 441 return stmt; 442 } 443 444 460 public void callproc(PyObject name, final PyObject params, PyObject bindings, PyObject maxRows) { 461 462 this.clear(); 463 464 try { 465 if (getMetaData().supportsStoredProcedures()) { 466 if (isSeqSeq(params)) { 467 throw zxJDBC.makeException(zxJDBC.NotSupportedError, "sequence of sequences is not supported"); 468 } 469 470 final Procedure procedure = datahandler.getProcedure(this, name); 471 Statement stmt = procedure.prepareCall(this.rsType, this.rsConcur); 472 473 if (maxRows != Py.None) { 474 stmt.setMaxRows(((PyInteger)maxRows.__int__()).getValue()); 475 } 476 477 PyDictionary callableBindings = new PyDictionary(); 479 480 procedure.normalizeInput(params, callableBindings); 481 482 if (bindings instanceof PyDictionary) { 484 callableBindings.update((PyDictionary)bindings); 485 } 486 487 this.statement = new PyStatement(stmt, procedure); 488 489 this.execute(params, callableBindings); 490 } else { 491 throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC.getString("noStoredProc")); 492 } 493 } catch (PyException e) { 494 throw e; 495 } catch (Throwable e) { 496 throw zxJDBC.makeException(e); 497 } finally { 498 if (this.statement != null) { 499 500 this.statement.close(); 502 } 503 } 504 } 505 506 522 public void executemany(PyObject sql, PyObject params, PyObject bindings, PyObject maxRows) { 523 execute(sql, params, bindings, maxRows); 524 } 525 526 556 public void execute(final PyObject sql, PyObject params, PyObject bindings, PyObject maxRows) { 557 558 this.clear(); 559 560 boolean hasParams = hasParams(params); 561 PyStatement stmt = this.prepareStatement(sql, maxRows, hasParams); 562 563 if (stmt == null) { 564 return; 565 } 566 567 this.statement = stmt; 568 569 try { 570 synchronized (this.statement) { 571 if (hasParams) { 572 573 if (isSeqSeq(params)) { 575 576 for (int i = 0, len = params.__len__(); i < len; i++) { 578 PyObject param = params.__getitem__(i); 579 580 this.execute(param, bindings); 581 } 582 } else { 583 this.execute(params, bindings); 584 } 585 } else { 586 587 this.execute(Py.None, Py.None); 589 } 590 } 591 } catch (PyException e) { 592 throw e; 593 } catch (Throwable e) { 594 throw zxJDBC.makeException(e); 595 } finally { 596 if (this.statement != null) { 597 598 if (!(sql instanceof PyStatement) && (!this.dynamicFetch)) { 600 this.statement.close(); 601 } 602 } 603 } 604 } 605 606 610 protected void execute(PyObject params, PyObject bindings) { 611 612 try { 613 Statement stmt = this.statement.statement; 614 615 this.datahandler.preExecute(stmt); 616 617 this.statement.execute(this, params, bindings); 619 620 this.lastrowid = this.datahandler.getRowId(stmt); 621 622 int uc = stmt.getUpdateCount(); 623 624 this.updatecount = (uc < 0) ? Py.None : Py.newInteger(uc); 625 626 warning(new WarningEvent(this, stmt.getWarnings())); 627 this.datahandler.postExecute(stmt); 628 } catch (PyException e) { 629 throw e; 630 } catch (Throwable e) { 631 throw zxJDBC.makeException(e); 632 } 633 } 634 635 644 public PyObject fetchone() { 645 return this.fetch.fetchone(); 646 } 647 648 659 public PyObject fetchall() { 660 return this.fetch.fetchall(); 661 } 662 663 686 public PyObject fetchmany(int size) { 687 return this.fetch.fetchmany(size); 688 } 689 690 695 public PyObject nextset() { 696 return this.fetch.nextset(); 697 } 698 699 706 public PyStatement prepare(PyObject sql) { 707 708 PyStatement s = this.prepareStatement(sql, Py.None, true); 709 710 this.connection.add(s); 712 713 return s; 714 } 715 716 739 public void scroll(int value, String mode) { 740 this.fetch.scroll(value, mode); 741 } 742 743 748 public void warning(WarningEvent event) { 749 750 if (this.warnings == Py.None) { 751 this.warnings = new PyList(); 752 } 753 754 SQLWarning warning = event.getWarning(); 755 while(warning != null) { 756 757 PyObject[] warn = new PyObject[] { 758 Py.java2py(warning.getMessage()), 760 Py.java2py(warning.getSQLState()), 761 Py.newInteger(warning.getErrorCode()) 762 }; 763 764 ((PyList)this.warnings).append(new PyTuple(warn)); 766 767 warning = warning.getNextWarning(); 768 } 769 } 770 771 776 protected void clear() { 777 778 if (closed) { 779 throw zxJDBC.makeException(zxJDBC.ProgrammingError, "cursor is closed"); 780 } 781 782 this.warnings = Py.None; 783 this.lastrowid = Py.None; 784 this.updatecount = Py.newInteger(-1); 785 786 try { 787 this.fetch.close(); 788 } catch (Throwable e) {} 789 finally { 790 this.fetch = Fetch.newFetch(this.datahandler, this.dynamicFetch); 791 792 this.fetch.addWarningListener(this); 793 } 794 795 if (this.statement != null) { 796 797 try { 802 if (this.dynamicFetch && (!this.connection.contains(this.statement))) { 803 this.statement.close(); 804 } 805 } finally { 806 this.statement = null; 807 } 808 } 809 } 810 811 819 public static boolean isSeq(PyObject object) { 820 821 if ((object == null) || (object == Py.None)) { 822 return false; 823 } 824 825 if (object.__tojava__(List.class) != Py.NoConversion) { 826 return true; 827 } 828 829 return (object instanceof PyList) || (object instanceof PyTuple); 832 } 833 834 842 public static boolean hasParams(PyObject params) { 843 if(Py.None == params) { 844 return false; 845 } 846 847 boolean isSeq = isSeq(params); 848 if (!isSeq) { 850 throw zxJDBC.makeException(zxJDBC.ProgrammingError, zxJDBC.getString("optionalSecond")); 851 } 852 return params.__len__() > 0; 853 } 854 855 863 public static boolean isSeqSeq(PyObject object) { 864 865 if (isSeq(object) && (object.__len__() > 0)) { 866 for (int i = 0; i < object.__len__(); i++) { 867 if (!isSeq(object.__finditem__(i))) { 868 return false; 869 } 870 } 871 return true; 872 } 873 return false; 874 } 875 } 876 877 class CursorFunc extends PyBuiltinFunctionSet { 878 CursorFunc(String name, int index, int argcount, String doc) { 879 super(name, index, argcount, argcount, true, doc); 880 } 881 CursorFunc(String name, int index, int minargs, int maxargs, String doc) { 882 super(name, index, minargs, maxargs, true, doc); 883 } 884 885 public PyObject __call__() { 886 PyCursor cursor = (PyCursor)__self__; 887 switch (index) { 888 case 0 : 889 return cursor.fetchmany(cursor.arraysize); 890 case 1 : 891 cursor.close(); 892 return Py.None; 893 case 2 : 894 return cursor.fetchall(); 895 case 3 : 896 return cursor.fetchone(); 897 case 4 : 898 return cursor.nextset(); 899 default : 900 throw argCountError(0); 901 } 902 } 903 904 public PyObject __call__(PyObject arg) { 905 PyCursor cursor = (PyCursor)__self__; 906 switch (index) { 907 case 0 : 908 return cursor.fetchmany(((PyInteger)arg.__int__()).getValue()); 909 case 5 : 910 cursor.execute(arg, Py.None, Py.None, Py.None); 911 return Py.None; 912 case 6 : 913 case 7 : 914 return Py.None; 915 case 8 : 916 cursor.callproc(arg, Py.None, Py.None, Py.None); 917 return Py.None; 918 case 9 : 919 cursor.executemany(arg, Py.None, Py.None, Py.None); 920 return Py.None; 921 case 10 : 922 cursor.scroll(((PyInteger)arg.__int__()).getValue(), "relative"); 923 return Py.None; 924 case 11 : 925 cursor.execute(arg, Py.None, Py.None, Py.None); 926 return Py.None; 927 case 12 : 928 return cursor.prepare(arg); 929 default : 930 throw argCountError(1); 931 } 932 } 933 934 public PyObject __call__(PyObject arga, PyObject argb) { 935 PyCursor cursor = (PyCursor)__self__; 936 switch (index) { 937 case 5 : 938 cursor.execute(arga, argb, Py.None, Py.None); 939 return Py.None; 940 case 7 : 941 return Py.None; 942 case 8 : 943 cursor.callproc(arga, argb, Py.None, Py.None); 944 return Py.None; 945 case 9 : 946 cursor.executemany(arga, argb, Py.None, Py.None); 947 return Py.None; 948 case 10 : 949 cursor.scroll(((PyInteger)arga.__int__()).getValue(), argb.toString()); 950 return Py.None; 951 default : 952 throw argCountError(2); 953 } 954 } 955 956 public PyObject __call__(PyObject arga, PyObject argb, PyObject argc) { 957 PyCursor cursor = (PyCursor)__self__; 958 switch (index) { 959 case 5 : 960 cursor.execute(arga, argb, argc, Py.None); 961 return Py.None; 962 case 8 : 963 cursor.callproc(arga, argb, argc, Py.None); 964 return Py.None; 965 case 9 : 966 cursor.executemany(arga, argb, argc, Py.None); 967 return Py.None; 968 default : 969 throw argCountError(3); 970 } 971 } 972 973 public PyObject __call__(PyObject[] args, String [] keywords) { 974 975 PyCursor cursor = (PyCursor)__self__; 976 PyArgParser parser = new PyArgParser(args, keywords); 977 PyObject sql = parser.arg(0); 978 PyObject params = parser.kw("params", Py.None); 979 PyObject bindings = parser.kw("bindings", Py.None); 980 PyObject maxrows = parser.kw("maxrows", Py.None); 981 982 params = (parser.numArg() >= 2) ? parser.arg(1) : params; 983 bindings = (parser.numArg() >= 3) ? parser.arg(2) : bindings; 984 maxrows = (parser.numArg() >= 4) ? parser.arg(3) : maxrows; 985 986 switch (index) { 987 case 5 : 988 cursor.execute(sql, params, bindings, maxrows); 989 return Py.None; 990 case 8 : 991 cursor.callproc(sql, params, bindings, maxrows); 992 return Py.None; 993 case 9 : 994 cursor.executemany(sql, params, bindings, maxrows); 995 return Py.None; 996 default : 997 throw argCountError(args.length); 998 } 999 } 1000} 1001 | Popular Tags |