Номер строки 0 находится вне диапазона 0..-1 LIBPQ
query = "select * results where id = '";
query.append(ID);
query.append("'");
res = PQexec(conn, query.c_str());
После выполнения этого утверждения я получаю следующую ошибку.
row number 0 is out of range 0..-1
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Однако когда я выполняю тот же запрос в postgresql, у него не возникает никаких проблем.
select * from results where id = 'hello'
Единственная проблема заключается в том, что если переданный параметр запроса отсутствует в базе данных, он выдаст ошибку времени выполнения. Если вы предоставите точный параметр запроса, который находится в базе данных, он выполняется нормально.
2 ответа
Это две отдельные ошибки, а не одна. Эта ошибка:
row number 0 is out of range 0..-1
из libpq
, но сообщается кодом, который вы здесь не указали.
Ошибка:
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
не из PostgreSQL, а из вашей среды выполнения C++.
Я не могу точно сказать, откуда это взялось. Вы должны действительно запустить программу под отладчиком, чтобы сказать это. Но если бы мне пришлось угадывать, основываясь на показанном коде, я бы сказал, что ID
является нулевым, так что:
query.append(ID);
поэтому прерывает программу.
Отдельно ваш код демонстрирует очень небезопасную практику, когда вы сочиняете SQL путем конкатенации строк. Это облегчает использование SQL-инъекций.
Представьте, что произошло бы, если бы ваша переменная "ID" была установлена в ';DROP TABLE results;--
злоумышленником.
Не вставляйте пользовательские значения в SQL, добавляя строки.
Вместо этого используйте параметры связывания через PQexecParams
, Это выглядит сложно, но большинство параметров не являются обязательными для простого использования. Версия для вашего запроса, при условии, что ID
ненулевой std::string
, будет выглядеть так:
PGresult res;
const char * values[1];
values[0] = ID.c_str();
res = PQexecParams("SELECT * FROM results WHERE id = $1",
1, NULL, values, NULL, NULL, 0);
Если вам нужно обработать пустые значения, вам нужен другой параметр; см. документацию
Может быть, слишком поздно, но просто хочу поставить мои 5 центов.
Получил эту ошибку также в эти дни с очень простой хранимой процедурой типа:
CREATE OR REPLACE FUNCTION selectMsgCounter()
RETURNS text AS
$BODY$
DECLARE
msgCnt text;
BEGIN
msgCnt:= (SELECT max(messageID)::text from messages);
RETURN 'messageCounter: ' || msgCnt;
END
$BODY$
LANGUAGE plpgsql STABLE;
Сделал некоторую отладку с:
if (PQntuples(res)>=1)
{
char* char_result=(char*) realloc(NULL,PQgetlength(res, 0,0)*sizeof(char));
strcpy( char_result,PQgetvalue(res, 0, 0));
bool ok=true;
messageCounter=QString(char_result).remove("messageCounter: ").toULongLong(&ok);
if (!ok) messageCounter=-1;
qDebug()<<"messageCounter: " << messageCounter;
free(char_result);
PQclear(res);
PQfinish(myConn); // or do call destructor later?
myConn=NULL;
}
else
{
fprintf(stderr, "storedProcGetMsgCounter Connection Error: %s",
PQerrorMessage(myConn));
PQclear(res);
PQfinish(myConn); // or do call destructor later?
myConn=NULL;
}
Оказалось, что владельцем хранимой процедуры был не тот, чьи учетные данные я использовал для входа в систему. Так что, по крайней мере, в моем случае эта ошибка "номер строки 0 выходит за пределы диапазона 0..-1" на первый взгляд оказалась ложноположительной.