Programming and my thoughts

percentile.c

extension-functions.c

SQLite 에서 기본적으로 지원하지 않는 함수들을 이용하려면 아래와 같은 방법을 이용할 수 있다.

1) SQLIte.Interop.dll 에 등록된 확장 함수의 경우 아래의 방법을 이용하자.

using (SQLiteConnection conn = new SQLiteConnection("Data Source=:memory:;"))
{
    conn.Open();
    conn.EnableExtensions(true);
    conn.LoadExtension("SQLite.Interop.dll", "sqlite3_percentile_init");
}

참고로, SQLite.Interop.dll 은 SQLIte 동작에 필요한 필수 파일중에 하나이다.
이미 이 파일안에 여러 확장함수들이 포함되어 있다. ( 내가 사용하려고 했던 확장함수도 이미 있었다, 예) percentile )
다만, 기본적으로 OFF 되어있으니 위와 같이 ON 해주는 센스가 필요하다.

2) 라이브러리를 빌드하여 런타임에 연동하는 방법

https://sqlite.org/loadext.html

위 링크의 Compiling A Loadable Extension 자세히 설명되어 있다.
참고로, 나는 gcc -g -shared YourCode.c -o YourCode.dll 이걸로 빌드했다.

이렇게 빌드한 다음, 1) 과 같은 코드를 추가하면 해당 확장함수들을 이용할 수 있다.

어떤 라이브러리 함수들은 아래와 같이 c 코드에서 dllexport 로 선언된 부분을 LoadExtension 함수의 두번째 파라메터로 넣어줘야 사용할 수 있다.
포스팅의 percentile.c 파일이 이 경우에 해당한다.
conn.LoadExtension("percentile.dll", "sqlite3_percentile_init"); 이렇게 호출하자.

반면… extension_functions.c 파일의 경우에는 두번째 파라메터를 넣을 필요가 없다.
즉, 빌드한 라이브러 파일이 ex.dll 인 경우, conn.LoadExtension(@"d:\ex.dll"); 이렇게만 하면 된다.

#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_percentile_init(
  sqlite3 *db, 
  char **pzErrMsg, 
  const sqlite3_api_routines *pApi
){
  int rc = SQLITE_OK;
  SQLITE_EXTENSION_INIT2(pApi);
  (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "percentile", 2, SQLITE_UTF8, 0,
                               0, percentStep, percentFinal);
  return rc;
}

3) 라이브러리를 정적으로 연동하여 사용하는 방법

https://sqlite.org/loadext.html
https://sqlite.org/c3ref/auto_extension.html

위 두 곳에 간략하게 언급되어 있는데,
만약 SQLite 커넥션을 여러번 열어서 다양한 확장함수들을 사용해야 하는 경우…
매번 1), 2) 와 같은 방법을 이용하기 보다는… 정적으로 연동하여 사용하는 것이 좋다.

SQLIte 소스를 수정하여 빌드해야 하는 것 같다. (나는 해보진 않았다)


본 포스팅이 SQLIte 를 이용하는 많은 분들에게 도움이 되면 좋겠습니다.