| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package AnyEvent::MySQL::Imp; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 1 |  |  | 1 |  | 6 | use strict; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 23 |  | 
| 4 | 1 |  |  | 1 |  | 4 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 65 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 1 |  |  | 1 |  | 464 | use AE; | 
|  | 1 |  |  |  |  | 5243 |  | 
|  | 1 |  |  |  |  | 31 |  | 
| 7 | 1 |  |  | 1 |  | 554 | use AnyEvent::Socket; | 
|  | 1 |  |  |  |  | 21489 |  | 
|  | 1 |  |  |  |  | 110 |  | 
| 8 | 1 |  |  | 1 |  | 824 | use AnyEvent::Handle; | 
|  | 1 |  |  |  |  | 5858 |  | 
|  | 1 |  |  |  |  | 41 |  | 
| 9 | 1 |  |  | 1 |  | 490 | use Digest::SHA1 qw(sha1); | 
|  | 1 |  |  |  |  | 617 |  | 
|  | 1 |  |  |  |  | 60 |  | 
| 10 | 1 |  |  | 1 |  | 7 | use List::Util qw(reduce); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 75 |  | 
| 11 | 1 |  |  | 1 |  | 6 | use Scalar::Util qw(dualvar); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 64 |  | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | use constant { | 
| 14 | 1 |  |  |  |  | 150 | DEV => 0, | 
| 15 | 1 |  |  | 1 |  | 5 | }; | 
|  | 1 |  |  |  |  | 2 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | use constant { | 
| 18 | 1 |  |  |  |  | 319 | CLIENT_LONG_PASSWORD      =>      1, # new more secure passwords + | 
| 19 |  |  |  |  |  |  | CLIENT_FOUND_ROWS         =>      2, # Found instead of affected rows * | 
| 20 |  |  |  |  |  |  | CLIENT_LONG_FLAG          =>      4, # Get all column flags * + | 
| 21 |  |  |  |  |  |  | CLIENT_CONNECT_WITH_DB    =>      8, # One can specify db on connect + | 
| 22 |  |  |  |  |  |  | CLIENT_NO_SCHEMA          =>     16, # Don't allow database.table.column | 
| 23 |  |  |  |  |  |  | CLIENT_COMPRESS           =>     32, # Can use compression protocol * | 
| 24 |  |  |  |  |  |  | CLIENT_ODBC               =>     64, # Odbc client | 
| 25 |  |  |  |  |  |  | CLIENT_LOCAL_FILES        =>    128, # Can use LOAD DATA LOCAL * | 
| 26 |  |  |  |  |  |  | CLIENT_IGNORE_SPACE       =>    256, # Ignore spaces before '(' * | 
| 27 |  |  |  |  |  |  | CLIENT_PROTOCOL_41        =>    512, # New 4.1 protocol + | 
| 28 |  |  |  |  |  |  | CLIENT_INTERACTIVE        =>   1024, # This is an interactive client * + | 
| 29 |  |  |  |  |  |  | CLIENT_SSL                =>   2048, # Switch to SSL after handshake * | 
| 30 |  |  |  |  |  |  | CLIENT_IGNORE_SIGPIPE     =>   4096, # IGNORE sigpipes | 
| 31 |  |  |  |  |  |  | CLIENT_TRANSACTIONS       =>   8192, # Client knows about transactions + | 
| 32 |  |  |  |  |  |  | CLIENT_RESERVED           =>  16384, # Old flag for 4.1 protocol | 
| 33 |  |  |  |  |  |  | CLIENT_SECURE_CONNECTION  =>  32768, # New 4.1 authentication * + | 
| 34 |  |  |  |  |  |  | CLIENT_MULTI_STATEMENTS   =>  65536, # Enable/disable multi-stmt support * + | 
| 35 |  |  |  |  |  |  | CLIENT_MULTI_RESULTS      => 131072, # Enable/disable multi-results * + | 
| 36 | 1 |  |  | 1 |  | 6 | }; | 
|  | 1 |  |  |  |  | 2 |  | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | use constant { | 
| 39 | 1 |  |  |  |  | 249 | COM_SLEEP               => "\x00", #   (none, this is an internal thread state) | 
| 40 |  |  |  |  |  |  | COM_QUIT                => "\x01", #   mysql_close | 
| 41 |  |  |  |  |  |  | COM_INIT_DB             => "\x02", #   mysql_select_db | 
| 42 |  |  |  |  |  |  | COM_QUERY               => "\x03", #   mysql_real_query | 
| 43 |  |  |  |  |  |  | COM_FIELD_LIST          => "\x04", #   mysql_list_fields | 
| 44 |  |  |  |  |  |  | COM_CREATE_DB           => "\x05", #   mysql_create_db (deprecated) | 
| 45 |  |  |  |  |  |  | COM_DROP_DB             => "\x06", #   mysql_drop_db (deprecated) | 
| 46 |  |  |  |  |  |  | COM_REFRESH             => "\x07", #   mysql_refresh | 
| 47 |  |  |  |  |  |  | COM_SHUTDOWN            => "\x08", #   mysql_shutdown | 
| 48 |  |  |  |  |  |  | COM_STATISTICS          => "\x09", #   mysql_stat | 
| 49 |  |  |  |  |  |  | COM_PROCESS_INFO        => "\x0a", #   mysql_list_processes | 
| 50 |  |  |  |  |  |  | COM_CONNECT             => "\x0b", #   (none, this is an internal thread state) | 
| 51 |  |  |  |  |  |  | COM_PROCESS_KILL        => "\x0c", #   mysql_kill | 
| 52 |  |  |  |  |  |  | COM_DEBUG               => "\x0d", #   mysql_dump_debug_info | 
| 53 |  |  |  |  |  |  | COM_PING                => "\x0e", #   mysql_ping | 
| 54 |  |  |  |  |  |  | COM_TIME                => "\x0f", #   (none, this is an internal thread state) | 
| 55 |  |  |  |  |  |  | COM_DELAYED_INSERT      => "\x10", #   (none, this is an internal thread state) | 
| 56 |  |  |  |  |  |  | COM_CHANGE_USER         => "\x11", #   mysql_change_user | 
| 57 |  |  |  |  |  |  | COM_BINLOG_DUMP         => "\x12", #   sent by the slave IO thread to request a binlog | 
| 58 |  |  |  |  |  |  | COM_TABLE_DUMP          => "\x13", #   LOAD TABLE ... FROM MASTER (deprecated) | 
| 59 |  |  |  |  |  |  | COM_CONNECT_OUT         => "\x14", #   (none, this is an internal thread state) | 
| 60 |  |  |  |  |  |  | COM_REGISTER_SLAVE      => "\x15", #   sent by the slave to register with the master (optional) | 
| 61 |  |  |  |  |  |  | COM_STMT_PREPARE        => "\x16", #   mysql_stmt_prepare | 
| 62 |  |  |  |  |  |  | COM_STMT_EXECUTE        => "\x17", #   mysql_stmt_execute | 
| 63 |  |  |  |  |  |  | COM_STMT_SEND_LONG_DATA => "\x18", #   mysql_stmt_send_long_data | 
| 64 |  |  |  |  |  |  | COM_STMT_CLOSE          => "\x19", #   mysql_stmt_close | 
| 65 |  |  |  |  |  |  | COM_STMT_RESET          => "\x1a", #   mysql_stmt_reset | 
| 66 |  |  |  |  |  |  | COM_SET_OPTION          => "\x1b", #   mysql_set_server_option | 
| 67 |  |  |  |  |  |  | COM_STMT_FETCH          => "\x1c", #   mysql_stmt_fetch | 
| 68 | 1 |  |  | 1 |  | 7 | }; | 
|  | 1 |  |  |  |  | 1 |  | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | use constant { | 
| 71 | 1 |  |  |  |  | 250 | MYSQL_TYPE_BIT                  => 16, | 
| 72 |  |  |  |  |  |  | MYSQL_TYPE_BLOB                 => 252, | 
| 73 |  |  |  |  |  |  | MYSQL_TYPE_DATE                 => 10, | 
| 74 |  |  |  |  |  |  | MYSQL_TYPE_DATETIME             => 12, | 
| 75 |  |  |  |  |  |  | MYSQL_TYPE_DECIMAL              => 0, | 
| 76 |  |  |  |  |  |  | MYSQL_TYPE_DOUBLE               => 5, | 
| 77 |  |  |  |  |  |  | MYSQL_TYPE_ENUM                 => 247, | 
| 78 |  |  |  |  |  |  | MYSQL_TYPE_FLOAT                => 4, | 
| 79 |  |  |  |  |  |  | MYSQL_TYPE_GEOMETRY             => 255, | 
| 80 |  |  |  |  |  |  | MYSQL_TYPE_INT24                => 9, | 
| 81 |  |  |  |  |  |  | MYSQL_TYPE_LONG                 => 3, | 
| 82 |  |  |  |  |  |  | MYSQL_TYPE_LONGLONG             => 8, | 
| 83 |  |  |  |  |  |  | MYSQL_TYPE_LONG_BLOB            => 251, | 
| 84 |  |  |  |  |  |  | MYSQL_TYPE_MEDIUM_BLOB          => 250, | 
| 85 |  |  |  |  |  |  | MYSQL_TYPE_NEWDATE              => 14, | 
| 86 |  |  |  |  |  |  | MYSQL_TYPE_NEWDECIMAL           => 246, | 
| 87 |  |  |  |  |  |  | MYSQL_TYPE_NULL                 => 6, | 
| 88 |  |  |  |  |  |  | MYSQL_TYPE_SET                  => 248, | 
| 89 |  |  |  |  |  |  | MYSQL_TYPE_SHORT                => 2, | 
| 90 |  |  |  |  |  |  | MYSQL_TYPE_STRING               => 254, | 
| 91 |  |  |  |  |  |  | MYSQL_TYPE_TIME                 => 11, | 
| 92 |  |  |  |  |  |  | MYSQL_TYPE_TIMESTAMP            => 7, | 
| 93 |  |  |  |  |  |  | MYSQL_TYPE_TINY                 => 1, | 
| 94 |  |  |  |  |  |  | MYSQL_TYPE_TINY_BLOB            => 249, | 
| 95 |  |  |  |  |  |  | MYSQL_TYPE_VARCHAR              => 15, | 
| 96 |  |  |  |  |  |  | MYSQL_TYPE_VAR_STRING           => 253, | 
| 97 |  |  |  |  |  |  | MYSQL_TYPE_YEAR                 => 13, | 
| 98 | 1 |  |  | 1 |  | 6 | }; | 
|  | 1 |  |  |  |  | 2 |  | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | use constant { | 
| 101 | 1 |  |  |  |  | 166 | NOT_NULL_FLAG           => 1,                 # Field can't be NULL | 
| 102 |  |  |  |  |  |  | PRI_KEY_FLAG            => 2,                 # Field is part of a primary key | 
| 103 |  |  |  |  |  |  | UNIQUE_KEY_FLAG         => 4,                 # Field is part of a unique key | 
| 104 |  |  |  |  |  |  | MULTIPLE_KEY_FLAG       => 8,                 # Field is part of a key | 
| 105 |  |  |  |  |  |  | BLOB_FLAG               => 16,                # Field is a blob | 
| 106 |  |  |  |  |  |  | UNSIGNED_FLAG           => 32,                # Field is unsigned | 
| 107 |  |  |  |  |  |  | ZEROFILL_FLAG           => 64,                # Field is zerofill | 
| 108 |  |  |  |  |  |  | BINARY_FLAG             => 128,               # Field is binary | 
| 109 |  |  |  |  |  |  | ENUM_FLAG               => 256,               # Field is an enum | 
| 110 |  |  |  |  |  |  | AUTO_INCREMENT_FLAG     => 512,               # Field is a autoincrement field | 
| 111 |  |  |  |  |  |  | TIMESTAMP_FLAG          => 1024,              # Field is a timestamp | 
| 112 |  |  |  |  |  |  | SET_FLAG                => 2048,              # Field is a set | 
| 113 |  |  |  |  |  |  | NO_DEFAULT_VALUE_FLAG   => 4096,              # Field doesn't have default value | 
| 114 |  |  |  |  |  |  | ON_UPDATE_NOW_FLAG      => 8192,              # Field is set to NOW on UPDATE | 
| 115 |  |  |  |  |  |  | NUM_FLAG                => 32768,             # Field is num (for clients) | 
| 116 |  |  |  |  |  |  | PART_KEY_FLAG           => 16384,             # Intern; Part of some key | 
| 117 |  |  |  |  |  |  | GROUP_FLAG              => 32768,             # Intern: Group field | 
| 118 |  |  |  |  |  |  | UNIQUE_FLAG             => 65536,             # Intern: Used by sql_yacc | 
| 119 |  |  |  |  |  |  | BINCMP_FLAG             => 131072,            # Intern: Used by sql_yacc | 
| 120 |  |  |  |  |  |  | GET_FIXED_FIELDS_FLAG   => (1<<18),           # Used to get fields in item tree | 
| 121 |  |  |  |  |  |  | FIELD_IN_PART_FUNC_FLAG => (1<<19),           # Field part of partition func | 
| 122 |  |  |  |  |  |  | FIELD_IN_ADD_INDEX      => (1<<20),           # Intern: Field used in ADD INDEX | 
| 123 |  |  |  |  |  |  | FIELD_IS_RENAMED        => (1<<21),           # Intern: Field is being renamed | 
| 124 | 1 |  |  | 1 |  | 5 | }; | 
|  | 1 |  |  |  |  | 2 |  | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | use constant { | 
| 127 | 1 |  |  |  |  | 764 | RES_OK => 0, | 
| 128 |  |  |  |  |  |  | RES_ERROR => 255, | 
| 129 |  |  |  |  |  |  | RES_RESULT => 1, | 
| 130 |  |  |  |  |  |  | RES_PREPARE => 2, | 
| 131 | 1 |  |  | 1 |  | 6 | }; | 
|  | 1 |  |  |  |  | 2 |  | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | =head2 $str = take_zstring($data(modified)) | 
| 134 |  |  |  |  |  |  | null terminated string | 
| 135 |  |  |  |  |  |  | =cut | 
| 136 |  |  |  |  |  |  | sub take_zstr { | 
| 137 | 0 |  |  | 0 | 1 |  | $_[0] =~ s/(.*?)\x00//s; | 
| 138 | 0 |  |  |  |  |  | return $1; | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | =head2 $num = take_lcb($data(modifed)) | 
| 142 |  |  |  |  |  |  | length coded binary | 
| 143 |  |  |  |  |  |  | =cut | 
| 144 |  |  |  |  |  |  | sub take_lcb { | 
| 145 | 0 |  |  | 0 | 1 |  | my $fb = substr($_[0], 0, 1, ''); | 
| 146 | 0 | 0 |  |  |  |  | if( $fb le "\xFA" ) { # 0-250 | 
| 147 | 0 |  |  |  |  |  | return ord($fb); | 
| 148 |  |  |  |  |  |  | } | 
| 149 | 0 | 0 |  |  |  |  | if( $fb eq "\xFB" ) { # 251 | 
| 150 | 0 |  |  |  |  |  | return undef; | 
| 151 |  |  |  |  |  |  | } | 
| 152 | 0 | 0 |  |  |  |  | if( $fb eq "\xFC" ) { # 252 | 
| 153 | 0 |  |  |  |  |  | return unpack('v', substr($_[0], 0, 2, '')); | 
| 154 |  |  |  |  |  |  | } | 
| 155 | 0 | 0 |  |  |  |  | if( $fb eq "\xFD" ) { # 253 | 
| 156 | 0 |  |  |  |  |  | return unpack('V', substr($_[0], 0, 3, '')."\x00"); | 
| 157 |  |  |  |  |  |  | } | 
| 158 | 0 | 0 |  |  |  |  | if( $fb eq "\xFE" ) { # 254 | 
| 159 | 0 |  |  |  |  |  | return unpack('Q<', substr($_[0], 0, 8, '')); | 
| 160 |  |  |  |  |  |  | } | 
| 161 | 0 |  |  |  |  |  | return undef; # error | 
| 162 |  |  |  |  |  |  | } | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | =head2 $str = take_lcs($data(modified)) | 
| 165 |  |  |  |  |  |  | length coded string | 
| 166 |  |  |  |  |  |  | =cut | 
| 167 |  |  |  |  |  |  | sub take_lcs { | 
| 168 | 0 |  |  | 0 | 1 |  | my $len = &take_lcb; | 
| 169 | 0 | 0 |  |  |  |  | if( defined $len ) { | 
| 170 | 0 |  |  |  |  |  | return substr($_[0], 0, $len, ''); | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  | else { | 
| 173 | 0 |  |  |  |  |  | return undef; | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  | } | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | =head2 $num = take_num($data(modified), $len) | 
| 178 |  |  |  |  |  |  | =cut | 
| 179 |  |  |  |  |  |  | sub take_num { | 
| 180 | 0 |  |  | 0 | 1 |  | return unpack('V', substr($_[0], 0, $_[1], '')."\x00\x00\x00"); | 
| 181 |  |  |  |  |  |  | } | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | =head2 $str = take_str($data(modified), $len) | 
| 184 |  |  |  |  |  |  | =cut | 
| 185 |  |  |  |  |  |  | sub take_str { | 
| 186 | 0 |  |  | 0 | 1 |  | return substr($_[0], 0, $_[1], ''); | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | =head2 () = take_filler($data(modified), $len) | 
| 190 |  |  |  |  |  |  | =cut | 
| 191 |  |  |  |  |  |  | sub take_filler { | 
| 192 | 0 |  |  | 0 | 1 |  | substr($_[0], 0, $_[1], ''); | 
| 193 | 0 |  |  |  |  |  | return (); | 
| 194 |  |  |  |  |  |  | } | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | =head2 $cell = take_type($data(modified), $type, $length, $flag) | 
| 197 |  |  |  |  |  |  | WARN: some MySQL data types are not implemented | 
| 198 |  |  |  |  |  |  | =cut | 
| 199 |  |  |  |  |  |  | sub take_type { | 
| 200 | 0 | 0 |  | 0 | 1 |  | if( $_[1]==MYSQL_TYPE_TINY ) { # tinyint | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 201 | 0 | 0 |  |  |  |  | if( $_[3] & UNSIGNED_FLAG ) { | 
| 202 | 0 |  |  |  |  |  | return ord(substr($_[0], 0, 1, '')); | 
| 203 |  |  |  |  |  |  | } | 
| 204 |  |  |  |  |  |  | else { | 
| 205 | 0 |  |  |  |  |  | return unpack('c', substr($_[0], 0, 1, '')); | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_SHORT ) { # smallint | 
| 208 | 0 | 0 |  |  |  |  | if( $_[3] & UNSIGNED_FLAG ) { | 
| 209 | 0 |  |  |  |  |  | return unpack('v', substr($_[0], 0, 2, '')); | 
| 210 |  |  |  |  |  |  | } | 
| 211 |  |  |  |  |  |  | else { | 
| 212 | 0 |  |  |  |  |  | return unpack('s<', substr($_[0], 0, 2, '')); | 
| 213 |  |  |  |  |  |  | } | 
| 214 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_INT24 ) { # mediumint | 
| 215 | 0 | 0 |  |  |  |  | if( $_[3] & UNSIGNED_FLAG ) { | 
| 216 | 0 |  |  |  |  |  | return unpack('V', substr($_[0], 0, 3, '')."\0"); | 
| 217 |  |  |  |  |  |  | } | 
| 218 |  |  |  |  |  |  | else { | 
| 219 | 0 |  |  |  |  |  | return unpack('l<', substr($_[0], 0, 3, '')."\0"); | 
| 220 |  |  |  |  |  |  | } | 
| 221 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_LONG ) { # int | 
| 222 | 0 | 0 |  |  |  |  | if( $_[3] & UNSIGNED_FLAG ) { | 
| 223 | 0 |  |  |  |  |  | return unpack('V', substr($_[0], 0, 4, '')); | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  | else { | 
| 226 | 0 |  |  |  |  |  | return unpack('l<', substr($_[0], 0, 4, '')); | 
| 227 |  |  |  |  |  |  | } | 
| 228 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_LONGLONG ) { # bigint | 
| 229 | 0 | 0 |  |  |  |  | if( $_[3] & UNSIGNED_FLAG ) { | 
| 230 | 0 |  |  |  |  |  | return unpack('Q<', substr($_[0], 0, 8, '')); | 
| 231 |  |  |  |  |  |  | } | 
| 232 |  |  |  |  |  |  | else { | 
| 233 | 0 |  |  |  |  |  | return unpack('q<', substr($_[0], 0, 8, '')); | 
| 234 |  |  |  |  |  |  | } | 
| 235 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_FLOAT ) { # float | 
| 236 | 0 |  |  |  |  |  | return unpack('f<', substr($_[0], 0, 4, '')); | 
| 237 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_DOUBLE ) { # double | 
| 238 | 0 |  |  |  |  |  | return unpack('d<', substr($_[0], 0, 8, '')); | 
| 239 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_NEWDECIMAL ) { # decimal, numeric | 
| 240 | 0 |  |  |  |  |  | warn "Not implement DECIMAL,NUMERIC yet"; | 
| 241 | 0 |  |  |  |  |  | return; | 
| 242 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_BIT ) { # bit(n) | 
| 243 | 0 |  |  |  |  |  | warn "Not implement BIT yet"; | 
| 244 | 0 |  |  |  |  |  | return; | 
| 245 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_DATE ) { # date | 
| 246 | 0 |  |  |  |  |  | warn "Not implement DATE yet"; | 
| 247 | 0 |  |  |  |  |  | return; | 
| 248 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_TIME ) { # time | 
| 249 | 0 |  |  |  |  |  | warn "Not implement TIME yet"; | 
| 250 | 0 |  |  |  |  |  | return; | 
| 251 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_DATETIME ) { # datetime | 
| 252 | 0 |  |  |  |  |  | warn "Not implement DATETIME yet"; | 
| 253 | 0 |  |  |  |  |  | return; | 
| 254 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_TIMESTAMP ) { # timestamp | 
| 255 | 0 |  |  |  |  |  | warn "Not implement TIMESTAMP yet"; | 
| 256 | 0 |  |  |  |  |  | return; | 
| 257 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_YEAR ) { # year | 
| 258 | 0 |  |  |  |  |  | return 1901+ord(substr($_[0], 0, 1, '')); | 
| 259 |  |  |  |  |  |  | } elsif( $_[1]==MYSQL_TYPE_STRING ) { # char(n), binary(n), enum(), set() | 
| 260 | 0 | 0 |  |  |  |  | if( $_[3] & ENUM_FLAG ) { | 
|  |  | 0 |  |  |  |  |  | 
| 261 | 0 |  |  |  |  |  | warn "Not implement ENUM yet"; | 
| 262 | 0 |  |  |  |  |  | return; | 
| 263 |  |  |  |  |  |  | } | 
| 264 |  |  |  |  |  |  | elsif( $_[3] & SET_FLAG ) { | 
| 265 | 0 |  |  |  |  |  | warn "Not implement SET yet"; | 
| 266 | 0 |  |  |  |  |  | return; | 
| 267 |  |  |  |  |  |  | } | 
| 268 |  |  |  |  |  |  | else { | 
| 269 | 0 |  |  |  |  |  | my $data = substr($_[0], 0, $_[2], ''); | 
| 270 | 0 |  |  |  |  |  | $data =~ s/ +$//; | 
| 271 | 0 |  |  |  |  |  | return $data; | 
| 272 |  |  |  |  |  |  | } | 
| 273 |  |  |  |  |  |  | } elsif( $_[1]==[ MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_BLOB]) { # varchar(n), varbinary(n) | tinyblob, tinytext, blob, text, mediumblob, mediumtext, longblob, longtext | 
| 274 | 0 |  |  |  |  |  | my $len; | 
| 275 | 0 | 0 |  |  |  |  | if( $_[2]<=0xFF ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 276 | 0 |  |  |  |  |  | $len = ord(substr($_[0], 0, 1, '')); | 
| 277 |  |  |  |  |  |  | } | 
| 278 |  |  |  |  |  |  | elsif( $_[2]<=0xFFFF ) { | 
| 279 | 0 |  |  |  |  |  | $len = unpack('v', substr($_[0], 0, 2, '')); | 
| 280 |  |  |  |  |  |  | } | 
| 281 |  |  |  |  |  |  | elsif( $_[2]<=0xFFFFFF ) { | 
| 282 | 0 |  |  |  |  |  | $len = unpack('V', substr($_[0], 0, 3, '')."\0"); | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  | else { | 
| 285 | 0 |  |  |  |  |  | $len = unpack('V', substr($_[0], 0, 4, '')); | 
| 286 |  |  |  |  |  |  | } | 
| 287 | 0 |  |  |  |  |  | return substr($_[0], 0, $len, ''); | 
| 288 |  |  |  |  |  |  | } else { | 
| 289 | 0 |  |  |  |  |  | warn "Unsupported type: $_"; | 
| 290 | 1 |  |  | 1 |  | 460 | use Devel::StackTrace; | 
|  | 1 |  |  |  |  | 4310 |  | 
|  | 1 |  |  |  |  | 518 |  | 
| 291 | 0 |  |  |  |  |  | print Devel::StackTrace->new->as_string; | 
| 292 | 0 |  |  |  |  |  | return; | 
| 293 |  |  |  |  |  |  | } | 
| 294 |  |  |  |  |  |  | } | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | =head2 put_type($data(modified), $cell, $type, $len, $flag) | 
| 297 |  |  |  |  |  |  | =cut | 
| 298 |  |  |  |  |  |  | sub put_type { | 
| 299 | 0 | 0 |  | 0 | 1 |  | if( $_[2]==MYSQL_TYPE_TINY ) { # tinyint | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 300 | 0 | 0 |  |  |  |  | if( $_[4] & UNSIGNED_FLAG ) { | 
| 301 | 0 |  |  |  |  |  | $_[0] .= chr($_[1]); | 
| 302 |  |  |  |  |  |  | } | 
| 303 |  |  |  |  |  |  | else { | 
| 304 | 0 |  |  |  |  |  | $_[0] .= pack('c', $_[1]); | 
| 305 |  |  |  |  |  |  | } | 
| 306 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_SHORT ) { # smallint | 
| 307 | 0 | 0 |  |  |  |  | $_[0] .= pack( $_[4] & UNSIGNED_FLAG ? 'v' : 's<' , $_[1]); | 
| 308 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_INT24 ) { # mediumint | 
| 309 | 0 | 0 |  |  |  |  | $_[0] .= substr(pack( $_[4] & UNSIGNED_FLAG ? 'V' : 'l<' , $_[1]), 0, 3); | 
| 310 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_LONG ) { # int | 
| 311 | 0 | 0 |  |  |  |  | $_[0] .= pack( $_[4] & UNSIGNED_FLAG ? 'V' : 'l<' , $_[1] ); | 
| 312 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_LONGLONG ) { # bigint | 
| 313 | 0 | 0 |  |  |  |  | $_[0] .= pack( $_[4] & UNSIGNED_FLAG ? 'Q<' : 'q<' , $_[1] ); | 
| 314 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_FLOAT ) { # float | 
| 315 | 0 |  |  |  |  |  | $_[0] .= pack('f<', $_[1]); | 
| 316 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_DOUBLE ) { # double | 
| 317 | 0 |  |  |  |  |  | $_[0] .= pack('d<', $_[1]); | 
| 318 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_NEWDECIMAL ) { # decimal, numeric | 
| 319 | 0 |  |  |  |  |  | warn "Not implement DECIMAL,NUMERIC yet"; | 
| 320 | 0 |  |  |  |  |  | return; | 
| 321 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_BIT ) { # bit(n) | 
| 322 | 0 |  |  |  |  |  | warn "Not implement BIT yet"; | 
| 323 | 0 |  |  |  |  |  | return; | 
| 324 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_DATE ) { # date | 
| 325 | 0 |  |  |  |  |  | warn "Not implement DATE yet"; | 
| 326 | 0 |  |  |  |  |  | return; | 
| 327 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_TIME ) { # time | 
| 328 | 0 |  |  |  |  |  | warn "Not implement TIME yet"; | 
| 329 | 0 |  |  |  |  |  | return; | 
| 330 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_DATETIME ) { # datetime | 
| 331 | 0 |  |  |  |  |  | warn "Not implement DATETIME yet"; | 
| 332 | 0 |  |  |  |  |  | return; | 
| 333 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_TIMESTAMP ) { # timestamp | 
| 334 | 0 |  |  |  |  |  | warn "Not implement TIMESTAMP yet"; | 
| 335 | 0 |  |  |  |  |  | return; | 
| 336 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_YEAR ) { # year | 
| 337 | 0 |  |  |  |  |  | $_[0] .= chr($_[1]-1901); | 
| 338 |  |  |  |  |  |  | } elsif( $_[2]==MYSQL_TYPE_STRING ) { # char(n), binary(n), enum(), set() | 
| 339 | 0 | 0 |  |  |  |  | if( $_[4] & ENUM_FLAG ) { | 
|  |  | 0 |  |  |  |  |  | 
| 340 | 0 |  |  |  |  |  | warn "Not implement ENUM yet"; | 
| 341 | 0 |  |  |  |  |  | return; | 
| 342 |  |  |  |  |  |  | } | 
| 343 |  |  |  |  |  |  | elsif( $_[4] & SET_FLAG ) { | 
| 344 | 0 |  |  |  |  |  | warn "Not implement SET yet"; | 
| 345 | 0 |  |  |  |  |  | return; | 
| 346 |  |  |  |  |  |  | } | 
| 347 |  |  |  |  |  |  | else { | 
| 348 | 0 | 0 |  |  |  |  | if( length($_[1]) >= $_[3] ) { | 
| 349 | 0 |  |  |  |  |  | $_[0] .= substr($_[1], 0, $_[3]); | 
| 350 |  |  |  |  |  |  | } | 
| 351 |  |  |  |  |  |  | else { | 
| 352 | 0 |  |  |  |  |  | $_[0] .= $_[1]; | 
| 353 | 0 |  |  |  |  |  | $_[0] .= ' ' x ($_[3] - length $_[1]); | 
| 354 |  |  |  |  |  |  | } | 
| 355 |  |  |  |  |  |  | } | 
| 356 |  |  |  |  |  |  | } elsif( $_[2]==[ MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_BLOB]) { # varchar(n), varbinary(n) | tinyblob, tinytext, blob, text, mediumblob, mediumtext, longblob, longtext | 
| 357 | 0 |  |  |  |  |  | my $len; | 
| 358 | 0 | 0 |  |  |  |  | $_[1] = substr($_[1], 0, $_[3]) if( length($_[1]) > $_[3] ); | 
| 359 | 0 | 0 |  |  |  |  | if( $_[3]<=0xFF ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 360 | 0 |  |  |  |  |  | $_[0] .= chr(length($_[1])); | 
| 361 |  |  |  |  |  |  | } | 
| 362 |  |  |  |  |  |  | elsif( $_[3]<=0xFFFF ) { | 
| 363 | 0 |  |  |  |  |  | $_[0] .= pack('v', length($_[1])); | 
| 364 |  |  |  |  |  |  | } | 
| 365 |  |  |  |  |  |  | elsif( $_[3]<=0xFFFFFF ) { | 
| 366 | 0 |  |  |  |  |  | $_[0] .= substr(pack('V', length($_[1])), 0, 3); | 
| 367 |  |  |  |  |  |  | } | 
| 368 |  |  |  |  |  |  | else { | 
| 369 | 0 |  |  |  |  |  | $_[0] .= pack('V', length($_[1])); | 
| 370 |  |  |  |  |  |  | } | 
| 371 | 0 |  |  |  |  |  | $_[0] .= $_[1]; | 
| 372 |  |  |  |  |  |  | } else { | 
| 373 | 0 |  |  |  |  |  | warn "Unsupported type: $_[2]"; | 
| 374 | 0 |  |  |  |  |  | return; | 
| 375 |  |  |  |  |  |  | } | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | =head2 put_num($data(modified), $num, $len) | 
| 379 |  |  |  |  |  |  | =cut | 
| 380 |  |  |  |  |  |  | sub put_num { | 
| 381 | 0 |  |  | 0 | 1 |  | $_[0] .= substr(pack('V', $_[1]), 0, $_[2]); | 
| 382 |  |  |  |  |  |  | } | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | =head2 put_str($data(modified), $str, $len) | 
| 385 |  |  |  |  |  |  | =cut | 
| 386 |  |  |  |  |  |  | sub put_str { | 
| 387 | 0 |  |  | 0 | 1 |  | $_[0] .= substr($_[1].("\x00" x $_[2]), 0, $_[2]); | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | =head2 put_zstr($data(modified), $str) | 
| 391 |  |  |  |  |  |  | =cut | 
| 392 |  |  |  |  |  |  | sub put_zstr { | 
| 393 | 1 |  |  | 1 |  | 7 | no warnings 'uninitialized'; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 840 |  | 
| 394 | 0 |  |  | 0 | 1 |  | $_[0] .= $_[1]; | 
| 395 | 0 |  |  |  |  |  | $_[0] .= "\x00"; | 
| 396 |  |  |  |  |  |  | } | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | =head2 put_lcb($data(modified), $num) | 
| 399 |  |  |  |  |  |  | =cut | 
| 400 |  |  |  |  |  |  | sub put_lcb { | 
| 401 | 0 | 0 |  | 0 | 1 |  | if( $_[1] <= 250 ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 402 | 0 |  |  |  |  |  | $_[0] .= chr($_[1]); | 
| 403 |  |  |  |  |  |  | } | 
| 404 |  |  |  |  |  |  | elsif( !defined($_[1]) ) { | 
| 405 | 0 |  |  |  |  |  | $_[0] .= "\xFB"; # 251 | 
| 406 |  |  |  |  |  |  | } | 
| 407 |  |  |  |  |  |  | elsif( $_[1] <= 65535 ) { | 
| 408 | 0 |  |  |  |  |  | $_[0] .= "\xFC"; # 252 | 
| 409 | 0 |  |  |  |  |  | $_[0] .= pack('v', $_[1]); | 
| 410 |  |  |  |  |  |  | } | 
| 411 |  |  |  |  |  |  | elsif( $_[1] <= 16777215 ) { | 
| 412 | 0 |  |  |  |  |  | $_[0] .= "\xFD"; # 253 | 
| 413 | 0 |  |  |  |  |  | $_[0] .= substr(pack('V', $_[1]), 0, 3); | 
| 414 |  |  |  |  |  |  | } | 
| 415 |  |  |  |  |  |  | else { | 
| 416 | 0 |  |  |  |  |  | $_[0] .= "\xFE"; # 254 | 
| 417 | 0 |  |  |  |  |  | $_[0] .= pack('Q<', $_[1]); | 
| 418 |  |  |  |  |  |  | } | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | =head2 put_lcs($data(modified), $str) | 
| 422 |  |  |  |  |  |  | =cut | 
| 423 |  |  |  |  |  |  | sub put_lcs { | 
| 424 | 0 |  |  | 0 | 1 |  | put_lcb($_[0], length($_[1])); | 
| 425 | 0 |  |  |  |  |  | $_[0] .= $_[1]; | 
| 426 |  |  |  |  |  |  | } | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | =head2 ($affected_rows, $insert_id, $server_status, $warning_count, $message) | $is = parse_ok($data(modified)) | 
| 429 |  |  |  |  |  |  | =cut | 
| 430 |  |  |  |  |  |  | sub parse_ok { | 
| 431 | 0 | 0 |  | 0 | 1 |  | if( substr($_[0], 0, 1) eq "\x00" ) { | 
| 432 | 0 | 0 |  |  |  |  | if( wantarray ) { | 
| 433 | 0 |  |  |  |  |  | substr($_[0], 0, 1, ''); | 
| 434 |  |  |  |  |  |  | return ( | 
| 435 | 0 |  |  |  |  |  | take_lcb($_[0]), | 
| 436 |  |  |  |  |  |  | take_lcb($_[0]), | 
| 437 |  |  |  |  |  |  | take_num($_[0], 2), | 
| 438 |  |  |  |  |  |  | take_num($_[0], 2), | 
| 439 |  |  |  |  |  |  | $_[0], | 
| 440 |  |  |  |  |  |  | ); | 
| 441 |  |  |  |  |  |  | } | 
| 442 |  |  |  |  |  |  | else { | 
| 443 | 0 |  |  |  |  |  | return 1; | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  | } | 
| 446 |  |  |  |  |  |  | else { | 
| 447 | 0 |  |  |  |  |  | return; | 
| 448 |  |  |  |  |  |  | } | 
| 449 |  |  |  |  |  |  | } | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | =head2 ($errno, $sqlstate, $message) = parse_error($data(modified)) | 
| 452 |  |  |  |  |  |  | =cut | 
| 453 |  |  |  |  |  |  | sub parse_error { | 
| 454 | 0 | 0 |  | 0 | 1 |  | if( substr($_[0], 0, 1) eq "\xFF" ) { | 
| 455 | 0 | 0 |  |  |  |  | if( wantarray ) { | 
| 456 | 0 |  |  |  |  |  | substr($_[0], 0, 1, ''); | 
| 457 |  |  |  |  |  |  | return ( | 
| 458 | 0 | 0 |  |  |  |  | take_num($_[0], 2), | 
| 459 |  |  |  |  |  |  | ( substr($_[0], 0, 1) eq '#' ? | 
| 460 |  |  |  |  |  |  | ( substr($_[0], 1, 5), substr($_[0], 6) ) : | 
| 461 |  |  |  |  |  |  | ( '', $_[0] ) | 
| 462 |  |  |  |  |  |  | ) | 
| 463 |  |  |  |  |  |  | ); | 
| 464 |  |  |  |  |  |  | } | 
| 465 |  |  |  |  |  |  | else { | 
| 466 | 0 |  |  |  |  |  | return 1; | 
| 467 |  |  |  |  |  |  | } | 
| 468 |  |  |  |  |  |  | } | 
| 469 |  |  |  |  |  |  | else { | 
| 470 | 0 |  |  |  |  |  | return; | 
| 471 |  |  |  |  |  |  | } | 
| 472 |  |  |  |  |  |  | } | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  | ## ($field_count, $extra) = parse_result_set_header($data(modified)) | 
| 475 |  |  |  |  |  |  | #sub parse_result_set_header { | 
| 476 |  |  |  |  |  |  | #    if( $substr($_[0], 0, 1) | 
| 477 |  |  |  |  |  |  | #} | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | =head2 recv_packet($hd, $cb->($packet)) | 
| 480 |  |  |  |  |  |  | =cut | 
| 481 |  |  |  |  |  |  | sub recv_packet { | 
| 482 | 0 |  |  | 0 | 1 |  | my $cb = pop; | 
| 483 | 0 |  |  |  |  |  | my($hd) = @_; | 
| 484 | 0 | 0 |  |  |  |  | if( $hd ) { | 
| 485 |  |  |  |  |  |  | $hd->push_read( chunk => 4, sub { | 
| 486 | 0 |  |  | 0 |  |  | my $len = unpack("V", $_[1]); | 
| 487 | 0 |  |  |  |  |  | my $num = $len >> 24; | 
| 488 | 0 |  |  |  |  |  | $len &= 0xFFFFFF; | 
| 489 | 0 |  |  |  |  |  | print "pack_len=$len, pack_num=$num\n" if DEV; | 
| 490 |  |  |  |  |  |  | $_[0]->unshift_read( chunk => $len, sub { | 
| 491 | 0 |  |  |  |  |  | $cb->($_[1]); | 
| 492 | 0 |  |  |  |  |  | } ); | 
| 493 | 0 |  |  |  |  |  | } ); | 
| 494 |  |  |  |  |  |  | } | 
| 495 |  |  |  |  |  |  | } | 
| 496 |  |  |  |  |  |  |  | 
| 497 |  |  |  |  |  |  | =head2 skip_until_eof($hd, $cb->()) | 
| 498 |  |  |  |  |  |  | =cut | 
| 499 |  |  |  |  |  |  | sub skip_until_eof { | 
| 500 | 0 |  |  | 0 | 1 |  | my($hd, $cb) = @_; | 
| 501 |  |  |  |  |  |  | recv_packet($hd, sub { | 
| 502 | 0 | 0 |  | 0 |  |  | if( substr($_[0], 0, 1) eq "\xFE" ) { | 
| 503 | 0 |  |  |  |  |  | $cb->(); | 
| 504 |  |  |  |  |  |  | } | 
| 505 |  |  |  |  |  |  | else { | 
| 506 | 0 |  |  |  |  |  | skip_until_eof($hd, $cb); | 
| 507 |  |  |  |  |  |  | } | 
| 508 | 0 |  |  |  |  |  | }); | 
| 509 |  |  |  |  |  |  | } | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | =head2 send_packet($hd, $packet_num, $packet_frag1, $pack_frag2, ...) | 
| 512 |  |  |  |  |  |  | =cut | 
| 513 |  |  |  |  |  |  | sub send_packet { | 
| 514 | 0 | 0 |  | 0 | 1 |  | return if !$_[0]; | 
| 515 | 0 |  |  |  |  |  | local $_[0] = $_[0]; | 
| 516 | 0 |  |  | 0 |  |  | my $len = reduce { $a + length($b) } 0, @_[2..$#_]; | 
|  | 0 |  |  |  |  |  |  | 
| 517 | 0 |  |  |  |  |  | $_[0]->push_write(substr(pack('V', $len), 0, 3) . chr($_[1]) . join('', @_[2..$#_])); | 
| 518 |  |  |  |  |  |  | } | 
| 519 |  |  |  |  |  |  |  | 
| 520 |  |  |  |  |  |  | =head2 _recv_field($hd, \@field) | 
| 521 |  |  |  |  |  |  | =cut | 
| 522 |  |  |  |  |  |  | sub _recv_field { | 
| 523 | 0 |  |  | 0 |  |  | warn "get field." if DEV; | 
| 524 | 0 |  |  |  |  |  | my $field = $_[1]; | 
| 525 |  |  |  |  |  |  | recv_packet($_[0], sub { | 
| 526 | 0 |  |  | 0 |  |  | warn "got field!" if DEV; | 
| 527 | 0 |  |  |  |  |  | push @$field, [ | 
| 528 |  |  |  |  |  |  | take_lcs($_[0]), take_lcs($_[0]), take_lcs($_[0]), | 
| 529 |  |  |  |  |  |  | take_lcs($_[0]), take_lcs($_[0]), take_lcs($_[0]), | 
| 530 |  |  |  |  |  |  | take_filler($_[0], 1), | 
| 531 |  |  |  |  |  |  | take_num($_[0], 2), | 
| 532 |  |  |  |  |  |  | take_num($_[0], 4), | 
| 533 |  |  |  |  |  |  | take_num($_[0], 1), | 
| 534 |  |  |  |  |  |  | take_num($_[0], 2), | 
| 535 |  |  |  |  |  |  | take_num($_[0], 1), | 
| 536 |  |  |  |  |  |  | take_filler($_[0], 2), | 
| 537 |  |  |  |  |  |  | take_lcb($_[0]), | 
| 538 |  |  |  |  |  |  | ]; | 
| 539 | 0 |  |  |  |  |  | }); | 
| 540 |  |  |  |  |  |  | } | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | =head2 recv_response($hd, %opt, $cb->(TYPE, data...)) | 
| 543 |  |  |  |  |  |  | RES_OK, $affected_rows, $insert_id, $server_status, $warning_count, $message | 
| 544 |  |  |  |  |  |  | RES_ERROR, $errno, $sqlstate, $message | 
| 545 |  |  |  |  |  |  | RES_RESULT, \@field, \@row | 
| 546 |  |  |  |  |  |  | $field[$i] = [$catalog, $db, $table, $org_table, $name, $org_name, $charsetnr, $length, $type, $flags, $decimals, $default] | 
| 547 |  |  |  |  |  |  | $row[$i] = [$field, $field, $field, ...] | 
| 548 |  |  |  |  |  |  | RES_PREPARE, $stmt_id, \@param, \@column, $warning_count | 
| 549 |  |  |  |  |  |  | $param[$i] = [$catalog, $db, $table, $org_table, $name, $org_name, $charsetnr, $length, $type, $flags, $decimals, $default] | 
| 550 |  |  |  |  |  |  | $column[$i] = [$catalog, $db, $table, $org_table, $name, $org_name, $charsetnr, $length, $type, $flags, $decimals, $default] | 
| 551 |  |  |  |  |  |  | opt: | 
| 552 |  |  |  |  |  |  | prepare (set to truthy to recv prepare_ok) | 
| 553 |  |  |  |  |  |  | =cut | 
| 554 |  |  |  |  |  |  | sub recv_response { | 
| 555 | 0 | 0 |  | 0 | 1 |  | my $cb = ref($_[-1]) eq 'CODE' ? pop : sub {}; | 
|  |  |  |  | 0 |  |  |  | 
| 556 | 0 |  |  |  |  |  | my($hd, %opt) = @_; | 
| 557 |  |  |  |  |  |  |  | 
| 558 | 0 |  |  |  |  |  | if( DEV ) { | 
| 559 |  |  |  |  |  |  | my $cb0 = $cb; | 
| 560 |  |  |  |  |  |  | $cb = sub { | 
| 561 | 1 |  |  | 1 |  | 556 | use Data::Dumper; | 
|  | 1 |  |  |  |  | 5475 |  | 
|  | 1 |  |  |  |  | 1712 |  | 
| 562 | 0 |  |  | 0 |  |  | warn "recv_response: ".Dumper(\@_); | 
| 563 | 0 |  |  |  |  |  | &$cb0; | 
| 564 |  |  |  |  |  |  | }; | 
| 565 |  |  |  |  |  |  | } | 
| 566 |  |  |  |  |  |  |  | 
| 567 |  |  |  |  |  |  | recv_packet($hd, sub { | 
| 568 | 0 |  |  | 0 |  |  | my $head = substr($_[0], 0, 1); | 
| 569 | 0 | 0 |  |  |  |  | if( $head eq "\x00" ) { # OK | 
|  |  | 0 |  |  |  |  |  | 
| 570 | 0 |  |  |  |  |  | substr($_[0], 0, 1, ''); | 
| 571 | 0 | 0 |  |  |  |  | if( $opt{prepare} ) { | 
| 572 | 0 |  |  |  |  |  | my $stmt_id = take_num($_[0], 4); | 
| 573 | 0 |  |  |  |  |  | my $column_count = take_num($_[0], 2); | 
| 574 | 0 |  |  |  |  |  | my $param_count = take_num($_[0], 2); | 
| 575 | 0 |  |  |  |  |  | take_filler($_[0], 1); | 
| 576 | 0 |  |  |  |  |  | my $warning_count = take_num($_[0], 2); | 
| 577 | 0 |  |  |  |  |  | warn "stmt_id=$stmt_id, column_count=$column_count, param_count=$param_count, warning_count=$warning_count" if DEV; | 
| 578 |  |  |  |  |  |  |  | 
| 579 | 0 |  |  |  |  |  | my(@param, @column); | 
| 580 |  |  |  |  |  |  |  | 
| 581 |  |  |  |  |  |  | my $end_cv = AE::cv { | 
| 582 | 0 |  |  |  |  |  | $cb->(RES_PREPARE, $stmt_id, \@param, \@column, $warning_count); | 
| 583 | 0 |  |  |  |  |  | }; | 
| 584 |  |  |  |  |  |  |  | 
| 585 | 0 |  |  |  |  |  | $end_cv->begin; | 
| 586 |  |  |  |  |  |  |  | 
| 587 | 0 | 0 |  |  |  |  | if( $param_count ) { | 
| 588 | 0 |  |  |  |  |  | $end_cv->begin; | 
| 589 | 0 |  |  |  |  |  | for(my $i=0; $i<$param_count; ++$i) { | 
| 590 | 0 |  |  |  |  |  | _recv_field($hd, \@param); | 
| 591 |  |  |  |  |  |  | } | 
| 592 | 0 |  |  |  |  |  | recv_packet($hd, sub { $end_cv->end }); # EOF | 
|  | 0 |  |  |  |  |  |  | 
| 593 |  |  |  |  |  |  | } | 
| 594 |  |  |  |  |  |  |  | 
| 595 | 0 | 0 |  |  |  |  | if( $column_count ) { | 
| 596 | 0 |  |  |  |  |  | $end_cv->begin; | 
| 597 | 0 |  |  |  |  |  | for(my $i=0; $i<$column_count; ++$i) { | 
| 598 | 0 |  |  |  |  |  | _recv_field($hd, \@column); | 
| 599 |  |  |  |  |  |  | } | 
| 600 | 0 |  |  |  |  |  | recv_packet($hd, sub { $end_cv->end }); # EOF | 
|  | 0 |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | } | 
| 602 |  |  |  |  |  |  |  | 
| 603 | 0 |  |  |  |  |  | $end_cv->end; | 
| 604 |  |  |  |  |  |  | } | 
| 605 |  |  |  |  |  |  | else { | 
| 606 | 0 |  |  |  |  |  | $cb->( | 
| 607 |  |  |  |  |  |  | RES_OK, | 
| 608 |  |  |  |  |  |  | take_lcb($_[0]), | 
| 609 |  |  |  |  |  |  | take_lcb($_[0]), | 
| 610 |  |  |  |  |  |  | take_num($_[0], 2), | 
| 611 |  |  |  |  |  |  | take_num($_[0], 2), | 
| 612 |  |  |  |  |  |  | $_[0], | 
| 613 |  |  |  |  |  |  | ); | 
| 614 |  |  |  |  |  |  | } | 
| 615 |  |  |  |  |  |  | } | 
| 616 |  |  |  |  |  |  | elsif( $head eq "\xFF" ) { # Error | 
| 617 | 0 |  |  |  |  |  | substr($_[0], 0, 1, ''); | 
| 618 | 0 | 0 |  |  |  |  | $cb->( | 
| 619 |  |  |  |  |  |  | RES_ERROR, | 
| 620 |  |  |  |  |  |  | take_num($_[0], 2), | 
| 621 |  |  |  |  |  |  | ( substr($_[0], 0, 1) eq '#' ? | 
| 622 |  |  |  |  |  |  | ( substr($_[0], 1, 5), substr($_[0], 6) ) : # ver 4.1 | 
| 623 |  |  |  |  |  |  | ( undef, $_[0] )                            # ver 4.0 | 
| 624 |  |  |  |  |  |  | ) | 
| 625 |  |  |  |  |  |  | ); | 
| 626 |  |  |  |  |  |  | } | 
| 627 |  |  |  |  |  |  | else { # Others (EOF shouldn't be here) | 
| 628 | 0 |  |  |  |  |  | my $field_count = take_lcb($_[0]); | 
| 629 | 0 | 0 |  |  |  |  | my $extra = $_[0] eq '' ? undef : take_lcb($_[0]); | 
| 630 |  |  |  |  |  |  |  | 
| 631 | 0 |  |  |  |  |  | warn "field_count=$field_count" if DEV; | 
| 632 |  |  |  |  |  |  |  | 
| 633 | 0 |  |  |  |  |  | my @field; | 
| 634 | 0 |  |  |  |  |  | for(my $i=0; $i<$field_count; ++$i) { | 
| 635 | 0 |  |  |  |  |  | _recv_field($hd, \@field); | 
| 636 |  |  |  |  |  |  | } | 
| 637 | 0 |  |  |  |  |  | recv_packet($hd, sub{ warn "got EOF" if DEV }); # EOF | 
|  | 0 |  |  |  |  |  |  | 
| 638 |  |  |  |  |  |  |  | 
| 639 | 0 |  |  |  |  |  | my @row; | 
| 640 |  |  |  |  |  |  | my $fetch_row; $fetch_row = sub { # text format | 
| 641 | 0 |  |  |  |  |  | warn "get row." if DEV; | 
| 642 |  |  |  |  |  |  | recv_packet($hd, sub { | 
| 643 | 0 | 0 |  |  |  |  | if( substr($_[0], 0, 1) eq "\xFE" ) { # EOF | 
| 644 | 0 |  |  |  |  |  | warn "got EOF!" if DEV; | 
| 645 | 0 |  |  |  |  |  | undef $fetch_row; | 
| 646 | 0 |  |  |  |  |  | $cb->( | 
| 647 |  |  |  |  |  |  | RES_RESULT, | 
| 648 |  |  |  |  |  |  | \@field, | 
| 649 |  |  |  |  |  |  | \@row, | 
| 650 |  |  |  |  |  |  | ); | 
| 651 |  |  |  |  |  |  | } | 
| 652 |  |  |  |  |  |  | else { | 
| 653 | 0 |  |  |  |  |  | warn "got row!" if DEV; | 
| 654 | 0 |  |  |  |  |  | my @cell; | 
| 655 | 0 | 0 |  |  |  |  | if( $opt{execute} ) { | 
| 656 | 0 |  |  |  |  |  | take_filler($_[0], 1); | 
| 657 | 0 |  |  |  |  |  | my $null_bit_map = substr($_[0], 0, $field_count + 9 >> 3, ''); | 
| 658 | 0 |  |  |  |  |  | for(my $i=0; $i<$field_count; ++$i) { | 
| 659 | 0 | 0 |  |  |  |  | if( vec($null_bit_map, 2+$i, 1) ) { | 
| 660 | 0 |  |  |  |  |  | push @cell, undef; | 
| 661 |  |  |  |  |  |  | } | 
| 662 |  |  |  |  |  |  | else { | 
| 663 | 0 |  |  |  |  |  | push @cell, take_type($_[0], $field[$i][8], $field[$i][7], $field[$i][9]); | 
| 664 |  |  |  |  |  |  | } | 
| 665 |  |  |  |  |  |  | } | 
| 666 |  |  |  |  |  |  | } | 
| 667 |  |  |  |  |  |  | else { | 
| 668 | 0 |  |  |  |  |  | for(my $i=0; $i<$field_count; ++$i) { | 
| 669 | 0 |  |  |  |  |  | push @cell, take_lcs($_[0]); | 
| 670 |  |  |  |  |  |  | } | 
| 671 |  |  |  |  |  |  | } | 
| 672 | 0 |  |  |  |  |  | push @row, \@cell; | 
| 673 | 0 |  |  |  |  |  | $fetch_row->(); | 
| 674 |  |  |  |  |  |  | } | 
| 675 | 0 |  |  |  |  |  | }); | 
| 676 | 0 |  |  |  |  |  | }; | 
| 677 | 0 |  |  |  |  |  | $fetch_row->(); | 
| 678 |  |  |  |  |  |  | } | 
| 679 | 0 |  |  |  |  |  | }); | 
| 680 |  |  |  |  |  |  | } | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | =head2 do_auth($hd, $username, [$password, [$database,]] $cb->($success, $err_num_and_msg, $thread_id)) | 
| 683 |  |  |  |  |  |  | =cut | 
| 684 |  |  |  |  |  |  | sub do_auth { | 
| 685 | 0 | 0 |  | 0 | 1 |  | my $cb = ref($_[-1]) eq 'CODE' ? pop : sub {}; | 
|  |  |  |  | 0 |  |  |  | 
| 686 | 0 |  |  |  |  |  | my($hd, $username, $password, $database) = @_; | 
| 687 |  |  |  |  |  |  |  | 
| 688 |  |  |  |  |  |  | recv_packet($hd, sub { | 
| 689 | 0 |  |  | 0 |  |  | if( DEV ) { | 
| 690 |  |  |  |  |  |  | my $hex = $_[0]; | 
| 691 |  |  |  |  |  |  | $hex =~ s/(.)/sprintf"%02X ",ord$1/ges; | 
| 692 |  |  |  |  |  |  | my $ascii = $_[0]; | 
| 693 |  |  |  |  |  |  | $ascii =~ s/([^\x20-\x7E])/./g; | 
| 694 |  |  |  |  |  |  | warn $hex, $ascii; | 
| 695 |  |  |  |  |  |  | } | 
| 696 | 0 |  |  |  |  |  | my $proto_ver = take_num($_[0], 1); warn "proto_ver:$proto_ver" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 697 | 0 |  |  |  |  |  | my $server_ver = take_zstr($_[0]); warn "server_ver:$server_ver" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 698 | 0 |  |  |  |  |  | my $thread_id = take_num($_[0], 4); warn "thread_id:$thread_id" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 699 | 0 |  |  |  |  |  | my $scramble_buff = take_str($_[0], 8).substr($_[0], 19, 12); warn "scramble_buff:$scramble_buff" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 700 | 0 |  |  |  |  |  | my $filler = take_num($_[0], 1); warn "filler:$filler" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 701 | 0 |  |  |  |  |  | my $server_cap = take_num($_[0], 2); | 
| 702 | 0 |  |  |  |  |  | my $server_lang = take_num($_[0], 1); warn "server_lang:$server_lang" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 703 | 0 |  |  |  |  |  | my $server_status = take_num($_[0], 2); warn "server_status:$server_status" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 704 | 0 |  |  |  |  |  | $server_cap += take_num($_[0], 2) << 16; | 
| 705 | 0 |  |  |  |  |  | if( DEV ) { | 
| 706 |  |  |  |  |  |  | warn "server_cap:"; | 
| 707 |  |  |  |  |  |  | warn "  CLIENT_LONG_PASSWORD" if( $server_cap & CLIENT_LONG_PASSWORD ); | 
| 708 |  |  |  |  |  |  | warn "  CLIENT_FOUND_ROWS" if( $server_cap & CLIENT_FOUND_ROWS ); | 
| 709 |  |  |  |  |  |  | warn "  CLIENT_LONG_FLAG" if( $server_cap & CLIENT_LONG_FLAG ); | 
| 710 |  |  |  |  |  |  | warn "  CLIENT_CONNECT_WITH_DB" if( $server_cap & CLIENT_CONNECT_WITH_DB ); | 
| 711 |  |  |  |  |  |  | warn "  CLIENT_NO_SCHEMA" if( $server_cap & CLIENT_NO_SCHEMA ); | 
| 712 |  |  |  |  |  |  | warn "  CLIENT_COMPRESS" if( $server_cap & CLIENT_COMPRESS ); | 
| 713 |  |  |  |  |  |  | warn "  CLIENT_ODBC" if( $server_cap & CLIENT_ODBC ); | 
| 714 |  |  |  |  |  |  | warn "  CLIENT_LOCAL_FILES" if( $server_cap & CLIENT_LOCAL_FILES ); | 
| 715 |  |  |  |  |  |  | warn "  CLIENT_IGNORE_SPACE" if( $server_cap & CLIENT_IGNORE_SPACE ); | 
| 716 |  |  |  |  |  |  | warn "  CLIENT_PROTOCOL_41" if( $server_cap & CLIENT_PROTOCOL_41 ); | 
| 717 |  |  |  |  |  |  | warn "  CLIENT_INTERACTIVE" if( $server_cap & CLIENT_INTERACTIVE ); | 
| 718 |  |  |  |  |  |  | warn "  CLIENT_SSL" if( $server_cap & CLIENT_SSL ); | 
| 719 |  |  |  |  |  |  | warn "  CLIENT_IGNORE_SIGPIPE" if( $server_cap & CLIENT_IGNORE_SIGPIPE ); | 
| 720 |  |  |  |  |  |  | warn "  CLIENT_TRANSACTIONS" if( $server_cap & CLIENT_TRANSACTIONS ); | 
| 721 |  |  |  |  |  |  | warn "  CLIENT_RESERVED" if( $server_cap & CLIENT_RESERVED ); | 
| 722 |  |  |  |  |  |  | warn "  CLIENT_SECURE_CONNECTION" if( $server_cap & CLIENT_SECURE_CONNECTION ); | 
| 723 |  |  |  |  |  |  | warn "  CLIENT_MULTI_STATEMENTS" if( $server_cap & CLIENT_MULTI_STATEMENTS ); | 
| 724 |  |  |  |  |  |  | warn "  CLIENT_MULTI_RESULTS" if( $server_cap & CLIENT_MULTI_RESULTS ); | 
| 725 |  |  |  |  |  |  | } | 
| 726 | 0 |  |  |  |  |  | my $scramble_len = take_num($_[0], 1); warn "scramble_len:$scramble_len" if DEV; | 
|  | 0 |  |  |  |  |  |  | 
| 727 |  |  |  |  |  |  |  | 
| 728 | 0 |  |  |  |  |  | my $packet = ''; | 
| 729 | 0 |  |  |  |  |  | put_num($packet, $server_cap & ( | 
| 730 |  |  |  |  |  |  | CLIENT_LONG_PASSWORD     | # new more secure passwords | 
| 731 |  |  |  |  |  |  | CLIENT_FOUND_ROWS        | # Found instead of affected rows | 
| 732 |  |  |  |  |  |  | CLIENT_LONG_FLAG         | # Get all column flags | 
| 733 |  |  |  |  |  |  | CLIENT_CONNECT_WITH_DB   | # One can specify db on connect | 
| 734 |  |  |  |  |  |  | # CLIENT_NO_SCHEMA         | # Don't allow database.table.column | 
| 735 |  |  |  |  |  |  | # CLIENT_COMPRESS          | # Can use compression protocol | 
| 736 |  |  |  |  |  |  | # CLIENT_ODBC              | # Odbc client | 
| 737 |  |  |  |  |  |  | # CLIENT_LOCAL_FILES       | # Can use LOAD DATA LOCAL | 
| 738 |  |  |  |  |  |  | # CLIENT_IGNORE_SPACE      | # Ignore spaces before '(' | 
| 739 |  |  |  |  |  |  | CLIENT_PROTOCOL_41       | # New 4.1 protocol | 
| 740 |  |  |  |  |  |  | # CLIENT_INTERACTIVE       | # This is an interactive client | 
| 741 |  |  |  |  |  |  | # CLIENT_SSL               | # Switch to SSL after handshake | 
| 742 |  |  |  |  |  |  | # CLIENT_IGNORE_SIGPIPE    | # IGNORE sigpipes | 
| 743 |  |  |  |  |  |  | CLIENT_TRANSACTIONS      | # Client knows about transactions | 
| 744 |  |  |  |  |  |  | # CLIENT_RESERVED          | # Old flag for 4.1 protocol | 
| 745 |  |  |  |  |  |  | CLIENT_SECURE_CONNECTION | # New 4.1 authentication | 
| 746 |  |  |  |  |  |  | CLIENT_MULTI_STATEMENTS  | # Enable/disable multi-stmt support | 
| 747 |  |  |  |  |  |  | CLIENT_MULTI_RESULTS     | # Enable/disable multi-results | 
| 748 |  |  |  |  |  |  | 0 | 
| 749 |  |  |  |  |  |  | ), 4); # client_flags | 
| 750 | 0 |  |  |  |  |  | put_num($packet, 0x1000000, 4); # max_packet_size | 
| 751 | 0 |  |  |  |  |  | put_num($packet, $server_lang, 1); # charset_number | 
| 752 | 0 |  |  |  |  |  | $packet .= "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; # filler | 
| 753 | 0 |  |  |  |  |  | put_zstr($packet, $username); # username | 
| 754 | 0 | 0 |  |  |  |  | if( $password eq '' ) { | 
| 755 | 0 |  |  |  |  |  | put_lcs($packet, ''); | 
| 756 |  |  |  |  |  |  | } | 
| 757 |  |  |  |  |  |  | else { | 
| 758 | 0 |  |  |  |  |  | my $stage1_hash = sha1($password); | 
| 759 | 0 |  |  |  |  |  | put_lcs($packet, sha1($scramble_buff.sha1($stage1_hash)) ^ $stage1_hash); # scramble buff | 
| 760 |  |  |  |  |  |  | } | 
| 761 | 0 |  |  |  |  |  | put_zstr($packet, $database); # database name | 
| 762 |  |  |  |  |  |  |  | 
| 763 | 0 |  |  |  |  |  | send_packet($hd, 1, $packet); | 
| 764 |  |  |  |  |  |  | recv_packet($hd, sub { | 
| 765 | 0 | 0 |  |  |  |  | if( parse_ok($_[0]) ) { | 
| 766 | 0 |  |  |  |  |  | $cb->(1, undef, $thread_id); | 
| 767 |  |  |  |  |  |  | } | 
| 768 |  |  |  |  |  |  | else { | 
| 769 | 0 |  |  |  |  |  | my($errno, $sqlstate, $message) = parse_error($_[0]); | 
| 770 | 0 |  |  |  |  |  | warn "$errno [$sqlstate] $message" if DEV; | 
| 771 | 0 |  |  |  |  |  | $cb->(0, dualvar($errno, $message)); | 
| 772 |  |  |  |  |  |  | } | 
| 773 | 0 |  |  |  |  |  | }); | 
| 774 | 0 |  |  |  |  |  | }); | 
| 775 |  |  |  |  |  |  | } | 
| 776 |  |  |  |  |  |  |  | 
| 777 |  |  |  |  |  |  | =head2 do_reset_stmt($hd, $stmt_id) | 
| 778 |  |  |  |  |  |  | =cut | 
| 779 |  |  |  |  |  |  | sub do_reset_stmt { | 
| 780 | 0 |  |  | 0 | 1 |  | my $packet = ''; | 
| 781 | 0 |  |  |  |  |  | put_num($packet, $_[1], 4); | 
| 782 | 0 |  |  |  |  |  | send_packet($_[0], 0, COM_STMT_RESET, $packet); | 
| 783 |  |  |  |  |  |  | } | 
| 784 |  |  |  |  |  |  |  | 
| 785 |  |  |  |  |  |  | =head2 do_long_data_packet($hd, $stmt_id, $param_num, $type, $data, $len, $flag, $packet_num) | 
| 786 |  |  |  |  |  |  | =cut | 
| 787 |  |  |  |  |  |  | sub do_long_data_packet { | 
| 788 | 0 |  |  | 0 | 1 |  | my $packet = ''; | 
| 789 | 0 |  |  |  |  |  | put_num($packet, $_[1], 4); | 
| 790 | 0 |  |  |  |  |  | put_num($packet, $_[2], 2); | 
| 791 | 0 |  |  |  |  |  | put_num($packet, $_[3], 2); | 
| 792 | 0 |  |  |  |  |  | put_type($packet, $_[4], $_[3], $_[5], $_[6]); | 
| 793 | 0 |  |  |  |  |  | send_packet($_[0], $_[7], COM_STMT_SEND_LONG_DATA, $packet); | 
| 794 |  |  |  |  |  |  | } | 
| 795 |  |  |  |  |  |  |  | 
| 796 |  |  |  |  |  |  | =head2 do_execute($hd, $stmt_id, $null_bit_map, $packet_num) | 
| 797 |  |  |  |  |  |  | =cut | 
| 798 |  |  |  |  |  |  | sub do_execute { | 
| 799 | 0 |  |  | 0 | 1 |  | my $packet = ''; | 
| 800 | 0 |  |  |  |  |  | put_num($packet, $_[1], 4); | 
| 801 | 0 |  |  |  |  |  | $packet .= "\0\1\0\0\0"; | 
| 802 | 0 |  |  |  |  |  | $packet .= $_[2]; | 
| 803 | 0 |  |  |  |  |  | $packet .= "\0"; | 
| 804 | 0 |  |  |  |  |  | send_packet($_[0], $_[3], COM_STMT_EXECUTE, $packet); | 
| 805 |  |  |  |  |  |  | } | 
| 806 |  |  |  |  |  |  |  | 
| 807 |  |  |  |  |  |  | =head2 do_execute_param($hd, $stmt_id, \@param, \@param_config) | 
| 808 |  |  |  |  |  |  | =cut | 
| 809 |  |  |  |  |  |  | sub do_execute_param { | 
| 810 | 0 | 0 |  | 0 | 1 |  | my $null_bit_map = pack('b*', join '', map { defined($_) ? '0' : '1' } @{$_[2]}); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 811 | 0 |  |  |  |  |  | my $packet = ''; | 
| 812 | 0 |  |  |  |  |  | put_num($packet, $_[1], 4); | 
| 813 | 0 |  |  |  |  |  | $packet .= "\0\1\0\0\0"; | 
| 814 | 0 |  |  |  |  |  | $packet .= $null_bit_map; | 
| 815 | 0 |  |  |  |  |  | $packet .= "\1"; | 
| 816 | 0 |  |  |  |  |  | for(my $i=0; $i<@{$_[2]}; ++$i) { | 
|  | 0 |  |  |  |  |  |  | 
| 817 |  |  |  |  |  |  | #put_num($packet, $_[3][$i][8], 2); | 
| 818 | 0 |  |  |  |  |  | put_num($packet, MYSQL_TYPE_BLOB, 2); | 
| 819 |  |  |  |  |  |  | } | 
| 820 | 0 |  |  |  |  |  | for(my $i=0; $i<@{$_[2]}; ++$i) { | 
|  | 0 |  |  |  |  |  |  | 
| 821 | 0 | 0 |  |  |  |  | if( defined($_[2][$i]) ) { | 
| 822 |  |  |  |  |  |  | #put_type($packet, $_[2][$i], $_[3][$i][8], $_[3][$i][7], $_[3][$i][9]); | 
| 823 | 0 |  |  |  |  |  | put_type($packet, $_[2][$i], MYSQL_TYPE_BLOB, length($_[2][$i]), $_[3][$i][9]); | 
| 824 |  |  |  |  |  |  | } | 
| 825 |  |  |  |  |  |  | } | 
| 826 | 0 |  |  |  |  |  | send_packet($_[0], 0, COM_STMT_EXECUTE, $packet); | 
| 827 |  |  |  |  |  |  | } | 
| 828 |  |  |  |  |  |  |  | 
| 829 |  |  |  |  |  |  | 1; |