以优雅的方式在sqlite数据库中创建自定义SQL函数
这里说的SQL函数,是指可在SQL语句中使用的函数,如常见的 count(),sum(),avg(),min(),max() 等。 在 sqlite 数据库中,SQL函数被分为两大类,一类称作“Scalar function”,一类称作“Aggregate function”。Scalar 和 Aggregate 实在不太清楚该怎么翻译,而其含义,也难于用言语表达,大概属于只可意会不可言传的情况。通俗来说,Scalar函数基本等同于C/C++函数,而上面提到的 count(),sum() 等函数则属于Aggregate函数。Aggregate函数不是根据参数直接得出结果,而是综合了符合条件的所有记录才最终计算出结果。 在 sqlite 中创建自定义SQL函数,需涉及以下接口函数: int sqlite3_create_function( void *sqlite3_user_data(sqlite3_context*); void *sqlite3_aggregate_context(sqlite3_context*,int nBytes); const void *sqlite3_value_blob(sqlite3_value*); void sqlite3_result_blob(sqlite3_context*,const void*,void(*)(void*)); 要编写sqlite3_create_function()所需的三个函数xFunc(),xStep(),xFinal(),不得不使用上面一堆接口函数,比较复杂的说。如果仅仅是单纯的将以上函数一一对应到EF中,无疑是把复杂的工作转稼给用户,意义不大。(值得一提的是,在易语言的sqlite支持库中,因为没有找到比较优雅的解决方案,未提供创建自定义SQL函数的功能。) 通过对sqlite api进行包装和再加工,我们在“易语言.飞扬”中提供了简洁易用的、面向对象的、优雅的操作接口,在很大程度上简化了创建自定义SQL函数的工作。 在“易语言.飞扬”中,要创建一个“Scalar function”,只需调用 SqliteDB.RegSQLScalarFunc(),传入一个实现了接口 SQLScalarFunction 的对象即可: public interface SQLScalarFunction{ public 文本取函数名称(); public 整数取参数个数(); public 通用型,整数执行(通用型[]参数); } 用户的工作主要集中在接口方法“通用型,整数执行(通用型[]参数)”中(对应前面提到的xFunc),只需根据通用型数组参数计算出结果并返回即可。在这之前通过调用sqlite3_value_*系列函数获取SQL参数,以及在这之后调用sqlite3_result_*系列函数将结果反馈到sqlite的工作,全部由类库代劳。用户接口非常简洁。 在“易语言.飞扬”中,要创建一个“Aggregate function”,只需调用 SqliteDB.RegSQLAggregateFunc(),传入一个实现了接口 SQLAggregateFunction 的对象即可: public interface SQLAggregateFunction{ public 文本取函数名称(); public 整数取参数个数(); public SQLAggregateExecutor创建执行者(); } public interface SQLAggregateExecutor { public 通用型,整数单步执行(通用型[]参数); public 通用型,整数最终执行(); } 在一个Aggregate function被调用时,将自动调用“SQLAggregateFunction.创建执行者()”为该函数创建一个“执行者”对象(实现接口SQLAggregateExecutor)。为什么要创建“执行者”对象呢?因为Aggregate function是“上下文有关的”,每个函数调用都需要单独维护各自的上下文信息。接口SQLAggregateExecutor中的方法“单步执行”“最终执行”分别对应前面提到的xStep,xFinal,聪明的您也许已经猜测到了。 “易语言.飞扬”sqlite类库(sqlite.efn)提供的以上接口,简洁易用、通俗易懂、面向对象、优雅大方,完全摆脱了sqlite api 的影子,是对原有接口的精心再加工,充分体现了我们“将复杂的事情简单化”的决心。 (注,以上涉及的类型名称和方法名称中英混用,也许是需要最终调整和完善的地方。) 根据以上接口,我们可以很轻松的实现自已版本的 sum() 函数——mysum(): public class MySum < interfaces = SQLAggregateFunction >{ public 文本取函数名称(){返回 " mysum " ;} public 整数取参数个数(){返回 1 ;} public SQLAggregateExecutor创建执行者(){返回 new MySumExecutor();} class MySumExecutor < interfaces = SQLAggregateExecutor > { private int _sum = 0 ; public 通用型,整数单步执行(通用型[]参数) { _sum += 参数[ 0 ]; } public 通用型,整数最终执行(){返回(_sum, 0 );}}} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |