#lang racket/base
(require racket/class
         db/private/sqlite3/connection)
(provide
 (protect-out sqlite3-load-extension
              sqlite3-create-function
              sqlite3-create-aggregate))

(define (sqlite3-load-extension c ext-path)
  (define who 'sqlite3-load-extension)
  (unless (is-a? c connection%)
    (raise-argument-error who "sqlite3 connection" 0 c ext-path))
  (unless (path-string? ext-path)
    (raise-argument-error who "path-string?" 1 c ext-path))
  (send c unsafe-load-extension who ext-path)
  (void))

(define (sqlite3-create-function c name arity proc)
  (define who 'sqlite3-create-function)
  (define (bad index expected)
    (raise-argument-error who expected index c name arity proc))
  (unless (is-a? c connection%)
    (bad 0 "sqlite3 connection"))
  (unless (or (string? name) (symbol? name))
    (bad 1 "(or/c string? symbol?)"))
  (unless (or (exact-nonnegative-integer? arity) (eq? arity #f))
    (bad 2 "(or/c exact-nonnegative-integer? #f)"))
  (unless (procedure? proc)
    (bad 3 "procedure?"))
  (let ([name (if (symbol? name) (symbol->string name) name)])
    (send c unsafe-create-function who name arity proc))
  (void))

(define (sqlite3-create-aggregate c name arity init step final)
  (define who 'sqlite3-create-aggregate)
  (define (bad index expected)
    (raise-argument-error who expected index c name arity step final init))
  (unless (is-a? c connection%)
    (bad 0 "sqlite3 connection"))
  (unless (or (string? name) (symbol? name))
    (bad 1 "(or/c string? symbol?)"))
  (unless (or (exact-nonnegative-integer? arity) (eq? arity #f))
    (bad 2 "(or/c exact-nonnegative-integer? #f)"))
  (unless (procedure? step)
    (bad 3 "procedure?"))
  (unless (procedure? final)
    (bad 4 "procedure?"))
  (let ([name (if (symbol? name) (symbol->string name) name)])
    (send c unsafe-create-aggregate who name arity step final init))
  (void))
