Сведения о сервере:
PHP v5.3.5
Использование клиентской версии API библиотеки MySQLi: mysqlnd 5.0.7-dev - 091210 - $ Редакция: 304625 $
MySQL Server v5.5.9
У меня есть сохраненная функция в MySQL, которая называется f_get_owner_locations (_in int).Он создает текстовую переменную, в которой хранятся данные о том, какие квартиры принадлежат конкретному владельцу.Если я запускаю
SELECT f_get_owner_locations( 3 );
из командной строки MySQL, он делает то, что должен, и возвращает одну строку:
+----------------------------+
| f_get_owner_locations( 3 ) |
+----------------------------+
| A-01 |
+----------------------------+
Однако всякий раз, когда я пытаюсь запустить его через PHPиспользуя библиотеку MySQLi следующим образом:
$sql = "SELECT f_get_owner_locations( 3 )";
$location = $GLOBALS['db']->fetch( $sql );
Я получаю эту ошибку:
Fatal error: Call to a member function fetch_field() on a non-object
in ~/kernel/Database.php on line 328
Эта строка относится к этому:
/**
* Binds results from a returning SQL statement to an array we can
* loop through.
*
* @param $statement Statement object we're binding from.
* @return Array of values being returned.
* @since 0.1
*/
private final function _bindResult( $statement )
{
$results = NULL;
$bind = array( );
//Get the result set, so we can loop through the fields.
$result = $statement->result_metadata( );
//Loop through the fields and get a reference to each.
while( $column = $result->fetch_field() ) //<=<=<=LINE 328
$bind[] = &$results[$column->name];
//Do the actual binding.
call_user_func_array( array( $statement, 'bind_result'), $bind );
//Free the memory since we already have the result.
$result->free_result();
return $results;
} //_bindResult
Имейте в виду, что это несбой, когда оператор SQL не включает в себя вызов функции.то есть это работает:
$sql = "SELECT `id` FROM `owners`";
$owners = $GLOBALS['db']->fetch( $sql );
Но как только я добавлю необходимость вложить в него принадлежащие ему квартиры (и этот оператор также работает через командную строку MySQL):
$sql = "SELECT `id`, f_get_owner_locations(`id`) FROM `owners`";
$owners = $GLOBALS['db']->fetch( $sql );
Это дает мне ошибку при вызове функции-члена для необъекта.
Я в тупике.Выполнение var_dump для $ result прямо перед циклом while, в моем методе _bindResults дает мне 1 правильный дамп, а затем останавливается, и эта ошибка возникает.
object(mysqli_result)#11 (5) {
["current_field"]=>
int(1)
["field_count"]=>
int(1)
["lengths"]=>
NULL
["num_rows"]=>
int(0)
["type"]=>
int(1)
}
Примечание: вызов f_get_owner_locations - это 2-е полев этом списке выбора, поэтому он не хранит правильное количество полей, несмотря на то, что он должен зацикливаться на правильном количестве полей.
Любые предложения по обходу этого небольшого дорожного блока или подтверждение того, что этоошибка в библиотеке MySQLi или проблема с моим кодом привязки была бы очень признательна.
ОБНОВЛЕНИЕ: Следующий код:
mysql_connect( ... );
mysql_query( "select f_get_owner_locations(3)" );
die( mysql_error() );
Дали мне этот вывод:
FUNCTION f_get_owner_locations does not exist.
Мне больше интересно, является ли это просто ошибкой в части PHP / MySQLi, чем моей?
ОБНОВЛЕНИЕ 2:
Как и требовалось, код, использованный для создания функции:
drop function if exists f_get_owner_locations;
delimiter |
create function f_get_owner_locations( _in int )
returns text deterministic
begin
declare _output text default "";
declare _location varchar(255);
declare _count int default 0;
declare _done int default 0;
declare _cursor cursor for
select
condos.location
from
owners left join
condo_owners on owners.id = condo_owners.owner left join
condos on condo_owners.condo = condos.id
where
owners.id = _in;
declare continue handler for not found set _done = 1;
open _cursor;
repeat
fetch _cursor into _location;
set_count = _count + 1;
set_output = concat( _output, ", ", _location );
until _done end repeat;
set _count = _count - 1;
close _cursor;
set _output = trim( leading ", " from _output );
set _output = substring( _output from 1 for (_count * 6) );
set _output = trim( trailing ", " from _output );
return _output;
end;|
delimiter ;
Допускается небольшой рефакторинг, который может быть немного чище, но это то, что я использовал.