KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > db > JdbcResultResource


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.lib.db;
31
32 import com.caucho.quercus.env.*;
33 import com.caucho.util.L10N;
34 import com.caucho.util.Log;
35
36 import java.io.IOException JavaDoc;
37 import java.io.InputStream JavaDoc;
38 import java.sql.ResultSet JavaDoc;
39 import java.sql.ResultSetMetaData JavaDoc;
40 import java.sql.SQLException JavaDoc;
41 import java.sql.Statement JavaDoc;
42 import java.sql.Types JavaDoc;
43 import java.util.logging.Level JavaDoc;
44 import java.util.logging.Logger JavaDoc;
45
46 /**
47  * Represents a JDBC Result value.
48  */

49 public class JdbcResultResource {
50   private static final Logger JavaDoc log = Log.open(JdbcResultResource.class);
51   private static final L10N L = new L10N(JdbcResultResource.class);
52
53   public static final int FETCH_ASSOC = 0x1;
54   public static final int FETCH_NUM = 0x2;
55   public static final int FETCH_BOTH = FETCH_ASSOC | FETCH_NUM;
56
57   public static final String JavaDoc INTEGER = "int";
58   public static final String JavaDoc BLOB = "blob";
59   public static final String JavaDoc STRING = "string";
60   public static final String JavaDoc DATE = "date";
61   public static final String JavaDoc DATETIME = "datetime";
62   public static final String JavaDoc REAL = "real";
63   public static final String JavaDoc UNKNOWN = "unknown";
64
65   private Statement JavaDoc _stmt;
66   private ResultSet JavaDoc _rs;
67   private int _fieldOffset;
68   private JdbcConnectionResource _conn;
69
70   private ResultSetMetaData JavaDoc _metaData;
71   private Value[] _columnNames;
72
73   private int _affectedRows;
74
75   boolean _closed;
76
77   /**
78    * Constructor for JdbcResultResource
79    *
80    * @param stmt the corresponding statement
81    * @param rs the corresponding result set
82    * @param conn the corresponding connection
83    */

84   public JdbcResultResource(Statement JavaDoc stmt,
85                             ResultSet JavaDoc rs,
86                             JdbcConnectionResource conn)
87   {
88     _closed = false;
89     _stmt = stmt;
90     _rs = rs;
91     _conn = conn;
92   }
93
94   /**
95    * Constructor for JdbcResultResource
96    *
97    * @param metaData the corresponding result set meta data
98    * @param conn the corresponding connection
99    */

100   public JdbcResultResource(ResultSetMetaData JavaDoc metaData,
101                             JdbcConnectionResource conn)
102   {
103     _closed = true;
104
105     _metaData = metaData;
106     _conn = conn;
107   }
108
109   /**
110    * Closes the result set.
111    */

112   public void close()
113   {
114     try {
115       if (_rs != null)
116         _rs.close();
117
118       _stmt = null;
119
120       _closed = true;
121
122     } catch (SQLException JavaDoc e) {
123       log.log(Level.FINE, e.toString(), e);
124     }
125
126   }
127
128   /**
129    * Fetch the next line as an array.
130    *
131    * @param type one of FETCH_ASSOC, FETCH_NUM, or FETCH_BOTH (default)
132    * By using the FETCH_ASSOC constant this function will behave
133    * identically to the mysqli_fetch_assoc(), while FETCH_NUM will
134    * behave identically to the mysqli_fetch_row() function. The final
135    * option FETCH_BOTH will create a single array with the attributes
136    * of both.
137    *
138    * @return the next result row as an associative,
139    * a numeric array, or both.
140    */

141   public ArrayValue fetchArray(Env env, int type)
142   {
143     try {
144       if (_rs.next()) {
145         ArrayValue array = new ArrayValueImpl();
146
147         if (_metaData == null)
148           _metaData = _rs.getMetaData();
149
150         int count = _metaData.getColumnCount();
151
152         if ((type & FETCH_ASSOC) != 0) {
153           _columnNames = new Value[count];
154
155           for (int i = 0; i < count; i++)
156             _columnNames[i] = new StringValueImpl(_metaData.getColumnName(i + 1));
157         }
158
159         for (int i = 0; i < count; i++) {
160           Value value = getColumnValue(env, _rs, _metaData, i + 1);
161
162           if ((type & FETCH_NUM) != 0)
163             array.put(LongValue.create(i), value);
164
165           if ((type & FETCH_ASSOC) != 0)
166             array.put(_columnNames[i], value);
167         }
168
169         return array;
170       } else {
171         return null;
172       }
173     } catch (SQLException JavaDoc e) {
174       log.log(Level.FINE, e.toString(), e);
175       return null;
176     }
177   }
178
179   /**
180    * Returns an associative array representing the row.
181    *
182    * @return an associative array representing the row
183    * or null if there are no more rows in the result set
184    */

185   public ArrayValue fetchAssoc(Env env)
186   {
187     return fetchArray(env, JdbcResultResource.FETCH_ASSOC);
188   }
189
190   /**
191    * Returns an object with the following fields: name, table, max_length,
192    * not_null, primary_key, multiple_key, numeric,
193    * blob, type, unsigned, zerofill.
194    * <p/>
195    * NOTE: does not have a field for unique_key.
196    *
197    * @param env the PHP executing environment
198    * @param maxLength the field maximum length
199    * @param tableName the field table name
200    * @param type the field type
201    * @return the next field in the result set or
202    * false if no information is available
203    */

204   public Value fetchField(Env env,
205                           int maxLength,
206                           String JavaDoc tableName,
207                           String JavaDoc type)
208   {
209     ObjectValue result = env.createObject();
210     LongValue one = new LongValue(1);
211     LongValue zero = new LongValue(0);
212
213     try {
214       _rs.next();
215       result.putField(env, "name", new StringValueImpl(_rs.getString(1)));
216       result.putField(env, "table", new StringValueImpl(tableName));
217       result.putField(env, "max_length", new LongValue(maxLength));
218
219       if (_rs.getString(4).indexOf("YES") == -1)
220         result.putField(env, "not_null", one);
221       else
222         result.putField(env, "not_null", zero);
223
224       if (_rs.getString(5).indexOf("PRI") != -1)
225         result.putField(env, "primary_key", one);
226       else
227         result.putField(env, "primary_key", zero);
228
229       if (_rs.getString(5).indexOf("MUL") != -1)
230         result.putField(env, "multiple_key", one);
231       else
232         result.putField(env, "multiple_key", zero);
233
234       if ((_rs.getString(2).indexOf("int") != -1) || (_rs.getString(2).indexOf("real") != -1))
235         result.putField(env, "numeric", one);
236       else
237         result.putField(env, "numeric", zero);
238
239       if (_rs.getString(2).indexOf("blob") != -1)
240         result.putField(env, "blob", one);
241       else
242         result.putField(env, "blob", zero);
243
244       result.putField(env, "type", new StringValueImpl(type));
245
246       if (_rs.getString(2).indexOf("unsigned") != -1)
247         result.putField(env, "unsigned", one);
248       else
249         result.putField(env, "unsigned", zero);
250
251       if (_rs.getString(2).indexOf("zerofill") != -1)
252         result.putField(env, "zerofill", one);
253       else
254         result.putField(env, "zerofill", zero);
255
256       return result;
257     } catch (SQLException JavaDoc e) {
258       log.log(Level.FINE, e.toString(), e);
259       return BooleanValue.FALSE;
260     }
261   }
262
263   /**
264    * Returns an object with the following fields:
265    *
266    * name: The name of the column
267    * orgname: The original name if an alias was specified
268    * table: The name of the table
269    * orgtable: The original name if an alias was specified
270    * def: default value for this field, represented as a string
271    * max_length: The maximum width of the field for the result set
272    * flags: An integer representing the bit-flags for the field
273    * type: An integer respresenting the data type used for this field
274    * decimals: The number of decimals used (for integer fields)
275    *
276    * @param env the PHP executing environment
277    * @param maxLength the field maximum length
278    * @param name the field name
279    * @param originalName the field original name
280    * @param table the field table name
281    * @param type the field type
282    * @param scale the field scale
283    * @return an object containing field metadata
284    */

285   protected Value fetchFieldImproved(Env env,
286                                      int maxLength,
287                                      String JavaDoc name,
288                                      String JavaDoc originalName,
289                                      String JavaDoc table,
290                                      int type,
291                                      int scale)
292   {
293     Value result = env.createObject();
294
295     try {
296       if (_metaData == null)
297         _metaData = _rs.getMetaData();
298
299       _rs.next();
300       result.putField(env, "name", new StringValueImpl(name));
301       result.putField(env, "orgname", new StringValueImpl(originalName));
302       result.putField(env, "table", new StringValueImpl(table));
303       //XXX: orgtable same as table
304
result.putField(env, "orgtable", new StringValueImpl(table));
305       if (_rs.getString(6) != null)
306         result.putField(env, "def", new StringValueImpl(_rs.getString(6)));
307       else
308         result.putField(env, "def", new StringValueImpl(""));
309       result.putField(env, "max_length", new LongValue(maxLength));
310
311       //generate flags
312
long flags = 0;
313
314       if (_rs.getString(4).indexOf("YES") == -1)
315         flags += MysqliModule.NOT_NULL_FLAG;
316
317       if (_rs.getString(5).indexOf("PRI") != -1) {
318         flags += MysqliModule.PRI_KEY_FLAG;
319         flags += MysqliModule.PART_KEY_FLAG;
320       }
321
322       if (_rs.getString(5).indexOf("MUL") != -1) {
323         flags += MysqliModule.MULTIPLE_KEY_FLAG;
324         flags += MysqliModule.PART_KEY_FLAG;
325       }
326
327       if ((_rs.getString(2).indexOf("blob") != -1) ||
328           (type == Types.LONGVARCHAR) ||
329           (type == Types.LONGVARBINARY))
330         flags += MysqliModule.BLOB_FLAG;
331
332       if (_rs.getString(2).indexOf("unsigned") != -1)
333         flags += MysqliModule.UNSIGNED_FLAG;
334
335       if (_rs.getString(2).indexOf("zerofill") != -1)
336         flags += MysqliModule.ZEROFILL_FLAG;
337
338       if ((_rs.getString(3).indexOf("bin") != -1) ||
339           (type == Types.LONGVARBINARY) ||
340           (type == Types.DATE) ||
341           (type == Types.TIMESTAMP))
342         flags += MysqliModule.BINARY_FLAG;
343
344       if (_rs.getString(2).indexOf("enum") != -1)
345         flags += MysqliModule.ENUM_FLAG;
346
347       if (_rs.getString(7).indexOf("auto") != -1)
348         flags += MysqliModule.AUTO_INCREMENT_FLAG;
349
350       if (_rs.getString(2).indexOf("set") != -1)
351         flags += MysqliModule.SET_FLAG;
352
353       if ((type == Types.BIGINT) ||
354           (type == Types.BIT) ||
355           (type == Types.BOOLEAN) ||
356           (type == Types.DECIMAL) ||
357           (type == Types.DOUBLE) ||
358           (type == Types.REAL) ||
359           (type == Types.INTEGER) ||
360           (type == Types.SMALLINT))
361         flags += MysqliModule.NUM_FLAG;
362
363       result.putField(env, "flags", new LongValue(flags));
364       //generate PHP type
365
int quercusType = 0;
366       switch (type) {
367       case Types.DECIMAL:
368         quercusType = MysqliModule.MYSQL_TYPE_DECIMAL;
369         break;
370       case Types.BIT:
371         quercusType = MysqliModule.MYSQL_TYPE_TINY;
372         break;
373       case Types.SMALLINT:
374         quercusType = MysqliModule.MYSQL_TYPE_SHORT;
375         break;
376       case Types.INTEGER: {
377         if (_rs.getString(2).indexOf("medium") == -1)
378           quercusType = MysqliModule.MYSQL_TYPE_LONG;
379         else
380           quercusType = MysqliModule.MYSQL_TYPE_INT24;
381         break;
382       }
383       case Types.REAL:
384         quercusType = MysqliModule.MYSQL_TYPE_FLOAT;
385         break;
386       case Types.DOUBLE:
387         quercusType = MysqliModule.MYSQL_TYPE_DOUBLE;
388         break;
389       case Types.BIGINT:
390         quercusType = MysqliModule.MYSQL_TYPE_LONGLONG;
391         break;
392       case Types.DATE:
393         quercusType = MysqliModule.MYSQL_TYPE_DATE;
394         break;
395       case Types.TIMESTAMP:
396         quercusType = MysqliModule.MYSQL_TYPE_DATETIME;
397         break;
398       case Types.LONGVARBINARY:
399       case Types.LONGVARCHAR:
400         quercusType = MysqliModule.MYSQL_TYPE_BLOB;
401         break;
402       case Types.CHAR:
403         quercusType = MysqliModule.MYSQL_TYPE_STRING;
404         break;
405       case Types.VARCHAR:
406         quercusType = MysqliModule.MYSQL_TYPE_VAR_STRING;
407         break;
408       // XXX: may need to revisit default
409
default:
410         quercusType = MysqliModule.MYSQL_TYPE_NULL;
411         break;
412       }
413       result.putField(env, "type", new LongValue(quercusType));
414       result.putField(env, "decimals", new LongValue(scale));
415
416     } catch (SQLException JavaDoc e) {
417       log.log(Level.FINE, e.toString(), e);
418       return BooleanValue.FALSE;
419     }
420
421     return result;
422   }
423
424   /**
425    * Returns an object with properties that correspond to the fetched row and
426    * moves the internal data pointer ahead.
427    *
428    * @param env the PHP executing environment
429    * @return an object representing the current fetched row
430    */

431   public Value fetchObject(Env env)
432   {
433     try {
434       if (_rs.next()) {
435         Value result = env.createObject();
436
437         if (_metaData == null)
438           _metaData = _rs.getMetaData();
439
440         int count = _metaData.getColumnCount();
441
442         for (int i = 0; i < count; i++) {
443           String JavaDoc name = _metaData.getColumnName(i + 1);
444           Value value = getColumnValue(env, _rs, _metaData, i + 1);
445
446
447           result.putField(env, name, value);
448         }
449
450         return result;
451
452       } else {
453         return NullValue.NULL;
454       }
455     } catch (SQLException JavaDoc e) {
456       log.log(Level.FINE, e.toString(), e);
457       return BooleanValue.FALSE;
458     }
459   }
460
461   /**
462    * Returns an array representing the row.
463    *
464    * @return an array containing the fecthed row
465    */

466   public ArrayValue fetchRow(Env env)
467   {
468     return fetchArray(env, JdbcResultResource.FETCH_NUM);
469   }
470
471   /**
472    * Returns a StringValue corresponding to the PHP return string
473    *
474    * @param dataType the column data type
475    * @return the column PHP name
476    */

477   public static String JavaDoc getColumnPHPName(int dataType)
478   {
479     switch (dataType) {
480     case Types.BIGINT:
481     case Types.BIT:
482     case Types.INTEGER:
483     case Types.SMALLINT:
484         return INTEGER;
485
486     case Types.LONGVARBINARY:
487     case Types.LONGVARCHAR:
488         return BLOB;
489
490     case Types.CHAR:
491     case Types.VARCHAR:
492         return STRING;
493
494     case Types.DATE:
495         return DATE;
496
497     case Types.TIMESTAMP:
498         return DATETIME;
499
500     case Types.DECIMAL:
501     case Types.DOUBLE:
502     case Types.REAL:
503         return REAL;
504
505     default:
506         return UNKNOWN;
507     }
508   }
509
510   /**
511    * Get the number of affected rows.
512    *
513    * @return the number of affected rows
514    */

515   public int getAffectedRows() {
516     return _affectedRows;
517   }
518
519   /**
520    * Gets the column number based on a generic Value.
521    *
522    * @param fieldNameOrNumber the field index or it's name
523    * @param base the numbering base: 0 or 1 (usually zero).
524    * @return the column number (always 0-based) or -1 on error
525    */

526   protected int getColumnNumber(Value fieldNameOrNumber,
527                                 int base)
528     throws SQLException JavaDoc
529   {
530     int fieldNumber = -1;
531
532     if ((fieldNameOrNumber != null) && fieldNameOrNumber.isLongConvertible()) {
533       // fieldNameOrNumber is the field number.
534
// Convert it to 0-based.
535
fieldNumber = fieldNameOrNumber.toInt() - base;
536     }
537
538     if (fieldNumber < 0) {
539       // fieldNameOrNumber is the field name
540
// Get column number (0-based).
541
fieldNumber = getColumnNumber(fieldNameOrNumber.toString());
542     }
543
544     return fieldNumber;
545   }
546
547   /**
548    * Gets the column number.
549    *
550    * @return the column number (0-based) or -1 on error
551    */

552   protected int getColumnNumber(String JavaDoc colName)
553     throws SQLException JavaDoc
554   {
555     return getColumnNumber(colName, getMetaData());
556   }
557
558   /**
559    * Helper function for getResultField returns a 0-based column number
560    *
561    * @param colName the column name
562    * @param rsmd the result set meta data
563    * @return the column number (0-based) or -1 on error
564    */

565   private int getColumnNumber(String JavaDoc colName,
566                               ResultSetMetaData JavaDoc rsmd)
567     throws SQLException JavaDoc
568   {
569
570     int numColumns = rsmd.getColumnCount();
571
572     if (colName.indexOf('.') == -1) {
573       for (int i = 1; i <= numColumns; i++) {
574         if (colName.equals(rsmd.getColumnName(i)))
575           return (i - 1);
576       }
577       return -1;
578     } else {
579       for (int i = 1; i <= numColumns; i++) {
580         if (colName.equals(rsmd.getTableName(i) + '.' + rsmd.getColumnName(i)))
581           return (i - 1);
582       }
583       return -1;
584     }
585
586   }
587
588   /**
589    * Get the column value in the specified result set.
590    *
591    * @param env the PHP executing environment
592    * @param rs the result set
593    * @param metaData the result set meta data
594    * @param column the column number
595    * @return the column value
596    */

597   public Value getColumnValue(Env env,
598                               ResultSet JavaDoc rs,
599                               ResultSetMetaData JavaDoc metaData,
600                               int column)
601     throws SQLException JavaDoc
602   {
603     // Note: typically, the PHP column value is returned as
604
// a String, except for binary values.
605

606     try {
607       switch (metaData.getColumnType(column)) {
608       case Types.NULL:
609         return NullValue.NULL;
610
611       case Types.BIT:
612         {
613           String JavaDoc typeName = metaData.getColumnTypeName(column);
614           // Postgres matches BIT for BOOL columns
615
if (!typeName.equals("bool")) {
616             long value = rs.getLong(column);
617
618             if (rs.wasNull())
619               return NullValue.NULL;
620             else
621               return StringValue.create(value);
622           }
623           // else fall to boolean
624
}
625
626       case Types.BOOLEAN:
627         {
628           boolean b = rs.getBoolean(column);
629           if (rs.wasNull())
630             return NullValue.NULL;
631           else
632             return StringValue.create(b ? "t" : "f");
633         }
634
635       case Types.TINYINT:
636       case Types.SMALLINT:
637       case Types.INTEGER:
638       case Types.BIGINT:
639         {
640           long value = rs.getLong(column);
641
642           if (rs.wasNull())
643             return NullValue.NULL;
644           else
645             return StringValue.create(value);
646         }
647
648       case Types.DOUBLE:
649         {
650           double value = rs.getDouble(column);
651
652           if (rs.wasNull())
653             return NullValue.NULL;
654           else {
655             StringBuilderValue sb = new StringBuilderValue();
656             if (metaData.isCurrency(column)) {
657               sb.append("$");
658             }
659             return sb.append(value);
660           }
661         }
662
663       case Types.BLOB:
664         {
665           Object JavaDoc object = rs.getBlob(column);
666           if (object.getClass().getName().equals("oracle.sql.BLOB")) {
667             OracleOciLob ociLob = new OracleOciLob((Oracle) _conn,
668                                                    OracleModule.OCI_D_LOB);
669             ociLob.setLob(object);
670             object = ociLob;
671           }
672           return env.wrapJava(object);
673         }
674
675       case Types.CLOB:
676         {
677           Object JavaDoc object = rs.getClob(column);
678           if (object.getClass().getName().equals("oracle.sql.CLOB")) {
679             OracleOciLob ociLob = new OracleOciLob((Oracle) _conn,
680                                                    OracleModule.OCI_D_LOB);
681             ociLob.setLob(object);
682             object = ociLob;
683           }
684           return env.wrapJava(object);
685         }
686
687       case Types.LONGVARBINARY:
688       case Types.VARBINARY:
689       case Types.BINARY:
690         {
691           BinaryBuilderValue bb = new BinaryBuilderValue();
692
693           InputStream JavaDoc is = rs.getBinaryStream(column);
694
695           if (is == null || rs.wasNull())
696             return NullValue.NULL;
697
698           try {
699             while (true) {
700               bb.prepareReadBuffer();
701
702               int len = is.read(bb.getBuffer(),
703                                 bb.getOffset(),
704                                 bb.getLength() - bb.getOffset());
705
706               if (len > 0) {
707                 bb.setOffset(bb.getOffset() + len);
708               }
709               else
710                 break;
711             }
712           } catch (IOException JavaDoc e) {
713             log.log(Level.WARNING, e.toString(), e);
714
715             return NullValue.NULL;
716           }
717
718           return bb;
719         }
720
721       default:
722         {
723           String JavaDoc strValue = rs.getString(column);
724
725           if (strValue == null || rs.wasNull())
726             return NullValue.NULL;
727           else
728             return StringValue.create(strValue);
729         }
730       }
731     } catch (SQLException JavaDoc e) {
732       // php/141e
733
log.log(Level.FINE, e.toString(), e);
734
735       return NullValue.NULL;
736     }
737   }
738
739   /**
740    * Get the connection corresponding to this result resource.
741    *
742    * @return a JDBC connection resource
743    */

744   public JdbcConnectionResource getConnection()
745   {
746     return _conn;
747   }
748
749   /**
750    * Get the field catalog name.
751    *
752    * @param fieldOffset the field number
753    * @return the field catalog name
754    */

755   public Value getFieldCatalog(int fieldOffset)
756   {
757     try {
758       if (_metaData == null)
759         _metaData = _rs.getMetaData();
760
761       if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0)
762         return BooleanValue.FALSE;
763       else
764         return new StringValueImpl(_metaData.getCatalogName(fieldOffset + 1));
765
766     } catch (SQLException JavaDoc e) {
767       log.log(Level.FINE, e.toString(), e);
768       return BooleanValue.FALSE;
769     }
770   }
771
772   /**
773    * Returns column count.
774    *
775    * @return the number of columns in the result set
776    */

777   public int getFieldCount()
778   {
779     try {
780       return getMetaData().getColumnCount();
781     } catch (SQLException JavaDoc e) {
782       throw new RuntimeException JavaDoc(e);
783     }
784   }
785
786   /**
787    * Returns the following field flags: not_null, primary_key, multiple_key, blob,
788    * unsigned zerofill, binary, enum, auto_increment and timestamp
789    * <p/>
790    * it does not return the MySQL / PHP flag unique_key
791    * <p/>
792    * MysqlModule generates a special result set with the appropriate values
793    *
794    * @return the field flags
795    */

796   public Value getFieldFlags()
797   {
798     try {
799       StringBuilder JavaDoc flags = new StringBuilder JavaDoc();
800
801       _rs.next();
802       if (_rs.getString(4).indexOf("YES") == -1)
803         flags.append("not_null");
804
805       if (_rs.getString(5).indexOf("PRI") != -1) {
806         if (flags.length() > 0)
807           flags.append(' ');
808         flags.append("primary_key");
809       } else {
810         if (_rs.getString(5).indexOf("MUL") != -1) {
811           if (flags.length() > 0)
812             flags.append(' ');
813           flags.append("multiple_key");
814         }
815       }
816
817       if (_rs.getString(2).indexOf("blob") != -1) {
818         if (flags.length() > 0)
819           flags.append(' ');
820         flags.append("blob");
821       }
822
823       if (_rs.getString(2).indexOf("unsigned") != -1) {
824         if (flags.length() > 0)
825           flags.append(' ');
826         flags.append("unsigned");
827       }
828
829       if (_rs.getString(2).indexOf("zerofill") != -1) {
830         if (flags.length() > 0)
831           flags.append(' ');
832         flags.append("zerofill");
833       }
834
835       if (_rs.getString(3).indexOf("bin") != -1) {
836         if (flags.length() > 0)
837           flags.append(' ');
838         flags.append("binary");
839       }
840
841       if (_rs.getString(2).indexOf("enum") != -1) {
842         if (flags.length() > 0)
843           flags.append(' ');
844         flags.append("enum");
845       }
846
847       if (_rs.getString(7).indexOf("auto_increment") != -1) {
848         if (flags.length() > 0)
849           flags.append(' ');
850         flags.append("auto_increment");
851       }
852
853       if (_rs.getString(2).indexOf("date") != -1) {
854         if (flags.length() > 0)
855           flags.append(' ');
856         flags.append("timestamp");
857       }
858
859       return new StringValueImpl(flags.toString());
860
861     } catch (SQLException JavaDoc e) {
862       log.log(Level.FINE, e.toString(), e);
863       return BooleanValue.FALSE;
864     }
865   }
866
867   /**
868    * Get field length.
869    *
870    * @param env the PHP executing environment
871    * @param fieldOffset the field number (0-based)
872    * @return length of field for specified column
873    */

874   public Value getFieldLength(Env env, int fieldOffset)
875   {
876     try {
877       if (_metaData == null)
878         _metaData = _rs.getMetaData();
879
880       if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0) {
881         env.invalidArgument("field", fieldOffset);
882         return BooleanValue.FALSE;
883       }
884       else
885         return new LongValue((long) _metaData.getPrecision(fieldOffset + 1));
886
887     } catch (SQLException JavaDoc e) {
888       log.log(Level.FINE, e.toString(), e);
889       return BooleanValue.FALSE;
890     }
891   }
892
893   /**
894    * Returns the column name.
895    *
896    * @param env the PHP executing environment
897    * @param fieldOffset 0-based field offset
898    *
899    * @return a StringValue containing the column name
900    */

901   public Value getFieldName(Env env, int fieldOffset)
902   {
903
904     try {
905       if (_metaData == null)
906         _metaData = _rs.getMetaData();
907
908       if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0) {
909         env.invalidArgument("field", fieldOffset);
910         return BooleanValue.FALSE;
911       }
912       else
913         return new StringValueImpl(_metaData.getColumnName(fieldOffset + 1));
914     } catch (Exception JavaDoc e) {
915       log.log(Level.FINE, e.toString(), e);
916       return BooleanValue.FALSE;
917     }
918   }
919
920   /**
921    * Returns a StringValue containing the column Alias.
922    *
923    * @param fieldOffset 0-based field offset
924    *
925    * @return the column alias
926    */

927   public Value getFieldNameAlias(int fieldOffset)
928   {
929
930     try {
931
932       if (_metaData == null)
933         _metaData = _rs.getMetaData();
934
935       if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0)
936         return BooleanValue.FALSE;
937       else
938         return new StringValueImpl(_metaData.getColumnLabel(fieldOffset + 1));
939
940     } catch (Exception JavaDoc e) {
941       log.log(Level.FINE, e.toString(), e);
942       return BooleanValue.FALSE;
943     }
944   }
945
946   /**
947    * Returns the column name.
948    *
949    * @param env the PHP executing environment
950    * @param fieldOffset 0-based field offset
951    *
952    * @return int(1) if the column is nullable, int(1) if it is not
953    */

954   public Value getFieldNotNull(Env env, int fieldOffset)
955   {
956     try {
957       if (_metaData == null)
958         _metaData = _rs.getMetaData();
959
960       if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0) {
961         env.invalidArgument("field", fieldOffset);
962         return BooleanValue.FALSE;
963       }
964       else
965         if (_metaData.isNullable(fieldOffset + 1) == ResultSetMetaData.columnNoNulls)
966           return LongValue.ONE;
967         else
968           return LongValue.ZERO;
969     } catch (Exception JavaDoc e) {
970       log.log(Level.FINE, e.toString(), e);
971       return BooleanValue.FALSE;
972     }
973   }
974
975   /**
976    * Get field offset.
977    *
978    * @return the current field offset
979    */

980   public int getFieldOffset()
981   {
982     return _fieldOffset;
983   }
984
985   /**
986    * Get field scale.
987    *
988    * @param fieldOffset the field offset
989    * @return number of digits to the right of the decimal point
990    */

991   public Value getFieldScale(int fieldOffset)
992   {
993     try {
994       if (_metaData == null)
995         _metaData = _rs.getMetaData();
996
997       if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0)
998         return BooleanValue.FALSE;
999       else
1000        return new LongValue((long) _metaData.getScale(fieldOffset + 1));
1001
1002    } catch (SQLException JavaDoc e) {
1003      log.log(Level.FINE, e.toString(), e);
1004      return BooleanValue.FALSE;
1005    }
1006  }
1007
1008  /**
1009   * Returns the table corresponding to the field.
1010   *
1011   * @param env the PHP executing environment
1012   * @param fieldOffset the field number
1013   * @return the field table name
1014   */

1015  public Value getFieldTable(Env env, int fieldOffset)
1016  {
1017    try {
1018      if (_metaData == null)
1019        _metaData = _rs.getMetaData();
1020
1021      if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0) {
1022        env.invalidArgument("field", fieldOffset);
1023        return BooleanValue.FALSE;
1024      }
1025      else {
1026        String JavaDoc tableName = _metaData.getTableName(fieldOffset + 1);
1027
1028        if (tableName == null || tableName.equals(""))
1029          return BooleanValue.FALSE;
1030        else
1031          return new StringValueImpl(tableName);
1032      }
1033    } catch (SQLException JavaDoc e) {
1034      log.log(Level.FINE, e.toString(), e);
1035      return BooleanValue.FALSE;
1036    }
1037  }
1038
1039  /**
1040   * Get a StringValue with the column type.
1041   *
1042   * @param env the PHP executing environment
1043   * @param fieldOffset need to add 1 because java is 1 based index and quercus is 0 based
1044   *
1045   * @return a StringValue containing the column type
1046   */

1047  public Value getFieldType(Env env, int fieldOffset)
1048  {
1049    try {
1050
1051      if (_metaData == null)
1052        _metaData = _rs.getMetaData();
1053
1054      if (_metaData.getColumnCount() <= fieldOffset || fieldOffset < 0) {
1055        env.invalidArgument("field", fieldOffset);
1056        return BooleanValue.FALSE;
1057      }
1058      else
1059        return new StringValueImpl(getColumnPHPName(_metaData.getColumnType(fieldOffset + 1)));
1060
1061    } catch (Exception JavaDoc e) {
1062      log.log(Level.FINE, e.toString(), e);
1063      return BooleanValue.FALSE;
1064    }
1065  }
1066
1067  /**
1068   * Returns the underlying SQL statement
1069   * associated to this result resource.
1070   */

1071  protected Statement JavaDoc getJavaStatement()
1072  {
1073    return _conn.getEnv().getQuercus().getStatement(getStatement());
1074  }
1075
1076  /**
1077   * Get type from Types enumeration
1078   *
1079   * @param fieldOffset the field number (0-based)
1080   * @return the JDBC type
1081   */

1082  protected Value getJdbcType(int fieldOffset)
1083  {
1084    try {
1085      if (_metaData == null)
1086        _metaData = _rs.getMetaData();
1087
1088      return new LongValue(_metaData.getColumnType(fieldOffset + 1));
1089
1090    } catch (Exception JavaDoc e) {
1091      log.log(Level.FINE, e.toString(), e);
1092      return BooleanValue.FALSE;
1093    }
1094  }
1095
1096  /**
1097   * Returns an ArrayValue column lengths in the most
1098   * recently accessed row. If a fetch function has not
1099   * yet been called this will return BooleanValue.FALSE
1100   *
1101   * @return an ArrayValue of column lengths in the most
1102   * recently accessed row
1103   */

1104  public Value getLengths()
1105  {
1106    Value result;
1107    ArrayValue array = new ArrayValueImpl();
1108
1109    try {
1110      if (_metaData == null)
1111        _metaData = _rs.getMetaData();
1112
1113      int numColumns = _metaData.getColumnCount();
1114
1115      for (int i = 1; i <= numColumns; i++) {
1116        array.put(new LongValue(_rs.getObject(i).toString().length()));
1117      }
1118      result = array;
1119
1120    } catch (SQLException JavaDoc e) {
1121      log.log(Level.FINE, e.toString(), e);
1122      return BooleanValue.FALSE;
1123    }
1124
1125    return result;
1126  }
1127
1128  /**
1129   * Get the result set meta data.
1130   *
1131   * @return the meta data for this result set
1132   */

1133  public ResultSetMetaData JavaDoc getMetaData()
1134    throws SQLException JavaDoc
1135  {
1136    if (_metaData == null && _rs != null)
1137      _metaData = _rs.getMetaData();
1138
1139    return _metaData;
1140  }
1141
1142  /**
1143   * Returns the number of columns returned in query.
1144   *
1145   * @return the number of columns for this result set
1146   */

1147  public Value getNumFields()
1148  {
1149
1150    try {
1151      Value result = NullValue.NULL;
1152
1153      if (_metaData == null)
1154        _metaData = _rs.getMetaData();
1155
1156      int count = _metaData.getColumnCount();
1157
1158      if (count != 0) {
1159        result = new LongValue((long) count);
1160      }
1161
1162      return result;
1163
1164    } catch (Exception JavaDoc e) {
1165      log.log(Level.FINE, e.toString(), e);
1166      return NullValue.NULL;
1167    }
1168  }
1169
1170  /**
1171   * Get the number of rows in this result set.
1172   *
1173   * @return the number of rows in this result set
1174   */

1175  public int getNumRows()
1176  {
1177    return getNumRows(_rs);
1178  }
1179
1180  /**
1181   * Returns number of rows returned in query
1182   *
1183   * @param rs a result set
1184   * @return the number of rows in the specified result set
1185   */

1186  public static int getNumRows(ResultSet JavaDoc rs)
1187  {
1188    if (rs == null)
1189      return -1;
1190
1191    try {
1192      int currentRow = rs.getRow();
1193
1194      try {
1195        rs.last();
1196        return rs.getRow();
1197      } catch (Exception JavaDoc e) {
1198        log.log(Level.FINE, e.toString(), e);
1199        return -1;
1200      } finally {
1201        if (currentRow == 0)
1202          rs.beforeFirst();
1203        else
1204          rs.absolute(currentRow);
1205      }
1206
1207    } catch (SQLException JavaDoc e) {
1208      log.log(Level.FINE, e.toString(), e);
1209      return -1;
1210    }
1211  }
1212
1213  /**
1214   * Returns the value at a particular row and column.
1215   *
1216   * @param env the PHP executing environment
1217   * @param row a particular row to get the field value from
1218   * @param field the field name or number
1219   * @return the value of the specified field
1220   */

1221  public Value getResultField(Env env, int row, Value field)
1222  {
1223    try {
1224      ResultSetMetaData JavaDoc md = getMetaData();
1225
1226      int colNumber;
1227
1228      if (field.isNumberConvertible())
1229        colNumber = field.toInt();
1230      else
1231        colNumber = getColumnNumber(field.toString(), _metaData);
1232
1233      if (colNumber < 0 || colNumber >= md.getColumnCount()) {
1234        env.invalidArgument("field", field);
1235        return BooleanValue.FALSE;
1236      }
1237
1238      int currentRow = _rs.getRow();
1239
1240      if ((!_rs.absolute(row + 1)) || _rs.isAfterLast()) {
1241        if (currentRow > 0)
1242          _rs.absolute(currentRow);
1243        else
1244          _rs.beforeFirst();
1245
1246        return BooleanValue.FALSE;
1247      }
1248
1249      return getColumnValue(env, _rs, _metaData, colNumber + 1);
1250
1251    } catch (SQLException JavaDoc e) {
1252      log.log(Level.FINE, e.toString(), e);
1253      return BooleanValue.FALSE;
1254    }
1255  }
1256
1257  /**
1258   * Get the underlying result set.
1259   *
1260   * @return the underlying ResultSet object
1261   */

1262  public ResultSet JavaDoc getResultSet()
1263  {
1264    return _rs;
1265  }
1266
1267  /**
1268   * Get the underlying statement.
1269   *
1270   * @return the underlying Statement object
1271   */

1272  public Statement JavaDoc getStatement()
1273  {
1274    return _stmt;
1275  }
1276
1277  /**
1278   * Seeks to an arbitrary result pointer specified
1279   * by the offset in the result set represented by result.
1280   * Returns TRUE on success or FALSE on failure
1281   *
1282   * @param env the PHP executing environment
1283   * @param rowNumber the row offset
1284   * @return true on success or false on failure
1285   */

1286  public boolean seek(Env env, int rowNumber)
1287  {
1288    if (setRowNumber(rowNumber))
1289      return true;
1290
1291    return false;
1292  }
1293
1294  /**
1295   * Set the number of affected rows to the specified value.
1296   *
1297   * @param affectedRows the new number of affected rows
1298   */

1299  public void setAffectedRows(int affectedRows) {
1300    _affectedRows = affectedRows;
1301  }
1302
1303  /**
1304   * Set a value for field offset.
1305   *
1306   * @param fieldOffset PHP is 0-based
1307   */

1308  public void setFieldOffset(int fieldOffset)
1309  {
1310    _fieldOffset = fieldOffset;
1311  }
1312
1313  /**
1314   * Points to the row right before "rowNumber".
1315   * Next fetchArray will increment to proper row.
1316   *
1317   * @param rowNumber the row offset
1318   * @return true on success or false on failure
1319   */

1320  public boolean setRowNumber(int rowNumber)
1321  {
1322    return setRowNumber(_rs, rowNumber);
1323  }
1324
1325  /**
1326   * Points to the row right before "rowNumber".
1327   * Next fetchArray will increment to proper row.
1328   *
1329   * @param rs the result set to move the row pointer
1330   * @param rowNumber the row offset
1331   * @return true on success or false on failure
1332   */

1333  public static boolean setRowNumber(ResultSet JavaDoc rs,
1334                                     int rowNumber)
1335  {
1336    // throw error if rowNumber is after last row
1337
int numRows = getNumRows(rs);
1338
1339    if (numRows <= rowNumber || rowNumber < 0) {
1340      return false;
1341    }
1342
1343    try {
1344      if (rowNumber == 0)
1345        rs.beforeFirst();
1346      else
1347        rs.absolute(rowNumber);
1348    } catch (SQLException JavaDoc e) {
1349      log.log(Level.FINE, e.toString(), e);
1350      return false;
1351    }
1352
1353    return true;
1354  }
1355
1356  /**
1357   * Convert this JDBC result resource to a hash code.
1358   *
1359   * @return a hash code of this JDBC result resource
1360   */

1361  public Value toKey()
1362  {
1363    // XXX: quercusbb seems to want this?
1364
return new StringValueImpl("JdbcResultResource$" + System.identityHashCode(this));
1365  }
1366
1367  /**
1368   * Returns a string representation for this object.
1369   *
1370   * @return a string representation for this object
1371   */

1372  public String JavaDoc toString()
1373  {
1374    return "com.caucho.quercus.resources.JdbcResultResource";
1375  }
1376
1377  /**
1378   * Validate this result set and return it.
1379   *
1380   * @return the validated result set
1381   */

1382  public JdbcResultResource validateResult()
1383  {
1384    return this;
1385  }
1386}
1387
1388
Popular Tags