0
query = "select * results where id = '";
query.append(ID);
query.append("'");
res = PQexec(conn, query.c_str());

After executing this statement, i get the following error.

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

However, when I run the same query in postgresql, it does not have any problem.

select * from results where id = 'hello'

The only problem is that if the query parameter passed is not in database, it would throw runtime error. If you provide the exact query parameter which is in database, it executes normally.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Irfan
  • 19
  • 4

2 Answers2

2

That's two separate errors, not one. This error:

row number 0 is out of range 0..-1

is from libpq, but is reported by code you have not shown here.

The error:

terminate called after throwing an instance of 'std::logic_error'
what():  basic_string::_S_construct null not valid

is not from PostgreSQL, it is from your C++ runtime.

It isn't possible for me to tell exactly where it came from. You should really run the program under a debugger to tell that. But if I had to guess, based on the code shown, I'd say that ID is null, so:

query.append(ID);

is therefore aborting the program.


Separately, your code is showing a very insecure practice where you compose SQL by string concatenation. This makes SQL injection exploits easy.

Imagine what would happen if your "ID" variable was set to ';DROP TABLE results;-- by a malicious user.

Do not insert user-supplied values into SQL by appending strings.

Instead, use bind parameters via PQexecParams. It looks complicated, but most parameters are optional for simple uses. A version for your query, assuming that ID is a non-null std::string, would look like:

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);

If you need to handle nulls you need another parameter; see the documentation.

Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
0

Maybe, a bit too late but just want to put in my 5 cents.

Got this error also these days with a very simple stored procedure of the kind like:

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;

Made some debugging with:

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;
 }

Turned out that the owner of the stored procedure was not the one whose credentials I used to log in with. So - at least - in my case this error "row number 0 is out of range 0..-1" was at first sight a false positive.

sirop
  • 181
  • 1
  • 13