00001 using System;
00002 using System.IO;
00003 using System.Runtime.InteropServices;
00004
00005
00006 namespace SQLiteCSLib.Inner
00007 {
00011 public class OSQLiteFunc : IDisposable
00012 {
00016 GCHandle m_funcpoint ;
00017 GCHandle m_steppoint ;
00018 GCHandle m_finalpoint ;
00019
00023 protected OSQLiteDBWrap m_db;
00024
00028 protected ICallUserFunction m_callinterface;
00029
00033 unsafe protected delegate void CallFuncDelegate( IntPtr context,int argc, void** inparams );
00034 unsafe protected delegate void CallStepDelegate( IntPtr context,int argc, void** inparams );
00035 unsafe protected delegate void CallFinalDelegate( IntPtr context );
00036
00037 #if MOBILEPC
00038
00042 protected IntPtr m_disposeevent = IntPtr.Zero;
00043
00047 protected IntPtr m_clrevent;
00048
00052 protected IntPtr m_nativepoint ;
00053 #endif
00054
00058 public OSQLiteFunc( OSQLiteDBWrap db, ICallUserFunction iCallinterface )
00059 {
00060 m_db = db;
00061 m_callinterface = iCallinterface;
00062
00063 unsafe
00064 {
00065 m_funcpoint = GCHandle.Alloc( new CallFuncDelegate( CallFunc ) );
00066 m_steppoint = GCHandle.Alloc( new CallStepDelegate( CallStep ) );
00067 m_finalpoint = GCHandle.Alloc( new CallFinalDelegate( CallFinal ) );
00068 }
00069
00070 #if MOBILEPC
00071 m_disposeevent = CreateEvent( IntPtr.Zero , true, false, IntPtr.Zero );
00072 #endif
00073 }
00074
00078 ‾OSQLiteFunc()
00079 {
00080 Dispose();
00081 }
00082
00086 public void Dispose()
00087 {
00088 #if MOBILEPC
00089 EventModify( m_disposeevent, 3 );
00090 CloseHandle( m_disposeevent );
00091 CloseHandle( m_clrevent );
00092 #endif
00093
00094 if( m_db != null )
00095 {
00096 m_funcpoint.Free();
00097 m_steppoint.Free();
00098 m_finalpoint.Free();
00099 m_db = null;
00100 m_callinterface = null;
00101 }
00102 }
00103
00104
00105
00106
00107 public ResultEnum CreateFunction( string funcname, int inArg )
00108 {
00109 #if MOBILEPC
00110 m_clrevent = CreateEvent( IntPtr.Zero , false, false, IntPtr.Zero );
00111
00112
00113 System.Threading.Thread thread = new System.Threading.Thread( new System.Threading.ThreadStart(OnCallBackThread) );
00114 thread.Start();
00115
00116 if( m_callinterface is IScalarCallUserFunction )
00117 {
00118
00119 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00120 m_clrevent, ref m_nativepoint, true, false, false );
00121 }
00122 else
00123 if( m_callinterface is IAggregateCallUserFunction )
00124 {
00125
00126 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00127 m_clrevent, ref m_nativepoint, false, true, true );
00128 }
00129
00130 return ResultEnum.ERROR;
00131 #else
00132 if( m_callinterface is IScalarCallUserFunction )
00133 {
00134
00135 unsafe
00136 {
00137 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00138 m_funcpoint.Target as CallFuncDelegate,
00139 null,null );
00140 }
00141 }
00142 else
00143 if( m_callinterface is IAggregateCallUserFunction )
00144 {
00145
00146 unsafe
00147 {
00148 return (ResultEnum)osqlite3_createfunction( m_db.internaldb(), funcname, inArg, (int)CAPI3REF.UTF16,
00149 null,
00150 m_steppoint.Target as CallStepDelegate,
00151 m_finalpoint.Target as CallFinalDelegate );
00152 }
00153 }
00154
00155 return ResultEnum.ERROR;
00156 #endif
00157 }
00158
00159 #if MOBILEPC
00160
00164 protected void OnCallBackThread()
00165 {
00166
00167 IntPtr[] handles = new IntPtr[2]{m_disposeevent,m_clrevent};
00168
00169 while( true )
00170 {
00171 int multiWaitRes = WaitForMultipleObjects( 2, handles, false, 3600000 );
00172 if( multiWaitRes == 0 )
00173 break;
00174 if( multiWaitRes == 1 )
00175 {
00176 IntPtr context = IntPtr.Zero;
00177 int argc = 0;
00178
00179 unsafe
00180 {
00181
00182 int iKind = osqlite3func_GetCallBackParam( m_nativepoint, ref argc );
00183
00184 switch( iKind )
00185 {
00186 case 1:
00187 {
00188
00189 CallFunc( context, argc, null );
00190 }
00191 break;
00192 case 2:
00193 {
00194
00195 CallStep( context, argc, null );
00196 }
00197 break;
00198 case 3:
00199
00200 CallFinal( context );
00201 break;
00202 }
00203
00204
00205 osqlite3func_FinishCallBackParam( m_nativepoint );
00206 }
00207 }
00208 }
00209 }
00210 #endif
00211
00218 unsafe protected virtual void CallFunc( IntPtr context,int argc, void** inparams )
00219 {
00220 IScalarCallUserFunction iScalar = m_callinterface as IScalarCallUserFunction;
00221 if( iScalar != null )
00222 {
00223 try
00224 {
00225 object returnval = iScalar.CallFunc( CreateParams(argc,inparams) );
00226 if( returnval != null )
00227 {
00228 SetResultValue( context, returnval );
00229 }
00230 }
00231 catch( CallUserException ex )
00232 {
00233 SetErrorResult( context, ex );
00234 }
00235 }
00236 }
00237
00244 unsafe protected virtual void CallStep( IntPtr context,int argc, void** inparams )
00245 {
00246 IAggregateCallUserFunction iAggregate = m_callinterface as IAggregateCallUserFunction;
00247 if( iAggregate != null )
00248 {
00249 try
00250 {
00251 iAggregate.CallStep( CreateParams(argc,inparams) );
00252 }
00253 catch( CallUserException ex )
00254 {
00255 SetErrorResult( context, ex );
00256 }
00257 }
00258 }
00259
00264 unsafe protected virtual void CallFinal( IntPtr context )
00265 {
00266 IAggregateCallUserFunction iAggregate = m_callinterface as IAggregateCallUserFunction;
00267 if( iAggregate != null )
00268 {
00269 try
00270 {
00271 object returnval = iAggregate.CallFinal();
00272 if( returnval != null )
00273 {
00274 SetResultValue( context, returnval );
00275 }
00276 }
00277 catch( CallUserException ex )
00278 {
00279 SetErrorResult( context, ex );
00280 }
00281 }
00282 }
00283
00284 #if MOBILEPC
00291 unsafe protected object[] CreateParams( int argc , void** inparams )
00292 {
00293 object[] argslist = new object[argc];
00294
00295 for( int iIdx=0; iIdx<argc; iIdx++ )
00296 {
00297 DATATYPE iType = (DATATYPE)osqlite3func_GetParamType( m_nativepoint, iIdx );
00298 switch( iType )
00299 {
00300 case DATATYPE.INTEGER:
00301 argslist[ iIdx ] = osqlite3func_GetParamInt( m_nativepoint, iIdx );
00302 break;
00303 case DATATYPE.FLOAT:
00304 {
00305 double dVal = 0.0;
00306 osqlite3func_GetParamDouble( m_nativepoint, iIdx, ref dVal );
00307 argslist[ iIdx ] = dVal;
00308 }
00309 break;
00310 case DATATYPE.BLOB:
00311 {
00312 int valsize = 0;
00313 IntPtr pBin = osqlite3func_GetParamBlob( m_nativepoint, iIdx, ref valsize );
00314
00315 byte[] managememory = new byte[valsize];
00316 Marshal.Copy( pBin, managememory, 0, valsize );
00317
00318 argslist[ iIdx ] = managememory;
00319 }
00320 break;
00321 case DATATYPE.DBNULL:
00322 argslist[ iIdx ] = null;
00323 break;
00324 case DATATYPE.TEXT:
00325 argslist[ iIdx ] = StringFromC.String( osqlite3func_GetParamText( m_nativepoint, iIdx ) );
00326 break;
00327 }
00328 }
00329
00330 return argslist;
00331 }
00332 #else
00339 unsafe protected object[] CreateParams( int argc , void** inparams )
00340 {
00341 object[] argslist = new object[argc];
00342
00343 for( int iIdx=0; iIdx<argc; iIdx++ )
00344 {
00345 void* val = inparams[ iIdx ];
00346
00347 if( val != null )
00348 {
00349 IntPtr context = new IntPtr(val);
00350
00351 DATATYPE iType = (DATATYPE)__sqlite3_value_type( context );
00352
00353 switch( iType )
00354 {
00355 case DATATYPE.INTEGER:
00356 argslist[ iIdx ] = __sqlite3_value_int64( context );
00357 break;
00358 case DATATYPE.FLOAT:
00359 argslist[ iIdx ] = __sqlite3_value_double( context ) ;
00360 break;
00361 case DATATYPE.BLOB:
00362 {
00363 IntPtr pBin = __sqlite3_value_blob( context );
00364 int valsize = __sqlite3_value_bytes( context );
00365
00366 byte[] managememory = new byte[valsize];
00367 Marshal.Copy( pBin, managememory, 0, valsize );
00368
00369 argslist[ iIdx ] = managememory;
00370 }
00371
00372 break;
00373 case DATATYPE.DBNULL:
00374 argslist[ iIdx ] = null;
00375 break;
00376 case DATATYPE.TEXT:
00377 argslist[ iIdx ] = __sqlite3_value_text16( context );
00378 break;
00379 }
00380 }
00381 }
00382
00383 return argslist;
00384 }
00385 #endif
00386
00387 #if MOBILEPC
00388
00389
00390
00391 void SetResultValue( IntPtr context, object returnval )
00392 {
00393 if( returnval is Int32 )
00394 {
00395 osqlite3func_SetResultInt( m_nativepoint, (Int32)returnval );
00396 return;
00397 }
00398 else
00399 if( returnval is Int64 )
00400 {
00401 osqlite3func_SetResultInt( m_nativepoint, (Int32)returnval );
00402 return;
00403 }
00404 else
00405 if( returnval is double )
00406 {
00407 double val = (double)returnval;
00408 osqlite3func_SetResultDouble( m_nativepoint, ref val );
00409 return;
00410 }
00411 else
00412 if( returnval is string )
00413 {
00414 string sRetStr = (string)returnval;
00415
00416 System.Text.Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
00417 int iLen = enc.GetByteCount( sRetStr.ToCharArray(), 0, sRetStr.Length, true );
00418 osqlite3func_SetResultText( m_nativepoint, sRetStr, iLen );
00419 return;
00420 }
00421 else
00422 if( returnval is byte[] )
00423 {
00424 byte[] bBin = returnval as byte[];
00425 int iValLen = (int)bBin.Length;
00426
00427
00428 IntPtr pBin = IntPtr.Zero;
00429 try
00430 {
00431
00432 pBin = AllocHGlobal( iValLen );
00433
00434
00435 Marshal.Copy( bBin, 0, pBin, iValLen );
00436
00437 osqlite3func_SetResultBlob( m_nativepoint, pBin, iValLen );
00438 }
00439 finally
00440 {
00441 if( pBin != IntPtr.Zero )
00442 {
00443 FreeHGlobal(pBin);
00444 }
00445 }
00446
00447 return;
00448 }
00449 }
00450
00456 void SetErrorResult( IntPtr context, CallUserException ex )
00457 {
00458
00459 if( ex.ErrorText != string.Empty )
00460 {
00461 System.Text.Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
00462 int iLen = enc.GetByteCount( ex.ErrorText.ToCharArray(), 0, ex.ErrorText.Length, true );
00463 osqlite3func_SetResultError( m_nativepoint, ex.ErrorText, iLen );
00464 }
00465
00466
00467 if( ex.Toobig == true )
00468 osqlite3func_SetResultErrorToobig( m_nativepoint );
00469
00470
00471 if( ex.Nomem == true )
00472 osqlite3func_SetResultErrorNomem( m_nativepoint );
00473
00474
00475 if( ex.ErrorCodeEnable == true )
00476 osqlite3func_SetResultErrorCode( m_nativepoint, ex.ErrorCode );
00477 }
00478
00479 #else
00480
00481
00482
00483 void SetResultValue( IntPtr context, object returnval )
00484 {
00485 if( returnval is Int32 )
00486 {
00487 __sqlite3_result_int( context, (Int32)returnval );
00488 return;
00489 }
00490 else
00491 if( returnval is Int64 )
00492 {
00493 __sqlite3_result_int64( context, (Int64)returnval );
00494 return;
00495 }
00496 else
00497 if( returnval is double )
00498 {
00499 __sqlite3_result_double( context, (double)returnval );
00500 return;
00501 }
00502 else
00503 if( returnval is string )
00504 {
00505 string sRetStr = (string)returnval;
00506
00507 System.Text.Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
00508 int iLen = enc.GetByteCount( sRetStr.ToCharArray(), 0, sRetStr.Length, true );
00509 __sqlite3_result_text16( context, sRetStr, iLen );
00510 return;
00511 }
00512 else
00513 if( returnval is byte[] )
00514 {
00515 byte[] bBin = returnval as byte[];
00516 int iValLen = (int)bBin.Length;
00517
00518
00519 IntPtr pBin = IntPtr.Zero;
00520 try
00521 {
00522
00523 pBin = Marshal.AllocHGlobal( iValLen );
00524
00525
00526 Marshal.Copy( bBin, 0, pBin, iValLen );
00527
00528 __sqlite3_result_blob( context, pBin, iValLen );
00529 }
00530 finally
00531 {
00532 if( pBin != IntPtr.Zero )
00533 {
00534 Marshal.FreeHGlobal(pBin);
00535 }
00536 }
00537
00538 return;
00539 }
00540 }
00541
00547 void SetErrorResult( IntPtr context, CallUserException ex )
00548 {
00549
00550 if( ex.ErrorText != string.Empty )
00551 {
00552 System.Text.Encoder enc = System.Text.Encoding.Unicode.GetEncoder();
00553 int iLen = enc.GetByteCount( ex.ErrorText.ToCharArray(), 0, ex.ErrorText.Length, true );
00554 __sqlite3_result_error16( context, ex.ErrorText, iLen );
00555 }
00556
00557
00558 if( ex.Toobig == true )
00559 __sqlite3_result_error_toobig( context );
00560
00561
00562 if( ex.Nomem == true )
00563 __sqlite3_result_error_nomem( context );
00564
00565
00566 if( ex.ErrorCodeEnable == true )
00567 __sqlite3_result_error_code( context, ex.ErrorCode );
00568 }
00569 #endif
00570
00571 #region アンマネージ定義
00572
00573 #if MOBILEPC
00574 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00575 protected extern static int osqlite3_createfunction( IntPtr instance, string funcname,
00576 int iarg, int eTextRep, IntPtr clrevent, ref IntPtr nativepoint, bool xFunc, bool xStep, bool xFinal );
00577
00578 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00579 protected extern static int osqlite3func_GetCallBackParam( IntPtr instance, ref int pargc );
00580
00581 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00582 protected extern static int osqlite3func_GetParamType( IntPtr instance, int iNo );
00583
00584 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00585 protected extern static int osqlite3func_GetParamInt( IntPtr instance, int iNo );
00586
00587 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00588 protected extern static void osqlite3func_GetParamDouble( IntPtr instance, int iNo, ref double pResult );
00589
00590 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00591 protected extern static IntPtr osqlite3func_GetParamText( IntPtr instance, int iNo );
00592
00593 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00594 protected extern static IntPtr osqlite3func_GetParamBlob( IntPtr instance, int iNo, ref int iLen );
00595
00596 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00597 protected extern static void osqlite3func_FinishCallBackParam( IntPtr instance );
00598
00599 [DllImport("coredll.dll", SetLastError=true)]
00600 static extern IntPtr CreateEvent(IntPtr lpsa, bool fManualReset, bool fInitialState, IntPtr lpszEventName );
00601
00602 [DllImport("coredll.dll", SetLastError=true)]
00603 static extern bool CloseHandle(IntPtr handle );
00604
00605 [DllImport("coredll.dll", SetLastError=true)]
00606 static extern bool EventModify(IntPtr handle, int dEvent );
00607
00608 [DllImport("coredll.dll", SetLastError=true)]
00609 static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
00610
00611 [DllImport("coredll.dll", SetLastError=true)]
00612 static extern int WaitForMultipleObjects( int nCount, IntPtr[] hHandles, bool fWaitAll, int dwMilliseconds);
00613
00614 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00615 protected extern static IntPtr AllocHGlobal( int isize );
00616
00617 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00618 protected extern static void FreeHGlobal( IntPtr pMem );
00619
00620 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00621 protected extern static void osqlite3func_SetResultInt(IntPtr instance, int val );
00622
00623 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00624 protected extern static void osqlite3func_SetResultDouble(IntPtr instance, ref double val );
00625
00626 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00627 protected extern static void osqlite3func_SetResultText(IntPtr instance, string val, int iLen );
00628
00629 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00630 protected extern static void osqlite3func_SetResultBlob(IntPtr instance, IntPtr val, int iLen );
00631
00632 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00633 protected extern static void osqlite3func_SetResultError(IntPtr instance, string val, int iLen );
00634
00635 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00636 protected extern static void osqlite3func_SetResultErrorToobig(IntPtr instance );
00637
00638 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00639 protected extern static void osqlite3func_SetResultErrorNomem(IntPtr instance );
00640
00641 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00642 protected extern static void osqlite3func_SetResultErrorCode(IntPtr instance, int iVal );
00643 #else
00644 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00645 protected extern static int osqlite3_createfunction( IntPtr instance, string funcname,
00646 int iarg, int eTextRep,
00647 CallFuncDelegate xFunc,
00648 CallStepDelegate xStep,
00649 CallFinalDelegate xFinal );
00650 #endif
00651 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00652 protected extern static int __sqlite3_value_type( IntPtr inparam );
00653
00654 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00655 protected extern static long __sqlite3_value_int64( IntPtr inparam );
00656
00657 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00658 protected extern static double __sqlite3_value_double( IntPtr inparam );
00659
00660 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00661 protected extern static int __sqlite3_value_bytes( IntPtr inparam );
00662
00663 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00664 protected extern static IntPtr __sqlite3_value_blob( IntPtr inparam );
00665
00666 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00667 protected extern static string __sqlite3_value_text16( IntPtr inparam );
00668
00669 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00670 protected extern static void __sqlite3_result_int( IntPtr inparam, int val );
00671
00672 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00673 protected extern static void __sqlite3_result_int64( IntPtr inparam, long val );
00674
00675 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00676 protected extern static void __sqlite3_result_double( IntPtr inparam, double val );
00677
00678 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00679 protected extern static void __sqlite3_result_text16( IntPtr inparam, string val, int ilen );
00680
00681 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00682 protected extern static void __sqlite3_result_blob( IntPtr inparam, IntPtr val, int ilen );
00683
00684 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00685 protected extern static void __sqlite3_result_error16( IntPtr inparam, string val, int ilen );
00686
00687 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00688 protected extern static void __sqlite3_result_error_toobig( IntPtr inparam );
00689
00690 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00691 protected extern static void __sqlite3_result_error_nomem( IntPtr inparam );
00692
00693 [DllImport("osqlite.dll",CharSet = CharSet.Unicode)]
00694 protected extern static void __sqlite3_result_error_code( IntPtr inparam, int icode );
00695
00696 #endregion
00697 }
00698 }