これはPGroonga 1.X用のドキュメントです。新しいPGroongaを使っているならPGroonga 2.xのドキュメントを見てください。
pgroonga.query_escape
関数1.1.9で追加。
pgroonga.query_escape
関数はクエリー構文で特別な意味を持つ文字をエスケープします。&@~
演算子、&@~|
演算子などがクエリー構文を使っています。
pgroonga.query_escape
関数はpgroonga.command
関数経由でGroongaコマンドインジェクションが発生することを防ぐときに有用です。Groongaコマンドインジェクションを防ぐことについてはpgroonga.command_escape_value
関数とpgroonga.escape
関数も参照してください。
この関数の構文は次の通りです。
text pgroonga.query_escape(query)
query
はクエリー構文を使っているtext
型の値です。
pgroonga.query_escape
はtext
型の値を返します。この値中の特別な意味を持つ文字はすべてエスケープされています。
サンプルスキーマとデータは次の通りです。
CREATE TABLE memos (
content text
);
CREATE INDEX pgroonga_memos_index
ON memos
USING pgroonga (content);
INSERT INTO memos VALUES ('PGroonga (PostgreSQL+Groonga) is great!');
クエリーが「(PostgreSQL」の場合はエラーが発生します。なぜなら対応する閉じカッコがないからです。
SELECT * FROM memos WHERE content @@ '(PostgreSQL';
-- ERROR: pgroonga: failed to parse expression: Syntax error: <(PostgreSQL||>
pgroonga.query_escape
関数を使うことで「(PostgreSQL」というクエリーそのもの(「(」を特別な文字として扱わない)で検索できます。
SELECT * FROM memos WHERE content @@ pgroonga.query_escape('(PostgreSQL');
-- content
-- -----------------------------------------
-- PGroonga (PostgreSQL+Groonga) is great!
-- (1 row)
pgroonga.command
関数でも同じことが発生します。
SELECT jsonb_pretty(
pgroonga.command('select ' ||
'--table ' || pgroonga.table_name('pgroonga_memos_index') || ' ' ||
'--match_columns content ' ||
'--query "(PostgreSQL"')::jsonb
);
-- jsonb_pretty
-- ------------------------------------------
-- [ +
-- [ +
-- -63, +
-- 1480432652.751489, +
-- 0.0007565021514892578, +
-- "Syntax error: <(PostgreSQL||>" +
-- ] +
-- ]
-- (1 row)
pgroonga.query_escape
関数をpgroonga.command_escape_value
関数と一緒に使うとこのケースを防ぐことができます。
SELECT jsonb_pretty(
pgroonga.command('select ' ||
'--table ' || pgroonga.table_name('pgroonga_memos_index') || ' ' ||
'--match_columns content ' ||
'--query ' || pgroonga.command_escape_value(pgroonga.query_escape('(PostgreSQL')))::jsonb
);
-- jsonb_pretty
-- ------------------------------------------------------------
-- [ +
-- [ +
-- 0, +
-- 1480432832.061276, +
-- 0.0252687931060791 +
-- ], +
-- [ +
-- [ +
-- [ +
-- 1 +
-- ], +
-- [ +
-- [ +
-- "_id", +
-- "UInt32" +
-- ], +
-- [ +
-- "content", +
-- "LongText" +
-- ], +
-- [ +
-- "ctid", +
-- "UInt64" +
-- ] +
-- ], +
-- [ +
-- 1, +
-- "PGroonga (PostgreSQL+Groonga) is great!",+
-- 1 +
-- ] +
-- ] +
-- ] +
-- ]
-- (1 row)
コマンドの引数を配列で指定するスタイルでpgroonga.command
関数使ってもこのケースを防ぐことができます。
SELECT jsonb_pretty(
pgroonga.command('select',
ARRAY[
'table', pgroonga.table_name('pgroonga_memos_index'),
'match_columns', 'content',
'query', pgroonga.query_escape('(PostgreSQL')
])::jsonb
);
-- jsonb_pretty
-- ------------------------------------------------------------
-- [ +
-- [ +
-- 0, +
-- 1480433038.482539, +
-- 0.0001201629638671875 +
-- ], +
-- [ +
-- [ +
-- [ +
-- 1 +
-- ], +
-- [ +
-- [ +
-- "_id", +
-- "UInt32" +
-- ], +
-- [ +
-- "content", +
-- "LongText" +
-- ], +
-- [ +
-- "ctid", +
-- "UInt64" +
-- ] +
-- ], +
-- [ +
-- 1, +
-- "PGroonga (PostgreSQL+Groonga) is great!",+
-- 1 +
-- ] +
-- ] +
-- ] +
-- ]
-- (1 row)