イントレ。
ユーザー定義関数がかなり有用な予感。
SQL文のRandom()とかSum()とかCount()みたいなのを独自に定義出来る。
System.Data.SQLiteを使うと、ユーザー関数をC#側からも定義出きます。
基本的には以下の流れ。
・SQLiteFunctionを継承したクラスを作成し
・SQLiteFunction属性をつける
・SQLiteFunction.RegisterFunction()で登録
呼ぶときはSQL文に普通に記述すればいい。
たとえば、「SELECT * FROM test ORDER BY value COLLATE NETFX_COLLATE」みたいな。
まずはCollation。
ORDER BY ~ COLLATEに使う文字の比較を定義出きます。
オーバーライドするのはCompare()だけでいいみたい。
[SQLiteFunction(Name="NETFX_COLLATE", FuncType=FunctionType.Collation)]
class NETFX_COLLATE : SQLiteFunction
{
public override int Compare(string param1, string param2)
{
return StringComparer.CurrentCulture.Compare(param1, param2);
}
}
Exolorerの文字ソートみたいに数字を考慮するならStrCmpLogicalW()を使ってこんなことも。
[SQLiteFunction(Name="Logical_COLLATE", FuncType=FunctionType.Collation)]
class Logical_COLLATE : SQLiteFunction
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
static extern int StrCmpLogicalW(string str1, string str2);
public override int Compare(string param1, string param2)
{
return StrCmpLogicalW(param1, param2);
}
}
次、Scaler。
Random()とかLower()とかみたいなやつ。
Argumentsには要求する引数の数。-1で可変数にも出来るみたい。
オーバーライドするのはInvoke()メソッド。
[SQLiteFunction(Name="NETFX_RANDOM", FuncType=FunctionType.Scalar, Arguments=0)]
class NETFX_RANDOM : SQLiteFunction
{
readonly static Random rand = new Random();
public override object Invoke(object[] args)
{
return rand.Next();
}
}
最後にAggregate。
Sum()とかCount()みたいに、結果を捜査して出力を返すタイプのもの。
Step()でコンテキストインスタンスを渡して値を保持しておきます。
Step()が必要回数呼ばれて、最後にFinal()が呼ばれます。
[SQLiteFunction(Name = "NETFX_Sum", FuncType = FunctionType.Aggregate, Arguments = 1)]
class NETFX_Sum : SQLiteFunction
{
class Context
{
public decimal Value = 0;
}
public override void Step(object[] args, int stepNumber, ref object contextData)
{
var data = (contextData as Context) ?? (Context)(contextData = new Context());
data.Value += Convert.ToDecimal(args[0]);
}
public override object Final(object contextData)
{
var data = contextData as Context;
return (data == null) ? null : (object)data.Value;
}
}
あーしかしやばいなー。
これは便利すぎる。
SQL文のRandom()とかSum()とかCount()みたいなのを独自に定義出来る。
System.Data.SQLiteを使うと、ユーザー関数をC#側からも定義出きます。
基本的には以下の流れ。
・SQLiteFunctionを継承したクラスを作成し
・SQLiteFunction属性をつける
・SQLiteFunction.RegisterFunction()で登録
呼ぶときはSQL文に普通に記述すればいい。
たとえば、「SELECT * FROM test ORDER BY value COLLATE NETFX_COLLATE」みたいな。
まずはCollation。
ORDER BY ~ COLLATEに使う文字の比較を定義出きます。
オーバーライドするのはCompare()だけでいいみたい。
[SQLiteFunction(Name="NETFX_COLLATE", FuncType=FunctionType.Collation)]
class NETFX_COLLATE : SQLiteFunction
{
public override int Compare(string param1, string param2)
{
return StringComparer.CurrentCulture.Compare(param1, param2);
}
}
Exolorerの文字ソートみたいに数字を考慮するならStrCmpLogicalW()を使ってこんなことも。
[SQLiteFunction(Name="Logical_COLLATE", FuncType=FunctionType.Collation)]
class Logical_COLLATE : SQLiteFunction
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
static extern int StrCmpLogicalW(string str1, string str2);
public override int Compare(string param1, string param2)
{
return StrCmpLogicalW(param1, param2);
}
}
次、Scaler。
Random()とかLower()とかみたいなやつ。
Argumentsには要求する引数の数。-1で可変数にも出来るみたい。
オーバーライドするのはInvoke()メソッド。
[SQLiteFunction(Name="NETFX_RANDOM", FuncType=FunctionType.Scalar, Arguments=0)]
class NETFX_RANDOM : SQLiteFunction
{
readonly static Random rand = new Random();
public override object Invoke(object[] args)
{
return rand.Next();
}
}
最後にAggregate。
Sum()とかCount()みたいに、結果を捜査して出力を返すタイプのもの。
Step()でコンテキストインスタンスを渡して値を保持しておきます。
Step()が必要回数呼ばれて、最後にFinal()が呼ばれます。
[SQLiteFunction(Name = "NETFX_Sum", FuncType = FunctionType.Aggregate, Arguments = 1)]
class NETFX_Sum : SQLiteFunction
{
class Context
{
public decimal Value = 0;
}
public override void Step(object[] args, int stepNumber, ref object contextData)
{
var data = (contextData as Context) ?? (Context)(contextData = new Context());
data.Value += Convert.ToDecimal(args[0]);
}
public override object Final(object contextData)
{
var data = contextData as Context;
return (data == null) ? null : (object)data.Value;
}
}
あーしかしやばいなー。
これは便利すぎる。
Loading...
Utilities
- タグ
- カレンダー
- 最近の更新
- Adsense