サム・マクベスの質問から:
JDBC仕様に何かを許可するものはありますか? エスケープして、パラメーターのプレースホルダー以外にする必要がありますか?
たとえば、Postgres では次?
の演算子を使用できます。
SELECT * FROM tbl WHERE tbl.data ? 'abc'
を使用できる JDBC ドライバーはありますか? オペレーターとしてまだ JDBC 準拠ですか?
サム・マクベスの質問から:
JDBC仕様に何かを許可するものはありますか? エスケープして、パラメーターのプレースホルダー以外にする必要がありますか?
たとえば、Postgres では次?
の演算子を使用できます。
SELECT * FROM tbl WHERE tbl.data ? 'abc'
を使用できる JDBC ドライバーはありますか? オペレーターとしてまだ JDBC 準拠ですか?
最新の postgresql ドライバーがある場合は、次を使用できます。
??
元のクエリの変更:
SELECT * FROM tbl WHERE tbl.data ?? 'abc'
詳細はこのプル リクエストにあります - https://github.com/pgjdbc/pgjdbc/pull/227 この変更は、元の質問のかなり後に行われましたが、簡単な答えが今あることに注意してください。
JDBCドライバーを使用して、オペレーターをエスケープ解除してそのまま使用できるようにすることは完全に許容できると思います?
が、1)パーサーがこのオペレーターからパラメーターを実際に識別するのを複雑にし、2)人々(およびおそらくツール)を混乱させる可能性があります)?
パラメータプレースホルダーのみを意味することに慣れている人。
したがって、私の提案は、ある種のエスケープ(または代替演算子)を提供することです。ただし、JDBC仕様を見ると、ドライバーはJDBCエスケープ構文のみを使用してJDBC仕様で定義されたエスケープを実装する必要があります(13.4.2:「エスケープ構文はユーザー定義またはベンダー固有のスカラー関数を呼び出すために使用されることを意図していません。 ";これは特に{fn ...}
エスケープに関するものですが)。
したがって、別のエスケープを使用するか、ルールを「破る」必要があります(誰も気にしないと思います)。より信頼できる回答が必要な場合は、 jdbc-spec-discussメーリングリストに質問を送信できます。Lance Andersen(JDBCスペックリード)が答えを提供すると確信しています。
編集:
また、JDBC仕様のセクション6.2(ガイドラインと要件)には次のように記載されていることに注意してください。
ドライバーは、JDBC APIを拡張する機能を含め、基盤となるデータソースによって実装されるすべての機能へのアクセスを提供する必要があります。この目的は、JDBC APIを使用するアプリケーションが、ネイティブアプリケーションと同じ機能セットにアクセスできるようにすることです。
?
したがって、 -operatorをサポートする必要がある(必須ではない)ことに基づいて、それを行うための実用的な方法を見つける必要があります。
Lance Andersenによると、JDBC仕様は疑問符に関してSQL仕様に従います。これらは?
、PostgreSQL hstore演算子のように使用する場合と同様に、クエリテキスト(もちろんコメントや引用符で囲まれたテキストを除く)のパラメータプレースホルダーとしてのみ使用できます。許可されていません。(このメッセージを参照してください)
利用可能なオプションは、将来の変更と競合しない限り、オペレーターにエイリアスまたはエスケープを提供することです(これは千里眼なしで行うのはかなり難しいです;)。将来のJDBCの変更に関する問題を防ぐための最善の解決策は、おそらくカスタムエスケープです。
JDBCは実際にはベンダーエスケープを定義していませんが、LanceAndersenはJDBCエスケープに類似したエスケープを提案しています{postgres <thing to be escaped>}
。このエスケープでvendornameまたはdrivernameを使用すると、仕様との競合を防ぐ名前空間の形式が提供されます。(このメッセージを参照してください)
'通常の'JDBC関数のエスケープと一致させるために、質問のクエリを次のように記述できるようにするエスケープを定義することをお勧めします。
SELECT * FROM tbl WHERE {postgres containskey(tbl.data, 'abc')}
hstoreのドキュメントcontainskey
の意味に基づいて選択しまし?
た。:)と:の同様の提案。一貫性を保つために、他のhstoreオペレーターに対してもこれを行うことを検討できます。?&
containsallkeys
?|
containsanykey
疑問符自体だけをエスケープすることもできます。たとえば、{postgres '?'}
または{postgres qm}
(疑問符の場合はqm)でエスケープします。読みやすさは私の関数エスケープの提案よりも少ないと思います:
SELECT * FROM tbl WHERE tbl.data {postgres '?'} 'abc'
次のJDBC仕様(4.4の番号が付けられている可能性があります)では、クエリのフラグメントを完全にエスケープする明示的なJDBCエスケープが追加され、パラメータマーカーに疑問符をネイティブに使用しないデータベースシステムの疑問符をエスケープできるようになります。疑問符の他の使用法をサポートする必要があります。
提案された構文は次のようになります{\ <thing-to escape> \}
(これは、非標準のエスケープとしてOracle JDBCドライバーによってすでにサポートされています)。この構文を使用すると、パラメーターマーカーを{\?\}
(文字列リテラル:){\\?\\}
でエスケープするか、より大きなフラグメントをエスケープして読みやすさを向上させることができます。
SQL 2016 MATCH RECOGNIZE JDBCパラメーターマーカー/エスケープ文字、およびjdbc-spec-discussメーリングリストに関する以前の説明も参照してください。
JDBC 仕様?
には、エスケープを許可するものは何もありません。それが言っているほとんどすべては次のとおり?
です。
「?」で表されるパラメータ マーカー SQL 文字列では、実行時に変化する可能性があるステートメントへの入力値を指定するために使用されます。[1]
以降...
適切な setter メソッドに渡される整数であるパラメーター序数は、1 から始まるステートメント内のパラメーター マーカー ("?") を参照します。[2]
そして、それは機能の小さなセットのエスケープ構文を定義するだけで、それらのどれにも適用できないように見えます?
:
JDBC では、次のエスケープ構文が定義されています。
- スカラー関数
- 日付と時刻のリテラル
- 外部結合
- ストアド プロシージャの呼び出し
- LIKE 句のエスケープ文字[3]
全体として、JDBC 仕様は非常に「厳密な」言語を持っているようには見えません (たとえば、mustとshouldを多く使用する W3C 仕様ドキュメントと比較して) ?
。 escaped は技術的に準拠していませんが、互換性はおそらくありません。
?
実際にSQLステートメントを解析するドライバーのメソッドはエスケープ文字をチェックしないため、Postgresドライバーでさえそれを許可するようには見えません。
1. JDBC 4.1 仕様、セクション 13.2 —PreparedStatement
インターフェース
2. JDBC 4.1 仕様、セクション 13.3.2 — パラメータの設定
3. JDBC 4.1 仕様、セクション 13.4 — エスケープ構文