RSQLiteで扱うテーブルの最大カラム数を変更する

# はじめに
Rで行数、列数が想定外に多いcsvを取り扱う必要があり、その際に試行錯誤したときの忘備録。

# やったこと
CSVを単にtidyverse系のパッケージで取り込むにもメモリを喰いすぎるし、動作も重くなるので、DBに突っ込んで使いやすく加工すればいいのではと考えた。
↓
とはいえ、DBサーバたてたりとかはさずがに面倒なので、SQLiteを使えるRSQLiteのパッケージを使うことに。
↓
しかし、通常通りにインストールすると列数が2000を超えたデータはSQLiteの制限に引っかかって取り込めず。
↓
SQLiteはRSQLiteにバンドルされてるってんで、インストール後に変更は難しそうなので、RSQLiteのソースをDLして、SQLiteのソースに手を加えてから、ビルドしてインストールすることにした。

# 環境
Linux(Ubuntu)
R 4.1.2
RSQLite 2.2.18

# 通常通りにRSQLiteをインストールして読み込ませた場合
- 32766列の適当なcsvファイルを作成する
```bash
for i in `seq 1 32766`; do if [ ${i} -ne 32766 ]; then echo -n A${i}, >> temp.csv; else echo A${i} >> temp.csv; fi; done
for i in `seq 1 32766`; do if [ ${i} -ne 32766 ]; then echo -n ${i}, >> temp.csv; else echo ${i} >> temp.csv; fi; done
```
- Rを起動し、上で作成したCSVを読み込ませる
```R
library(DBI)
library(tidyverse)

con <- dbConnect(RSQLite::SQLite(), "temp.sqlite3")
callback <- function(df, pos) {
   dbWriteTable(con, "temp_table", df, append = TRUE)
}
read_csv_chunked("temp.csv", DataFrameCallback$new(callback))
```
- 下のエラーメッセージが出て取り込めず
```
 エラー: too many columns on temp_table
```

大規模データの取り込みに参考にさせていただいたサイトはこちら。

https://connecto-data.com/archives/391

# テーブルの最大カラム数を変更したRSQLiteをインストール
## RSQLiteのソースデータをダウンロード
Rを起動して以下を実行
```R
download.packages(pkgs = 'RSQLite', destdir = ".",type = "source")
```
（試行時にDLできたのは、``RSQLite_2.2.18.tar.gz``）

## tar.gzを解凍
Rは一度終了し、DLしたファイルを解凍
```bash
tar -zxvf RSQLite_2.2.18.tar.gz
```
カレントディレクトリに``RSQLite``のディレクトリができる

## sqlite3.cを書き換える
```bash
./RSQLite/src/vendor/sqlite3/sqlite3.c
```
を開いて、下の部分を探す
```c
#ifndef SQLITE_MAX_COLUMN
# define SQLITE_MAX_COLUMN 2000
#endif
```
↑の部分を↓のように書き換える
```c
#ifndef SQLITE_MAX_COLUMN
# define SQLITE_MAX_COLUMN 32766
#endif
```
:::note warn
32767より大きい値を設定するとエラーで弾かれそうです
:::

## DESCRIPTIONも書き換える
パッケージのバージョンが混在しないようにするため、DESCRIPTIONも書き換えときます。
<b>※知識不足なので正しいやり方かどうかはわかりません。正しくはこうすべきってのがあれば教えてください。</b>
```bash
./RSQLite/DESCRIPTION
```
を開いて、下の部分を探す
```
Version: 2.2.18
```
↑の部分を↓のように書き換える
```
Version: 2.2.18.1
```
末尾に「.1」を追加しただけ
バージョンには数字と記号（「.」、「-」）しか使えなさげ？でした。（詳細わかりません）

## devtoolsでビルド
Rを起動し、以下を実行
```
devtools::build("RSQLite")
```
実行すると
```
Building the package will delete...
  '~~~~~~~~/RSQLite/inst/doc'
Are you sure?

1: Yes
2: No

Selection:
```
と聞かれたので、「1」を入力し、Enter

:::note warn
ここで私の環境では実行時にPandocがないと言われましたが、Pandocをインストールすれば通りました。
:::

成功するとカレントディレクトリに``RSQLite_2.2.18.1.tar.gz``が作成される

## RSQLiteをインストール
Rを起動して以下を実行
```R
install.packages("RSQLite_2.2.18.1.tar.gz", repos = NULL)
```

## これでRSQLiteで32766列以下のデータは扱えるはず

# 編集したRSQLiteをインストールした状態で、再度csvファイルを読み込ませる
- Rを起動し、CSVを読み込ませる
```R
library(DBI)
library(tidyverse)

con <- dbConnect(RSQLite::SQLite(), "temp.sqlite3")
callback <- function(df, pos) {
   dbWriteTable(con, "temp_table", df, append = TRUE)
}
read_csv_chunked("temp.csv", DataFrameCallback$new(callback))
```
<b>読み込める！！</b>
- 一応確認
```R
dbListFields(con, 'temp_table')
    [1] "A1"     "A2"     "A3"     "A4"     "A5"     "A6"     "A7"     "A8"
    [9] "A9"     "A10"    "A11"    "A12"    "A13"    "A14"    "A15"    "A16"
   [17] "A17"    "A18"    "A19"    "A20"    "A21"    "A22"    "A23"    "A24"
                                    ・
                                    ・
                                    ・
[32745] "A32745" "A32746" "A32747" "A32748" "A32749" "A32750" "A32751" "A32752"
[32753] "A32753" "A32754" "A32755" "A32756" "A32757" "A32758" "A32759" "A32760"
[32761] "A32761" "A32762" "A32763" "A32764" "A32765" "A32766"
```
# Windowsの場合どうやるのかわからん
似たような方法でできるとは思うが、申し訳ない…。

# さいごに
本来正しく正規化されたデータであれば、このような列数は必要ないかと思う。
が、現実には「え…？」と思うようなCSVファイル等が渡されるわけで…。
こんな感じでデータベースに取り込んで、一度に全ての列を使うわけでもなければ、SELECT分なりでいい感じに列を抜き出してデータ眺めたり、加工したり、解析したりしてみたらいいと思います。