/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Charles Reich */ package com.caucho.quercus.lib.db; import com.caucho.quercus.QuercusModuleException; import com.caucho.quercus.UnimplementedException; import com.caucho.quercus.annotation.Reference; import com.caucho.quercus.annotation.ReturnNullAsFalse; import com.caucho.quercus.env.BooleanValue; import com.caucho.quercus.env.Env; import com.caucho.quercus.env.LongValue; import com.caucho.quercus.env.NullValue; import com.caucho.quercus.env.StringValue; import com.caucho.quercus.env.Value; import com.caucho.util.L10N; import java.util.logging.Level; import java.util.logging.Logger; /** * mysqli object oriented API facade */ public class MysqliStatement extends JdbcStatementResource { private static final Logger log = Logger .getLogger(MysqliStatement.class.getName()); private static final L10N L = new L10N(MysqliStatement.class); /** * Constructor for MysqliStatement * * @param conn a Mysqli connection */ MysqliStatement(Mysqli conn) { super(conn); } /** * Quercus function to get the field 'affected_rows'. */ public int getaffected_rows(Env env) { return affected_rows(env); } /** * Returns the total number of rows changed, deleted, * or inserted by the last executed statement. * * @param env the PHP executing environment * @return an integer greater than zero indicates the number of * rows affected or retrieved. Zero indicates that no records were * updated for an UPDATE/DELETE statement, no rows matched the * WHERE clause in the query or that no query has yet been * executed. -1 indicates that the query has returned an error. */ public int affected_rows(Env env) { try { return validateConnection().getAffectedRows(); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return -1; } } /** * Binds variables to a prepared statement as parameters. * * @param env the PHP executing environment * @param types string of i,d,s,b (ie: "idds") * @param params array of values (probably Vars) * @return true on success or false on failure */ public boolean bind_param(Env env, StringValue types, @Reference Value[] params) { try { return bindParams(env, types.toString(), params); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return false; } } /** * Binds variables to a prepared statement for result storage. * * @param env the PHP executing environment * @param outParams the output variables * @return true on success or false on failure */ public boolean bind_result(Env env, @Reference Value[] outParams) { try { return bindResults(env, outParams); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return false; } } /** * Closes a prepared statement. * * @param env the PHP executing environment * @return true on success or false on failure */ public boolean close(Env env) { try { super.close(); return true; } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return false; } } /** * Seeks to an arbitrary row in statement result set. * * @param env the PHP executing environment * @param offset row offset * @return NULL on sucess or FALSE on failure */ public Value data_seek(Env env, int offset) { try { if (dataSeek(offset)) return NullValue.NULL; } catch (Exception e) { log.log(Level.FINE, e.toString(), e); } return BooleanValue.FALSE; } /** * Returns the error code for the most recent statement call. * * @param env the PHP executing environment * @return the error code or zero if no error occurred */ public int errno() { try { return errorCode(); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return -1; } } /** * Quercus function to get the field 'errno'. */ public int geterrno() { return errno(); } /** * Returns a string description for last statement error * * @param env the PHP executing environment * @return a string that describes the error or * an empty string if no error occurred. */ public StringValue error(Env env) { try { return env.createString(errorMessage()); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return null; } } /** * Quercus function to get the field 'error'. */ @ReturnNullAsFalse public StringValue geterror(Env env) { return error(env); } /** * Executes a prepared Query. The statement has * been prepared using mysqli_prepare. * * @param env the PHP executing environment * @return true on success or false on failure */ public boolean execute(Env env) { try { return super.execute(env); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return false; } } /** * Fetch results from a prepared statement into the bound variables. * * @param env the PHP executing environment * @return true on success, false on failure or * null if no more rows/data exists */ public Value fetch(Env env) { try { return super.fetch(env); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); env.error(e); return BooleanValue.FALSE; } } /** * Frees the associated result. * * @param env the PHP executing environment */ public void free_result(Env env) { try { freeResult(); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); } } /** * Quercus function to get the field 'num_rows'. */ public Value getnum_rows(Env env) { return num_rows(env); } /** * Returns the number of rows in the result. * * @param env the PHP executing environment * @return the number of rows in the result set */ public Value num_rows(Env env) { try { if (getResultSet() != null) return LongValue.create(JdbcResultResource.getNumRows(getResultSet())); else return BooleanValue.FALSE; } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return BooleanValue.FALSE; } } /** * Quercus function to get the field 'param_count'. */ public int getparam_count(Env env) { return param_count(env); } /** * Returns the number of parameter markers for this statement. * * @param env the PHP executing environment * @return the number of parameter markers for this statement */ public int param_count(Env env) { try { return paramCount(); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return -1; } } /** * Prepare a SQL statement for execution. * * @param env the PHP executing environment * @param query SQL query * @return true on success or false on failure */ public boolean prepare(Env env, StringValue query) { try { return super.prepare(env, query); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return false; } } /** * Resets the statement. * * @param env the PHP executing environment * @return true on success or false on failure */ public boolean reset(Env env) { return true; } /** * mysqli_stmt_result_metadata seems to be some initial * step towards getting metadata from a resultset created * by a SELECT run by a prepared statement. * * NB: the $field variable in the following 2 PHP * scripts will be equivalent: * * $result = mysqli_query($link,"SELECT * FROM test"); * $field = mysqli_fetch_field($result); * * AND * * $stmt = mysqli_prepare($link, "SELECT * FROM test"); * mysqli_stmt_execute($stmt); * $metaData = mysqli_stmt_result_metadata($stmt); * $field = mysqli_fetch_field($metaData); * * So it seems that this function just provides a link into * the resultset. * * The PHP documentation is clear that this function returns * a mysqli_result with NO DATA. * * For simplicity, we return a mysqli_result with all the data. * * We check that mysqli_stmt_execute() has been run. * * From libmysql.c: * This function should be used after mysql_stmt_execute(). * ... * Next steps you may want to make: * - find out number of columns is result set by calling * mysql_num_fields(res).... * - fetch metadata for any column with mysql_fetch_field... * * So basically, this function seems to exist only to be a * way to get at the metadata from a resultset generated * by a prepared statement. * * @param env the PHP executing environment * @return a result with meta data or false on failure */ @ReturnNullAsFalse public MysqliResult result_metadata(Env env) { try { if (getResultSet() != null) { return new MysqliResult(env, getMetaData(), (Mysqli) validateConnection()); } else return null; } catch (Exception e) { throw new QuercusModuleException(e); } } /** * Send data in blocks. * * @param env the PHP executing environment * @param paramNumber indicates which parameter to associate the data with * @param data the data to be sent * @return true on success or false on failure */ public boolean send_long_data(Env env, int paramNumber, String data) { throw new UnimplementedException("mysqli_stmt_send_long_data"); } /** * Quercus function to get the field 'sqlstate'. */ public StringValue getsqlstate(Env env) { return sqlstate(env); } /** * Returns SQLSTATE error from previous statement operation. * * @param env the PHP executing environment * @return the SQLSTATE (5-characters string) for * the last error. '00000' means no error */ public StringValue sqlstate(Env env) { int code = errno(); return env.createString(Mysqli.lookupSqlstate(code)); } /** * Saves the result as buffered. * * @param env the PHP executing environment * @return true on success or false on failure */ public boolean store_result(Env env) { return true; } /** * Quercus function to get the field 'field_count'. */ public int getfield_count(Env env) { return field_count(env); } /** * Returns the number of columns in the last query. */ public int field_count(Env env) { try { return getFieldCount(); } catch (Exception e) { log.log(Level.FINE, e.toString(), e); return -1; } } /** * Quercus function to get the field 'insert_id'. */ public Value getinsert_id(Env env) { return insert_id(env); } public Value insert_id(Env env) { return ((Mysqli) validateConnection()).insert_id(env); } }