Verticaのユーザー定義関数をR言語で実装する

## 概要
VerticaのUDF（ユーザー定義関数）を、R言語で実装する方法メモ。
62進数を10進数に変換する関数を実装します。

## 関連記事
- [言語別、62進数<->10進数の変換スクリプトたち (R, Python, Java)](https://qiita.com/Esfahan/items/2f1a919a3fd361ff64ae)

## 関数を作成
`decode_decimal62`がメインの関数で、`decode_decimal62Factory`というFactoryという関数で、メインの関数の設定をする必要があるみたい。

```r:/home/user/decode_decimal62.r
# メインの、62進数を10進数に変換する関数
decode_decimal62 <- function(x, y) {
    # 変換対象62進数
    str <- as.character(x[,1])
    str_list <- unlist(strsplit(str, split = ""))
    # base62
    chars=c(0:9, letters, LETTERS)
    # length = 62
    base <- length(chars)

    # optional parameter
    version <- ifelse(!is.null(y[['version']]), as.character(y[['version']]), '')
    if (version > 1) {
        num <- 0
        for (char in str_list) {
            num <- num * base + which(chars == char) - 1
        }
        num
    } else {
        as.integer(str)
    }
}

# optional paramters
decode_decimal62Parameters <- function()　{
    params <- data.frame(
                         datatype=rep(NA, 1),
                         length=rep(NA,1),
                         scale=rep(NA,1),
                         name=rep(NA,1)
    )
    # y[['version']]で取り出す
    params[1,1] = "int"
    params[1,4] = "version"
    params
}

# メインの関数の設定をする関数
decode_decimal62Factory <- function()　{
    list ( name = decode_decimal62,
           # scalarかtransformを選択する。
           udxtype = c("scalar"),
           # メインの関数の引数の型。複数ある場合はカンマ区切りで指定
           intype = c("varchar"),
           # 戻り値の型
           outtype = c("int"),
           # 実際にSQLで使用するときの関数名を指定
           outnames = c("udfDecodeDecimal62"),
           # optional paramters
           parametertypecallback = decode_decimal62Parameters
         )
}
```

## Create
関数を登録します。

`LIBRARY DecodeDecimal62Lib`の部分は、任意のライブラリ名を付ける。
`FUNCTION udfDecodeDecimal62`の部分は、RScriptの`decode_decimal62Factory`関数の`outnames`で指定した名前を付ける。

```sql
CREATE OR REPLACE LIBRARY DecodeDecimal62Lib AS '/home/user/decode_decimal62.r' LANGUAGE 'R';
CREATE OR REPLACE FUNCTION udfDecodeDecimal62 AS LANGUAGE 'R' NAME 'decode_decimal62Factory' LIBRARY DecodeDecimal62Lib;
```

## 実行
引数に62進数を入れて実行すると、10進数になって返ってきました。

オプション引数あり

```sql
vertica=> select udfDecodeDecimal62('3d7' USING PARAMETERS version = 2);
-[ RECORD 1 ]------+------
udfDecodeDecimal62 | 12345
```

オプション引数なし

```sql
vertica=> select udfDecodeDecimal62('54321');
-[ RECORD 1 ]------+------
udfDecodeDecimal62 | 54321
```

以上

## 参考
- [Vertica – Writing simple and effective User Defined Functions: normal distribution](https://www.linkedin.com/pulse/vertica-writing-simple-effective-user-defined-functions-felici)
- [vertica/UDx-Examples](https://github.com/vertica/UDx-Examples/blob/master/Java-and-C%2B%2B/JavaFunctions.sql)
- [Verticaでファンクション機能を利用する方法](http://vertica-tech.ashisuto.co.jp/create_function/)
- [Creating R Functions](https://my.vertica.com/docs/7.0.x/HTML/Content/Authoring/ProgrammersGuide/UserDefinedFunctions/UDxR/CreatingRFunctions.htm)
- [parametertypecallback Function](https://my.vertica.com/docs/8.1.x/HTML/index.htm#Authoring/R-SDK/RParameterCallbackFunction.htm)
- [Using R function in Vertica](https://bineeshthomas.wordpress.com/2015/09/03/using-r-function-in-vertica/)