├── README.md ├── amysql.c ├── amysql.so ├── setup.py └── test.py /README.md: -------------------------------------------------------------------------------- 1 |

Simple and High Performance MySQL Driver(Python).

2 | 8 |

Current Supported Functions:

9 | 14 |

Interface:

15 | 42 |

Todo:

43 |
    44 |
  • 0. As needed;

    45 |

46 | 47 | -------------------------------------------------------------------------------- /amysql.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012 Abael Heyijun 2 | free for non-commercial use, All rights reserved. */ 3 | 4 | 5 | #ifndef __UMY_H__ 6 | #define __UMY_H__ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | //////// Python 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | //////// System - Level 22 | #define true 1 23 | #define false 0 24 | #define LOCK(con) con->rwlock =1 25 | #define UNLOCK(con) con->rwlock =0 26 | #ifdef Py_PYTHON_H 27 | #define THROW(...) do{fprintf(stderr,"Exception call: %s (%s:%ld)\n",__FUNCTION__, __FILE__, (long)__LINE__);fprintf(stderr, __VA_ARGS__);fflush(stderr);exit(-1);}while(0) 28 | #define MyMalloc(ptr, size) if((ptr=PyMem_Malloc(size))==NULL){THROW("Exception memory alloction(size:%d) ",(size));} 29 | #define MyCalloc(ptr, n, size) if((ptr=PyMem_Malloc((n) *(size)))==NULL){THROW("Exception memory alloction(size:%d) ",(size));} 30 | #define MyRealloc(ptr, size) if((ptr=PyMem_Realloc((void *)(ptr),size))==NULL){THROW("Exception memory alloction(size:%d) ",(size));} 31 | #define MyFree(p) if(p)PyMem_Free(p) 32 | #else 33 | #define THROW(...) do{fprintf(stderr,"Exception call: %s (%s:%ld)\n",__FUNCTION__, __FILE__, (long)__LINE__);fprintf(stderr, __VA_ARGS__);fflush(stderr);exit(-1);}while(0) 34 | #define MyMalloc(ptr, size) if((ptr=malloc(size)==NULL){THROW("Exception memory alloction(size:%d) ",(size));} 35 | #define MyCalloc(ptr, n, size) if((ptr=calloc(n, (size)))==NULL){THROW("Exception memory alloction(size:%d) ",(size));} 36 | #define MyRealloc(ptr, size) if((ptr=realloc((void *)(ptr), (size)))==NULL){THROW("Exception memory alloction(size:%d) ",(size));} 37 | #define MyFree(p) if(p)free(p) 38 | #endif 39 | #define EXPORTFUNCTION extern "C" __declspec(dllexport) 40 | typedef u_int8_t UINT1; 41 | typedef u_int16_t UINT2; 42 | typedef u_int32_t UINT4; 43 | typedef u_int64_t UINT8; 44 | 45 | typedef int8_t INT1; 46 | typedef int16_t INT2; 47 | typedef int32_t INT4; 48 | typedef int64_t INT8; 49 | typedef unsigned long long ulonglong; 50 | typedef unsigned long ulong; 51 | typedef unsigned char bool; 52 | 53 | 54 | //////// App Level 55 | #define MY_BUFFER_MAX 1073741824 // (1024*1024*1024) 56 | #define MY_PACKET_MAX 16777215 // (1024*1024*16 -1) 57 | #define MY_HANDSHAKE_SIZE 74 58 | #define MY_HEADER_SIZE 4 59 | #define MY_SQLSTATE_LENGTH 5 60 | #define MY_PROTOCOL_VERSION 0xa 61 | #define MY_SHA1_HASH_SIZE 20 62 | #define MY_NULL_LENGTH ((unsigned long) ~0) 63 | #define MY_SCRAMBLE_LENGTH 20 64 | #define MY_SCRAMBLE_LENGTH_323 8 65 | #define MY_PACKET_ERROR 0 66 | #define MY_TX_BUFFER_SIZE 4194304 //(1024*1024*4) 67 | #define MY_BUFFER_SIZE 16777216 // (1024*1024*16) 68 | #define MY_PACKET_MAX 16777215 // (1024*1024*16 -1) 69 | #define SERVER_STATUS_IN_TRANS 1 70 | #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ 71 | #define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */ 72 | #define SERVER_QUERY_NO_GOOD_INDEX_USED 16 73 | #define SERVER_QUERY_NO_INDEX_USED 32 74 | #define PVERSION41_CHAR '*' 75 | 76 | #define SHA1CircularShift(bits,word) (((word) << (bits)) | ((word) >> (32-(bits)))) 77 | enum sha_result_codes { 78 | SHA_SUCCESS = 0, SHA_NULL, /* Null pointer parameter */ 79 | SHA_INPUT_TOO_LONG, /* input data too long */ 80 | SHA_STATE_ERROR /* called Input after Result */ 81 | }; 82 | typedef struct SHA1_CONTEXT { 83 | ulonglong Length; /* Message length in bits */ 84 | UINT4 Intermediate_Hash[MY_SHA1_HASH_SIZE / 4]; /* Message Digest */ 85 | int Computed; /* Is the digest computed? */ 86 | int Corrupted; /* Is the message digest corrupted? */ 87 | INT2 Message_Block_Index; /* Index into message block array */ 88 | UINT1 Message_Block[64]; /* 512-bit message blocks */ 89 | } SHA1_CONTEXT; 90 | static const UINT4 sha_const_key[5] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476,0xC3D2E1F0 }; 91 | static const UINT4 SHA1_KEY[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; 92 | 93 | static PyObject *sockmodule = NULL; 94 | static PyObject *sockclass = NULL; 95 | static PyTypeObject ConType; 96 | static PyObject *amysql_Error; 97 | static PyObject *amysql_SQLError; 98 | 99 | enum MY_CHARSETS { 100 | MCS_UNDEFINED = 0, 101 | MCS_big5_chinese_ci = 1, 102 | MCS_big5_bin = 84, 103 | MCS_dec8_swedish_ci = 3, 104 | MCS_dec8_bin = 69, 105 | MCS_cp850_general_ci = 4, 106 | MCS_cp850_bin = 80, 107 | MCS_hp8_english_ci = 6, 108 | MCS_hp8_bin = 72, 109 | MCS_koi8r_general_ci = 7, 110 | MCS_koi8r_bin = 74, 111 | MCS_latin1_german1_ci = 5, 112 | MCS_latin1_swedish_ci = 8, 113 | MCS_latin1_danish_ci = 15, 114 | MCS_latin1_german2_ci = 31, 115 | MCS_latin1_bin = 47, 116 | MCS_latin1_general_ci = 48, 117 | MCS_latin1_general_cs = 49, 118 | MCS_latin1_spanish_ci = 94, 119 | MCS_latin2_czech_cs = 2, 120 | MCS_latin2_general_ci = 9, 121 | MCS_latin2_hungarian_ci = 21, 122 | MCS_latin2_croatian_ci = 27, 123 | MCS_latin2_bin = 77, 124 | MCS_swe7_swedish_ci = 10, 125 | MCS_swe7_bin = 82, 126 | MCS_ascii_general_ci = 11, 127 | MCS_ascii_bin = 65, 128 | MCS_ujis_japanese_ci = 12, 129 | MCS_ujis_bin = 91, 130 | MCS_sjis_japanese_ci = 13, 131 | MCS_sjis_bin = 88, 132 | MCS_hebrew_general_ci = 16, 133 | MCS_hebrew_bin = 71, 134 | MCS_tis620_thai_ci = 18, 135 | MCS_tis620_bin = 89, 136 | MCS_euckr_korean_ci = 19, 137 | MCS_euckr_bin = 85, 138 | MCS_koi8u_general_ci = 22, 139 | MCS_koi8u_bin = 75, 140 | MCS_gb2312_chinese_ci = 24, 141 | MCS_gb2312_bin = 86, 142 | MCS_greek_general_ci = 25, 143 | MCS_greek_bin = 70, 144 | MCS_cp1250_general_ci = 26, 145 | MCS_cp1250_czech_cs = 34, 146 | MCS_cp1250_croatian_ci = 44, 147 | MCS_cp1250_bin = 66, 148 | MCS_cp1250_polish_ci = 99, 149 | MCS_gbk_chinese_ci = 28, 150 | MCS_gbk_bin = 87, 151 | MCS_latin5_turkish_ci = 30, 152 | MCS_latin5_bin = 78, 153 | MCS_armscii8_general_ci = 32, 154 | MCS_armscii8_bin = 64, 155 | MCS_utf8_general_ci = 33, 156 | MCS_utf8_bin = 83, 157 | MCS_utf8_unicode_ci = 192, 158 | MCS_utf8_icelandic_ci = 193, 159 | MCS_utf8_latvian_ci = 194, 160 | MCS_utf8_romanian_ci = 195, 161 | MCS_utf8_slovenian_ci = 196, 162 | MCS_utf8_polish_ci = 197, 163 | MCS_utf8_estonian_ci = 198, 164 | MCS_utf8_spanish_ci = 199, 165 | MCS_utf8_swedish_ci = 200, 166 | MCS_utf8_turkish_ci = 201, 167 | MCS_utf8_czech_ci = 202, 168 | MCS_utf8_danish_ci = 203, 169 | MCS_utf8_lithuanian_ci = 204, 170 | MCS_utf8_slovak_ci = 205, 171 | MCS_utf8_spanish2_ci = 206, 172 | MCS_utf8_roman_ci = 207, 173 | MCS_utf8_persian_ci = 208, 174 | MCS_utf8_esperanto_ci = 209, 175 | MCS_utf8_hungarian_ci = 210, 176 | MCS_utf8_sinhala_ci = 211, 177 | MCS_ucs2_general_ci = 35, 178 | MCS_ucs2_bin = 90, 179 | MCS_ucs2_unicode_ci = 128, 180 | MCS_ucs2_icelandic_ci = 129, 181 | MCS_ucs2_latvian_ci = 130, 182 | MCS_ucs2_romanian_ci = 131, 183 | MCS_ucs2_slovenian_ci = 132, 184 | MCS_ucs2_polish_ci = 133, 185 | MCS_ucs2_estonian_ci = 134, 186 | MCS_ucs2_spanish_ci = 135, 187 | MCS_ucs2_swedish_ci = 136, 188 | MCS_ucs2_turkish_ci = 137, 189 | MCS_ucs2_czech_ci = 138, 190 | MCS_ucs2_danish_ci = 139, 191 | MCS_ucs2_lithuanian_ci = 140, 192 | MCS_ucs2_slovak_ci = 141, 193 | MCS_ucs2_spanish2_ci = 142, 194 | MCS_ucs2_roman_ci = 143, 195 | MCS_ucs2_persian_ci = 144, 196 | MCS_ucs2_esperanto_ci = 145, 197 | MCS_ucs2_hungarian_ci = 146, 198 | MCS_ucs2_sinhala_ci = 147, 199 | MCS_cp866_general_ci = 36, 200 | MCS_cp866_bin = 68, 201 | MCS_keybcs2_general_ci = 37, 202 | MCS_keybcs2_bin = 73, 203 | MCS_macce_general_ci = 38, 204 | MCS_macce_bin = 43, 205 | MCS_macroman_general_ci = 39, 206 | MCS_macroman_bin = 53, 207 | MCS_cp852_general_ci = 40, 208 | MCS_cp852_bin = 81, 209 | MCS_latin7_estonian_cs = 20, 210 | MCS_latin7_general_ci = 41, 211 | MCS_latin7_general_cs = 42, 212 | MCS_latin7_bin = 79, 213 | MCS_utf8mb4_general_ci = 45, 214 | MCS_utf8mb4_bin = 46, 215 | MCS_utf8mb4_unicode_ci = 224, 216 | MCS_utf8mb4_icelandic_ci = 225, 217 | MCS_utf8mb4_latvian_ci = 226, 218 | MCS_utf8mb4_romanian_ci = 227, 219 | MCS_utf8mb4_slovenian_ci = 228, 220 | MCS_utf8mb4_polish_ci = 229, 221 | MCS_utf8mb4_estonian_ci = 230, 222 | MCS_utf8mb4_spanish_ci = 231, 223 | MCS_utf8mb4_swedish_ci = 232, 224 | MCS_utf8mb4_turkish_ci = 233, 225 | MCS_utf8mb4_czech_ci = 234, 226 | MCS_utf8mb4_danish_ci = 235, 227 | MCS_utf8mb4_lithuanian_ci = 236, 228 | MCS_utf8mb4_slovak_ci = 237, 229 | MCS_utf8mb4_spanish2_ci = 238, 230 | MCS_utf8mb4_roman_ci = 239, 231 | MCS_utf8mb4_persian_ci = 240, 232 | MCS_utf8mb4_esperanto_ci = 241, 233 | MCS_utf8mb4_hungarian_ci = 242, 234 | MCS_utf8mb4_sinhala_ci = 243, 235 | MCS_cp1251_bulgarian_ci = 14, 236 | MCS_cp1251_ukrainian_ci = 23, 237 | MCS_cp1251_bin = 50, 238 | MCS_cp1251_general_ci = 51, 239 | MCS_cp1251_general_cs = 52, 240 | MCS_utf16_general_ci = 54, 241 | MCS_utf16_bin = 55, 242 | MCS_utf16_unicode_ci = 101, 243 | MCS_utf16_icelandic_ci = 102, 244 | MCS_utf16_latvian_ci = 103, 245 | MCS_utf16_romanian_ci = 104, 246 | MCS_utf16_slovenian_ci = 105, 247 | MCS_utf16_polish_ci = 106, 248 | MCS_utf16_estonian_ci = 107, 249 | MCS_utf16_spanish_ci = 108, 250 | MCS_utf16_swedish_ci = 109, 251 | MCS_utf16_turkish_ci = 110, 252 | MCS_utf16_czech_ci = 111, 253 | MCS_utf16_danish_ci = 112, 254 | MCS_utf16_lithuanian_ci = 113, 255 | MCS_utf16_slovak_ci = 114, 256 | MCS_utf16_spanish2_ci = 115, 257 | MCS_utf16_roman_ci = 116, 258 | MCS_utf16_persian_ci = 117, 259 | MCS_utf16_esperanto_ci = 118, 260 | MCS_utf16_hungarian_ci = 119, 261 | MCS_utf16_sinhala_ci = 120, 262 | MCS_cp1256_general_ci = 57, 263 | MCS_cp1256_bin = 67, 264 | MCS_cp1257_lithuanian_ci = 29, 265 | MCS_cp1257_bin = 58, 266 | MCS_cp1257_general_ci = 59, 267 | MCS_utf32_general_ci = 60, 268 | MCS_utf32_bin = 61, 269 | MCS_utf32_unicode_ci = 160, 270 | MCS_utf32_icelandic_ci = 161, 271 | MCS_utf32_latvian_ci = 162, 272 | MCS_utf32_romanian_ci = 163, 273 | MCS_utf32_slovenian_ci = 164, 274 | MCS_utf32_polish_ci = 165, 275 | MCS_utf32_estonian_ci = 166, 276 | MCS_utf32_spanish_ci = 167, 277 | MCS_utf32_swedish_ci = 168, 278 | MCS_utf32_turkish_ci = 169, 279 | MCS_utf32_czech_ci = 170, 280 | MCS_utf32_danish_ci = 171, 281 | MCS_utf32_lithuanian_ci = 172, 282 | MCS_utf32_slovak_ci = 173, 283 | MCS_utf32_spanish2_ci = 174, 284 | MCS_utf32_roman_ci = 175, 285 | MCS_utf32_persian_ci = 176, 286 | MCS_utf32_esperanto_ci = 177, 287 | MCS_utf32_hungarian_ci = 178, 288 | MCS_utf32_sinhala_ci = 179, 289 | MCS_binary = 63, 290 | MCS_geostd8_general_ci = 92, 291 | MCS_geostd8_bin = 93, 292 | MCS_cp932_japanese_ci = 95, 293 | MCS_cp932_bin = 96, 294 | MCS_eucjpms_japanese_ci = 97, 295 | MCS_eucjpms_bin = 98, 296 | }; 297 | 298 | enum MY_CMD { 299 | COM_SLEEP, 300 | COM_QUIT, 301 | COM_INIT_DB, 302 | COM_QUERY, 303 | COM_FIELD_LIST, 304 | COM_CREATE_DB, 305 | COM_DROP_DB, 306 | COM_REFRESH, 307 | COM_SHUTDOWN, 308 | COM_STATISTICS, 309 | COM_PROCESS_INFO, 310 | COM_CONNECT, 311 | COM_PROCESS_KILL, 312 | COM_DEBUG, 313 | COM_PING, 314 | COM_TIME, 315 | COM_DELAYED_INSERT, 316 | COM_CHANGE_USER, 317 | COM_BINLOG_DUMP, 318 | COM_TABLE_DUMP, 319 | COM_CONNECT_OUT, 320 | COM_REGISTER_SLAVE, 321 | COM_STMT_PREPARE, 322 | COM_STMT_EXECUTE, 323 | COM_STMT_SEND_LONG_DATA, 324 | COM_STMT_CLOSE, 325 | COM_STMT_RESET, 326 | COM_SET_OPTION, 327 | COM_STMT_FETCH, 328 | COM_DAEMON, 329 | COM_END 330 | }; 331 | 332 | enum MY_FIELDFLAG { 333 | MFFLAG_NOT_NULL_FLAG = 0x0001, 334 | MFFLAG_PRI_KEY_FLAG = 0x0002, 335 | MFFLAG_UNIQUE_KEY_FLAG = 0x0004, 336 | MFFLAG_MULTIPLE_KEY_FLAG = 0x0008, 337 | MFFLAG_BLOB_FLAG = 0x0010, 338 | MFFLAG_UNSIGNED_FLAG = 0x0020, 339 | MFFLAG_ZEROFILL_FLAG = 0x0040, 340 | MFFLAG_BINARY_FLAG = 0x0080, 341 | MFFLAG_ENUM_FLAG = 0x0100, 342 | MFFLAG_AUTO_INCREMENT_FLAG = 0x0200, 343 | MFFLAG_TIMESTAMP_FLAG = 0x0400, 344 | MFFLAG_SET_FLAG = 0x0800, 345 | }; 346 | 347 | enum MY_STATUS { 348 | MY_STATUS_READY, MY_STATUS_GET_RESULT, MY_STATUS_USE_RESULT 349 | }; 350 | 351 | enum MY_PACKETREAD { 352 | MPR_NONE = 0, 353 | MPR_MORE = 1, 354 | MPR_ERROR = 2, 355 | MPR_TRUE = 4, 356 | MPR_START = 8, 357 | MPR_END = 16, 358 | MPR_EOF = 32, 359 | }; 360 | 361 | enum MY_FIELDTYPE { 362 | MFTYPE_DECIMAL = 0x00, 363 | MFTYPE_TINY = 0x01, 364 | MFTYPE_SHORT = 0x02, 365 | MFTYPE_LONG = 0x03, 366 | MFTYPE_FLOAT = 0x04, 367 | MFTYPE_DOUBLE = 0x05, 368 | MFTYPE_NULL = 0x06, 369 | MFTYPE_TIMESTAMP = 0x07, 370 | MFTYPE_LONGLONG = 0x08, 371 | MFTYPE_INT24 = 0x09, 372 | MFTYPE_DATE = 0x0a, 373 | MFTYPE_TIME = 0x0b, 374 | MFTYPE_DATETIME = 0x0c, 375 | MFTYPE_YEAR = 0x0d, 376 | MFTYPE_NEWDATE = 0x0e, 377 | MFTYPE_VARCHAR = 0x0f, 378 | MFTYPE_BIT = 0x10, 379 | MFTYPE_NEWDECIMAL = 0xf6, 380 | MFTYPE_ENUM = 0xf7, 381 | MFTYPE_SET = 0xf8, 382 | MFTYPE_TINY_BLOB = 0xf9, 383 | MFTYPE_MEDIUM_BLOB = 0xfa, 384 | MFTYPE_LONG_BLOB = 0xfb, 385 | MFTYPE_BLOB = 0xfc, 386 | MFTYPE_VAR_STRING = 0xfd, 387 | MFTYPE_STRING = 0xfe, 388 | MFTYPE_GEOMETRY = 0xff, 389 | }; 390 | 391 | enum MY_CAPABILITIES { 392 | MCP_LONG_PASSWORD = (1 << 0), // new more secure passwords 393 | MCP_FOUND_ROWS = (1 << 1), //Found instead of affected rows 394 | MCP_LONG_FLAG = (1 << 2), //Get all column flags */ 395 | MCP_CONNECT_WITH_DB = (1 << 3), // One can specify db on connect */ 396 | MCP_NO_SCHEMA = (1 << 4), // /* Don't allow database.table.column */ 397 | MCP_COMPRESS = (1 << 5), // Can use compression protocol */ 398 | MCP_ODBC = (1 << 6), // Odbc client */ 399 | MCP_LOCAL_FILES = (1 << 7), // Can use LOAD DATA LOCAL */ 400 | MCP_IGNORE_SPACE = (1 << 8), // Ignore spaces before '(' */ 401 | MCP_PROTOCOL_41 = (1 << 9), // New 4.1 protocol */ 402 | MCP_INTERACTIVE = (1 << 10), // This is an interactive client */ 403 | MCP_SSL = (1 << 11), //Switch to SSL after handshake */ 404 | MCP_IGNORE_SIGPIPE = (1 << 12), // IGNORE sigpipes */ 405 | MCP_TRANSACTIONS = (1 << 13), // Client knows about transactions */ 406 | MCP_RESERVED = (1 << 14), // Old flag for 4.1 protocol */ 407 | MCP_SECURE_CONNECTION = (1 << 15), // New 4.1 authentication */ 408 | MCP_MULTI_STATEMENTS = (1 << 16), // Enable/disable multi-stmt support */ 409 | MCP_MULTI_RESULTS = (1 << 17), // Enable/disable multi-results */ 410 | }; 411 | 412 | typedef struct Field { 413 | PyObject *name; 414 | UINT1 type; 415 | UINT2 flags; 416 | UINT2 charset; 417 | UINT2 decimal; 418 | } Field; 419 | 420 | //////// The Core Data Struct 421 | typedef struct { 422 | PyObject_HEAD 423 | PyObject *(*PFN_PyUnicode_Encode)(const Py_UNICODE *data, Py_ssize_t length, 424 | const char *errors); 425 | 426 | PyObject *Error; 427 | PyObject *SQLError; 428 | 429 | /* query-wide random string */ 430 | void *sock; 431 | UINT1 *readerStartPtr, *readerReadPtr, *readerWritePtr, *readerEndPtr; 432 | UINT1 *writerStartPtr, *writerReadPtr, *writerWritePtr, *writerEndPtr; 433 | UINT1 *readerPktPtr; 434 | PyObject *fields; 435 | PyObject *rows; 436 | PyObject *curs; 437 | UINT4 nums; 438 | UINT1 columns; 439 | UINT1 nid; // next packet sequence id; 440 | UINT1 sqlstate[MY_SQLSTATE_LENGTH + 1]; // 441 | UINT2 lasterrno; // last errno; 442 | char *errmsg; 443 | 444 | UINT8 affectedRows; 445 | UINT8 insertId; /* id if insert on table with NEXTNR */ 446 | UINT8 fieldCount; 447 | UINT4 serverStatus; 448 | UINT4 serverLanguage; 449 | UINT4 warningCount; 450 | 451 | /* session-wide random string */ 452 | UINT1 ver; 453 | UINT4 cid; /* Con Id for connection in server */ 454 | UINT4 tid; /* thread Id for connection in server */ 455 | UINT4 pid; 456 | 457 | UINT1 serverLang; 458 | UINT2 serverCaps; 459 | UINT4 clientFlag; 460 | char scramble[MY_SCRAMBLE_LENGTH + 1]; 461 | 462 | UINT4 timeout; /* set to 1 if automatic reconnect */ 463 | UINT4 port; //ac: auto Commit 464 | char *host, *user, *pswd, *db, *serverVersion; 465 | bool ac; 466 | enum MY_CHARSETS charset; 467 | } Con; 468 | 469 | // for error and DEBUG 470 | void pbuf(FILE *file, void *_offset, size_t len, int perRow) { 471 | size_t cnt = 0; 472 | int index; 473 | 474 | char *offset = (char *) _offset; 475 | char *end = offset + len; 476 | 477 | int orgPerRow = perRow; 478 | 479 | fprintf(file, "<< %u(0x%x) %p - %p --------------\n", (unsigned int)len, (unsigned int)len, _offset, 480 | _offset + (unsigned int)len); 481 | 482 | while (offset != end) { 483 | fprintf(file, "%08x: ", (unsigned int)cnt); 484 | 485 | if (end - offset < perRow) { 486 | perRow = end - offset; 487 | } 488 | 489 | for (index = 0; index < perRow; index++) { 490 | int chr = (unsigned char) *offset; 491 | 492 | if (isprint(chr)) { 493 | fprintf(file, "%c", chr); 494 | } else { 495 | fprintf(file, "."); 496 | } 497 | 498 | offset++; 499 | } 500 | 501 | offset -= perRow; 502 | 503 | for (index = perRow; index < orgPerRow; index++) { 504 | fprintf(file, " "); 505 | } 506 | 507 | fprintf(file, " "); 508 | 509 | for (index = 0; index < perRow; index++) { 510 | int chr = (unsigned char) *offset; 511 | 512 | fprintf(file, "%02x ", chr); 513 | offset++; 514 | } 515 | 516 | fprintf(file, "\n"); 517 | 518 | cnt += perRow; 519 | } 520 | } 521 | 522 | PyObject *API_error(Con *self, const char *msg) { 523 | PyObject *value; 524 | 525 | if (self->sock) { 526 | if (PyErr_Occurred()) { 527 | value = Py_BuildValue("(s,o,i,s)", 528 | "Python exception when local error is set", 529 | PyErr_Occurred(), self->lasterrno, self->errmsg); 530 | PyErr_Clear(); 531 | PyErr_SetObject(amysql_Error, value); 532 | Py_DECREF(value); 533 | return NULL; 534 | } 535 | 536 | value = Py_BuildValue("(s,s)", msg, "Should not happen"); 537 | PyErr_SetObject(PyExc_RuntimeError, value); 538 | Py_DECREF(value); 539 | return NULL; 540 | } 541 | 542 | if (PyErr_Occurred()) { 543 | return NULL; 544 | } 545 | 546 | value = Py_BuildValue("(s, s)", msg, 547 | "No error or Python error specified"); 548 | PyErr_SetObject(PyExc_RuntimeError, value); 549 | if (value) 550 | Py_DECREF(value); 551 | return NULL; 552 | } 553 | 554 | // SHA1 555 | inline void SHA1ProcessMessageBlock(register SHA1_CONTEXT *context) { 556 | register int t, idx; /* Loop counter */ 557 | UINT4 temp; /* Temporary word value */ 558 | UINT4 W[80]; /* Word sequence */ 559 | UINT4 A, B, C, D, E; /* Word buffers */ 560 | 561 | for (t = 0; t < 16; t++) { 562 | idx = t * 4; 563 | W[t] = context->Message_Block[idx] << 24; 564 | W[t] |= context->Message_Block[idx + 1] << 16; 565 | W[t] |= context->Message_Block[idx + 2] << 8; 566 | W[t] |= context->Message_Block[idx + 3]; 567 | } 568 | 569 | for (t = 16; t < 80; t++) { 570 | W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 571 | } 572 | 573 | A = context->Intermediate_Hash[0]; 574 | B = context->Intermediate_Hash[1]; 575 | C = context->Intermediate_Hash[2]; 576 | D = context->Intermediate_Hash[3]; 577 | E = context->Intermediate_Hash[4]; 578 | 579 | for (t = 0; t < 20; t++) { 580 | temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] 581 | + SHA1_KEY[0]; 582 | E = D; 583 | D = C; 584 | C = SHA1CircularShift(30,B); 585 | B = A; 586 | A = temp; 587 | } 588 | 589 | for (t = 20; t < 40; t++) { 590 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + SHA1_KEY[1]; 591 | E = D; 592 | D = C; 593 | C = SHA1CircularShift(30,B); 594 | B = A; 595 | A = temp; 596 | } 597 | 598 | for (t = 40; t < 60; t++) { 599 | temp = (SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E 600 | + W[t] + SHA1_KEY[2]); 601 | E = D; 602 | D = C; 603 | C = SHA1CircularShift(30,B); 604 | B = A; 605 | A = temp; 606 | } 607 | 608 | for (t = 60; t < 80; t++) { 609 | temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + SHA1_KEY[3]; 610 | E = D; 611 | D = C; 612 | C = SHA1CircularShift(30,B); 613 | B = A; 614 | A = temp; 615 | } 616 | 617 | context->Intermediate_Hash[0] += A; 618 | context->Intermediate_Hash[1] += B; 619 | context->Intermediate_Hash[2] += C; 620 | context->Intermediate_Hash[3] += D; 621 | context->Intermediate_Hash[4] += E; 622 | 623 | context->Message_Block_Index = 0; 624 | } 625 | inline void SHA1PadMessage(SHA1_CONTEXT *context) { 626 | int i = context->Message_Block_Index; 627 | 628 | if (i > 55) { 629 | context->Message_Block[i++] = 0x80; 630 | bzero((char*) &context->Message_Block[i], 631 | sizeof(context->Message_Block[0]) * (64 - i)); 632 | context->Message_Block_Index = 64; 633 | 634 | /* This function sets context->Message_Block_Index to zero */ 635 | SHA1ProcessMessageBlock(context); 636 | 637 | bzero((char*) &context->Message_Block[0], 638 | sizeof(context->Message_Block[0]) * 56); 639 | context->Message_Block_Index = 56; 640 | } else { 641 | context->Message_Block[i++] = 0x80; 642 | bzero((char*) &context->Message_Block[i], 643 | sizeof(context->Message_Block[0]) * (56 - i)); 644 | context->Message_Block_Index = 56; 645 | } 646 | 647 | context->Message_Block[56] = (UINT1) (context->Length >> 56); 648 | context->Message_Block[57] = (UINT1) (context->Length >> 48); 649 | context->Message_Block[58] = (UINT1) (context->Length >> 40); 650 | context->Message_Block[59] = (UINT1) (context->Length >> 32); 651 | context->Message_Block[60] = (UINT1) (context->Length >> 24); 652 | context->Message_Block[61] = (UINT1) (context->Length >> 16); 653 | context->Message_Block[62] = (UINT1) (context->Length >> 8); 654 | context->Message_Block[63] = (UINT1) (context->Length); 655 | 656 | SHA1ProcessMessageBlock(context); 657 | } 658 | static int sha1_reset(SHA1_CONTEXT *context) { 659 | context->Length = 0; 660 | context->Message_Block_Index = 0; 661 | 662 | context->Intermediate_Hash[0] = sha_const_key[0]; 663 | context->Intermediate_Hash[1] = sha_const_key[1]; 664 | context->Intermediate_Hash[2] = sha_const_key[2]; 665 | context->Intermediate_Hash[3] = sha_const_key[3]; 666 | context->Intermediate_Hash[4] = sha_const_key[4]; 667 | 668 | context->Computed = 0; 669 | context->Corrupted = 0; 670 | 671 | return SHA_SUCCESS; 672 | } 673 | static int sha1_result(SHA1_CONTEXT *context, 674 | UINT1 Message_Digest[MY_SHA1_HASH_SIZE]) { 675 | UINT4 i; 676 | if (!context->Computed) { 677 | SHA1PadMessage(context);/* message may be sensitive, clear it out */ 678 | for (i = 0; i < 64; ++i) 679 | context->Message_Block[i] = 0; 680 | context->Length = 0; /* and clear length */ 681 | context->Computed = 1; 682 | } 683 | 684 | for (i = 0; i < MY_SHA1_HASH_SIZE; i++) 685 | Message_Digest[i] = (INT1) (context->Intermediate_Hash[i >> 2] 686 | >> 8 * (3 - (i & 0x03))); 687 | return SHA_SUCCESS; 688 | } 689 | static int sha1_input(SHA1_CONTEXT *context, const UINT1 *message_array, 690 | unsigned length) { 691 | if (!length) 692 | return SHA_SUCCESS; 693 | while (length--) { 694 | context->Message_Block[context->Message_Block_Index++] = (*message_array 695 | & 0xFF); 696 | context->Length += 8; /* Length is in bits */ 697 | 698 | if (context->Message_Block_Index == 64) { 699 | SHA1ProcessMessageBlock(context); 700 | } 701 | message_array++; 702 | } 703 | return SHA_SUCCESS; 704 | } 705 | static void scramble_password(UINT1 *to, const UINT1 *message, const UINT1 *password) { 706 | SHA1_CONTEXT sha1_context; 707 | UINT1 hash_stage1[MY_SHA1_HASH_SIZE]; 708 | UINT1 hash_stage2[MY_SHA1_HASH_SIZE]; 709 | int index = 0; 710 | 711 | sha1_reset(&sha1_context); 712 | sha1_input(&sha1_context, (UINT1 *) password, (UINT4) strlen(password)); 713 | sha1_result(&sha1_context, hash_stage1); 714 | sha1_reset(&sha1_context); 715 | sha1_input(&sha1_context, hash_stage1, MY_SHA1_HASH_SIZE); 716 | sha1_result(&sha1_context, hash_stage2); 717 | sha1_reset(&sha1_context); 718 | sha1_input(&sha1_context, (const UINT1 *) message, MY_SCRAMBLE_LENGTH); 719 | sha1_input(&sha1_context, hash_stage2, MY_SHA1_HASH_SIZE); 720 | sha1_result(&sha1_context, to); 721 | for (index = 0; index < MY_SHA1_HASH_SIZE; ++index)to[index] ^= hash_stage1[index];/* xor allows 'from' and 'to' overlap: lets take advantage of it */ 722 | } 723 | 724 | //////// Python socket interface 725 | inline void * 726 | API_getSocket() { 727 | PyObject *sockobj; 728 | sockobj = PyObject_Call(sockclass, PyTuple_New(0), NULL); 729 | return sockobj; 730 | } 731 | inline int 732 | API_setTimeout(void *sock, int timeoutSec) { 733 | PyObject *intobj; 734 | PyObject *retobj; 735 | PyObject *methodObj; 736 | 737 | intobj = PyFloat_FromDouble((double) timeoutSec); 738 | 739 | methodObj = PyString_FromString("settimeout"); 740 | retobj = PyObject_CallMethodObjArgs((PyObject *) sock, methodObj, intobj, 741 | NULL); 742 | Py_DECREF(intobj); 743 | Py_DECREF(methodObj); 744 | if (retobj == NULL) { 745 | PyErr_Clear(); 746 | return 0; 747 | } 748 | 749 | Py_DECREF(retobj); 750 | return 1; 751 | 752 | } 753 | inline bool API_closeSocket(void *sock) { 754 | PyObject *res = PyObject_CallMethod((PyObject *) sock, "close", NULL); 755 | 756 | if (res == NULL) 757 | return 0; 758 | 759 | Py_DECREF(res); 760 | Py_DECREF((PyObject *) sock); 761 | return 1; 762 | } 763 | inline bool API_setblockingSocket(void *sock, bool flag) { 764 | PyObject *res = PyObject_CallMethod((PyObject *) sock, "setblocking", "i", 765 | &flag); 766 | 767 | if (res == NULL) 768 | return 0; 769 | 770 | Py_DECREF(res); 771 | Py_DECREF((PyObject *) sock); 772 | return 1; 773 | } 774 | inline int API_connectSocket(void *sock, const char *host, int port) { 775 | PyObject *res; 776 | PyObject *addrTuple; 777 | PyObject *connectStr; 778 | 779 | addrTuple = PyTuple_New(2); 780 | PyTuple_SET_ITEM(addrTuple, 0, PyString_FromString(host)); 781 | PyTuple_SET_ITEM(addrTuple, 1, PyInt_FromLong(port)); 782 | 783 | connectStr = PyString_FromString("connect_ex"); 784 | res = PyObject_CallMethodObjArgs((PyObject *) sock, connectStr, addrTuple, 785 | NULL); 786 | 787 | Py_DECREF(connectStr); 788 | Py_DECREF(addrTuple); 789 | 790 | if (res == NULL) 791 | return 0; 792 | Py_DECREF(res); 793 | return 1; 794 | } 795 | inline int API_recvSocket(void *sock,UINT1 *buffer, size_t size) { 796 | int ret; 797 | PyObject *res; 798 | if ((res = PyObject_CallMethodObjArgs((PyObject *) sock, 799 | PyString_FromString("recv"), PyInt_FromLong(size), NULL)) == NULL) 800 | return -1; 801 | ret = (long) PyString_GET_SIZE(res); 802 | memcpy(buffer, PyString_AS_STRING(res), ret); 803 | Py_DECREF(res); 804 | return ret; 805 | } 806 | inline int API_sendSocket(void *sock, const char *buffer, int cbBuffer) { 807 | PyObject *res; 808 | PyObject *pybuffer; 809 | PyObject *funcStr; 810 | int ret; 811 | 812 | funcStr = PyString_FromString("send"); 813 | pybuffer = PyString_FromStringAndSize(buffer, cbBuffer); 814 | res = PyObject_CallMethodObjArgs((PyObject *) sock, funcStr, pybuffer, 815 | NULL); 816 | Py_DECREF(funcStr); 817 | Py_DECREF(pybuffer); 818 | 819 | if (res == NULL) { 820 | return -1; 821 | } 822 | 823 | ret = (int) PyInt_AsLong(res); 824 | Py_DECREF(res); 825 | return ret; 826 | } 827 | 828 | //////// Con buffers( reader/writer ) interface 829 | inline UINT1 readerUINT1(Con *self) { 830 | assert(self->readerReadPtr + 1 < self->readerPktPtr); 831 | return *self->readerReadPtr++; 832 | } 833 | inline UINT2 readerUINT2(Con *self) { 834 | assert(self->readerReadPtr + 2 <= self->readerPktPtr); 835 | UINT2 ret = *((UINT2 *)self->readerReadPtr); 836 | self->readerReadPtr += 2; 837 | return ret; 838 | } 839 | inline UINT4 readerUINT3(Con *self) { 840 | assert(self->readerReadPtr + 3 < self->readerPktPtr); 841 | UINT4 ret = 0xffffff & *((UINT4 *) self->readerReadPtr); 842 | self->readerReadPtr += 3; 843 | return ret; 844 | } 845 | inline UINT4 readerUINT4(Con *self) { 846 | assert(self->readerReadPtr + 4 <= self->readerPktPtr); 847 | UINT4 ret = *((UINT4 *) self->readerReadPtr); 848 | self->readerReadPtr += 4; 849 | return ret; 850 | } 851 | inline UINT4 Con_WriteUINT4(Con *self) { 852 | assert(self->writerWritePtr + 4 < self->writerEndPtr); 853 | UINT4 ret = *((UINT4 *) self->readerReadPtr); 854 | self->readerReadPtr += 4; 855 | return *self->readerReadPtr++; 856 | return ret; 857 | } 858 | inline UINT8 readerCodedLength(Con *self) { 859 | assert(self->readerReadPtr < self->readerPktPtr); 860 | register UINT1 *pos = self->readerReadPtr; 861 | 862 | switch (*pos) { 863 | case 0xfe: 864 | self->readerReadPtr += 9; 865 | return *((UINT8 *) (pos + 1)); 866 | case 0xfd: 867 | self->readerReadPtr += 4; 868 | return pos[1] | pos[2] << 8 | pos[3] << 16; 869 | case 0xfc: 870 | self->readerReadPtr += 3; 871 | return *((UINT2 *) pos); 872 | case 0xfb: 873 | self->readerReadPtr++; 874 | return MY_NULL_LENGTH; 875 | default: 876 | self->readerReadPtr++; 877 | return *pos; 878 | } 879 | } 880 | inline ulong readerFieldLength(Con *self) { 881 | assert(self->readerReadPtr < self->readerPktPtr); 882 | register UINT1 *pos = self->readerReadPtr; 883 | switch (*pos) { 884 | case 0xfe: 885 | self->readerReadPtr += 9; 886 | return *((const UINT4 *) (pos + 1)); 887 | case 0xfd: 888 | self->readerReadPtr += 4; 889 | return 0xffffff & *((const UINT4 *) (pos + 1)); 890 | case 0xfc: 891 | self->readerReadPtr += 3; 892 | return *((const UINT2 *) (pos + 1)); 893 | case 0xfb: 894 | self->readerReadPtr++; 895 | return MY_NULL_LENGTH; 896 | default: 897 | self->readerReadPtr++; 898 | return (ulong) *pos; 899 | } 900 | } 901 | inline UINT1 *readerBytes(Con *self, size_t size) { 902 | assert( 903 | self->readerReadPtr + size < self->readerPktPtr 904 | && self->readerPktPtr <= self->readerWritePtr); 905 | UINT1 *ret = (UINT1 *) self->readerReadPtr; 906 | self->readerReadPtr += size; 907 | return ret; 908 | } 909 | inline char *readerNTString(Con *self) { 910 | assert( 911 | self->readerReadPtr < self->readerPktPtr 912 | && self->readerPktPtr <= self->readerEndPtr); 913 | char *ret = (char *)self->readerReadPtr; 914 | while (self->readerReadPtr < self->readerPktPtr) 915 | if ((*self->readerReadPtr++) == '\0') 916 | return ret; 917 | assert(0); 918 | return NULL; 919 | } 920 | #define readerReset(con) do{if(!con->readerStartPtr || con->readerEndPtr -con->readerStartPtr>MY_BUFFER_SIZE){MyRealloc(con->readerStartPtr, MY_BUFFER_SIZE);con->readerEndPtr= con->readerStartPtr +MY_BUFFER_SIZE;};con->nid=0;con->readerPktPtr=con->readerReadPtr=con->readerWritePtr=con->readerStartPtr;}while(0) 921 | #define writerINT1(con,u) do{*((UINT1*)con->writerWritePtr)=(u);con->writerWritePtr++;}while(0) 922 | #define writerINT4(con,u) do{*((UINT4*)con->writerWritePtr)=(u);con->writerWritePtr+=4;}while(0) 923 | #define writerSize(con) (con->writerEndPtr-con->writerStartPtr) 924 | #define writerIsDone(con) (con->writerReadPtr ==con->writerWritePtr) 925 | #define writerPush(con, ptr, sz) do{assert(con->writeWritePtr +sz>0 && con->writeWritePtr +szwriterEndPtr);memcpy(con->writeWritePtr,p,sz);con->writeWritePtr+=sz;}while(0) 926 | #define writerPull(con,sz) do{assert(con->writeReadPtr+sz>0 && writeReadPtr+sz<=writeWritePtr);writeReadPtr +=sz;}while(0) 927 | inline void writerReset(Con *self) { 928 | if (!self->writerStartPtr 929 | || self->writerEndPtr - self->writerStartPtr <= MY_PACKET_MAX 930 | || self->writerEndPtr - self->writerStartPtr >= MY_BUFFER_MAX) { 931 | MyRealloc(self->writerStartPtr, MY_BUFFER_SIZE); 932 | self->writerWritePtr = self->writerReadPtr = self->writerStartPtr; 933 | self->writerEndPtr = self->writerStartPtr + MY_BUFFER_SIZE; 934 | } 935 | self->writerWritePtr = self->writerReadPtr; 936 | *((UINT4*) self->writerWritePtr) = 0; 937 | self->writerWritePtr += MY_HEADER_SIZE; 938 | } 939 | inline void writerFinalize(Con *self, UINT4 sid) { 940 | *((UINT4 *) self->writerReadPtr) = 0xffffff 941 | & ((UINT4) (self->writerWritePtr - self->writerReadPtr 942 | - MY_HEADER_SIZE)); 943 | self->writerReadPtr[3] = (UINT1) sid; 944 | } 945 | inline bool writerNTString(Con *self, char *p) { 946 | if (!p) { 947 | assert(self->writerWritePtr < self->writerEndPtr); 948 | *(self->writerWritePtr++) = '\0'; 949 | } 950 | while (*p && self->writerWritePtr < self->writerEndPtr) 951 | *(self->writerWritePtr++) = *p++; 952 | assert(self->writerWritePtr < self->writerEndPtr); 953 | *(self->writerWritePtr)++ = '\0'; 954 | return true; 955 | } 956 | inline bool writerBytes(Con *self, char *p, UINT4 sz) { 957 | if (!p || sz == 0 || self->writerEndPtr - self->writerWritePtr < sz) 958 | return false; 959 | while (self->writerWritePtr < self->writerEndPtr && sz-- > 0) 960 | *(self->writerWritePtr++) = *p++; 961 | if (sz != 0) 962 | return false; 963 | return true; 964 | } 965 | 966 | inline INT4 parseINT4(UINT1 *start, UINT1 *end) { 967 | INT4 intValue = 0; 968 | INT4 intNeg = 1; 969 | INT4 chr; 970 | 971 | if (*start == '-') { 972 | start++; 973 | intNeg = -1; 974 | } 975 | 976 | while (start < end) { 977 | chr = (INT4) (unsigned char) *(start++); 978 | switch (chr) { 979 | case '0': 980 | case '1': 981 | case '2': 982 | case '3': 983 | case '4': 984 | case '5': 985 | case '6': 986 | case '7': 987 | case '8': 988 | case '9': 989 | intValue = intValue * 10 + (INT4) (chr - 48); 990 | break; 991 | 992 | default: 993 | break; 994 | } 995 | } 996 | 997 | return intValue * intNeg; 998 | } 999 | inline INT8 parseINT8(UINT1 *start, char *end) { 1000 | INT8 intValue = 0; 1001 | INT8 intNeg = 1; 1002 | INT8 chr; 1003 | 1004 | if (*start == '-') { 1005 | start++; 1006 | intNeg = -1; 1007 | } 1008 | 1009 | while (start < end) { 1010 | chr = (INT4) (unsigned char) *(start++); 1011 | 1012 | switch (chr) { 1013 | case '0': 1014 | case '1': 1015 | case '2': 1016 | case '3': 1017 | case '4': 1018 | case '5': 1019 | case '6': 1020 | case '7': 1021 | case '8': 1022 | case '9': 1023 | intValue = intValue * 10 + (INT8) (chr - 48); 1024 | break; 1025 | 1026 | default: 1027 | break; 1028 | } 1029 | } 1030 | 1031 | return intValue * intNeg; 1032 | } 1033 | 1034 | 1035 | 1036 | static PyObject *Con_Connect(Con *self, PyObject *args); 1037 | int Con_Constructor(Con *self, PyObject *args) { 1038 | self->tid = 0; 1039 | self->sock = NULL; 1040 | self->Error = amysql_Error; 1041 | self->SQLError = amysql_SQLError; 1042 | self->PFN_PyUnicode_Encode = NULL; 1043 | readerReset(self); 1044 | writerReset(self); 1045 | if (PyErr_Occurred()) { 1046 | PyErr_Format(PyExc_RuntimeError, "Exception is set for no error in %s", 1047 | __FUNCTION__); 1048 | return -1; 1049 | } 1050 | 1051 | if (args && PyObject_IsTrue(args)) 1052 | Con_Connect(self, args); 1053 | Py_INCREF(self); 1054 | return 0; 1055 | } 1056 | static int Con_Clear(Con *self) { 1057 | Py_CLEAR(self->rows); 1058 | Py_CLEAR(self->fields); 1059 | Py_CLEAR(self->sock); 1060 | return 0; 1061 | } 1062 | static PyObject * 1063 | Con_New(PyTypeObject *type, PyObject *args, PyObject *kwds) 1064 | { 1065 | Con *self; 1066 | self = (Con *)type->tp_alloc(type, 0); 1067 | return (PyObject *)self; 1068 | } 1069 | static void Con_Destructor(Con *self) { 1070 | if (self->sock) { 1071 | self->tid = 0; 1072 | writerReset(self); 1073 | writerINT1(self, 0x1); 1074 | writerFinalize(self, 0); 1075 | API_sendSocket(self->sock, self->writerReadPtr, 1076 | self->writerWritePtr - self->writerReadPtr); 1077 | if(self->readerStartPtr)MyFree(self->readerStartPtr); 1078 | if(self->writerStartPtr)MyFree(self->writerStartPtr); 1079 | API_closeSocket(self->sock); 1080 | Con_Clear(self); 1081 | self->readerStartPtr=self->readerReadPtr=self->readerPktPtr=self->readerWritePtr=self->readerEndPtr \ 1082 | =self->writerStartPtr=self->writerReadPtr=self->writerWritePtr=self->writerEndPtr \ 1083 | =self->rows =self->fields =self->sock =NULL; 1084 | } 1085 | } 1086 | static int 1087 | Con_Traverse(Con *self, visitproc visit, void *arg) 1088 | { 1089 | if(self->rows)Py_VISIT(self->rows); 1090 | if(self->fields)Py_VISIT(self->fields); 1091 | return 0; 1092 | } 1093 | 1094 | inline static PyObject *Con_PacketRecv(Con *self, bool skipCols) { 1095 | register UINT1 *pos; 1096 | register ulong cols, i, pktlen, remain; 1097 | register long len; 1098 | register Field *fields = NULL, *col = NULL; 1099 | register PyObject *row, *valobj, *sobj; 1100 | static long RSLen, PRLen, WPLen; 1101 | int year; 1102 | int month; 1103 | int day; 1104 | int hour; 1105 | int minute; 1106 | int second; 1107 | char temp[20]; 1108 | 1109 | self->serverStatus &= ~SERVER_MORE_RESULTS_EXISTS; 1110 | pos = self->readerReadPtr = self->readerPktPtr; 1111 | if (self->readerWritePtr - self->readerPktPtr < MY_HEADER_SIZE) { 1112 | if (self->readerEndPtr - self->readerPktPtr < MY_HEADER_SIZE) { 1113 | do { 1114 | len = self->readerEndPtr - self->readerStartPtr; 1115 | if (len <= 0) { 1116 | len = MY_BUFFER_SIZE; 1117 | } else 1118 | len <<= 1; 1119 | assert(0 < len && len <= MY_BUFFER_MAX); 1120 | RSLen = self->readerReadPtr - self->readerStartPtr; 1121 | PRLen = self->readerPktPtr - self->readerReadPtr; 1122 | WPLen = self->readerWritePtr - self->readerPktPtr; 1123 | MyRealloc(self->readerStartPtr, len); 1124 | self->readerEndPtr = self->readerStartPtr + len; 1125 | self->readerReadPtr = self->readerStartPtr + RSLen; 1126 | self->readerPktPtr = self->readerReadPtr + PRLen; 1127 | self->readerWritePtr = self->readerPktPtr + WPLen; 1128 | } while (self->readerEndPtr - self->readerPktPtr 1129 | < MY_HEADER_SIZE); 1130 | } 1131 | do { 1132 | len = API_recvSocket(self->sock, self->readerWritePtr, 1133 | self->readerEndPtr - self->readerWritePtr); 1134 | if (len <= 0L) { 1135 | break; 1136 | } else 1137 | self->readerWritePtr += len; 1138 | } while (self->readerWritePtr - self->readerPktPtr < MY_HEADER_SIZE); 1139 | } 1140 | remain = 0xffffff & *((UINT4 *) pos); 1141 | if (self->readerWritePtr - self->readerPktPtr < remain) { 1142 | if (self->readerEndPtr - self->readerPktPtr < remain) { 1143 | do { 1144 | len = self->readerEndPtr - self->readerStartPtr; 1145 | if (len <= 0) { 1146 | len = MY_BUFFER_SIZE; 1147 | } else 1148 | len = len << 1; 1149 | assert(0 < len && len <= MY_BUFFER_MAX); 1150 | RSLen = self->readerReadPtr - self->readerStartPtr; 1151 | PRLen = self->readerPktPtr - self->readerReadPtr; 1152 | WPLen = self->readerWritePtr - self->readerPktPtr; 1153 | MyRealloc(self->readerStartPtr, len); 1154 | self->readerEndPtr = self->readerStartPtr + len; 1155 | self->readerReadPtr = self->readerStartPtr + RSLen; 1156 | self->readerPktPtr = self->readerReadPtr + PRLen; 1157 | self->readerWritePtr = self->readerPktPtr + WPLen; 1158 | } while (self->readerEndPtr - self->readerPktPtr < remain); 1159 | } 1160 | do { 1161 | len = API_recvSocket(self->sock, self->readerWritePtr, 1162 | self->readerEndPtr - self->readerWritePtr); 1163 | if (len <= 0L) { 1164 | break; 1165 | } else 1166 | self->readerWritePtr += len; 1167 | } while (self->readerWritePtr - self->readerPktPtr < remain); 1168 | } 1169 | self->nid = pos[3]; 1170 | self->readerReadPtr = pos = pos + MY_HEADER_SIZE; 1171 | self->readerPktPtr = pos + remain; 1172 | 1173 | if (*pos == 0x0) { // OK 1174 | self->readerReadPtr = pos+1; 1175 | self->affectedRows = readerCodedLength(self); 1176 | self->insertId = readerCodedLength(self); 1177 | self->serverStatus = readerUINT2(self); 1178 | self->warningCount = readerUINT2(self); 1179 | self->readerReadPtr=self->readerPktPtr; 1180 | fprintf(stderr, "\nAFFECTED ROWS: %llu INSERT ID: %llu STATUS: %u WARNC: %u \n", 1181 | self->affectedRows, self->insertId, self->serverStatus, 1182 | self->warningCount); 1183 | return self; 1184 | } else if (*pos == 0xff) { // Error 1185 | self->serverStatus &= ~SERVER_MORE_RESULTS_EXISTS; 1186 | if (remain > 3) { 1187 | self->lasterrno =*((UINT2 *) (pos + 1)); 1188 | pos += 3; 1189 | if (*(pos++) == '#') { 1190 | self->sqlstate[MY_SQLSTATE_LENGTH] = '\0'; 1191 | for (len = 0; len < MY_SQLSTATE_LENGTH; ++len) 1192 | self->sqlstate[len] = *(pos++); 1193 | self->errmsg = pos; 1194 | } else { 1195 | self->sqlstate[0] = 'H'; 1196 | self->sqlstate[1] = 'Y'; 1197 | self->sqlstate[2] = '0'; 1198 | self->sqlstate[3] = '0'; 1199 | self->sqlstate[4] = '0'; 1200 | self->sqlstate[5] = '\0'; 1201 | self->errmsg = pos; 1202 | } 1203 | }; 1204 | readerReset(self); 1205 | THROW("Got error: %d/%s (%s)", self->lasterrno, self->sqlstate, self->errmsg); 1206 | return NULL; 1207 | } else if (*pos == 0xfe && remain <8) { // EOF Packet 1208 | self->readerReadPtr= pos+1; 1209 | self->warningCount = readerUINT2(self); 1210 | self->serverStatus = readerUINT2(self); 1211 | self->readerReadPtr= self->readerPktPtr; 1212 | if (self->serverStatus & SERVER_MORE_RESULTS_EXISTS) 1213 | return self; 1214 | THROW("Unexpected EOF when decoding result"); 1215 | } 1216 | 1217 | if (!(self->serverStatus & SERVER_STATUS_AUTOCOMMIT)) 1218 | self->serverStatus |= SERVER_STATUS_IN_TRANS; 1219 | switch (*pos) { 1220 | case 0xfe: 1221 | cols = *((UINT4 *) (pos + 1)); 1222 | pos += 9; 1223 | break; 1224 | case 0xfd: 1225 | cols = 0xffffff & *((UINT4 *) (pos + 1)); 1226 | pos += 4; 1227 | break; 1228 | case 0xfc: 1229 | cols = *((UINT2 *) (pos + 1)); 1230 | pos += 3; 1231 | break; 1232 | case 0xfb: 1233 | cols = MY_NULL_LENGTH; 1234 | pos++; 1235 | break; 1236 | default: 1237 | cols = *pos++; 1238 | break; 1239 | } 1240 | assert(pos == self->readerPktPtr); 1241 | self->readerReadPtr = pos; 1242 | 1243 | if (self->rows){Py_DECREF(self->rows);self->rows=NULL;} 1244 | if (self->fields){Py_DECREF(self->fields);self->fields=NULL;} 1245 | self->rows = PyList_New(0); 1246 | self->fields = PyTuple_New(cols); 1247 | if (self->rows && self->fields){ 1248 | Py_INCREF(self->rows); 1249 | Py_INCREF(self->fields); 1250 | } else if (PyErr_Occurred()) { 1251 | PyErr_Format(PyExc_ValueError, "Parse packet field: %s", pos); 1252 | return 0; 1253 | } 1254 | 1255 | MyRealloc(fields, cols*sizeof(Field)); 1256 | for (i = 0; i <= cols; i++) { // Fields 1257 | pos = self->readerReadPtr = self->readerPktPtr; 1258 | if (self->readerWritePtr - self->readerPktPtr < MY_HEADER_SIZE) { 1259 | if (self->readerEndPtr - self->readerPktPtr < MY_HEADER_SIZE) { 1260 | do { 1261 | len = self->readerEndPtr - self->readerStartPtr; 1262 | if (len <= 0) { 1263 | len = MY_BUFFER_SIZE; 1264 | } else 1265 | len <<= 1; 1266 | assert(0 < len && len <= MY_BUFFER_MAX); 1267 | RSLen = self->readerReadPtr - self->readerStartPtr; 1268 | PRLen = self->readerPktPtr - self->readerReadPtr; 1269 | WPLen = self->readerWritePtr - self->readerPktPtr; 1270 | MyRealloc(self->readerStartPtr, len); 1271 | self->readerEndPtr = self->readerStartPtr + len; 1272 | self->readerReadPtr = self->readerStartPtr + RSLen; 1273 | self->readerPktPtr = self->readerReadPtr + PRLen; 1274 | self->readerWritePtr = self->readerPktPtr + WPLen; 1275 | } while (self->readerEndPtr - self->readerPktPtr 1276 | < MY_HEADER_SIZE); 1277 | } 1278 | do { 1279 | len = API_recvSocket(self->sock, self->readerWritePtr, 1280 | self->readerEndPtr - self->readerWritePtr); 1281 | if (len <= 0L) { 1282 | break; 1283 | } else 1284 | self->readerWritePtr += len; 1285 | } while (self->readerWritePtr - self->readerPktPtr < MY_HEADER_SIZE); 1286 | } 1287 | remain = 0xffffff & *((UINT4 *) pos); 1288 | self->nid = pos[3]; 1289 | self->readerPktPtr = pos = pos + MY_HEADER_SIZE; 1290 | if (self->readerWritePtr - self->readerPktPtr < remain) { 1291 | if (self->readerEndPtr - self->readerPktPtr < remain) { 1292 | do { 1293 | len = self->readerEndPtr - self->readerStartPtr; 1294 | if (len <= 0) { 1295 | len = MY_BUFFER_SIZE; 1296 | } else 1297 | len = len << 1; 1298 | assert(0 < len && len <= MY_BUFFER_MAX); 1299 | RSLen = self->readerReadPtr - self->readerStartPtr; 1300 | PRLen = self->readerPktPtr - self->readerReadPtr; 1301 | WPLen = self->readerWritePtr - self->readerPktPtr; 1302 | MyRealloc(self->readerStartPtr, len); 1303 | self->readerEndPtr = self->readerStartPtr + len; 1304 | self->readerReadPtr = self->readerStartPtr + RSLen; 1305 | self->readerPktPtr = self->readerReadPtr + PRLen; 1306 | self->readerWritePtr = self->readerPktPtr + WPLen; 1307 | } while (self->readerEndPtr - self->readerPktPtr < remain); 1308 | } 1309 | do { 1310 | len = API_recvSocket(self->sock, self->readerWritePtr, 1311 | self->readerEndPtr - self->readerWritePtr); 1312 | if (len <= 0L) { 1313 | break; 1314 | } else 1315 | self->readerWritePtr += len; 1316 | } while (self->readerWritePtr - self->readerPktPtr < remain); 1317 | } 1318 | self->readerReadPtr =pos; 1319 | self->readerPktPtr = pos + remain; 1320 | if (*pos == 0xfe) { // fields DONE! 1321 | assert(i == cols); 1322 | break; 1323 | } 1324 | switch (*pos) { //UINT1 *catalog 1325 | case 0xfd: 1326 | pos += 4 + 0xffffff & *((const UINT4 *) (pos + 1)); 1327 | break; 1328 | case 0xfc: 1329 | pos += 3 + *((const UINT2 *) (pos + 1)); 1330 | break; 1331 | case 0xfb: 1332 | pos += 1 + MY_NULL_LENGTH; 1333 | break; 1334 | default: 1335 | pos += 1 + *pos; 1336 | break; 1337 | }; 1338 | switch (*pos) { //UINT1 *db : scheme name 1339 | case 0xfe: 1340 | pos += 9 + *((const UINT4 *) (pos + 1)); 1341 | break; 1342 | case 0xfd: 1343 | pos += 4 + 0xffffff & *((const UINT4 *) (pos + 1)); 1344 | break; 1345 | case 0xfc: 1346 | pos += 3 + *((const UINT2 *) (pos + 1)); 1347 | break; 1348 | case 0xfb: 1349 | pos += 1 + MY_NULL_LENGTH; 1350 | break; 1351 | default: 1352 | pos += 1 + *pos; 1353 | break; 1354 | } 1355 | switch (*pos) { //UINT1 *table : virtual table name 1356 | case 0xfe: 1357 | pos += 9 + *((const UINT4 *) (pos + 1)); 1358 | break; 1359 | case 0xfd: 1360 | pos += 4 + 0xffffff & *((const UINT4 *) (pos + 1)); 1361 | break; 1362 | case 0xfc: 1363 | pos += 3 + *((const UINT2 *) (pos + 1)); 1364 | break; 1365 | case 0xfb: 1366 | pos += 1 + MY_NULL_LENGTH; 1367 | break; 1368 | default: 1369 | pos += 1 + *pos; 1370 | break; 1371 | } 1372 | switch (*pos) { //UINT1 *org_table : physical table name 1373 | case 0xfe: 1374 | pos += 9 + *((const UINT4 *) (pos + 1)); 1375 | break; 1376 | case 0xfd: 1377 | pos += 4 + 0xffffff & *((const UINT4 *) (pos + 1)); 1378 | break; 1379 | case 0xfc: 1380 | pos += 3 + *((const UINT2 *) (pos + 1)); 1381 | break; 1382 | case 0xfb: 1383 | pos += 1 + MY_NULL_LENGTH; 1384 | break; 1385 | default: 1386 | pos += 1 + *pos; 1387 | break; 1388 | } 1389 | switch (*pos) { //UINT1 *name 1390 | case 0xfe: 1391 | pos += 9; 1392 | len = *((const UINT4 *) (pos + 1)); 1393 | break; 1394 | case 0xfd: 1395 | pos += 4; 1396 | len = 0xffffff & *((const UINT4 *) (pos + 1)); 1397 | break; 1398 | case 0xfc: 1399 | pos += 3; 1400 | len = *((const UINT2 *) (pos + 1)); 1401 | break; 1402 | case 0xfb: 1403 | pos++; 1404 | len = MY_NULL_LENGTH; 1405 | break; 1406 | default: 1407 | len = *pos++; 1408 | break; 1409 | } 1410 | fields[i].name = PyString_FromStringAndSize(pos, len); 1411 | if (fields[i].name == NULL) { 1412 | if (PyErr_Occurred()) { 1413 | PyErr_Format(PyExc_ValueError, "Parse packet field: %s", 1414 | pos); 1415 | return 0; 1416 | } 1417 | }else pos += len; // 1418 | switch (*pos) { //UINT1 *org_name 1419 | case 0xfe: 1420 | pos += 9 + *((const UINT4 *) (pos + 1)); 1421 | break; 1422 | case 0xfd: 1423 | pos += 4 + 0xffffff & *((const UINT4 *) (pos + 1)); 1424 | break; 1425 | case 0xfc: 1426 | pos += 3 + *((const UINT2 *) (pos + 1)); 1427 | break; 1428 | case 0xfb: 1429 | pos += 1 + MY_NULL_LENGTH; 1430 | break; 1431 | default: 1432 | pos += 1 + *pos; 1433 | break; 1434 | } 1435 | assert(*pos++ == 0xc); 1436 | fields[i].charset = *((UINT2 *) pos); 1437 | pos += 2; //UINT2 charset 1438 | pos += 4; //UINT4 length = 1439 | fields[i].type = *pos++; //UINT1 type = 1440 | fields[i].flags = *((UINT2 *) pos); pos += 2; //UINT1 flags = 1441 | fields[i].decimal = *pos; //UINT2 decimals =; 1442 | self->readerReadPtr = self->readerPktPtr; 1443 | 1444 | PyTuple_SET_ITEM(self->fields, i, fields[i].name); 1445 | } 1446 | 1447 | self->nums =0; 1448 | while (1) { // ROWS 1449 | pos = self->readerReadPtr = self->readerPktPtr; 1450 | if (self->readerWritePtr - self->readerPktPtr < MY_HEADER_SIZE) { 1451 | if (self->readerEndPtr - self->readerPktPtr < MY_HEADER_SIZE) { 1452 | do { 1453 | len = self->readerEndPtr - self->readerStartPtr; 1454 | if (len <= 0) { 1455 | len = MY_BUFFER_SIZE; 1456 | } else 1457 | len = len << 1; 1458 | assert(0 < len && len <= MY_BUFFER_MAX); 1459 | RSLen = self->readerReadPtr - self->readerStartPtr; 1460 | PRLen = self->readerPktPtr - self->readerReadPtr; 1461 | WPLen = self->readerWritePtr - self->readerPktPtr; 1462 | MyRealloc(self->readerStartPtr, len); 1463 | self->readerEndPtr = self->readerStartPtr + len; 1464 | self->readerReadPtr = self->readerStartPtr + RSLen; 1465 | self->readerPktPtr = self->readerReadPtr + PRLen; 1466 | self->readerWritePtr = self->readerPktPtr + WPLen; 1467 | } while (self->readerEndPtr - self->readerPktPtr 1468 | < MY_HEADER_SIZE); 1469 | } 1470 | do { 1471 | len = API_recvSocket(self->sock, self->readerWritePtr, 1472 | self->readerEndPtr - self->readerWritePtr); 1473 | if (len <= 0L) { 1474 | break; 1475 | } else 1476 | self->readerWritePtr += len; 1477 | } while (self->readerWritePtr - self->readerPktPtr 1478 | < MY_HEADER_SIZE); 1479 | } 1480 | remain = 0xffffff & *((UINT4 *) pos); 1481 | self->nid = pos[3]; 1482 | self->readerPktPtr = pos = pos + MY_HEADER_SIZE; 1483 | if (self->readerWritePtr - self->readerPktPtr < remain) { 1484 | if (self->readerEndPtr - self->readerPktPtr < remain) { 1485 | do { 1486 | len = self->readerEndPtr - self->readerStartPtr; 1487 | if (len <= 0) { 1488 | len = MY_BUFFER_SIZE; 1489 | } else 1490 | len = len << 1; 1491 | assert(0 < len && len <= MY_BUFFER_MAX); 1492 | RSLen = self->readerReadPtr - self->readerStartPtr; 1493 | PRLen = self->readerPktPtr - self->readerReadPtr; 1494 | WPLen = self->readerWritePtr - self->readerPktPtr; 1495 | MyRealloc(self->readerStartPtr, len); 1496 | self->readerEndPtr = self->readerStartPtr + len; 1497 | self->readerReadPtr = self->readerStartPtr + RSLen; 1498 | self->readerPktPtr = self->readerReadPtr + PRLen; 1499 | self->readerWritePtr = self->readerPktPtr + WPLen; 1500 | } while (self->readerEndPtr - self->readerPktPtr 1501 | < remain); 1502 | } 1503 | do { 1504 | len = API_recvSocket(self->sock, self->readerWritePtr, 1505 | self->readerEndPtr - self->readerWritePtr); 1506 | if (len <= 0L) { 1507 | break; 1508 | } else 1509 | self->readerWritePtr += len; 1510 | } while (self->readerWritePtr - self->readerPktPtr < remain); 1511 | } 1512 | self->readerPktPtr = pos + remain; 1513 | self->readerReadPtr = pos; 1514 | if (*pos == 0xff) { // ERROR packet 1515 | if (self->rows){Py_DECREF(self->rows);self->rows=NULL;} 1516 | if (self->fields){Py_DECREF(self->fields);self->fields=NULL;} 1517 | return self; 1518 | }else if (*pos == 0xfe || remain < 8) {// EOF packet 1519 | if (self->serverStatus & SERVER_MORE_RESULTS_EXISTS) { 1520 | self->warningCount = readerUINT2(self); 1521 | self->serverStatus = readerUINT2(self); 1522 | self->readerReadPtr = self->readerPktPtr; 1523 | return self; 1524 | } 1525 | self->readerReadPtr = self->readerPktPtr; 1526 | break; 1527 | }else if (*pos ==0x0 || *pos == 0xfb){// OK|NULL packet 1528 | self->readerReadPtr = self->readerPktPtr; 1529 | break; 1530 | } 1531 | 1532 | row = PyTuple_New(cols); 1533 | for (i =0; i < cols; i++) { 1534 | col = fields + i; 1535 | if (*pos == 0xfb){ /* null field */ 1536 | PyTuple_SET_ITEM(row, i, Py_None); 1537 | pos++; 1538 | continue; 1539 | } 1540 | switch (*pos){ 1541 | case 0xfe: 1542 | len = *((const UINT4 *) (pos + 1)); 1543 | pos += 9; 1544 | break; 1545 | case 0xfd: 1546 | len = 0xffffff & *((const UINT4 *) (pos + 1)); 1547 | pos += 4; 1548 | break; 1549 | case 0xfc: 1550 | len = *((const UINT2 *) (pos + 1)); 1551 | pos += 3; 1552 | break; 1553 | default: 1554 | len = *pos; 1555 | pos++; 1556 | break; 1557 | } 1558 | switch (col->type) { 1559 | case MFTYPE_NULL://PyNone: 1560 | valobj = Py_None; 1561 | Py_INCREF(valobj); 1562 | break; 1563 | 1564 | case MFTYPE_TINY://PyInt 1565 | case MFTYPE_SHORT: 1566 | case MFTYPE_LONG: 1567 | case MFTYPE_INT24: 1568 | valobj = PyInt_FromLong(parseINT4(pos, pos + len)); 1569 | break; 1570 | 1571 | case MFTYPE_LONGLONG://PyLong 1572 | valobj = PyLong_FromLongLong( 1573 | parseINT8(pos, pos + len)); 1574 | break; 1575 | 1576 | case MFTYPE_FLOAT://PyFloat 1577 | case MFTYPE_DOUBLE: 1578 | sobj = PyString_FromStringAndSize(pos, len);//FIXME: Too slow 1579 | valobj = PyFloat_FromString(sobj, NULL); 1580 | Py_DECREF(sobj); 1581 | break; 1582 | 1583 | case MFTYPE_DATE: 1584 | year = parseINT4(pos, pos + 4); 1585 | if (year < 1) { 1586 | valobj = Py_None; 1587 | Py_INCREF(valobj); 1588 | break; 1589 | } 1590 | month = parseINT4(pos + 5, pos + 7); 1591 | day = parseINT4(pos + 8, pos + 10); 1592 | valobj = PyDate_FromDate(year, month, day); 1593 | break; 1594 | 1595 | case MFTYPE_DATETIME: 1596 | //9999-12-31 23:59:59 1597 | memcpy(temp, pos, len); 1598 | temp[len] = '\0'; 1599 | year = parseINT4(pos, pos + 4); 1600 | month = parseINT4(pos + 5, pos + 7); 1601 | day = parseINT4(pos + 8, pos + 10); 1602 | hour = parseINT4(pos + 11, pos + 13); 1603 | minute = parseINT4(pos + 14, pos + 16); 1604 | second = parseINT4(pos + 17, pos + 19); 1605 | if (year < 1) { 1606 | valobj = Py_None; 1607 | Py_IncRef(valobj); 1608 | break; 1609 | } 1610 | valobj = PyDateTime_FromDateAndTime(year, month, day, 1611 | hour, minute, second, 0); 1612 | break; 1613 | 1614 | case MFTYPE_TIMESTAMP:// We ignore these 1615 | case MFTYPE_TIME: 1616 | case MFTYPE_YEAR: 1617 | case MFTYPE_NEWDATE: 1618 | // Fall through for string encoding 1619 | //Blob goes as String 1620 | case MFTYPE_TINY_BLOB: 1621 | case MFTYPE_MEDIUM_BLOB: 1622 | case MFTYPE_LONG_BLOB: 1623 | case MFTYPE_BLOB: 1624 | if (col->flags & MFFLAG_BINARY_FLAG) { 1625 | valobj = PyString_FromStringAndSize(pos, len); 1626 | break; 1627 | } 1628 | case MFTYPE_VAR_STRING://PyString family 1629 | case MFTYPE_VARCHAR: 1630 | case MFTYPE_STRING: 1631 | switch (col->charset) { 1632 | case MCS_binary: 1633 | valobj=PyString_FromStringAndSize(pos, len); 1634 | break; 1635 | case MCS_ascii_general_ci: //11, 1636 | case MCS_ascii_bin: //65, 1637 | valobj=PyUnicode_DecodeASCII(pos, len, NULL); 1638 | break; 1639 | case MCS_utf8_general_ci: //33, 1640 | case MCS_utf8_bin: //83, 1641 | case MCS_utf8_unicode_ci: //192, 1642 | valobj=PyUnicode_DecodeUTF8(pos, len, NULL); 1643 | break; 1644 | case MCS_utf16_general_ci: //54, 1645 | case MCS_utf16_bin: //55, 1646 | case MCS_utf16_unicode_ci: //101, 1647 | valobj=PyUnicode_DecodeUTF16(pos, len/2, NULL, NULL); 1648 | break; 1649 | case MCS_utf32_general_ci: //60, 1650 | case MCS_utf32_bin: //61, 1651 | case MCS_utf32_unicode_ci: //160, 1652 | valobj=PyUnicode_DecodeUTF32(pos, len / 4, NULL, NULL); 1653 | break; 1654 | default: 1655 | fprintf(stderr,"Exception call:%s (%s:%l) :\n",(char *)__FUNCTION__, (char *)__FILE__, (long)__LINE__); 1656 | fprintf(stderr,"Error decoding field: TYPE: %02x CHRS: %02x FLAG: %02x NAME: %s\n", col->type, col->charset, col->flags, PyString_AsString(col->name)); 1657 | return; 1658 | } 1659 | break; 1660 | 1661 | case MFTYPE_ENUM: 1662 | case MFTYPE_GEOMETRY: 1663 | case MFTYPE_BIT: 1664 | case MFTYPE_NEWDECIMAL: 1665 | case MFTYPE_SET: 1666 | case MFTYPE_DECIMAL: 1667 | // Fall through for string encoding 1668 | valobj = PyString_FromStringAndSize(pos, len); 1669 | break; 1670 | default: 1671 | fprintf(stdout, "COL ERROR: TYPE: %x CHAS:%x NAME: %s\n", col->type, col->charset, col->name); 1672 | } 1673 | pos += len; 1674 | PyTuple_SET_ITEM(row, i, valobj); 1675 | } 1676 | Py_INCREF(row); 1677 | PyList_Append(self->rows, row); 1678 | self->nums ++; 1679 | } 1680 | 1681 | self->readerPktPtr += pktlen; 1682 | self->readerPktPtr = self->readerReadPtr; 1683 | if (PyErr_Occurred()) { 1684 | PyErr_Format(PyExc_ValueError, "Parse packet."); 1685 | return 0; 1686 | } 1687 | return self->readerWritePtr - self->readerReadPtr; 1688 | } 1689 | 1690 | PyObject *Con_isConnected(Con *self, PyObject *args) { 1691 | if (self->sock) { 1692 | Py_RETURN_TRUE; 1693 | } 1694 | self->tid = 0; 1695 | Py_RETURN_FALSE; 1696 | } 1697 | 1698 | static PyObject *Con_Connect(Con *self, PyObject *args) { 1699 | /* 1700 | Args: Con conn, const char *_host, int _port, const char *_username, const char *_password, const char *_database, int _autoCommit, const char *_charset*/ 1701 | ulong i, len; 1702 | UINT1 *pos; 1703 | char *pstrCharset = NULL; 1704 | 1705 | if (!PyArg_ParseTuple(args, "sisss|bsb", &self->host, &self->port, 1706 | &self->user, &self->pswd, &self->db, &self->ac, &pstrCharset)) 1707 | return -1; 1708 | self->ac = (self->ac) ? 1 : 0; 1709 | self->host = self->host ? self->host : "localhost"; 1710 | self->user = self->user ? self->user : ""; 1711 | self->pswd = self->pswd ? self->pswd : ""; 1712 | self->port = self->port ? self->port : 3306; 1713 | if (pstrCharset) { 1714 | if (strcmp(pstrCharset, "utf8") == 0) { 1715 | self->charset = MCS_utf8_general_ci; 1716 | self->PFN_PyUnicode_Encode = PyUnicode_EncodeUTF8; 1717 | } else if (strcmp(pstrCharset, "latin1") == 0) { 1718 | self->charset = MCS_latin1_general_ci; 1719 | self->PFN_PyUnicode_Encode = PyUnicode_EncodeLatin1; 1720 | } else if (strcmp(pstrCharset, "ascii") == 0) { 1721 | self->charset = MCS_ascii_general_ci; 1722 | self->PFN_PyUnicode_Encode = PyUnicode_EncodeASCII; 1723 | } else if (strcmp(pstrCharset, "utf8bin") == 0) { 1724 | self->charset = MCS_utf8_bin; 1725 | self->PFN_PyUnicode_Encode = PyUnicode_DecodeUTF8; 1726 | } else if (strcmp(pstrCharset, "bin") == 0) { 1727 | self->charset = MCS_binary; 1728 | self->PFN_PyUnicode_Encode = PyString_FromStringAndSize; 1729 | } else { 1730 | return PyErr_Format(PyExc_ValueError, 1731 | "Unsupported character set '%s' specified", pstrCharset); 1732 | } 1733 | } else { 1734 | self->charset = MCS_utf8_general_ci; 1735 | self->PFN_PyUnicode_Encode = PyUnicode_EncodeUTF8; 1736 | } 1737 | 1738 | if (self->sock) 1739 | return PyErr_Format(PyExc_ValueError, "Already connected: TID:%d", 1740 | self->tid); 1741 | 1742 | if (!(self->sock = API_getSocket()) 1743 | || !API_connectSocket(self->sock, self->host, self->port)) { 1744 | self->pid--; 1745 | return API_error(self, "connect"); 1746 | } 1747 | 1748 | if (!self->readerStartPtr || !self->readerEndPtr 1749 | || self->readerReadPtr == self->readerWritePtr) 1750 | readerReset(self); 1751 | 1752 | self->readerWritePtr = self->readerReadPtr = self->readerPktPtr =self->readerStartPtr; 1753 | while(self->readerEndPtr -self->readerPktPtr readerEndPtr -self->readerStartPtr; 1755 | if(len<=0){ 1756 | len=MY_BUFFER_SIZE; 1757 | }else len =len<<1; 1758 | assert(0readerReadPtr -self->readerStartPtr; 1761 | PRLen=self->readerPktPtr -self->readerReadPtr; 1762 | WPLen=self->readerWritePtr-self->readerPktPtr; 1763 | MyRealloc(self->readerStartPtr,len); 1764 | self->readerEndPtr =self->readerStartPtr +len; 1765 | self->readerReadPtr =self->readerStartPtr +RSLen; 1766 | self->readerPktPtr =self->readerReadPtr +PRLen; 1767 | self->readerWritePtr=self->readerPktPtr +WPLen; 1768 | }; 1769 | while (self->readerWritePtr -self->readerPktPtr sock, self->readerWritePtr, self->readerEndPtr-self->readerWritePtr); 1771 | if(len<= 0L){ 1772 | break; 1773 | }else self->readerWritePtr +=len; 1774 | }assert(self->readerWritePtr -self->readerPktPtr >=MY_HEADER_SIZE); 1775 | 1776 | pos =self->readerPktPtr; 1777 | i=len=pos[0] | pos[1]<<8 | pos[2]<<16; 1778 | self->nid =pos[3]; 1779 | self->readerReadPtr=self->readerPktPtr =pos =pos +MY_HEADER_SIZE; 1780 | while(self->readerEndPtr -self->readerPktPtr readerEndPtr -self->readerStartPtr; 1782 | if(len<=0){ 1783 | len=MY_BUFFER_SIZE; 1784 | }else len =len<<1; 1785 | assert(0readerReadPtr -self->readerStartPtr; 1788 | PRLen=self->readerPktPtr -self->readerReadPtr; 1789 | WPLen=self->readerWritePtr-self->readerPktPtr; 1790 | MyRealloc(self->readerStartPtr,len); 1791 | self->readerEndPtr =self->readerStartPtr +len; 1792 | self->readerReadPtr =self->readerStartPtr +RSLen; 1793 | self->readerPktPtr =self->readerReadPtr +PRLen; 1794 | self->readerWritePtr=self->readerPktPtr +WPLen; 1795 | }; 1796 | while (self->readerWritePtr -self->readerPktPtr sock, self->readerWritePtr, self->readerEndPtr-self->readerWritePtr); 1798 | if(len<= 0L){ 1799 | break; 1800 | }else self->readerWritePtr +=len; 1801 | }assert(self->readerWritePtr -self->readerPktPtr>=i); 1802 | self->readerPktPtr =pos +i; 1803 | if(i<64){ 1804 | self->pid--; 1805 | return API_error(self, "packet receiving"); 1806 | } 1807 | 1808 | len=i; 1809 | self->nid =pos[3]; 1810 | self->ver = readerUINT1(self); 1811 | if (self->ver == 0xff) { 1812 | THROW("Too many connections reported by server"); 1813 | return false; 1814 | } 1815 | if (self->ver != MY_PROTOCOL_VERSION) { 1816 | THROW( 1817 | "Protocol version expect:%0x, got(%0x)\n", MY_PROTOCOL_VERSION, self->ver); 1818 | return false; 1819 | } 1820 | self->serverVersion = readerNTString(self); 1821 | self->cid = readerUINT4(self); 1822 | for (i = 0; i < MY_SCRAMBLE_LENGTH_323; i++, self->readerReadPtr++) 1823 | self->scramble[i] = *self->readerReadPtr; 1824 | self->scramble[MY_SCRAMBLE_LENGTH_323] = *(self->readerReadPtr++); 1825 | 1826 | i=len; 1827 | self->serverCaps = readerUINT2(self); 1828 | if (!(self->serverCaps & MCP_PROTOCOL_41)) { 1829 | THROW("Authentication < 4.1 not supported"); 1830 | return false; 1831 | } 1832 | UINT1 serverLang = readerUINT1(self); 1833 | self->serverStatus = readerUINT2(self); 1834 | self->serverCaps |= readerUINT2(self) << 16; 1835 | len = readerUINT1(self); 1836 | if (len < 13 + MY_SCRAMBLE_LENGTH_323) 1837 | len = 13; 1838 | readerBytes(self, 10); 1839 | 1840 | for (i = MY_SCRAMBLE_LENGTH_323; i <= len; ++i, ++self->readerReadPtr) 1841 | self->scramble[i] = *self->readerReadPtr; 1842 | 1843 | self->readerReadPtr = self->readerPktPtr; 1844 | assert(self->readerPktPtr == self->readerWritePtr); 1845 | 1846 | self->clientFlag = self->serverCaps; 1847 | self->clientFlag &= ~MCP_COMPRESS; 1848 | self->clientFlag &= ~MCP_NO_SCHEMA; 1849 | self->clientFlag &= ~MCP_SSL; 1850 | self->clientFlag |= MCP_MULTI_STATEMENTS; 1851 | self->clientFlag |= MCP_MULTI_RESULTS; 1852 | self->clientFlag |= MCP_CONNECT_WITH_DB; 1853 | /* 1854 | #ifdef DEBUG 1855 | fprintf(stderr,"host: %s:%u user: %s pswd:%s db: %s autocommit: %01u flag: %06x caps: %04x blocking: %u\n\n", 1856 | self->host ? self->host : "(Null)", self->port, 1857 | self->user ? self->user : "(Null)", self->pswd ? self->pswd : "(Null)", 1858 | self->db ? self->db : "(Null)", (UINT4)self->ac, self->clientFlag, self->serverCaps, self->blocking); 1859 | #endif 1860 | */ 1861 | writerReset(self); 1862 | writerINT4(self, self->clientFlag); 1863 | writerINT4(self, MY_BUFFER_SIZE); 1864 | if (self->charset != MCS_UNDEFINED) { 1865 | writerINT1(self, (UINT1)self->charset); 1866 | } else { 1867 | writerINT1(self, self->serverLang); 1868 | } 1869 | for (i = 0; i < 23; i++) 1870 | writerINT1(self, 0); 1871 | 1872 | if (self->user) { 1873 | writerNTString(self, self->user); 1874 | } else 1875 | writerINT1(self, 0x0); 1876 | 1877 | if (self->pswd && self->pswd[0]) { 1878 | writerINT1(self, MY_SHA1_HASH_SIZE); 1879 | UINT8 token[MY_SHA1_HASH_SIZE + 1]; 1880 | token[MY_SHA1_HASH_SIZE] = 0; 1881 | scramble_password(token, self->scramble, self->pswd); 1882 | writerBytes(self, token, MY_SHA1_HASH_SIZE); 1883 | } else 1884 | writerINT1(self, 0x0); 1885 | if (self->serverCaps & MCP_CONNECT_WITH_DB && self->db) { 1886 | writerNTString(self, self->db); 1887 | } else 1888 | writerINT1(self, 0x0); 1889 | writerFinalize(self, 1); 1890 | API_sendSocket(self->sock, self->writerReadPtr, self->writerWritePtr - self->writerReadPtr); 1891 | self->readerWritePtr = self->readerReadPtr = self->readerPktPtr =self->readerStartPtr; 1892 | while (self->readerWritePtr -self->readerPktPtr sock, self->readerWritePtr, self->readerEndPtr-self->readerWritePtr); 1894 | if(len<= 0L){ 1895 | break; 1896 | }else self->readerWritePtr +=len; 1897 | }assert(self->readerWritePtr -self->readerPktPtr >=MY_HEADER_SIZE); 1898 | pos =self->readerPktPtr; 1899 | i=len=pos[0] | pos[1]<<8 | pos[2]<<16; 1900 | self->nid =pos[3]; 1901 | if(pos[4] != 0x0){ 1902 | self->pid--; 1903 | return API_error(self, "packet receiving"); 1904 | } 1905 | self->readerWritePtr = self->readerReadPtr = self->readerPktPtr =self->readerStartPtr; 1906 | 1907 | 1908 | char strTemp[256 + 1]; 1909 | if (self->ac) { 1910 | len =snprintf(strTemp, 256, 1911 | "SET AUTOCOMMIT=1,time_zone='+0:00',sql_mode='TRADITIONAL',character_set_client='binary',character_set_results='binary'"); 1912 | } else { 1913 | len =snprintf(strTemp, 256, 1914 | "SET AUTOCOMMIT=0,time_zone='+0:00',sql_mode='TRADITIONAL',character_set_client='binary',character_set_results='binary'"); 1915 | } 1916 | writerReset(self); 1917 | writerINT1(self, COM_QUERY); 1918 | writerBytes(self, strTemp, len); 1919 | writerFinalize(self, 0); 1920 | API_sendSocket(self->sock, self->writerReadPtr,self->writerWritePtr - self->writerReadPtr); 1921 | self->readerWritePtr = self->readerReadPtr = self->readerPktPtr =self->readerStartPtr; 1922 | while (self->readerWritePtr -self->readerPktPtr sock, self->readerWritePtr, self->readerEndPtr-self->readerWritePtr); 1924 | if(len<= 0L){ 1925 | break; 1926 | }else self->readerWritePtr +=len; 1927 | }assert(self->readerWritePtr -self->readerPktPtr >=MY_HEADER_SIZE); 1928 | pos =self->readerPktPtr; 1929 | i=len=pos[0] | pos[1]<<8 | pos[2]<<16; 1930 | self->nid =pos[3]; 1931 | if(pos[4] != 0x0){ 1932 | self->pid--; 1933 | return API_error(self, "packet receiving"); 1934 | } 1935 | self->readerWritePtr = self->readerReadPtr = self->readerPktPtr =self->readerStartPtr; 1936 | self->writerWritePtr = self->writerReadPtr =self->writerStartPtr; 1937 | return self; 1938 | } 1939 | 1940 | int AppendAndEscapeString(char *buffStart, char *buffEnd, const char *strStart, 1941 | const char *strEnd, int quote) { 1942 | //{'\0': '\\0', '\n': '\\n', '\r': '\\r', '\\': '\\\\', "'": "\\'", '"': '\\"', '\x1a': '\\Z'}): 1943 | char *buffOffset = buffStart; 1944 | 1945 | if (quote) { 1946 | (*buffOffset++) = '\''; 1947 | } 1948 | 1949 | while (strStart < strEnd) { 1950 | switch (*strStart) { 1951 | case '\0': // NULL 1952 | (*buffOffset++) = '\\'; 1953 | (*buffOffset++) = '0'; 1954 | break; 1955 | case '\n': // LF 1956 | (*buffOffset++) = '\\'; 1957 | (*buffOffset++) = 'n'; 1958 | break; 1959 | case '\r': // CR 1960 | (*buffOffset++) = '\\'; 1961 | (*buffOffset++) = 'r'; 1962 | break; 1963 | case '\\': // BACKSLASH 1964 | (*buffOffset++) = '\\'; 1965 | (*buffOffset++) = '\\'; 1966 | break; 1967 | case '\'': // SINGLE QUOTE 1968 | (*buffOffset++) = '\\'; 1969 | (*buffOffset++) = '\''; 1970 | break; 1971 | case '\"': // DOUBLE QUOTE 1972 | (*buffOffset++) = '\\'; 1973 | (*buffOffset++) = '\"'; 1974 | break; 1975 | case '\x1a': // SUBSTITUTE CONTROL CHARACTER 1976 | (*buffOffset++) = '\\'; 1977 | (*buffOffset++) = 'Z'; 1978 | break; 1979 | 1980 | default: 1981 | (*buffOffset++) = (*strStart); 1982 | break; 1983 | } 1984 | 1985 | strStart++; 1986 | } 1987 | 1988 | if (quote) { 1989 | (*buffOffset++) = '\''; 1990 | } 1991 | 1992 | return (int) (buffOffset - buffStart); 1993 | } 1994 | 1995 | int AppendEscapedArg(Con *self, char *start, char *end, PyObject *obj) { 1996 | int ret; 1997 | PyObject *strobj; 1998 | 1999 | /* 2000 | FIXME: Surround strings with '' could be performed in this function to avoid extra logic in AppendAndEscapeString */ 2001 | if (PyString_Check(obj)) { 2002 | return AppendAndEscapeString(start, end, PyString_AS_STRING(obj), 2003 | PyString_AS_STRING(obj) + PyString_GET_SIZE(obj), true); 2004 | } else if (PyUnicode_Check(obj)) { 2005 | strobj = self->PFN_PyUnicode_Encode(PyUnicode_AS_UNICODE(obj), 2006 | PyUnicode_GET_SIZE(obj), NULL); 2007 | 2008 | if (strobj == NULL) { 2009 | if (PyErr_Occurred()) { 2010 | return -1; 2011 | } 2012 | 2013 | PyErr_SetObject(PyExc_ValueError, obj); 2014 | return -1; 2015 | } 2016 | 2017 | ret = AppendAndEscapeString(start, end, PyString_AS_STRING(strobj), 2018 | PyString_AS_STRING(strobj) + PyString_GET_SIZE(strobj), true); 2019 | Py_DECREF(strobj); 2020 | 2021 | return ret; 2022 | } else if (obj == Py_None) { 2023 | (*start++) = 'n'; 2024 | (*start++) = 'u'; 2025 | (*start++) = 'l'; 2026 | (*start++) = 'l'; 2027 | return 4; 2028 | } else if (PyDateTime_Check(obj)) { 2029 | int len = sprintf(start, "'%04d-%02d-%02d %02d:%02d:%02d'", 2030 | PyDateTime_GET_YEAR(obj), PyDateTime_GET_MONTH(obj), 2031 | PyDateTime_GET_DAY(obj), PyDateTime_DATE_GET_HOUR(obj), 2032 | PyDateTime_DATE_GET_MINUTE(obj), 2033 | PyDateTime_DATE_GET_SECOND(obj)); 2034 | 2035 | return len; 2036 | } else if (PyDate_Check(obj)) { 2037 | int len = sprintf(start, "'%04d:%02d:%02d'", PyDateTime_GET_YEAR(obj), 2038 | PyDateTime_GET_MONTH(obj), PyDateTime_GET_DAY(obj)); 2039 | 2040 | return len; 2041 | } 2042 | 2043 | //FIXME: Might possible to avoid this? 2044 | strobj = PyObject_Str(obj); 2045 | ret = AppendAndEscapeString(start, end, PyString_AS_STRING(strobj), 2046 | PyString_AS_STRING(strobj) + PyString_GET_SIZE(strobj), false); 2047 | Py_DECREF(strobj); 2048 | return ret; 2049 | } 2050 | 2051 | PyObject *EscapeQueryArguments(Con *self, PyObject *inQuery, PyObject *iterable) { 2052 | size_t cbOutQuery = 0; 2053 | char *obuffer; 2054 | char *optr; 2055 | char *iptr; 2056 | int heap = 0; 2057 | int appendLen; 2058 | PyObject *retobj; 2059 | PyObject *iterator; 2060 | PyObject *arg; 2061 | 2062 | // Estimate output length 2063 | 2064 | cbOutQuery += PyString_GET_SIZE(inQuery); 2065 | 2066 | iterator = PyObject_GetIter(iterable); 2067 | 2068 | while ((arg = PyIter_Next(iterator))) { 2069 | // Quotes; 2070 | cbOutQuery += 2; 2071 | 2072 | // Worst case escape and utf-8 2073 | if (PyString_Check(arg)) 2074 | cbOutQuery += (PyString_GET_SIZE(arg) * 2); 2075 | else if (PyUnicode_Check(arg)) 2076 | cbOutQuery += (PyUnicode_GET_SIZE(arg) * 6); 2077 | else 2078 | cbOutQuery += 64; 2079 | 2080 | Py_DECREF(arg); 2081 | } 2082 | 2083 | Py_DECREF(iterator); 2084 | 2085 | if (cbOutQuery > (1024 * 64)) { 2086 | /* 2087 | FIXME: Allocate a PyString and resize it just like the Python code does it */ 2088 | obuffer = (char *) PyObject_Malloc(cbOutQuery); 2089 | heap = 1; 2090 | } else { 2091 | obuffer = (char *) alloca(cbOutQuery); 2092 | } 2093 | 2094 | optr = obuffer; 2095 | iptr = PyString_AS_STRING(inQuery); 2096 | 2097 | iterator = PyObject_GetIter(iterable); 2098 | 2099 | while (1) { 2100 | switch (*iptr) { 2101 | case '\0': 2102 | goto END_PARSE; 2103 | 2104 | case '%': 2105 | 2106 | iptr++; 2107 | 2108 | if (*iptr != 's' && *iptr != '%') { 2109 | Py_DECREF(iterator); 2110 | if (heap) 2111 | PyObject_Free(obuffer); 2112 | return PyErr_Format(PyExc_ValueError, 2113 | "Found character %c expected %%", *iptr); 2114 | } 2115 | 2116 | if (*iptr == '%') { 2117 | *(optr++) = *(iptr)++; 2118 | break; 2119 | } 2120 | 2121 | iptr++; 2122 | 2123 | arg = PyIter_Next(iterator); 2124 | 2125 | if (arg == NULL) { 2126 | Py_DECREF(iterator); 2127 | if (heap) 2128 | PyObject_Free(obuffer); 2129 | return PyErr_Format(PyExc_ValueError, 2130 | "Unexpected end of iterator found"); 2131 | } 2132 | 2133 | appendLen = AppendEscapedArg(self, optr, obuffer + cbOutQuery, arg); 2134 | Py_DECREF(arg); 2135 | 2136 | if (appendLen == -1) { 2137 | Py_DECREF(iterator); 2138 | if (heap) 2139 | PyObject_Free(obuffer); 2140 | return NULL; 2141 | } 2142 | 2143 | optr += appendLen; 2144 | 2145 | break; 2146 | 2147 | default: 2148 | *(optr++) = *(iptr)++; 2149 | break; 2150 | } 2151 | } 2152 | 2153 | END_PARSE: Py_DECREF(iterator); 2154 | 2155 | retobj = PyString_FromStringAndSize(obuffer, (optr - obuffer)); 2156 | 2157 | if (heap) { 2158 | PyObject_Free(obuffer); 2159 | } 2160 | 2161 | return retobj; 2162 | } 2163 | 2164 | PyObject *Con_Query(Con *self, PyObject *args) { 2165 | int retMore = 0; 2166 | PyObject *inQuery = NULL; 2167 | PyObject *iterable = NULL; 2168 | PyObject *escapedQuery = NULL; 2169 | PyObject *query = NULL; 2170 | 2171 | if (!self->sock) 2172 | return PyErr_Format(PyExc_RuntimeError, "Not connected"); 2173 | if (!PyArg_ParseTuple(args, "O|O", &inQuery, &iterable)) { 2174 | return NULL; 2175 | } 2176 | 2177 | if (iterable) { 2178 | PyObject *iterator = PyObject_GetIter(iterable); 2179 | if (iterator == NULL) { 2180 | PyErr_Clear(); 2181 | return PyErr_Format(PyExc_TypeError, "Expected iterable"); 2182 | } 2183 | Py_DECREF(iterator); 2184 | } 2185 | if (!PyString_Check(inQuery)) { 2186 | if (!PyUnicode_Check(inQuery)) { 2187 | return PyErr_Format(PyExc_TypeError, 2188 | "Query argument must be either String or Unicode"); 2189 | } 2190 | query = self->PFN_PyUnicode_Encode(PyUnicode_AS_UNICODE(inQuery), 2191 | PyUnicode_GET_SIZE(inQuery), NULL); 2192 | if (query == NULL) { 2193 | if (!PyErr_Occurred()) { 2194 | PyErr_SetObject(PyExc_ValueError, query); 2195 | return NULL; 2196 | } 2197 | return NULL; 2198 | } 2199 | } else { 2200 | query = inQuery; 2201 | Py_INCREF(query); 2202 | } 2203 | 2204 | if (iterable) { 2205 | escapedQuery = EscapeQueryArguments(self, query, iterable); 2206 | Py_DECREF(query); 2207 | 2208 | if (escapedQuery == NULL) { 2209 | if (!PyErr_Occurred()) { 2210 | return PyErr_Format(PyExc_RuntimeError, 2211 | "Exception not set in EscapeQueryArguments chain"); 2212 | } 2213 | return NULL; 2214 | } 2215 | } else { 2216 | escapedQuery = query; 2217 | } 2218 | 2219 | writerReset(self); 2220 | writerINT1(self, COM_QUERY); 2221 | writerBytes(self, PyString_AS_STRING(escapedQuery), 2222 | PyString_GET_SIZE(escapedQuery)); 2223 | writerFinalize(self, 0); 2224 | API_sendSocket(self->sock, self->writerReadPtr, self->writerWritePtr - self->writerReadPtr); 2225 | /* 2226 | #ifdef DEBUG 2227 | pbuf(stderr, self->writerReadPtr, self->writerWritePtr -self->writerReadPtr, 16); 2228 | fprintf(stderr, "\nS: %p R: %p P: %p W: %p E: %p\n",self->readerStartPtr, self->readerReadPtr, 2229 | self->readerPktPtr, self->readerWritePtr, self->readerEndPtr); 2230 | #endif 2231 | */ 2232 | self->writerWritePtr = self->writerReadPtr =self->writerStartPtr; 2233 | self->readerWritePtr = self->readerReadPtr = self->readerPktPtr =self->readerStartPtr; 2234 | Con_PacketRecv(self, 0); 2235 | 2236 | if (PyErr_Occurred()) { 2237 | PyErr_Print(); 2238 | Py_INCREF(Py_None); 2239 | return Py_None; 2240 | } 2241 | Py_INCREF(Py_None); 2242 | return Py_None; 2243 | 2244 | /* 2245 | if ((*PyString_AS_STRING(escapedQuery)) == ' ')retMore = 1; 2246 | // ret = Con_Query(self, PyString_AS_STRING(escapedQuery), PyString_GET_SIZE(escapedQuery), retMore); 2247 | 2248 | Py_DECREF(escapedQuery); 2249 | 2250 | if (ret == NULL) 2251 | { 2252 | return API_error(self, "query result"); 2253 | } 2254 | 2255 | if(PyTuple_Check(ret))return ret; // it's a OK packet, return (affectedRows, insertID, ... ), see above API_resultOK(); 2256 | 2257 | if(retMore){ 2258 | PyObject *tuple = PyTuple_New(2); 2259 | PyTuple_SET_ITEM(tuple, 0, ret->fields); 2260 | PyTuple_SET_ITEM(tuple, 1, ret->rows); 2261 | return tuple; 2262 | }else return ret->rows; 2263 | */ 2264 | } 2265 | 2266 | static PyMethodDef Con_methods[] = 2267 | { 2268 | { "connect", (PyCFunction) Con_Connect, METH_VARARGS, 2269 | "Connects to database server. Arguments: host, port, username, password, database, autocommit, charset" }, 2270 | { "query", (PyCFunction) Con_Query, METH_VARARGS, 2271 | "Performs a query. Arguments: query, arguments to escape" }, 2272 | { "close", (PyCFunction) Con_Clear, METH_NOARGS, 2273 | "Closes connection" }, 2274 | // {"ping", (PyCFunction) Con_ping, METH_NOARGS, "Check connection status"}, 2275 | { "isConnected", (PyCFunction) Con_isConnected, METH_NOARGS, 2276 | "Check connection status" }, 2277 | // {"setTimeout", (PyCFunction) Con_setTimeout, METH_VARARGS, "Sets connection timeout in seconds"}, 2278 | // {"setTxBufferSize", (PyCFunction) Con_setTxBufferSize, METH_VARARGS, "Sets connection timeout in seconds"}, 2279 | // {"setRxBufferSize", (PyCFunction) Con_setRxBufferSize, METH_VARARGS, "Sets connection timeout in seconds"}, 2280 | { NULL } }; 2281 | static PyMemberDef Con_members[] = { 2282 | 2283 | { "Error", T_OBJECT, offsetof(Con, Error), READONLY }, 2284 | { "SQLError", T_OBJECT, offsetof(Con, SQLError), READONLY }, 2285 | { "tid", T_INT, offsetof(Con, tid), READONLY, "Server side thread id" }, 2286 | { "sock", T_OBJECT, offsetof(Con, sock), 1, "Server side Python Socket" }, 2287 | { "rows", T_OBJECT, offsetof(Con, rows), 1, "Query result rows" }, 2288 | { "fields",T_OBJECT, offsetof(Con, fields), 1, "Query result fields" }, 2289 | { "host", T_STRING, offsetof(Con,host), READONLY, "Server host name" }, 2290 | { "username", T_STRING, offsetof(Con, user), READONLY, "user name" }, 2291 | { "password", T_STRING, offsetof(Con, pswd), READONLY, "password" }, 2292 | {"port", T_INT, offsetof(Con, port), READONLY, "Server side port" }, 2293 | { NULL } }; 2294 | 2295 | static PyTypeObject ConType = { 2296 | PyObject_HEAD_INIT(NULL) 2297 | 0, /* ob_size */ 2298 | "amysql.Con", /* tp_name */ 2299 | sizeof(Con), /* tp_basicsize */ 2300 | 0, /* tp_itemsize */ 2301 | Con_Destructor, /* tp_dealloc */ 2302 | 0, /* tp_print */ 2303 | 0, /* tp_getattr */ 2304 | 0, /* tp_setattr */ 2305 | 0, /* tp_compare */ 2306 | 0, /* tp_repr */ 2307 | 0, /* tp_as_number */ 2308 | 0, /* tp_as_sequence */ 2309 | 0, /* tp_as_mapping */ 2310 | 0, /* tp_hash */ 2311 | 0, /* tp_call */ 2312 | 0, /* tp_str */ 2313 | 0, /* tp_getattro */ 2314 | 0, /* tp_setattro */ 2315 | 0, /* tp_as_buffer */ 2316 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 2317 | "", /* tp_doc */ 2318 | Con_Traverse, /* tp_traverse */ 2319 | Con_Clear, /* tp_clear */ 2320 | 0, /* tp_richcompare */ 2321 | 0, /* tp_weaklistoffset */ 2322 | 0, /* tp_iter */ 2323 | 0, /* tp_iternext */ 2324 | Con_methods, /* tp_methods */ 2325 | Con_members, /* tp_members */ 2326 | 0, /* tp_getset */ 2327 | 0, /* tp_base */ 2328 | 0, /* tp_dict */ 2329 | 0, /* tp_descr_get */ 2330 | 0, /* tp_descr_set */ 2331 | 0, /* tp_dictoffset */ 2332 | (initproc)Con_Constructor, /* tp_init */ 2333 | 0, /* tp_alloc */ 2334 | Con_New, /* tp_new */ 2335 | }; 2336 | 2337 | static PyMethodDef methods[] = { { NULL, NULL, 0, NULL } /* Sentinel */ 2338 | }; 2339 | 2340 | PyMODINIT_FUNC initamysql(void) { 2341 | PyObject* m; 2342 | PyObject *dict; 2343 | PyDateTime_IMPORT; 2344 | 2345 | m = Py_InitModule3("amysql", methods, ""); 2346 | if (m == NULL) 2347 | return; 2348 | 2349 | dict = PyModule_GetDict(m); 2350 | 2351 | ConType.tp_new = PyType_GenericNew; 2352 | if (PyType_Ready(&ConType) < 0) 2353 | return; 2354 | Py_INCREF(&ConType); 2355 | PyModule_AddObject(m, "Con", (PyObject *) &ConType); 2356 | 2357 | amysql_Error = PyErr_NewException("amysql.Error", PyExc_Error, 2358 | NULL); 2359 | amysql_SQLError = PyErr_NewException("amysql.SQLError", amysql_Error, NULL); 2360 | 2361 | PyDict_SetItemString(dict, "Error", amysql_Error); 2362 | PyDict_SetItemString(dict, "SQLError", amysql_SQLError); 2363 | 2364 | if (sockclass == NULL) { 2365 | if(sockmodule == NULL){ 2366 | sockmodule = PyImport_ImportModule("socket"); 2367 | if (sockmodule == NULL){fprintf(stderr, "Error importing Python standard socket module\n");exit(-1);} 2368 | } 2369 | sockclass = PyObject_GetAttrString(sockmodule, "socket"); 2370 | if (!sockclass ||!PyType_Check(sockclass) ||!PyCallable_Check(sockclass)){fprintf(stderr, "Error get 'socket.socket' method\n");exit(-1);} 2371 | } 2372 | } 2373 | 2374 | 2375 | #endif 2376 | 2377 | 2378 | 2379 | 2380 | -------------------------------------------------------------------------------- /amysql.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abaelhe/amysql/9854a459144fda7e0adb2d046a88c40ced4a63c7/amysql.so -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | import shutil 3 | import sys 4 | 5 | CLASSIFIERS = filter(None, map(str.strip, 6 | """ 7 | Intended Audience :: Developers 8 | License :: Private :: All Rights Reserved! 9 | Programming Language :: Python 10 | Topic :: Database 11 | Topic :: Software Development :: Libraries :: Python Modules 12 | """.splitlines())) 13 | 14 | libs = [] 15 | 16 | if sys.platform != "win32": 17 | libs.append("stdc++") 18 | 19 | if sys.platform == "win32": 20 | libs.append("ws2_32") 21 | 22 | 23 | module1 = Extension('amysql', 24 | sources = ["./amysql.c" ], 25 | include_dirs = [ "./"], 26 | library_dirs = [ "./"], 27 | libraries=libs, 28 | define_macros=[('WIN32_LEAN_AND_MEAN', None), ('DEBUG', None)]) 29 | 30 | setup (name = 'amysql', 31 | version = "2.5", 32 | description = "Async MySQL driver for Python", 33 | ext_modules = [module1], 34 | extra_compile_args=["-O0"], 35 | extra_link_args=["-O0"], 36 | author="Abael Heyijun", 37 | author_email="hyjdyx@gmail.com", 38 | license="BSD License", 39 | platforms=['any'], 40 | url="http://www.abael.com", 41 | classifiers=CLASSIFIERS, 42 | ) 43 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import amysql 2 | c=amysql.Con() 3 | c.connect('localhost',3306, 'xweb', 'xweb123', 'xweb') 4 | from time import time 5 | def pf(func, n): 6 | t=time() 7 | for i in xrange(n): 8 | func() 9 | d=time() 10 | return n/(d-t) 11 | 12 | print pf(lambda:c.query("select * from sys_usr"), 10000) 13 | --------------------------------------------------------------------------------