0
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'

唯一の問題は、渡されたクエリ パラメータがデータベースにない場合、実行時エラーがスローされることです。データベースにある正確なクエリパラメーターを指定すると、正常に実行されます。

4

2 に答える 2

2

これは 1 つではなく 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は null であると言えます。

query.append(ID);

したがって、プログラムを中止しています。


これとは別に、コードは、文字列連結によって SQL を構成する非常に安全でない方法を示しています。これにより、SQL インジェクションのエクスプロイトが容易になります。

';DROP TABLE results;--悪意のあるユーザーによって「ID」変数が設定された場合にどうなるか想像してみてください。

文字列を追加して、ユーザー指定の値を SQL に挿入しないでください。

代わりに、 経由でバインド パラメータを使用しますPQexecParams。複雑に見えますが、ほとんどのパラメーターは単純な使用のためのオプションです。IDクエリのバージョンは、それが非 null であると仮定すると、次の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);

null を処理する必要がある場合は、別のパラメーターが必要です。ドキュメントを参照してください。

于 2015-04-10T01:18:49.717 に答える
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 から外れています」は、一見誤検知でした。

于 2015-09-20T11:22:57.447 に答える