1 using System; 2 using System.Text; 3 using System.Runtime.InteropServices; 4 5 namespace GigaBaseNet 6 { 7 /// <summary> 8 /// Exception thrown by Gigabase CLI implementation. 9 /// </summary> 10 public class CliError : Exception { 11 public int ErrorCode; 12 13 ///<summary> 14 /// Constructor of the exception object. 15 /// </summary> 16 /// <param name="Msg">message describing the reason of the fault</param> CliError(string Msg)17 public CliError(string Msg) : this((int)CLI.ErrorCode.cli_unknown_error, Msg) {} 18 ///<summary> 19 /// Constructor of the exception object. 20 /// </summary> 21 /// <param name="Code">Error code describing the reason of the fault</param> CliError(int Code)22 public CliError(int Code) : this(Code, "") {} 23 ///<summary> 24 /// Constructor of the exception object. 25 /// </summary> 26 /// <param name="Code">Error code describing the reason of the fault</param> 27 /// <param name="Msg">Message describing the reason of the fault</param> CliError(int Code, string Msg)28 public CliError(int Code, string Msg): base(FormatMessage(Code, Msg)) { 29 ErrorCode = Code; 30 } FormatMessage(int Code, string Msg)31 private static string FormatMessage(int Code, string Msg) { 32 if (Msg != "") 33 Msg += ". " + CLI.CliErrorToStr(Code); 34 else 35 Msg = CLI.CliErrorToStr(Code); 36 return Msg; 37 } 38 } 39 40 41 /// <summary> 42 /// GigaBASE CLI interface. 43 /// </summary> 44 public class CLI { 45 46 #if FASTDB 47 #if LINUX 48 public const string libname = "libfastdb_r.so"; 49 #else 50 public const string libname = "FastDB.dll"; 51 #endif 52 #else 53 #if LINUX 54 public const string libname = "libgigabase_r.so"; 55 #else 56 public const string libname = "GigaBase.dll"; 57 #endif 58 #endif 59 60 //----------------------------------------- 61 // cli_result_code 62 //----------------------------------------- 63 public enum ErrorCode : int { 64 cli_ok = 0, 65 cli_bad_address = -1, 66 cli_connection_refused = -2, 67 cli_database_not_found = -3, 68 cli_bad_statement = -4, 69 cli_parameter_not_found = -5, 70 cli_unbound_parameter = -6, 71 cli_column_not_found = -7, 72 cli_incompatible_type = -8, 73 cli_network_error = -9, 74 cli_runtime_error = -10, 75 cli_bad_descriptor = -11, 76 cli_unsupported_type = -12, 77 cli_not_found = -13, 78 cli_not_update_mode = -14, 79 cli_table_not_found = -15, 80 cli_not_all_columns_specified = -16, 81 cli_not_fetched = -17, 82 cli_already_updated = -18, 83 cli_table_already_exists = -19, 84 cli_not_implemented = -20, 85 #if !FASTDB 86 cli_login_failed = -21, 87 cli_empty_parameter = -22, 88 cli_closed_connection = -23, 89 #endif 90 91 //----------------------------------------- 92 // cli_error_class 93 // Note: When calling CliErrorToStr in TCliErrorHandler subtract 100 from the 94 // code passed as ErrorClassCode in order to get correct description 95 //----------------------------------------- 96 cli_query_error = 1 -100, 97 cli_arithmetic_error = 2 -100, 98 cli_index_out_of_range_error = 3 -100, 99 cli_database_open_error = 4 -100, 100 cli_file_error = 5 -100, 101 cli_out_of_memory_error = 6 -100, 102 cli_deadlock = 7 -100, 103 cli_null_reference_error = 8 -100, 104 cli_lock_revoked = 9 -100, 105 cli_file_limit_exeeded = 10 -100, 106 107 //----------------------------------------- 108 // Extended Error Codes 109 //----------------------------------------- 110 cli_error_loading_library = -200, 111 cli_session_not_assigned = -201, 112 cli_database_already_open = -202, 113 cli_invalid_field_size = -203, 114 cli_empty_query = -204, 115 cli_item_already_defined = -205, 116 cli_wrong_inverse_reference = -206, 117 cli_no_fields_defined = -207, 118 cli_access_violation = -208, 119 cli_unknown_error = -999 120 } 121 122 //----------------------------------------- 123 // Field Types 124 //----------------------------------------- 125 public enum FieldType : int { 126 cli_oid = 0, 127 cli_bool = 1, 128 cli_int1 = 2, 129 cli_int2 = 3, 130 cli_int4 = 4, 131 cli_int8 = 5, 132 cli_real4 = 6, 133 cli_real8 = 7, 134 cli_decimal = 8, //{ not supported in FastDB } 135 cli_asciiz = 9, //{ zero terminated string (Get/Set function can be used) } 136 cli_pasciiz = 10, //{ pointer to zero terminated string } 137 cli_cstring = 11, //{ not supported in FastDB } 138 cli_array_of_oid = 12, 139 cli_array_of_bool = 13, 140 cli_array_of_int1 = 14, 141 cli_array_of_int2 = 15, 142 cli_array_of_int4 = 16, 143 cli_array_of_int8 = 17, 144 cli_array_of_real4 = 18, 145 cli_array_of_real8 = 19, 146 cli_array_of_decimal = 20, //{ not supported in FastDB } 147 cli_array_of_string = 21, 148 cli_any = 22, //{ not supported in FastDB } 149 cli_datetime = 23, //{ not supported in FastDB } 150 cli_autoincrement = 24, 151 cli_rectangle = 25, //{ not supported in FastDB } 152 cli_unknown = 26, 153 //--- Custom types not supported by the database directly ----- 154 cli_subst // Reserved for substitution variables 155 }; 156 157 internal static int[] SizeOfCliType = 158 new int[] { 159 Marshal.SizeOf(typeof(int)), // cli_oid 160 Marshal.SizeOf(typeof(bool)), // cli_bool 161 Marshal.SizeOf(typeof(sbyte)), // cli_int1 162 Marshal.SizeOf(typeof(short)), // cli_int2 163 Marshal.SizeOf(typeof(int)), // cli_int4 164 Marshal.SizeOf(typeof(long)), // cli_int8_t 165 Marshal.SizeOf(typeof(float)), // cli_real4_t 166 Marshal.SizeOf(typeof(double)), // cli_real8_t 167 0, // cli_decimal 168 0, // cli_asciiz, 169 0, // cli_pasciiz, 170 0, // cli_cstring, 171 0, // cli_array_of_oid, 172 0, // cli_array_of_bool, 173 0, // cli_array_of_int1, 174 0, // cli_array_of_int2, 175 0, // cli_array_of_int4, 176 0, // cli_array_of_int8, 177 0, // cli_array_of_real4, 178 0, // cli_array_of_real8, 179 0, // cli_array_of_decimal, 180 0, // cli_array_of_string, 181 0, // cli_any, 182 Marshal.SizeOf(typeof(double)), // cli_datetime, 183 Marshal.SizeOf(typeof(int)), // cli_autoincrement, 184 0, // cli_rectangle, 185 0, // cli_unknown 186 0 // ctSubst 187 }; 188 CliTypeToStr(FieldType type, bool ExtendedSyntax)189 public static string CliTypeToStr(FieldType type, bool ExtendedSyntax) { 190 StringBuilder s = new StringBuilder(""); 191 FieldType ft = type; 192 if (ExtendedSyntax && type >= CLI.FieldType.cli_array_of_oid && type <= CLI.FieldType.cli_array_of_string) { 193 s.Append("array of "); 194 ft = (CLI.FieldType)((int)type - (int)CLI.FieldType.cli_array_of_oid); 195 } 196 197 switch(ft) { 198 case CLI.FieldType.cli_oid: 199 s.Append((ExtendedSyntax)? "reference" : "(oid)"); break; 200 case CLI.FieldType.cli_bool: 201 s.Append((ExtendedSyntax)? "bool" : "Boolean"); break; 202 case CLI.FieldType.cli_int1: 203 s.Append((ExtendedSyntax)? "int1" : "Byte"); break; 204 case CLI.FieldType.cli_int2: 205 s.Append((ExtendedSyntax)? "int2" : "SmallInt"); break; 206 case CLI.FieldType.cli_autoincrement: 207 case CLI.FieldType.cli_int4: 208 s.Append((ExtendedSyntax)? "int4" : "Integer"); break; 209 case CLI.FieldType.cli_int8: 210 s.Append((ExtendedSyntax)? "int8" : "Int64"); break; 211 case CLI.FieldType.cli_real4: 212 s.Append((ExtendedSyntax)? "real4" : "Single"); break; 213 case CLI.FieldType.cli_datetime: 214 s.Append((ExtendedSyntax)? "real8" : "DateTime"); break; 215 case CLI.FieldType.cli_real8: 216 s.Append((ExtendedSyntax)? "real8" : "Double"); break; 217 case CLI.FieldType.cli_asciiz: 218 case CLI.FieldType.cli_pasciiz: 219 s.Append((ExtendedSyntax)? "string" : "String"); break; 220 default: 221 if (!ExtendedSyntax) 222 s.Append(Enum.GetName(typeof(CLI.FieldType), ft).Substring(4)); break; 223 } 224 return s.ToString(); 225 } 226 IsArrayType(FieldType tp)227 public static bool IsArrayType(FieldType tp) { 228 return tp >= FieldType.cli_array_of_oid && tp <= FieldType.cli_array_of_real8; 229 } 230 CliCheck(int code, string Msg)231 public static int CliCheck(int code, string Msg) { 232 if (code < 0) 233 throw new CliError(code, Msg); 234 else 235 return code; 236 } 237 CliCheck(int code)238 public static int CliCheck(int code) { 239 return CliCheck(code, ""); 240 } 241 242 // translate error code to string CliErrorToStr(int Code)243 public static string CliErrorToStr(int Code) { 244 if (Code >= 0) 245 return null; 246 else 247 switch (Code) { 248 case (int)ErrorCode.cli_bad_address : return "Invalid format of server URL"; 249 case (int)ErrorCode.cli_connection_refused : return "Connection with server could not be established"; 250 case (int)ErrorCode.cli_database_not_found : return "Database cannot be found"; 251 case (int)ErrorCode.cli_bad_statement : return "Text of SQL statement is not correct"; 252 case (int)ErrorCode.cli_parameter_not_found : return "Parameter was not found in statement"; 253 case (int)ErrorCode.cli_unbound_parameter : return "Parameter was not specified"; 254 case (int)ErrorCode.cli_column_not_found : return "No such colunm in the table"; 255 case (int)ErrorCode.cli_incompatible_type : return "Conversion between application and database type is not possible"; 256 case (int)ErrorCode.cli_network_error : return "Connection with server is broken"; 257 case (int)ErrorCode.cli_runtime_error : return "Error during query execution"; 258 case (int)ErrorCode.cli_bad_descriptor : return "Invalid statement/session description"; 259 case (int)ErrorCode.cli_unsupported_type : return "Unsupported type for parameter or column"; 260 case (int)ErrorCode.cli_not_found : return "Record was not found"; 261 case (int)ErrorCode.cli_not_update_mode : return "Attempt to update records selected by view only cursor"; 262 case (int)ErrorCode.cli_table_not_found : return "There is no table with specified name in the database"; 263 case (int)ErrorCode.cli_not_all_columns_specified : return "Insert statement doesn''t specify values for all table columns"; 264 case (int)ErrorCode.cli_not_fetched : return "cli_fetch method was not called"; 265 case (int)ErrorCode.cli_already_updated : return "cli_update method was invoked more than once for the same record"; 266 case (int)ErrorCode.cli_table_already_exists : return "Attempt to create existing table"; 267 case (int)ErrorCode.cli_not_implemented : return "Function is not implemented"; 268 //----- Severe Error Class Codes--------- 269 case (int)ErrorCode.cli_query_error : return "Query error"; 270 case (int)ErrorCode.cli_arithmetic_error : return "Arithmetic error"; 271 case (int)ErrorCode.cli_index_out_of_range_error : return "Index out of range"; 272 case (int)ErrorCode.cli_database_open_error : return "Database open error"; 273 case (int)ErrorCode.cli_file_error : return "File error"; 274 case (int)ErrorCode.cli_out_of_memory_error : return "Out of memory"; 275 case (int)ErrorCode.cli_deadlock : return "Deadlock detected"; 276 case (int)ErrorCode.cli_null_reference_error : return "Null reference"; 277 case (int)ErrorCode.cli_lock_revoked : return "Lock revoked"; 278 case (int)ErrorCode.cli_file_limit_exeeded : return "File limit exeeded"; 279 //----- Custom Error Codes--------------- 280 case (int)ErrorCode.cli_error_loading_library : return "Error loading library"; 281 case (int)ErrorCode.cli_session_not_assigned : return "Session not assigned or not connected"; 282 case (int)ErrorCode.cli_database_already_open : return "Database already open"; 283 case (int)ErrorCode.cli_invalid_field_size : return "Invalid field size"; 284 case (int)ErrorCode.cli_empty_query : return "Query SQL text is not assigned"; 285 case (int)ErrorCode.cli_item_already_defined : return "Field/Variable is already defined"; 286 case (int)ErrorCode.cli_wrong_inverse_reference : return "Wrong inverse reference"; 287 case (int)ErrorCode.cli_no_fields_defined : return "No fields defined"; 288 case (int)ErrorCode.cli_access_violation : return "Access Violation"; 289 default: return String.Format("({0})", Code); 290 } 291 } 292 293 [Flags] 294 public enum CliOpenAttribute : int { 295 oaReadWrite = 0x00, //cli_open_default 296 oaReadOnly = 0x01, //cli_open_readonly 297 oaTruncate = 0x02, //cli_open_truncate 298 oaOpenConcurrent = 0x04 //cli_open_concurrent 299 }; 300 301 /*===================================================================== 302 * cli_open 303 * Establish connection with the server 304 * Parameters: 305 * server_url - zero terminated string with server address and port, 306 * for example "localhost:5101", "195.239.208.240:6100",... 307 * max_connect_attempts - number of attempts to establish connection 308 * reconnect_timeout_sec - timeput in seconds between connection attempts 309 * Gigabase users: 310 * =============== 311 * user_name - user name for login 312 * password - password for login 313 * pooled_connection - if not 0, then connection will be allocated from the connection pool 314 * 315 * Returns: 316 * >= 0 - connectiondescriptor to be used in all other cli calls 317 * < 0 - error code as described in cli_result_code enum 318 */ 319 [DllImport(libname, 320 CharSet = CharSet.Ansi, // We want ANSI String 321 CallingConvention = CallingConvention.Cdecl)] cli_open( string ServerURL, int MaxConnectAttempts, int ReconnectTimeoutSec , string UserName , string Password , bool PooledConnection )322 internal static extern int cli_open( 323 string ServerURL, 324 int MaxConnectAttempts, 325 int ReconnectTimeoutSec 326 #if !FASTDB 327 , string UserName 328 , string Password 329 , bool PooledConnection 330 #endif 331 ); 332 333 /*===================================================================== 334 * cli_create 335 * Create connection to the local database 336 * Parameters: 337 * databaseName - name of the database 338 * fileName - path to the database file 339 * transactionCommitDelay - trasnaction commit delay (specify 0 to disable) 340 * openAttr - mask of cli_open_attributes 341 * initDatabaseSize - initial size of the database 342 * extensionQuantum - database extension quantum 343 * initIndexSize - initial size of object index 344 * fileSizeLimit - limit for file size (0 - unlimited) 345 * Returns: 346 * >= 0 - connection descriptor to be used in all other cli calls 347 * < 0 - error code as described in cli_result_code enum 348 */ 349 350 [DllImport(libname, 351 CharSet = CharSet.Ansi, // We want ANSI String 352 CallingConvention = CallingConvention.Cdecl)] cli_create( string databasePath, uint TransactionCommitDelay, int openAttr, int PoolSize )353 internal static extern int cli_create( 354 #if !FASTDB 355 string databasePath, 356 uint TransactionCommitDelay, 357 int openAttr, 358 int PoolSize 359 #else 360 string databaseName, //[MarshalAs(UnmanagedType.LPStr)] string databaseName, 361 string filePath, //[MarshalAs(UnmanagedType.LPStr)] string filePath, 362 uint transactionCommitDelay, 363 int openAttr, 364 int initDatabaseSize, 365 int extensionQuantum, 366 int initIndexSize, 367 int fileSizeLimit 368 #endif 369 ); 370 371 /*===================================================================== 372 * cli_create_replication_node 373 * Create connection to the local database with support of replication 374 * Parameters: 375 * nodeId - node identifier: 0 <= nodeId < nServers 376 * nServers - number of replication nodes (primary + standby) 377 * nodeNames - array with URLs of the nodes (address:port) 378 * databaseName - name of the database 379 * fileName - path to the database file 380 * transactionCommitDelay - trasnaction commit delay (specify 0 to disable) 381 * openAttr - mask of cli_open_attributes (to allow concurrent read access to replication node, 382 * cli_open_concurrent attribute should be set) 383 * initDatabaseSize - initial size of the database 384 * extensionQuantum - database extension quantum 385 * initIndexSize - initial size of object index 386 * fileSizeLimit - limit for file size (0 - unlimited) 387 * Returns: 388 * >= 0 - connection descriptor to be used in all other cli calls 389 * < 0 - error code as described in cli_result_code enum 390 */ 391 392 [DllImport(libname, 393 CharSet = CharSet.Ansi, // We want ANSI String 394 CallingConvention = CallingConvention.Cdecl)] cli_create_replication_node( int nodeId, int nServers, [In, Out] String[] nodeNames, string databaseName, string filePath, int openAttr, int initDatabaseSize, int extensionQuantum, int initIndexSize, int fileSizeLimit)395 internal static extern int cli_create_replication_node( 396 int nodeId, 397 int nServers, 398 [In, Out] String[] nodeNames, 399 string databaseName, 400 string filePath, 401 int openAttr, 402 int initDatabaseSize, 403 int extensionQuantum, 404 int initIndexSize, 405 int fileSizeLimit); 406 407 /*===================================================================== 408 * cli_close 409 * Close session 410 * Parameters: 411 * session - session descriptor returned by cli_open 412 * Returns: 413 * result code as described in cli_result_code enum 414 */ 415 [DllImport(libname, 416 CharSet = CharSet.Ansi, // We want ANSI String 417 CallingConvention = CallingConvention.Cdecl)] cli_close(int session)418 internal static extern int cli_close(int session); 419 420 /*===================================================================== 421 * cli_statement 422 * Specify SubSQL statement to be executed at server 423 * Binding to the parameters and columns can be established 424 * Parameters: 425 * session - session descriptor returned by cli_open 426 * stmt - zero terminated string with SubSQL statement 427 * Returns: 428 * >= 0 - statement descriptor 429 * < 0 - error code as described in cli_result_code enum 430 */ 431 [DllImport(libname, 432 CharSet = CharSet.Ansi, // We want ANSI String 433 CallingConvention = CallingConvention.Cdecl)] cli_statement(int session, string stmt)434 internal static extern int cli_statement(int session, string stmt); 435 436 /*===================================================================== 437 * cli_parameter 438 * Bind parameter to the statement 439 * Parameters: 440 * statement - statememt descriptor returned by cli_statement 441 * param_name - zero terminated string with parameter name 442 * Paramter name should start with '%' 443 * var_type - type of variable as described in CliVarType enum. 444 * Only scalar and zero terminated string types are supported. 445 * var_ptr - pointer to the variable 446 * Returns: 447 * result code as described in cli_result_code enum 448 */ 449 [DllImport(libname, 450 CharSet = CharSet.Ansi, // We want ANSI String 451 CallingConvention = CallingConvention.Cdecl)] cli_parameter( int statement, string param_name, int var_type, IntPtr var_ptr)452 internal static extern int cli_parameter( 453 int statement, 454 string param_name, 455 int var_type, 456 IntPtr var_ptr); 457 458 /*===================================================================== 459 * cli_column 460 * Bind extracted column of select or insert statement 461 * Parameters: 462 * statement - statememt descriptor returned by cli_statement 463 * column_name - zero terminated string with column name 464 * var_type - type of variable as described in CliVarType enum 465 * var_len - pointer to the variable to hold length of array variable. 466 * This variable should be assigned the maximal length 467 * of the array/string buffer, pointed by var_ptr. 468 * After the execution of the statement it is assigned the 469 * real length of the fetched array/string. If it is large 470 * than length of the buffer, then only part of the array 471 * will be placed in the buffer, but var_len still will 472 * contain the actual array length. 473 * var_ptr - pointer to the variable 474 * Returns: 475 * result code as described in cli_result_code enum 476 */ 477 [DllImport(libname, 478 CharSet = CharSet.Ansi, // We want ANSI String 479 CallingConvention = CallingConvention.Cdecl)] cli_column( int statement, string column_name, int var_type, ref int var_len, IntPtr var_data)480 public static extern int cli_column( 481 int statement, 482 string column_name, 483 int var_type, 484 ref int var_len, 485 IntPtr var_data); 486 487 [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )] 488 public struct UnmanagedBuffer { 489 public int type; 490 public int capacity; 491 public int size; 492 public bool fetch_data; 493 public IntPtr data; 494 } 495 496 /* The C# does not allow you to specify the calling convention of the callback. 497 * It is just one of the C# limitations. IL, managed C++ and the runtime itself 498 * supports the cdecl calling convention for delegates through 499 * modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) on the 500 * internal Invoke method of the delegate. Run ildasm on a small example in 501 * managed C++ if you want to know the exact syntax. 502 */ 503 504 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] CliColumnSetEx( int var_type, IntPtr var_ptr, int len, [MarshalAs(UnmanagedType.LPStr)] string column_name, int statement, IntPtr source_ptr, void* buffer)505 internal unsafe delegate IntPtr CliColumnSetEx( 506 int var_type, 507 IntPtr var_ptr, 508 int len, 509 [MarshalAs(UnmanagedType.LPStr)] 510 string column_name, 511 int statement, 512 IntPtr source_ptr, 513 void* buffer); 514 515 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] CliColumnGetEx( int var_type, IntPtr var_ptr, ref int len, string column_name, int statement, void* buffer)516 internal unsafe delegate IntPtr CliColumnGetEx( 517 int var_type, 518 IntPtr var_ptr, 519 ref int len, 520 string column_name, int statement, 521 void* buffer); 522 523 524 /*===================================================================== 525 * cli_array_column 526 * Specify get/set functions for the array column 527 * Parameters: 528 * statement - statememt descriptor returned by cli_statement 529 * column_name - zero terminated string with column name 530 * var_type - type of variable as described in CliVarType enum 531 * var_ptr - pointer to the variable 532 * set - function which will be called to construct fetched 533 * field. It receives pointer to the variable, 534 * length of the fetched array and returns pointer to th 535 * array's elements 536 * get - function which will be called to update the field in the 537 * database. Given pointer to the variable, it should return 538 * pointer to the array elements and store length of the 539 * array to the variable pointer by len parameter 540 * Returns: 541 * result code as described in cli_result_code enum 542 */ 543 [DllImport(libname, 544 CharSet = CharSet.Ansi, // We want ANSI String 545 CallingConvention = CallingConvention.Cdecl)] cli_array_column_ex( int statement, string column_name, int var_type, IntPtr var_ptr, CliColumnSetEx SetCallback, CliColumnGetEx GetCallback, void* user_data)546 internal unsafe static extern int cli_array_column_ex( 547 int statement, 548 string column_name, 549 int var_type, 550 IntPtr var_ptr, 551 CliColumnSetEx SetCallback, 552 CliColumnGetEx GetCallback, 553 void* user_data); 554 555 public enum QueryType: int { 556 cli_view_only = 0, 557 cli_for_update = 1 558 } 559 560 /*===================================================================== 561 * cli_fetch 562 * Execute select statement. 563 * Parameters: 564 * statement - statememt descriptor returned by cli_statement 565 * queryType - not zero if fetched rows will be updated 566 * Returns: 567 * >= 0 - success, for select statements number of fetched rows is returned 568 * < 0 - error code as described in cli_result_code enum 569 */ 570 [DllImport(libname, 571 CharSet = CharSet.Ansi, // We want ANSI String 572 CallingConvention = CallingConvention.Cdecl)] cli_fetch(int statement, QueryType queryType)573 internal static extern int cli_fetch(int statement, QueryType queryType); 574 575 /*===================================================================== 576 * cli_insert 577 * Execute insert statement. 578 * Parameters: 579 * statement - statememt descriptor returned by cli_statement 580 * oid - object identifier of created record. 581 * Returns: 582 * status code as described in cli_result_code enum 583 */ 584 [DllImport(libname, 585 CharSet = CharSet.Ansi, // We want ANSI String 586 CallingConvention = CallingConvention.Cdecl)] cli_insert(int statement, ref uint oid)587 internal static extern int cli_insert(int statement, ref uint oid); 588 589 /*===================================================================== 590 * cli_get_first 591 * Get first row of the selection. 592 * Parameters: 593 * statement - statememt descriptor returned by cli_statement 594 * Returns: 595 * result code as described in cli_result_code enum 596 */ 597 [DllImport(libname, 598 CharSet = CharSet.Ansi, // We want ANSI String 599 CallingConvention = CallingConvention.Cdecl)] cli_get_first(int statement)600 internal static extern int cli_get_first(int statement); 601 602 /*===================================================================== 603 * cli_get_last 604 * Get last row of the selection. 605 * Parameters: 606 * statement - statememt descriptor returned by cli_statement 607 * Returns: 608 * result code as described in cli_result_code enum 609 */ 610 [DllImport(libname, 611 CharSet = CharSet.Ansi, // We want ANSI String 612 CallingConvention = CallingConvention.Cdecl)] cli_get_last(int statement)613 internal static extern int cli_get_last(int statement); 614 615 /*===================================================================== 616 * cli_get_next 617 * Get next row of the selection. If get_next records is called 618 * exactly after cli_fetch function call, is will fetch the first record 619 * in selection. 620 * Parameters: 621 * statement - statememt descriptor returned by cli_statement 622 * Returns: 623 * result code as described in cli_result_code enum 624 */ 625 [DllImport(libname, 626 CharSet = CharSet.Ansi, // We want ANSI String 627 CallingConvention = CallingConvention.Cdecl)] cli_get_next(int statement)628 internal static extern int cli_get_next(int statement); 629 630 /*===================================================================== 631 * cli_get_prev 632 * Get previous row of the selection. If get_next records is called 633 * exactly after cli_fetch function call, is will fetch the last record 634 * in selection. 635 * Parameters: 636 * statement - statememt descriptor returned by cli_statement 637 * Returns: 638 * result code as described in cli_result_code enum 639 */ 640 [DllImport(libname, 641 CharSet = CharSet.Ansi, // We want ANSI String 642 CallingConvention = CallingConvention.Cdecl)] cli_get_prev(int statement)643 internal static extern int cli_get_prev(int statement); 644 645 /*===================================================================== 646 * cli_skip 647 * Skip specified number of rows. 648 * Parameters: 649 * statement - statememt descriptor returned by cli_statement 650 * n - number of objects to be skipped 651 * - if "n" is positive, then this function has the same effect as 652 * executing cli_get_next() function "n" times. 653 * - if "n" is negative, then this function has the same effect as 654 * executing cli_get_prev() function "-n" times. 655 * - if "n" is zero, this method just reloads current record 656 * Returns: 657 * result code as described in cli_result_code enum 658 */ 659 [DllImport(libname, 660 CharSet = CharSet.Ansi, // We want ANSI String 661 CallingConvention = CallingConvention.Cdecl)] cli_skip(int statement, int n)662 internal static extern int cli_skip(int statement, int n); 663 664 /*===================================================================== 665 * cli_seek 666 * Position cursor to the record with specified OID 667 * Parameters: 668 * statement - statememt descriptor returned by cli_statement 669 * oid - object identifier of the record to which cursor should be positioned 670 * Returns: 671 * >= 0 - success, position of the record in the selection 672 * < 0 - error code as described in cli_result_code enum 673 */ 674 [DllImport(libname, 675 CharSet = CharSet.Ansi, // We want ANSI String 676 CallingConvention = CallingConvention.Cdecl)] cli_seek(int statement, uint oid)677 internal static extern int cli_seek(int statement, uint oid); 678 679 680 /*===================================================================== 681 * cli_get_oid 682 * Get object identifier of the current record 683 * Parameters: 684 * statement - statememt descriptor returned by cli_statement 685 * Returns: 686 * object identifier or 0 if no object is seleected 687 */ 688 [DllImport(libname, 689 CharSet = CharSet.Ansi, // We want ANSI String 690 CallingConvention = CallingConvention.Cdecl)] cli_get_oid(int statement)691 internal static extern uint cli_get_oid(int statement); 692 693 /*===================================================================== 694 * cli_update 695 * Update the current row in the selection. You have to set 696 * for_update parameter of cli_fetch to 1 in order to be able 697 * to perform updates. Updated value of row fields will be taken 698 * from bound column variables. 699 * Parameters: 700 * statement - statememt descriptor returned by cli_statement 701 * Returns: 702 * result code as described in cli_result_code enum 703 */ 704 [DllImport(libname, 705 CharSet = CharSet.Ansi, // We want ANSI String 706 CallingConvention = CallingConvention.Cdecl)] cli_update(int statement)707 internal static extern int cli_update(int statement); 708 709 /*===================================================================== 710 * cli_remove 711 * Remove all selected records. You have to set 712 * for_update parameter of cli_fetch to 1 in order to be able 713 * to remove records. 714 * Parameters: 715 * statement - statememt descriptor returned by cli_statement 716 * Returns: 717 * result code as described in cli_result_code enum 718 */ 719 [DllImport(libname, 720 CharSet = CharSet.Ansi, // We want ANSI String 721 CallingConvention = CallingConvention.Cdecl)] cli_remove(int statement)722 internal static extern int cli_remove(int statement); 723 724 /*===================================================================== 725 * cli_free 726 * Deallocate statement and all associated data 727 * Parameters: 728 * statement - statememt descriptor returned by cli_statement 729 * Returns: 730 * result code as described in cli_result_code enum 731 */ 732 [DllImport(libname, 733 CharSet = CharSet.Ansi, // We want ANSI String 734 CallingConvention = CallingConvention.Cdecl)] cli_free(int statement)735 internal static extern int cli_free(int statement); 736 737 /*===================================================================== 738 * cli_commit 739 * Commit current database transaction 740 * Parameters: 741 * session - session descriptor as returned by cli_open 742 * Returns: 743 * result code as described in cli_result_code enum 744 */ 745 [DllImport(libname, 746 CharSet = CharSet.Ansi, // We want ANSI String 747 CallingConvention = CallingConvention.Cdecl)] cli_commit(int session)748 internal static extern int cli_commit(int session); 749 750 /*===================================================================== 751 * cli_precommit 752 * Release all locks set by transaction. This methods allows other clients 753 * to proceed, but it doesn't flush transaction to the disk. 754 * Parameters: 755 * session - session descriptor as returned by cli_open 756 * Returns: 757 * result code as described in cli_result_code enum 758 */ 759 [DllImport(libname, 760 CharSet = CharSet.Ansi, // We want ANSI String 761 CallingConvention = CallingConvention.Cdecl)] cli_precommit(int session)762 internal static extern int cli_precommit(int session); 763 764 /*===================================================================== 765 * cli_abort 766 * Abort current database transaction 767 * Parameters: 768 * session - session descriptor as returned by cli_open 769 * Returns: 770 * result code as described in cli_result_code enum 771 */ 772 [DllImport(libname, 773 CharSet = CharSet.Ansi, // We want ANSI String 774 CallingConvention = CallingConvention.Cdecl)] cli_abort(int session)775 internal static extern int cli_abort(int session); 776 777 public enum FieldFlags: int { 778 cli_noindex = 0, /* no indexes */ 779 cli_hashed = 1, /* field should be indexed usnig hash table */ 780 cli_indexed = 2 /* field should be indexed using B-Tree */ 781 }; 782 783 [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )] 784 internal struct CliFieldDescriptor { 785 public FieldType type; 786 public FieldFlags flags; 787 public IntPtr name; 788 public IntPtr refTableName; 789 public IntPtr inverseRefFieldName; 790 }; 791 792 /*===================================================================== 793 * cli_describe 794 * Describe fileds of specified table 795 * Parameters: 796 * session - session descriptor as returned by cli_open 797 * table - name of the table 798 * fields - address of the pointer to the array of fields descriptors, 799 * this array should be later deallocated by application by cli_free_memory() 800 * Returns: 801 * >= 0 - number of fields in the table 802 * < 0 - result code as described in cli_result_code enum 803 */ 804 [DllImport(libname, 805 CharSet = CharSet.Ansi, // We want ANSI String 806 CallingConvention = CallingConvention.Cdecl)] cli_describe( int session, string table, ref void* fields)807 internal static extern unsafe int cli_describe( 808 int session, 809 string table, 810 ref void* fields); 811 //[In,Out] ref CliFieldDescriptor[] fields); // cli_field_descriptor** fields 812 813 /*===================================================================== 814 * cli_get_field_size 815 * Calculate field size 816 * Parameters: 817 * fields - array with fields descriptors obtained using cli_describe function 818 * field_no - number of the field 819 */ 820 [DllImport(libname, 821 CharSet = CharSet.Ansi, // We want ANSI String 822 CallingConvention = CallingConvention.Cdecl)] cli_get_field_size( [In, Out] CliFieldDescriptor[] fields, int field_no)823 internal static extern int cli_get_field_size( 824 [In, Out] CliFieldDescriptor[] fields, // cli_field_descriptor* fields 825 int field_no); 826 827 /*===================================================================== 828 * cli_get_field_offset 829 * Calculate offset of the field 830 * Parameters: 831 * fields - array with fields descriptors obtained using cli_describe function 832 * field_no - number of the field 833 */ 834 [DllImport(libname, 835 CharSet = CharSet.Ansi, // We want ANSI String 836 CallingConvention = CallingConvention.Cdecl)] cli_get_field_offset( [In, Out] CliFieldDescriptor[] fields, int field_no)837 internal static extern int cli_get_field_offset( 838 [In, Out] CliFieldDescriptor[] fields, // cli_field_descriptor* fields 839 int field_no); 840 841 [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )] 842 internal struct CliTableDescriptor { 843 public IntPtr name; 844 } 845 846 /*===================================================================== 847 * cli_show_tables 848 * Show all tables of specified database 849 * Parameters: 850 * session - session descriptor as returned by cli_open 851 * tables - address of the pointer to the array of tables descriptors, 852 * this array should be later deallocated by application by cli_free_memory() 853 * Returns: 854 * >= 0 - number of tables in the database (Metatable is not returned/counted) 855 * < 0 - result code as described in cli_result_code enum 856 */ 857 [DllImport(libname, 858 CharSet = CharSet.Ansi, // We want ANSI String 859 CallingConvention = CallingConvention.Cdecl)] cli_show_tables( int session, ref IntPtr tables)860 internal static extern int cli_show_tables( 861 int session, 862 //[In, Out] CliTableDescriptor[] tables 863 ref IntPtr tables); // cli_table_descriptor** tables 864 865 /*===================================================================== 866 * cli_create_table 867 * Create new table 868 * Parameters: 869 * session - session descriptor as returned by cli_open 870 * tableName - name of new table 871 * nFields - number of columns in the table 872 * fields - array with table columns descriptors 873 * Returns: 874 * result code as described in cli_result_code enum 875 */ 876 [DllImport(libname, 877 CharSet = CharSet.Ansi, // We want ANSI String 878 CallingConvention = CallingConvention.Cdecl)] cli_create_table( int session, string tableName, int nFields, [In, Out] CliFieldDescriptor[] fields)879 internal static extern int cli_create_table( 880 int session, 881 string tableName, 882 int nFields, 883 [In, Out] CliFieldDescriptor[] fields); // cli_field_descriptor* fields 884 885 /*===================================================================== 886 * cli_alter_table 887 * Change table format 888 * Parameters: 889 * session - session descriptor as returned by cli_open 890 * tableName - name of existing table 891 * nFields - number of columns in the table 892 * fields - array with new table columns descriptors 893 * Returns: 894 * result code as described in cli_result_code enum 895 */ 896 [DllImport(libname, 897 CharSet = CharSet.Ansi, // We want ANSI String 898 CallingConvention = CallingConvention.Cdecl)] cli_alter_table( int session, string tableName, int nFields, [MarshalAs(UnmanagedType.LPArray)] CliFieldDescriptor[] fields)899 internal static extern int cli_alter_table( 900 int session, 901 string tableName, 902 int nFields, 903 [MarshalAs(UnmanagedType.LPArray)] 904 CliFieldDescriptor[] fields); // cli_field_descriptor* fields); 905 906 /*===================================================================== 907 * cli_drop_table 908 * drop the table 909 * Parameters: 910 * session - session descriptor as returned by cli_open 911 * tableName - name of deleted table 912 * Returns: 913 * result code as described in cli_result_code enum 914 */ 915 [DllImport(libname, 916 CharSet = CharSet.Ansi, // We want ANSI String 917 CallingConvention = CallingConvention.Cdecl)] cli_drop_table(int session, string tableName)918 internal static extern int cli_drop_table(int session, string tableName); 919 920 921 /*===================================================================== 922 * cli_alter_index 923 * add or remove column index 924 * Parameters: 925 * session - session descriptor as returned by cli_open 926 * tableName - name of the table 927 * fieldName - name of field 928 * newFlags - new flags of the field, if index exists for this field, but is not specified in 929 * <code>newFlags</code> mask, then it will be removed; if index not exists, but is 930 * specified in <code>newFlags</code> mask, then it will be created. * 931 * Returns: 932 * result code as described in cli_result_code enum 933 */ 934 [DllImport(libname, 935 CharSet = CharSet.Ansi, // We want ANSI String 936 CallingConvention = CallingConvention.Cdecl)] cli_alter_index( int session, string tableName, string fieldName, FieldFlags newFlags)937 internal static extern int cli_alter_index( 938 int session, string tableName, string fieldName, 939 FieldFlags newFlags); 940 941 /*===================================================================== 942 * cli_set_error_handler 943 * Set GigaBASE error handler. Handler should be no-return function which perform stack unwind. 944 * Parameters: 945 * session - session descriptor as returned by cli_open 946 * handler - error handler 947 * Returns: 948 * previous handler 949 */ 950 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] CliErrorHandler(int error, [MarshalAs(UnmanagedType.LPStr)] string msg, int msgarg, IntPtr context)951 public delegate void CliErrorHandler(int error, 952 [MarshalAs(UnmanagedType.LPStr)] string msg, int msgarg, IntPtr context); 953 954 [DllImport(libname, 955 CharSet = CharSet.Ansi, // We want ANSI String 956 CallingConvention = CallingConvention.Cdecl)] cli_set_error_handler(int session, CliErrorHandler new_handler, IntPtr context)957 internal static extern CliErrorHandler cli_set_error_handler(int session, CliErrorHandler new_handler, IntPtr context); 958 959 /*===================================================================== 960 * cli_freeze 961 * Freeze cursor. Make it possible to reused cursor after commit of the current transaction. 962 * Parameters: 963 * statement - statememt descriptor returned by cli_statement 964 * Returns: 965 * result code as described in cli_result_code enum 966 */ 967 [DllImport(libname, 968 CharSet = CharSet.Ansi, // We want ANSI String 969 CallingConvention = CallingConvention.Cdecl)] cli_freeze(int statement)970 internal static extern int cli_freeze(int statement); 971 972 /*===================================================================== 973 * cli_unfreeze 974 * Unfreeze cursor. Reuse previously frozen cursor. 975 * Parameters: 976 * statement - statememt descriptor returned by cli_statement 977 * Returns: 978 * result code as described in cli_result_code enum 979 */ 980 [DllImport(libname, 981 CharSet = CharSet.Ansi, // We want ANSI String 982 CallingConvention = CallingConvention.Cdecl)] cli_unfreeze(int statement)983 internal static extern int cli_unfreeze(int statement); 984 985 986 /*===================================================================== 987 * cli_attach 988 * Attach thread to the database. Each thread except one opened the database should first 989 * attach to the database before any access to the database, and detach after end of the work with database 990 * Parameters: 991 * session - session descriptor returned by cli_open 992 * Returns: 993 * result code as described in cli_result_code enum 994 */ 995 [DllImport(libname, 996 CharSet = CharSet.Ansi, // We want ANSI String 997 CallingConvention = CallingConvention.Cdecl)] cli_attach(int session)998 internal static extern int cli_attach(int session); 999 1000 /*===================================================================== 1001 * cli_detach 1002 * Detach thread from the database. Each thread except one opened the database should perform 1003 * attach to the database before any access to the database, and detach after end of the work with database 1004 * Parameters: 1005 * session - session descriptor returned by cli_open 1006 * detach_mode - bit mask representing detach mode 1007 * Returns: 1008 * result code as described in cli_result_code enum 1009 */ 1010 [Flags] 1011 public enum CliDetachMode : int { 1012 cli_commit_on_detach = 1, 1013 cli_destroy_context_on_detach = 2 1014 }; 1015 1016 [DllImport(libname, 1017 CharSet = CharSet.Ansi, // We want ANSI String 1018 CallingConvention = CallingConvention.Cdecl)] cli_detach(int session, CliDetachMode detach_mode)1019 internal static extern int cli_detach(int session, CliDetachMode detach_mode); 1020 1021 1022 /*===================================================================== 1023 * cli_free_memory 1024 * Free memory allocated by cli_show_tables and cli_describe 1025 * Parameters: 1026 * session - session descriptor returned by cli_open 1027 * ptr - pointer to the allocated buffer 1028 */ 1029 [DllImport(libname, 1030 CharSet = CharSet.Ansi, // We want ANSI String 1031 CallingConvention = CallingConvention.Cdecl)] cli_free_memory(int session, void* ptr)1032 internal static extern unsafe void cli_free_memory(int session, void* ptr); 1033 1034 [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )] 1035 public struct CliDatabaseMonitor { 1036 public int n_readers; 1037 public int n_writers; 1038 public int n_blocked_readers; 1039 public int n_blocked_writers; 1040 public int n_users; 1041 }; 1042 1043 /*===================================================================== 1044 * cli_get_database_state 1045 * Obtain information about current state of the database 1046 * Parameters: 1047 * session - session descriptor returned by cli_open 1048 * monitor - pointer to the monitor structure. The folloing fields are set: 1049 * n_readers: number of granted shared locks 1050 * n_writers: number of granted exclusive locks 1051 * n_blocked_reader: number of threads which shared lock request was blocked 1052 * n_blocked_writers: number of threads which exclusive lock request was blocked 1053 * n_users: number of processes openned the database 1054 * Returns: 1055 * result code as described in cli_result_code enum 1056 */ 1057 [DllImport(libname, 1058 CharSet = CharSet.Ansi, // We want ANSI String 1059 CallingConvention = CallingConvention.Cdecl)] cli_get_database_state(int session, ref CliDatabaseMonitor monitor)1060 internal static extern int cli_get_database_state(int session, ref CliDatabaseMonitor monitor); 1061 1062 /*===================================================================== 1063 * cli_set_trace_function 1064 * Set trace function which will be used to output GigaBASE trace messages 1065 * Parameters: 1066 * func - pointer to trace function which receives trace message terminated with new line character 1067 */ 1068 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] CliTraceFunction(string msg)1069 public delegate void CliTraceFunction(string msg); 1070 1071 [DllImport(libname, 1072 CharSet = CharSet.Ansi, // We want ANSI String 1073 CallingConvention = CallingConvention.Cdecl)] cli_set_trace_function(CliTraceFunction func)1074 internal static extern void cli_set_trace_function(CliTraceFunction func); 1075 1076 /*===================================================================== 1077 * cli_prepare_query 1078 * Prepare SubSQL query statement. 1079 * Parameters: 1080 * session - session descriptor returned by cli_open 1081 * query - query string with optional parameters. Parameters are specified 1082 * as '%T' where T is one or two character code of parameter type using the same notation 1083 * as in printf: %d or %i - int, %f - float or double, %ld - int8, %s - string, %p - oid... 1084 * Returns: 1085 * >= 0 - statement descriptor 1086 * < 0 - error code as described in cli_result_code enum 1087 */ 1088 [DllImport(libname, 1089 CharSet = CharSet.Ansi, // We want ANSI String 1090 CallingConvention = CallingConvention.Cdecl)] cli_prepare_query(int session, string query)1091 internal static extern int cli_prepare_query(int session, string query); 1092 1093 /* 1094 * cli_execute_query 1095 * Execute query previously prepared by cli_prepare_query 1096 * Parameters: 1097 * statement - statement descriptor returned by cli_prepare_query 1098 * for_update - not zero if fetched rows will be updated 1099 * record_struct - structure to receive selected record fields 1100 * ... - varying list of query parameters 1101 * Returns: 1102 * >= 0 - success, for select statements number of fetched rows is returned 1103 * < 0 - error code as described in cli_result_code enum 1104 */ 1105 [DllImport(libname, 1106 CharSet = CharSet.Ansi, // We want ANSI String 1107 CallingConvention = CallingConvention.Cdecl)] cli_execute_query( int statement, QueryType queryType, IntPtr record_struct, params object[] list)1108 internal static extern int cli_execute_query( 1109 int statement, 1110 QueryType queryType, 1111 IntPtr record_struct, // void* 1112 params object[] list); 1113 1114 /* 1115 * cli_insert_struct 1116 * Insert new record represented as C structure 1117 * Parameters: 1118 * session - session descriptor returned by cli_open 1119 * table_name - name of the destination table 1120 * record_struct - structure specifying value of record fields 1121 * oid - pointer to the location to receive OID of created record (may be NULL) 1122 * Returns: 1123 * result code as described in cli_result_code enum 1124 */ 1125 [DllImport(libname, 1126 CharSet = CharSet.Ansi, // We want ANSI String 1127 CallingConvention = CallingConvention.Cdecl)] cli_insert_struct( int session, string table_name, IntPtr record_struct, ref uint oid)1128 internal static extern int cli_insert_struct( 1129 int session, 1130 string table_name, 1131 IntPtr record_struct, // void* 1132 ref uint oid); 1133 1134 1135 /** 1136 * cli_lock 1137 * Set exclusive database lock 1138 * Parameters: 1139 * session - session descriptor returned by cli_open 1140 * Returns: 1141 * result code as described in cli_result_code enum 1142 */ 1143 [DllImport(libname, 1144 CharSet = CharSet.Ansi, // We want ANSI String 1145 CallingConvention = CallingConvention.Cdecl)] cli_lock(int session)1146 internal static extern int cli_lock(int session); 1147 1148 /** 1149 * cli_backup 1150 * Perform database backup 1151 * Parameters: 1152 * session - session descriptor returned by cli_open 1153 * file_name - backup file name 1154 * compatify - if true then databae will be compactified during backup - 1155 * i.e. all used objects will be placed together without holes; if false then 1156 * backup is performed by just writting memory mapped object to the backup file. 1157 * Returns: 1158 * result code as described in cli_result_code enum 1159 */ 1160 [DllImport(libname, 1161 CharSet = CharSet.Ansi, // We want ANSI String 1162 CallingConvention = CallingConvention.Cdecl)] cli_backup(int session, string file_name, int compactify)1163 internal static extern int cli_backup(int session, string file_name, int compactify); 1164 1165 /** 1166 * cli_backup 1167 * Schedule database backup 1168 * Parameters: 1169 * session - session descriptor returned by cli_open 1170 * file_name - path to backup file. If name ends with '?', then 1171 * each backup willbe placed in seprate file with '?' replaced with current timestamp 1172 * period - period of performing backups in seconds 1173 * Returns: 1174 * result code as described in cli_result_code enum 1175 */ 1176 [DllImport(libname, 1177 CharSet = CharSet.Ansi, // We want ANSI String 1178 CallingConvention = CallingConvention.Cdecl)] cli_schedule_backup(int session, string file_name, int period)1179 internal static extern int cli_schedule_backup(int session, string file_name, int period); 1180 } 1181 } 1182