Exception: PostgrestException(message: there is no unique or exclusio
💡Tips
Supabaseにデータを追加しようとするとエラーが出た???
ポリシーの許可以外に、Columnに制約をつける必要があったみたいだ...
今回だと、user_name
というのに必要だった。
error log
ter: ----------------FIREBASE CRASHLYTICS---------------- flutter: Exception: PostgrestException(message: there is no unique or exclusion constraint matching the ON CONFLICT specification, code: 42P10, details: Bad Request, hint: null) flutter: #0 InputMyPage.build. (package:work_stream/supabase_pj/view/page/input_my_page.dart:218:23) flutter: -----------
AIに聞いてみた
エラーメッセージは、ON CONFLICT指定に一致する一意または排他制約がないことを示しています。これは、upsert操作で指定したonConflictパラメータが、データベースのテーブルに存在する一意性制約または排他制約と一致しないために発生します。
あなたのコードでは、onConflictパラメータに'user_name'が指定されています。これは、'user_name'カラムに一意性制約が存在することを前提としています。しかし、エラーメッセージから判断すると、そのような制約が存在しないようです。
この問題を解決するためには、以下の2つの方法が考えられます:
データベースのスキーマを変更して、'user_name'カラムに一意性制約を追加します。これにより、同じ'user_name'を持つ複数のレコードが存在しないことが保証されます。
コードを変更して、onConflictパラメータに一意性制約または排他制約が存在するカラム名を指定します。これは、'user_name'カラムに一意性制約を追加することが適切でない場合に適しています。
どちらの方法を選択するかは、あなたのアプリケーションの要件とデータベースの現在の状態によります。
SQLのクエリを直接実行して制約をつけるのが簡単だったので、これを実行した。
ALTER TABLE users
ADD CONSTRAINT unique_user_name UNIQUE (user_name);
今回使ったメソッドは、uuidと自動生成されるidの他に色々データを保存するメソッドですね。実験用に作ったのですけど、uuidがテーブルにないと、ログインしているユーザーを特定する情報がないので、追加しました💦
// ユーザーの新規登録
Future<void> createUserOrUpdate(
String userName,
String dateText,
String iconImagePath,
String profile,
String jobId,
) async {
try {
final session = SupabaseInstance().supabase.client.auth.currentSession;
final user = session?.user;
if (user?.id == null) {
throw Exception('User ID is null');
}
final jaUtc = DateTime.now().toUtc().toIso8601String();
await SupabaseInstance().supabase.client.from('users').upsert(
{
'uuid': user?.id,
'user_name': userName,
'birthday': dateText,
'iconImagePath': iconImagePath,
'job_id': jobId,
'profile': profile,
'created_at': jaUtc,
'updated_at': jaUtc,
'is_delete': false,
},
onConflict: 'user_name',
);
} on Exception catch (e) {
logger.d('😇createUserOrUpdate error: $e');
rethrow;
}
}
一応保存できた💦
まとめ
今回の記事は、Dartのロジックというより、Supabaseのエラーでハマったのでその解決方法を試してみた記事でした。気をつけることは、テーブル定義とColumnに名前が一致した引数をメソッドに書き忘れないようにすることです。
テーブル定義するとこんな感じですね。重要なのは、uuid
が必要だってことと今回は、user_name
に制約をつけることでしたね。
Column Name | Data Type | Constraints |
---|---|---|
uuid | UUID | PRIMARY KEY |
user_name | VARCHAR(255) | NOT NULL, UNIQUE |
birthday | DATE | |
iconImagePath | TEXT | |
job_id | INT | |
profile | TEXT | |
created_at | TIMESTAMP WITH TIME ZONE | |
updated_at | TIMESTAMP WITH TIME ZONE | |
is_delete | BOOLEAN | DEFAULT FALSE |
Discussion