get_exam_student_papers()#

Belirtilen sınava ait tüm öğrenci kağıtlarını (student papers) detaylı bilgileriyle birlikte getiren fonksiyon.


Fonksiyon İmzası#

CREATE OR REPLACE FUNCTION get_exam_student_papers(p_exam_id INTEGER)
RETURNS TABLE(...)
STABLE SECURITY DEFINER
SET search_path TO 'public'

Amaç#

Bir sınava yüklenmiş tüm öğrenci kağıtlarını listeler. Her kağıt için öğrenci bilgileri, AI ve öğretmen puanları, OCR sonuçları ve durum bilgilerini içerir. Sonuçlar öğrenci ismine göre alfabetik sıralanır.


Parametreler#

ParametreTipAçıklama
p_exam_idINTEGERKağıtları listelenecek sınavın ID’si

Dönüş Değeri#

Type: TABLE

Kolonlar#

KolonTipAçıklama
paper_idINTEGERKağıt ID’si
student_idINTEGERÖğrenci ID’si (NULL olabilir)
student_nameVARCHARÖğrenci adı
student_emailVARCHARÖğrenci e-posta
student_school_numberVARCHAROkul numarası
ai_scoreDOUBLE PRECISIONAI tarafından verilen puan
teacher_scoreDOUBLE PRECISIONÖğretmen puanı
feedbackTEXTÖğretmen yorumu
evaluation_summaryTEXTDeğerlendirme özeti
ocr_student_infoJSONBOCR’dan çıkarılan öğrenci bilgisi
ocr_all_papersJSONBTüm sayfaların OCR sonuçları
comparison_resultJSONBCevap anahtarıyla karşılaştırma sonucu
statusTEXTKağıt durumu (pending, processing, completed)
uploaded_atTIMESTAMPYüklenme zamanı
updated_atTIMESTAMPSon güncellenme

SQL Kodu#

CREATE OR REPLACE FUNCTION public.get_exam_student_papers(p_exam_id integer)
 RETURNS TABLE(
   paper_id integer, 
   student_id integer, 
   student_name character varying, 
   student_email character varying, 
   student_school_number character varying, 
   ai_score double precision, 
   teacher_score double precision, 
   feedback text, 
   evaluation_summary text, 
   ocr_student_info jsonb, 
   ocr_all_papers jsonb, 
   comparison_result jsonb, 
   status text, 
   uploaded_at timestamp with time zone, 
   updated_at timestamp with time zone
 )
 LANGUAGE plpgsql
 STABLE SECURITY DEFINER
 SET search_path TO 'public'
AS $function$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM exams WHERE id = p_exam_id) THEN
    RAISE EXCEPTION 'Sınav bulunamadı: %', p_exam_id;
  END IF;

  RETURN QUERY
  SELECT 
    sp.id as paper_id,
    sp.student_id,
    u.name as student_name,
    u.email as student_email,
    u.school_number as student_school_number,
    sp.ai_score,
    sp.teacher_score,
    sp.feedback,
    sp.evaluation_summary,
    sp.ocr_student_info,
    sp.ocr_all_papers,
    sp.comparison_result,
    sp.status::text,
    sp.uploaded_at,
    sp.updated_at
  FROM student_papers sp
  LEFT JOIN users u ON sp.student_id = u.id
  WHERE sp.exam_id = p_exam_id
  ORDER BY 
    CASE 
      WHEN u.name IS NOT NULL THEN 0
      ELSE 1
    END,
    u.name ASC,
    sp.uploaded_at DESC;
END;
$function$

Kullanım Örneği#

Projede Kullanım#

Dosya: lib/common/services/api/exam_api.dart
Satır: ~233-242
Açıklama: Exam API servisinde sınava yüklenmiş öğrenci kağıtlarını listelemek için kullanılır.

/// Calls: get_exam_student_papers(p_exam_id)
final response = await _supabase.rpc(
  'get_exam_student_papers',
  params: {'p_exam_id': examId}
);

SQL Örneği#

-- Sınavın tüm kağıtlarını listele
SELECT * FROM get_exam_student_papers(42);

-- Sadece belirli kolonları getir
SELECT paper_id, student_name, ai_score, teacher_score, status
FROM get_exam_student_papers(42);

-- Sadece değerlendirme tamamlanmış kağıtlar
SELECT * FROM get_exam_student_papers(42)
WHERE status = 'completed';

-- AI puanı 80'den yüksek olanlar
SELECT student_name, ai_score
FROM get_exam_student_papers(42)
WHERE ai_score > 80
ORDER BY ai_score DESC;

Sıralama Mantığı#

ORDER BY 
  CASE 
    WHEN u.name IS NOT NULL THEN 0  -- Öğrencisi tanımlı olanlar önce
    ELSE 1                           -- Öğrencisi tanımlanmayanlar sonda
  END,
  u.name ASC,                        -- Alfabetik sıralama
  sp.uploaded_at DESC                -- Aynı öğrencinin birden fazla kağıdı varsa en yeni önce

JSON Alanları#

ocr_student_info#

{
  "name": "Ahmet Yılmaz",
  "school_number": "12345",
  "class": "10-A",
  "confidence": 0.95
}

ocr_all_papers#

{
  "pages": [
    {
      "page_number": 1,
      "text": "OCR çıktısı...",
      "answers": {
        "1": "A",
        "2": "C",
        "3": "B"
      }
    }
  ]
}

comparison_result#

{
  "total_questions": 20,
  "correct_answers": 15,
  "wrong_answers": 3,
  "empty_answers": 2,
  "score": 75.0,
  "details": [
    {
      "question": 1,
      "student_answer": "A",
      "correct_answer": "A",
      "is_correct": true
    }
  ]
}

Durum (Status) Değerleri#

StatusAçıklama
pendingKağıt yüklendi, henüz işlenmedi
processingOCR ve AI değerlendirmesi yapılıyor
completedDeğerlendirme tamamlandı
errorİşlem sırasında hata oluştu

Özellikler#

  • LEFT JOIN: Öğrencisi tanımlanmamış kağıtları da gösterir
  • NULL handling: student_id NULL olabilir
  • STABLE: Aynı parametreyle aynı sonucu döner (cache-friendly)
  • SECURITY DEFINER: Owner yetkisiyle çalışır
  • Sıralı sonuç: İsimli kağıtlar önce, alfabetik

Hata Kontrolü#

-- Sınav yoksa hata fırlatır
IF NOT EXISTS (SELECT 1 FROM exams WHERE id = p_exam_id) THEN
  RAISE EXCEPTION 'Sınav bulunamadı: %', p_exam_id;
END IF;

İlgili Tablolar#

  • public.student_papers
  • public.exams
  • public.users
  • public.student_paper_files (dolaylı)

Performans İpuçları#

  1. Index kullanımı:
CREATE INDEX idx_student_papers_exam_id ON student_papers(exam_id);
CREATE INDEX idx_student_papers_student_id ON student_papers(student_id);
  1. Filtreleme:
-- Tüm kağıtları değil, sadece gerekli olanları getir
SELECT * FROM get_exam_student_papers(42)
WHERE status = 'completed';

İlgili Fonksiyonlar#

  • get_answer_key_details() - Sınavın cevap anahtarını getir
  • get_exam_student_papers() - Bu fonksiyon