├── .gitignore ├── Makefile ├── README.md ├── dist.ini └── lib └── resty ├── mysql ├── const.lua ├── packet.lua └── proxy.lua └── test.lua /.gitignore: -------------------------------------------------------------------------------- 1 | t/servroot 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OPENRESTY_PREFIX=/usr/local/openresty 2 | 3 | PREFIX ?= /usr/local 4 | LUA_INCLUDE_DIR ?= $(PREFIX)/include 5 | LUA_LIB_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION) 6 | INSTALL ?= install 7 | 8 | .PHONY: all test install 9 | 10 | all: ; 11 | 12 | install: all 13 | $(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/resty/ 14 | $(INSTALL) lib/resty/*.lua $(DESTDIR)/$(LUA_LIB_DIR)/resty/ 15 | 16 | test: all 17 | util/lua-releng 18 | PATH=$(OPENRESTY_PREFIX)/nginx/sbin:$$PATH prove -I../test-nginx/lib -r t/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # work-in-progress 2 | 3 | Name 4 | ==== 5 | 6 | lua-resty-mysql-toolset - Lua mysql client and server toolset based on openresty/lua-resty-mysql 7 | 8 | Table of Contents 9 | ================= 10 | * [Name](#name) 11 | * [Status](#status) 12 | * [Synopsis](#synopsis) 13 | 14 | Status 15 | ====== 16 | 17 | This library is still in its early stages of development. 18 | 19 | 20 | Synopsis 21 | ======== 22 | 23 | ``` 24 | stream { 25 | server { 26 | -- mysql proxy listen on 1234 27 | -- user: runner 28 | -- password: runner123456 29 | listen 1234; 30 | content_by_lua_block { 31 | local proxy = require "resty.mysql.proxy" 32 | local conn, err = proxy:new({user="runner", password="runner123456"}) 33 | if err then 34 | return 35 | end 36 | err = conn:handshake() 37 | if err then 38 | return 39 | end 40 | conn:process() 41 | } 42 | } 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | name=lua-resty-mysql-toolset 2 | abstract=Lua mysql client and server toolset based on openresty/lua-resty-mysql 3 | author= huangnauh huanglibo2010@gmail.com 4 | is_original=yes 5 | license=2bsd 6 | lib_dir=lib 7 | repo_link=https://github.com/huangnauh/lua-resty-mysql-toolset 8 | requires = luajit >= 2.1.0, ngx_http_lua >= 0.10.6 -------------------------------------------------------------------------------- /lib/resty/mysql/const.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2017 Libo Huang (huangnauh), UPYUN Inc. 2 | local bit = require "bit" 3 | local bor = bit.bor 4 | 5 | local _M = { _VERSION = '0.01' } 6 | 7 | _M.ERROR = { 8 | ER_ERROR_FIRST = 1000, 9 | ER_HASHCHK = 1000, 10 | ER_NISAMCHK = 1001, 11 | ER_NO = 1002, 12 | ER_YES = 1003, 13 | ER_CANT_CREATE_FILE = 1004, 14 | ER_CANT_CREATE_TABLE = 1005, 15 | ER_CANT_CREATE_DB = 1006, 16 | ER_DB_CREATE_EXISTS = 1007, 17 | ER_DB_DROP_EXISTS = 1008, 18 | ER_DB_DROP_DELETE = 1009, 19 | ER_DB_DROP_RMDIR = 1010, 20 | ER_CANT_DELETE_FILE = 1011, 21 | ER_CANT_FIND_SYSTEM_REC = 1012, 22 | ER_CANT_GET_STAT = 1013, 23 | ER_CANT_GET_WD = 1014, 24 | ER_CANT_LOCK = 1015, 25 | ER_CANT_OPEN_FILE = 1016, 26 | ER_FILE_NOT_FOUND = 1017, 27 | ER_CANT_READ_DIR = 1018, 28 | ER_CANT_SET_WD = 1019, 29 | ER_CHECKREAD = 1020, 30 | ER_DISK_FULL = 1021, 31 | ER_DUP_KEY = 1022, 32 | ER_ERROR_ON_CLOSE = 1023, 33 | ER_ERROR_ON_READ = 1024, 34 | ER_ERROR_ON_RENAME = 1025, 35 | ER_ERROR_ON_WRITE = 1026, 36 | ER_FILE_USED = 1027, 37 | ER_FILSORT_ABORT = 1028, 38 | ER_FORM_NOT_FOUND = 1029, 39 | ER_GET_ERRNO = 1030, 40 | ER_ILLEGAL_HA = 1031, 41 | ER_KEY_NOT_FOUND = 1032, 42 | ER_NOT_FORM_FILE = 1033, 43 | ER_NOT_KEYFILE = 1034, 44 | ER_OLD_KEYFILE = 1035, 45 | ER_OPEN_AS_READONLY = 1036, 46 | ER_OUTOFMEMORY = 1037, 47 | ER_OUT_OF_SORTMEMORY = 1038, 48 | ER_UNEXPECTED_EOF = 1039, 49 | ER_CON_COUNT_ERROR = 1040, 50 | ER_OUT_OF_RESOURCES = 1041, 51 | ER_BAD_HOST_ERROR = 1042, 52 | ER_HANDSHAKE_ERROR = 1043, 53 | ER_DBACCESS_DENIED_ERROR = 1044, 54 | ER_ACCESS_DENIED_ERROR = 1045, 55 | ER_NO_DB_ERROR = 1046, 56 | ER_UNKNOWN_COM_ERROR = 1047, 57 | ER_BAD_NULL_ERROR = 1048, 58 | ER_BAD_DB_ERROR = 1049, 59 | ER_TABLE_EXISTS_ERROR = 1050, 60 | ER_BAD_TABLE_ERROR = 1051, 61 | ER_NON_UNIQ_ERROR = 1052, 62 | ER_SERVER_SHUTDOWN = 1053, 63 | ER_BAD_FIELD_ERROR = 1054, 64 | ER_WRONG_FIELD_WITH_GROUP = 1055, 65 | ER_WRONG_GROUP_FIELD = 1056, 66 | ER_WRONG_SUM_SELECT = 1057, 67 | ER_WRONG_VALUE_COUNT = 1058, 68 | ER_TOO_LONG_IDENT = 1059, 69 | ER_DUP_FIELDNAME = 1060, 70 | ER_DUP_KEYNAME = 1061, 71 | ER_DUP_ENTRY = 1062, 72 | ER_WRONG_FIELD_SPEC = 1063, 73 | ER_PARSE_ERROR = 1064, 74 | ER_EMPTY_QUERY = 1065, 75 | ER_NONUNIQ_TABLE = 1066, 76 | ER_INVALID_DEFAULT = 1067, 77 | ER_MULTIPLE_PRI_KEY = 1068, 78 | ER_TOO_MANY_KEYS = 1069, 79 | ER_TOO_MANY_KEY_PARTS = 1070, 80 | ER_TOO_LONG_KEY = 1071, 81 | ER_KEY_COLUMN_DOES_NOT_EXITS = 1072, 82 | ER_BLOB_USED_AS_KEY = 1073, 83 | ER_TOO_BIG_FIELDLENGTH = 1074, 84 | ER_WRONG_AUTO_KEY = 1075, 85 | ER_READY = 1076, 86 | ER_NORMAL_SHUTDOWN = 1077, 87 | ER_GOT_SIGNAL = 1078, 88 | ER_SHUTDOWN_COMPLETE = 1079, 89 | ER_FORCING_CLOSE = 1080, 90 | ER_IPSOCK_ERROR = 1081, 91 | ER_NO_SUCH_INDEX = 1082, 92 | ER_WRONG_FIELD_TERMINATORS = 1083, 93 | ER_BLOBS_AND_NO_TERMINATED = 1084, 94 | ER_TEXTFILE_NOT_READABLE = 1085, 95 | ER_FILE_EXISTS_ERROR = 1086, 96 | ER_LOAD_INFO = 1087, 97 | ER_ALTER_INFO = 1088, 98 | ER_WRONG_SUB_KEY = 1089, 99 | ER_CANT_REMOVE_ALL_FIELDS = 1090, 100 | ER_CANT_DROP_FIELD_OR_KEY = 1091, 101 | ER_INSERT_INFO = 1092, 102 | ER_UPDATE_TABLE_USED = 1093, 103 | ER_NO_SUCH_THREAD = 1094, 104 | ER_KILL_DENIED_ERROR = 1095, 105 | ER_NO_TABLES_USED = 1096, 106 | ER_TOO_BIG_SET = 1097, 107 | ER_NO_UNIQUE_LOGFILE = 1098, 108 | ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099, 109 | ER_TABLE_NOT_LOCKED = 1100, 110 | ER_BLOB_CANT_HAVE_DEFAULT = 1101, 111 | ER_WRONG_DB_NAME = 1102, 112 | ER_WRONG_TABLE_NAME = 1103, 113 | ER_TOO_BIG_SELECT = 1104, 114 | ER_UNKNOWN_ERROR = 1105, 115 | ER_UNKNOWN_PROCEDURE = 1106, 116 | ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107, 117 | ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108, 118 | ER_UNKNOWN_TABLE = 1109, 119 | ER_FIELD_SPECIFIED_TWICE = 1110, 120 | ER_INVALID_GROUP_FUNC_USE = 1111, 121 | ER_UNSUPPORTED_EXTENSION = 1112, 122 | ER_TABLE_MUST_HAVE_COLUMNS = 1113, 123 | ER_RECORD_FILE_FULL = 1114, 124 | ER_UNKNOWN_CHARACTER_SET = 1115, 125 | ER_TOO_MANY_TABLES = 1116, 126 | ER_TOO_MANY_FIELDS = 1117, 127 | ER_TOO_BIG_ROWSIZE = 1118, 128 | ER_STACK_OVERRUN = 1119, 129 | ER_WRONG_OUTER_JOIN = 1120, 130 | ER_NULL_COLUMN_IN_INDEX = 1121, 131 | ER_CANT_FIND_UDF = 1122, 132 | ER_CANT_INITIALIZE_UDF = 1123, 133 | ER_UDF_NO_PATHS = 1124, 134 | ER_UDF_EXISTS = 1125, 135 | ER_CANT_OPEN_LIBRARY = 1126, 136 | ER_CANT_FIND_DL_ENTRY = 1127, 137 | ER_FUNCTION_NOT_DEFINED = 1128, 138 | ER_HOST_IS_BLOCKED = 1129, 139 | ER_HOST_NOT_PRIVILEGED = 1130, 140 | ER_PASSWORD_ANONYMOUS_USER = 1131, 141 | ER_PASSWORD_NOT_ALLOWED = 1132, 142 | ER_PASSWORD_NO_MATCH = 1133, 143 | ER_UPDATE_INFO = 1134, 144 | ER_CANT_CREATE_THREAD = 1135, 145 | ER_WRONG_VALUE_COUNT_ON_ROW = 1136, 146 | ER_CANT_REOPEN_TABLE = 1137, 147 | ER_INVALID_USE_OF_NULL = 1138, 148 | ER_REGEXP_ERROR = 1139, 149 | ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140, 150 | ER_NONEXISTING_GRANT = 1141, 151 | ER_TABLEACCESS_DENIED_ERROR = 1142, 152 | ER_COLUMNACCESS_DENIED_ERROR = 1143, 153 | ER_ILLEGAL_GRANT_FOR_TABLE = 1144, 154 | ER_GRANT_WRONG_HOST_OR_USER = 1145, 155 | ER_NO_SUCH_TABLE = 1146, 156 | ER_NONEXISTING_TABLE_GRANT = 1147, 157 | ER_NOT_ALLOWED_COMMAND = 1148, 158 | ER_SYNTAX_ERROR = 1149, 159 | ER_DELAYED_CANT_CHANGE_LOCK = 1150, 160 | ER_TOO_MANY_DELAYED_THREADS = 1151, 161 | ER_ABORTING_CONNECTION = 1152, 162 | ER_NET_PACKET_TOO_LARGE = 1153, 163 | ER_NET_READ_ERROR_FROM_PIPE = 1154, 164 | ER_NET_FCNTL_ERROR = 1155, 165 | ER_NET_PACKETS_OUT_OF_ORDER = 1156, 166 | ER_NET_UNCOMPRESS_ERROR = 1157, 167 | ER_NET_READ_ERROR = 1158, 168 | ER_NET_READ_INTERRUPTED = 1159, 169 | ER_NET_ERROR_ON_WRITE = 1160, 170 | ER_NET_WRITE_INTERRUPTED = 1161, 171 | ER_TOO_LONG_STRING = 1162, 172 | ER_TABLE_CANT_HANDLE_BLOB = 1163, 173 | ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164, 174 | ER_DELAYED_INSERT_TABLE_LOCKED = 1165, 175 | ER_WRONG_COLUMN_NAME = 1166, 176 | ER_WRONG_KEY_COLUMN = 1167, 177 | ER_WRONG_MRG_TABLE = 1168, 178 | ER_DUP_UNIQUE = 1169, 179 | ER_BLOB_KEY_WITHOUT_LENGTH = 1170, 180 | ER_PRIMARY_CANT_HAVE_NULL = 1171, 181 | ER_TOO_MANY_ROWS = 1172, 182 | ER_REQUIRES_PRIMARY_KEY = 1173, 183 | ER_NO_RAID_COMPILED = 1174, 184 | ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175, 185 | ER_KEY_DOES_NOT_EXITS = 1176, 186 | ER_CHECK_NO_SUCH_TABLE = 1177, 187 | ER_CHECK_NOT_IMPLEMENTED = 1178, 188 | ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179, 189 | ER_ERROR_DURING_COMMIT = 1180, 190 | ER_ERROR_DURING_ROLLBACK = 1181, 191 | ER_ERROR_DURING_FLUSH_LOGS = 1182, 192 | ER_ERROR_DURING_CHECKPOINT = 1183, 193 | ER_NEW_ABORTING_CONNECTION = 1184, 194 | ER_DUMP_NOT_IMPLEMENTED = 1185, 195 | ER_FLUSH_MASTER_BINLOG_CLOSED = 1186, 196 | ER_INDEX_REBUILD = 1187, 197 | ER_MASTER = 1188, 198 | ER_MASTER_NET_READ = 1189, 199 | ER_MASTER_NET_WRITE = 1190, 200 | ER_FT_MATCHING_KEY_NOT_FOUND = 1191, 201 | ER_LOCK_OR_ACTIVE_TRANSACTION = 1192, 202 | ER_UNKNOWN_SYSTEM_VARIABLE = 1193, 203 | ER_CRASHED_ON_USAGE = 1194, 204 | ER_CRASHED_ON_REPAIR = 1195, 205 | ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196, 206 | ER_TRANS_CACHE_FULL = 1197, 207 | ER_SLAVE_MUST_STOP = 1198, 208 | ER_SLAVE_NOT_RUNNING = 1199, 209 | ER_BAD_SLAVE = 1200, 210 | ER_MASTER_INFO = 1201, 211 | ER_SLAVE_THREAD = 1202, 212 | ER_TOO_MANY_USER_CONNECTIONS = 1203, 213 | ER_SET_CONSTANTS_ONLY = 1204, 214 | ER_LOCK_WAIT_TIMEOUT = 1205, 215 | ER_LOCK_TABLE_FULL = 1206, 216 | ER_READ_ONLY_TRANSACTION = 1207, 217 | ER_DROP_DB_WITH_READ_LOCK = 1208, 218 | ER_CREATE_DB_WITH_READ_LOCK = 1209, 219 | ER_WRONG_ARGUMENTS = 1210, 220 | ER_NO_PERMISSION_TO_CREATE_USER = 1211, 221 | ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212, 222 | ER_LOCK_DEADLOCK = 1213, 223 | ER_TABLE_CANT_HANDLE_FT = 1214, 224 | ER_CANNOT_ADD_FOREIGN = 1215, 225 | ER_NO_REFERENCED_ROW = 1216, 226 | ER_ROW_IS_REFERENCED = 1217, 227 | ER_CONNECT_TO_MASTER = 1218, 228 | ER_QUERY_ON_MASTER = 1219, 229 | ER_ERROR_WHEN_EXECUTING_COMMAND = 1220, 230 | ER_WRONG_USAGE = 1221, 231 | ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222, 232 | ER_CANT_UPDATE_WITH_READLOCK = 1223, 233 | ER_MIXING_NOT_ALLOWED = 1224, 234 | ER_DUP_ARGUMENT = 1225, 235 | ER_USER_LIMIT_REACHED = 1226, 236 | ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227, 237 | ER_LOCAL_VARIABLE = 1228, 238 | ER_GLOBAL_VARIABLE = 1229, 239 | ER_NO_DEFAULT = 1230, 240 | ER_WRONG_VALUE_FOR_VAR = 1231, 241 | ER_WRONG_TYPE_FOR_VAR = 1232, 242 | ER_VAR_CANT_BE_READ = 1233, 243 | ER_CANT_USE_OPTION_HERE = 1234, 244 | ER_NOT_SUPPORTED_YET = 1235, 245 | ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236, 246 | ER_SLAVE_IGNORED_TABLE = 1237, 247 | ER_INCORRECT_GLOBAL_LOCAL_VAR = 1238, 248 | ER_WRONG_FK_DEF = 1239, 249 | ER_KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240, 250 | ER_OPERAND_COLUMNS = 1241, 251 | ER_SUBQUERY_NO_1_ROW = 1242, 252 | ER_UNKNOWN_STMT_HANDLER = 1243, 253 | ER_CORRUPT_HELP_DB = 1244, 254 | ER_CYCLIC_REFERENCE = 1245, 255 | ER_AUTO_CONVERT = 1246, 256 | ER_ILLEGAL_REFERENCE = 1247, 257 | ER_DERIVED_MUST_HAVE_ALIAS = 1248, 258 | ER_SELECT_REDUCED = 1249, 259 | ER_TABLENAME_NOT_ALLOWED_HERE = 1250, 260 | ER_NOT_SUPPORTED_AUTH_MODE = 1251, 261 | ER_SPATIAL_CANT_HAVE_NULL = 1252, 262 | ER_COLLATION_CHARSET_MISMATCH = 1253, 263 | ER_SLAVE_WAS_RUNNING = 1254, 264 | ER_SLAVE_WAS_NOT_RUNNING = 1255, 265 | ER_TOO_BIG_FOR_UNCOMPRESS = 1256, 266 | ER_ZLIB_Z_MEM_ERROR = 1257, 267 | ER_ZLIB_Z_BUF_ERROR = 1258, 268 | ER_ZLIB_Z_DATA_ERROR = 1259, 269 | ER_CUT_VALUE_GROUP_CONCAT = 1260, 270 | ER_WARN_TOO_FEW_RECORDS = 1261, 271 | ER_WARN_TOO_MANY_RECORDS = 1262, 272 | ER_WARN_NULL_TO_NOTNULL = 1263, 273 | ER_WARN_DATA_OUT_OF_RANGE = 1264, 274 | WARN_DATA_TRUNCATED = 1265, 275 | ER_WARN_USING_OTHER_HANDLER = 1266, 276 | ER_CANT_AGGREGATE_2COLLATIONS = 1267, 277 | ER_DROP_USER = 1268, 278 | ER_REVOKE_GRANTS = 1269, 279 | ER_CANT_AGGREGATE_3COLLATIONS = 1270, 280 | ER_CANT_AGGREGATE_NCOLLATIONS = 1271, 281 | ER_VARIABLE_IS_NOT_STRUCT = 1272, 282 | ER_UNKNOWN_COLLATION = 1273, 283 | ER_SLAVE_IGNORED_SSL_PARAMS = 1274, 284 | ER_SERVER_IS_IN_SECURE_AUTH_MODE = 1275, 285 | ER_WARN_FIELD_RESOLVED = 1276, 286 | ER_BAD_SLAVE_UNTIL_COND = 1277, 287 | ER_MISSING_SKIP_SLAVE = 1278, 288 | ER_UNTIL_COND_IGNORED = 1279, 289 | ER_WRONG_NAME_FOR_INDEX = 1280, 290 | ER_WRONG_NAME_FOR_CATALOG = 1281, 291 | ER_WARN_QC_RESIZE = 1282, 292 | ER_BAD_FT_COLUMN = 1283, 293 | ER_UNKNOWN_KEY_CACHE = 1284, 294 | ER_WARN_HOSTNAME_WONT_WORK = 1285, 295 | ER_UNKNOWN_STORAGE_ENGINE = 1286, 296 | ER_WARN_DEPRECATED_SYNTAX = 1287, 297 | ER_NON_UPDATABLE_TABLE = 1288, 298 | ER_FEATURE_DISABLED = 1289, 299 | ER_OPTION_PREVENTS_STATEMENT = 1290, 300 | ER_DUPLICATED_VALUE_IN_TYPE = 1291, 301 | ER_TRUNCATED_WRONG_VALUE = 1292, 302 | ER_TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293, 303 | ER_INVALID_ON_UPDATE = 1294, 304 | ER_UNSUPPORTED_PS = 1295, 305 | ER_GET_ERRMSG = 1296, 306 | ER_GET_TEMPORARY_ERRMSG = 1297, 307 | ER_UNKNOWN_TIME_ZONE = 1298, 308 | ER_WARN_INVALID_TIMESTAMP = 1299, 309 | ER_INVALID_CHARACTER_STRING = 1300, 310 | ER_WARN_ALLOWED_PACKET_OVERFLOWED = 1301, 311 | ER_CONFLICTING_DECLARATIONS = 1302, 312 | ER_SP_NO_RECURSIVE_CREATE = 1303, 313 | ER_SP_ALREADY_EXISTS = 1304, 314 | ER_SP_DOES_NOT_EXIST = 1305, 315 | ER_SP_DROP_FAILED = 1306, 316 | ER_SP_STORE_FAILED = 1307, 317 | ER_SP_LILABEL_MISMATCH = 1308, 318 | ER_SP_LABEL_REDEFINE = 1309, 319 | ER_SP_LABEL_MISMATCH = 1310, 320 | ER_SP_UNINIT_VAR = 1311, 321 | ER_SP_BADSELECT = 1312, 322 | ER_SP_BADRETURN = 1313, 323 | ER_SP_BADSTATEMENT = 1314, 324 | ER_UPDATE_LOG_DEPRECATED_IGNORED = 1315, 325 | ER_UPDATE_LOG_DEPRECATED_TRANSLATED = 1316, 326 | ER_QUERY_INTERRUPTED = 1317, 327 | ER_SP_WRONG_NO_OF_ARGS = 1318, 328 | ER_SP_COND_MISMATCH = 1319, 329 | ER_SP_NORETURN = 1320, 330 | ER_SP_NORETURNEND = 1321, 331 | ER_SP_BAD_CURSOR_QUERY = 1322, 332 | ER_SP_BAD_CURSOR_SELECT = 1323, 333 | ER_SP_CURSOR_MISMATCH = 1324, 334 | ER_SP_CURSOR_ALREADY_OPEN = 1325, 335 | ER_SP_CURSOR_NOT_OPEN = 1326, 336 | ER_SP_UNDECLARED_VAR = 1327, 337 | ER_SP_WRONG_NO_OF_FETCH_ARGS = 1328, 338 | ER_SP_FETCH_NO_DATA = 1329, 339 | ER_SP_DUP_PARAM = 1330, 340 | ER_SP_DUP_VAR = 1331, 341 | ER_SP_DUP_COND = 1332, 342 | ER_SP_DUP_CURS = 1333, 343 | ER_SP_CANT_ALTER = 1334, 344 | ER_SP_SUBSELECT_NYI = 1335, 345 | ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336, 346 | ER_SP_VARCOND_AFTER_CURSHNDLR = 1337, 347 | ER_SP_CURSOR_AFTER_HANDLER = 1338, 348 | ER_SP_CASE_NOT_FOUND = 1339, 349 | ER_FPARSER_TOO_BIG_FILE = 1340, 350 | ER_FPARSER_BAD_HEADER = 1341, 351 | ER_FPARSER_EOF_IN_COMMENT = 1342, 352 | ER_FPARSER_ERROR_IN_PARAMETER = 1343, 353 | ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344, 354 | ER_VIEW_NO_EXPLAIN = 1345, 355 | ER_FRM_UNKNOWN_TYPE = 1346, 356 | ER_WRONG_OBJECT = 1347, 357 | ER_NONUPDATEABLE_COLUMN = 1348, 358 | ER_VIEW_SELECT_DERIVED = 1349, 359 | ER_VIEW_SELECT_CLAUSE = 1350, 360 | ER_VIEW_SELECT_VARIABLE = 1351, 361 | ER_VIEW_SELECT_TMPTABLE = 1352, 362 | ER_VIEW_WRONG_LIST = 1353, 363 | ER_WARN_VIEW_MERGE = 1354, 364 | ER_WARN_VIEW_WITHOUT_KEY = 1355, 365 | ER_VIEW_INVALID = 1356, 366 | ER_SP_NO_DROP_SP = 1357, 367 | ER_SP_GOTO_IN_HNDLR = 1358, 368 | ER_TRG_ALREADY_EXISTS = 1359, 369 | ER_TRG_DOES_NOT_EXIST = 1360, 370 | ER_TRG_ON_VIEW_OR_TEMP_TABLE = 1361, 371 | ER_TRG_CANT_CHANGE_ROW = 1362, 372 | ER_TRG_NO_SUCH_ROW_IN_TRG = 1363, 373 | ER_NO_DEFAULT_FOR_FIELD = 1364, 374 | ER_DIVISION_BY_ZERO = 1365, 375 | ER_TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366, 376 | ER_ILLEGAL_VALUE_FOR_TYPE = 1367, 377 | ER_VIEW_NONUPD_CHECK = 1368, 378 | ER_VIEW_CHECK_FAILED = 1369, 379 | ER_PROCACCESS_DENIED_ERROR = 1370, 380 | ER_RELAY_LOG_FAIL = 1371, 381 | ER_PASSWD_LENGTH = 1372, 382 | ER_UNKNOWN_TARGET_BINLOG = 1373, 383 | ER_IO_ERR_LOG_INDEX_READ = 1374, 384 | ER_BINLOG_PURGE_PROHIBITED = 1375, 385 | ER_FSEEK_FAIL = 1376, 386 | ER_BINLOG_PURGE_FATAL_ERR = 1377, 387 | ER_LOG_IN_USE = 1378, 388 | ER_LOG_PURGE_UNKNOWN_ERR = 1379, 389 | ER_RELAY_LOG_INIT = 1380, 390 | ER_NO_BINARY_LOGGING = 1381, 391 | ER_RESERVED_SYNTAX = 1382, 392 | ER_WSAS_FAILED = 1383, 393 | ER_DIFF_GROUPS_PROC = 1384, 394 | ER_NO_GROUP_FOR_PROC = 1385, 395 | ER_ORDER_WITH_PROC = 1386, 396 | ER_LOGGING_PROHIBIT_CHANGING_OF = 1387, 397 | ER_NO_FILE_MAPPING = 1388, 398 | ER_WRONG_MAGIC = 1389, 399 | ER_PS_MANY_PARAM = 1390, 400 | ER_KEY_PART_0 = 1391, 401 | ER_VIEW_CHECKSUM = 1392, 402 | ER_VIEW_MULTIUPDATE = 1393, 403 | ER_VIEW_NO_INSERT_FIELD_LIST = 1394, 404 | ER_VIEW_DELETE_MERGE_VIEW = 1395, 405 | ER_CANNOT_USER = 1396, 406 | ER_XAER_NOTA = 1397, 407 | ER_XAER_INVAL = 1398, 408 | ER_XAER_RMFAIL = 1399, 409 | ER_XAER_OUTSIDE = 1400, 410 | ER_XAER_RMERR = 1401, 411 | ER_XA_RBROLLBACK = 1402, 412 | ER_NONEXISTING_PROC_GRANT = 1403, 413 | ER_PROC_AUTO_GRANT_FAIL = 1404, 414 | ER_PROC_AUTO_REVOKE_FAIL = 1405, 415 | ER_DATA_TOO_LONG = 1406, 416 | ER_SP_BAD_SQLSTATE = 1407, 417 | ER_STARTUP = 1408, 418 | ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409, 419 | ER_CANT_CREATE_USER_WITH_GRANT = 1410, 420 | ER_WRONG_VALUE_FOR_TYPE = 1411, 421 | ER_TABLE_DEF_CHANGED = 1412, 422 | ER_SP_DUP_HANDLER = 1413, 423 | ER_SP_NOT_VAR_ARG = 1414, 424 | ER_SP_NO_RETSET = 1415, 425 | ER_CANT_CREATE_GEOMETRY_OBJECT = 1416, 426 | ER_FAILED_ROUTINE_BREAK_BINLOG = 1417, 427 | ER_BINLOG_UNSAFE_ROUTINE = 1418, 428 | ER_BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419, 429 | ER_EXEC_STMT_WITH_OPEN_CURSOR = 1420, 430 | ER_STMT_HAS_NO_OPEN_CURSOR = 1421, 431 | ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422, 432 | ER_NO_DEFAULT_FOR_VIEW_FIELD = 1423, 433 | ER_SP_NO_RECURSION = 1424, 434 | ER_TOO_BIG_SCALE = 1425, 435 | ER_TOO_BIG_PRECISION = 1426, 436 | ER_M_BIGGER_THAN_D = 1427, 437 | ER_WRONG_LOCK_OF_SYSTEM_TABLE = 1428, 438 | ER_CONNECT_TO_FOREIGN_DATA_SOURCE = 1429, 439 | ER_QUERY_ON_FOREIGN_DATA_SOURCE = 1430, 440 | ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431, 441 | ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432, 442 | ER_FOREIGN_DATA_STRING_INVALID = 1433, 443 | ER_CANT_CREATE_FEDERATED_TABLE = 1434, 444 | ER_TRG_IN_WRONG_SCHEMA = 1435, 445 | ER_STACK_OVERRUN_NEED_MORE = 1436, 446 | ER_TOO_LONG_BODY = 1437, 447 | ER_WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438, 448 | ER_TOO_BIG_DISPLAYWIDTH = 1439, 449 | ER_XAER_DUPID = 1440, 450 | ER_DATETIME_FUNCTION_OVERFLOW = 1441, 451 | ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442, 452 | ER_VIEW_PREVENT_UPDATE = 1443, 453 | ER_PS_NO_RECURSION = 1444, 454 | ER_SP_CANT_SET_AUTOCOMMIT = 1445, 455 | ER_MALFORMED_DEFINER = 1446, 456 | ER_VIEW_FRM_NO_USER = 1447, 457 | ER_VIEW_OTHER_USER = 1448, 458 | ER_NO_SUCH_USER = 1449, 459 | ER_FORBID_SCHEMA_CHANGE = 1450, 460 | ER_ROW_IS_REFERENCED_2 = 1451, 461 | ER_NO_REFERENCED_ROW_2 = 1452, 462 | ER_SP_BAD_VAR_SHADOW = 1453, 463 | ER_TRG_NO_DEFINER = 1454, 464 | ER_OLD_FILE_FORMAT = 1455, 465 | ER_SP_RECURSION_LIMIT = 1456, 466 | ER_SP_PROC_TABLE_CORRUPT = 1457, 467 | ER_SP_WRONG_NAME = 1458, 468 | ER_TABLE_NEEDS_UPGRADE = 1459, 469 | ER_SP_NO_AGGREGATE = 1460, 470 | ER_MAX_PREPARED_STMT_COUNT_REACHED = 1461, 471 | ER_VIEW_RECURSIVE = 1462, 472 | ER_NON_GROUPING_FIELD_USED = 1463, 473 | ER_TABLE_CANT_HANDLE_SPKEYS = 1464, 474 | ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA = 1465, 475 | ER_REMOVED_SPACES = 1466, 476 | ER_AUTOINC_READ_FAILED = 1467, 477 | ER_USERNAME = 1468, 478 | ER_HOSTNAME = 1469, 479 | ER_WRONG_STRING_LENGTH = 1470, 480 | ER_NON_INSERTABLE_TABLE = 1471, 481 | ER_ADMIN_WRONG_MRG_TABLE = 1472, 482 | ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT = 1473, 483 | ER_NAME_BECOMES_EMPTY = 1474, 484 | ER_AMBIGUOUS_FIELD_TERM = 1475, 485 | ER_FOREIGN_SERVER_EXISTS = 1476, 486 | ER_FOREIGN_SERVER_DOESNT_EXIST = 1477, 487 | ER_ILLEGAL_HA_CREATE_OPTION = 1478, 488 | ER_PARTITION_REQUIRES_VALUES_ERROR = 1479, 489 | ER_PARTITION_WRONG_VALUES_ERROR = 1480, 490 | ER_PARTITION_MAXVALUE_ERROR = 1481, 491 | ER_PARTITION_SUBPARTITION_ERROR = 1482, 492 | ER_PARTITION_SUBPART_MIX_ERROR = 1483, 493 | ER_PARTITION_WRONG_NO_PART_ERROR = 1484, 494 | ER_PARTITION_WRONG_NO_SUBPART_ERROR = 1485, 495 | ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR = 1486, 496 | ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR = 1487, 497 | ER_FIELD_NOT_FOUND_PART_ERROR = 1488, 498 | ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR = 1489, 499 | ER_INCONSISTENT_PARTITION_INFO_ERROR = 1490, 500 | ER_PARTITION_FUNC_NOT_ALLOWED_ERROR = 1491, 501 | ER_PARTITIONS_MUST_BE_DEFINED_ERROR = 1492, 502 | ER_RANGE_NOT_INCREASING_ERROR = 1493, 503 | ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR = 1494, 504 | ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR = 1495, 505 | ER_PARTITION_ENTRY_ERROR = 1496, 506 | ER_MIX_HANDLER_ERROR = 1497, 507 | ER_PARTITION_NOT_DEFINED_ERROR = 1498, 508 | ER_TOO_MANY_PARTITIONS_ERROR = 1499, 509 | ER_SUBPARTITION_ERROR = 1500, 510 | ER_CANT_CREATE_HANDLER_FILE = 1501, 511 | ER_BLOB_FIELD_IN_PART_FUNC_ERROR = 1502, 512 | ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF = 1503, 513 | ER_NO_PARTS_ERROR = 1504, 514 | ER_PARTITION_MGMT_ON_NONPARTITIONED = 1505, 515 | ER_FOREIGN_KEY_ON_PARTITIONED = 1506, 516 | ER_DROP_PARTITION_NON_EXISTENT = 1507, 517 | ER_DROP_LAST_PARTITION = 1508, 518 | ER_COALESCE_ONLY_ON_HASH_PARTITION = 1509, 519 | ER_REORG_HASH_ONLY_ON_SAME_NO = 1510, 520 | ER_REORG_NO_PARAM_ERROR = 1511, 521 | ER_ONLY_ON_RANGE_LIST_PARTITION = 1512, 522 | ER_ADD_PARTITION_SUBPART_ERROR = 1513, 523 | ER_ADD_PARTITION_NO_NEW_PARTITION = 1514, 524 | ER_COALESCE_PARTITION_NO_PARTITION = 1515, 525 | ER_REORG_PARTITION_NOT_EXIST = 1516, 526 | ER_SAME_NAME_PARTITION = 1517, 527 | ER_NO_BINLOG_ERROR = 1518, 528 | ER_CONSECUTIVE_REORG_PARTITIONS = 1519, 529 | ER_REORG_OUTSIDE_RANGE = 1520, 530 | ER_PARTITION_FUNCTION_FAILURE = 1521, 531 | ER_PART_STATE_ERROR = 1522, 532 | ER_LIMITED_PART_RANGE = 1523, 533 | ER_PLUGIN_IS_NOT_LOADED = 1524, 534 | ER_WRONG_VALUE = 1525, 535 | ER_NO_PARTITION_FOR_GIVEN_VALUE = 1526, 536 | ER_FILEGROUP_OPTION_ONLY_ONCE = 1527, 537 | ER_CREATE_FILEGROUP_FAILED = 1528, 538 | ER_DROP_FILEGROUP_FAILED = 1529, 539 | ER_TABLESPACE_AUTO_EXTEND_ERROR = 1530, 540 | ER_WRONG_SIZE_NUMBER = 1531, 541 | ER_SIZE_OVERFLOW_ERROR = 1532, 542 | ER_ALTER_FILEGROUP_FAILED = 1533, 543 | ER_BINLOG_ROW_LOGGING_FAILED = 1534, 544 | ER_BINLOG_ROW_WRONG_TABLE_DEF = 1535, 545 | ER_BINLOG_ROW_RBR_TO_SBR = 1536, 546 | ER_EVENT_ALREADY_EXISTS = 1537, 547 | ER_EVENT_STORE_FAILED = 1538, 548 | ER_EVENT_DOES_NOT_EXIST = 1539, 549 | ER_EVENT_CANT_ALTER = 1540, 550 | ER_EVENT_DROP_FAILED = 1541, 551 | ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG = 1542, 552 | ER_EVENT_ENDS_BEFORE_STARTS = 1543, 553 | ER_EVENT_EXEC_TIME_IN_THE_PAST = 1544, 554 | ER_EVENT_OPEN_TABLE_FAILED = 1545, 555 | ER_EVENT_NEITHER_M_EXPR_NOR_M_AT = 1546, 556 | ER_OBSOLETE_COL_COUNT_DOESNT_MATCH_CORRUPTED = 1547, 557 | ER_OBSOLETE_CANNOT_LOAD_FROM_TABLE = 1548, 558 | ER_EVENT_CANNOT_DELETE = 1549, 559 | ER_EVENT_COMPILE_ERROR = 1550, 560 | ER_EVENT_SAME_NAME = 1551, 561 | ER_EVENT_DATA_TOO_LONG = 1552, 562 | ER_DROP_INDEX_FK = 1553, 563 | ER_WARN_DEPRECATED_SYNTAX_WITH_VER = 1554, 564 | ER_CANT_WRITE_LOCK_LOG_TABLE = 1555, 565 | ER_CANT_LOCK_LOG_TABLE = 1556, 566 | ER_FOREIGN_DUPLICATE_KEY_OLD_UNUSED = 1557, 567 | ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE = 1558, 568 | ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR = 1559, 569 | ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT = 1560, 570 | ER_NDB_CANT_SWITCH_BINLOG_FORMAT = 1561, 571 | ER_PARTITION_NO_TEMPORARY = 1562, 572 | ER_PARTITION_CONST_DOMAIN_ERROR = 1563, 573 | ER_PARTITION_FUNCTION_IS_NOT_ALLOWED = 1564, 574 | ER_DDL_LOG_ERROR = 1565, 575 | ER_NULL_IN_VALUES_LESS_THAN = 1566, 576 | ER_WRONG_PARTITION_NAME = 1567, 577 | ER_CANT_CHANGE_TX_CHARACTERISTICS = 1568, 578 | ER_DUP_ENTRY_AUTOINCREMENT_CASE = 1569, 579 | ER_EVENT_MODIFY_QUEUE_ERROR = 1570, 580 | ER_EVENT_SET_VAR_ERROR = 1571, 581 | ER_PARTITION_MERGE_ERROR = 1572, 582 | ER_CANT_ACTIVATE_LOG = 1573, 583 | ER_RBR_NOT_AVAILABLE = 1574, 584 | ER_BASE64_DECODE_ERROR = 1575, 585 | ER_EVENT_RECURSION_FORBIDDEN = 1576, 586 | ER_EVENTS_DB_ERROR = 1577, 587 | ER_ONLY_INTEGERS_ALLOWED = 1578, 588 | ER_UNSUPORTED_LOG_ENGINE = 1579, 589 | ER_BAD_LOG_STATEMENT = 1580, 590 | ER_CANT_RENAME_LOG_TABLE = 1581, 591 | ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT = 1582, 592 | ER_WRONG_PARAMETERS_TO_NATIVE_FCT = 1583, 593 | ER_WRONG_PARAMETERS_TO_STORED_FCT = 1584, 594 | ER_NATIVE_FCT_NAME_COLLISION = 1585, 595 | ER_DUP_ENTRY_WITH_KEY_NAME = 1586, 596 | ER_BINLOG_PURGE_EMFILE = 1587, 597 | ER_EVENT_CANNOT_CREATE_IN_THE_PAST = 1588, 598 | ER_EVENT_CANNOT_ALTER_IN_THE_PAST = 1589, 599 | ER_SLAVE_INCIDENT = 1590, 600 | ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT = 1591, 601 | ER_BINLOG_UNSAFE_STATEMENT = 1592, 602 | ER_SLAVE_FATAL_ERROR = 1593, 603 | ER_SLAVE_RELAY_LOG_READ_FAILURE = 1594, 604 | ER_SLAVE_RELAY_LOG_WRITE_FAILURE = 1595, 605 | ER_SLAVE_CREATE_EVENT_FAILURE = 1596, 606 | ER_SLAVE_MASTER_COM_FAILURE = 1597, 607 | ER_BINLOG_LOGGING_IMPOSSIBLE = 1598, 608 | ER_VIEW_NO_CREATION_CTX = 1599, 609 | ER_VIEW_INVALID_CREATION_CTX = 1600, 610 | ER_SR_INVALID_CREATION_CTX = 1601, 611 | ER_TRG_CORRUPTED_FILE = 1602, 612 | ER_TRG_NO_CREATION_CTX = 1603, 613 | ER_TRG_INVALID_CREATION_CTX = 1604, 614 | ER_EVENT_INVALID_CREATION_CTX = 1605, 615 | ER_TRG_CANT_OPEN_TABLE = 1606, 616 | ER_CANT_CREATE_SROUTINE = 1607, 617 | ER_NEVER_USED = 1608, 618 | ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT = 1609, 619 | ER_SLAVE_CORRUPT_EVENT = 1610, 620 | ER_LOAD_DATA_INVALID_COLUMN = 1611, 621 | ER_LOG_PURGE_NO_FILE = 1612, 622 | ER_XA_RBTIMEOUT = 1613, 623 | ER_XA_RBDEADLOCK = 1614, 624 | ER_NEED_REPREPARE = 1615, 625 | ER_DELAYED_NOT_SUPPORTED = 1616, 626 | WARN_NO_MASTER_INFO = 1617, 627 | WARN_OPTION_IGNORED = 1618, 628 | WARN_PLUGIN_DELETE_BUILTIN = 1619, 629 | WARN_PLUGIN_BUSY = 1620, 630 | ER_VARIABLE_IS_READONLY = 1621, 631 | ER_WARN_ENGINE_TRANSACTION_ROLLBACK = 1622, 632 | ER_SLAVE_HEARTBEAT_FAILURE = 1623, 633 | ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE = 1624, 634 | ER_NDB_REPLICATION_SCHEMA_ERROR = 1625, 635 | ER_CONFLICT_FN_PARSE_ERROR = 1626, 636 | ER_EXCEPTIONS_WRITE_ERROR = 1627, 637 | ER_TOO_LONG_TABLE_COMMENT = 1628, 638 | ER_TOO_LONG_FIELD_COMMENT = 1629, 639 | ER_FUNC_INEXISTENT_NAME_COLLISION = 1630, 640 | ER_DATABASE_NAME = 1631, 641 | ER_TABLE_NAME = 1632, 642 | ER_PARTITION_NAME = 1633, 643 | ER_SUBPARTITION_NAME = 1634, 644 | ER_TEMPORARY_NAME = 1635, 645 | ER_RENAMED_NAME = 1636, 646 | ER_TOO_MANY_CONCURRENT_TRXS = 1637, 647 | WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED = 1638, 648 | ER_DEBUG_SYNC_TIMEOUT = 1639, 649 | ER_DEBUG_SYNC_HIT_LIMIT = 1640, 650 | ER_DUP_SIGNAL_SET = 1641, 651 | ER_SIGNAL_WARN = 1642, 652 | ER_SIGNAL_NOT_FOUND = 1643, 653 | ER_SIGNAL_EXCEPTION = 1644, 654 | ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER = 1645, 655 | ER_SIGNAL_BAD_CONDITION_TYPE = 1646, 656 | WARN_COND_ITEM_TRUNCATED = 1647, 657 | ER_COND_ITEM_TOO_LONG = 1648, 658 | ER_UNKNOWN_LOCALE = 1649, 659 | ER_SLAVE_IGNORE_SERVER_IDS = 1650, 660 | ER_QUERY_CACHE_DISABLED = 1651, 661 | ER_SAME_NAME_PARTITION_FIELD = 1652, 662 | ER_PARTITION_COLUMN_LIST_ERROR = 1653, 663 | ER_WRONG_TYPE_COLUMN_VALUE_ERROR = 1654, 664 | ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR = 1655, 665 | ER_MAXVALUE_IN_VALUES_IN = 1656, 666 | ER_TOO_MANY_VALUES_ERROR = 1657, 667 | ER_ROW_SINGLE_PARTITION_FIELD_ERROR = 1658, 668 | ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD = 1659, 669 | ER_PARTITION_FIELDS_TOO_LONG = 1660, 670 | ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE = 1661, 671 | ER_BINLOG_ROW_MODE_AND_STMT_ENGINE = 1662, 672 | ER_BINLOG_UNSAFE_AND_STMT_ENGINE = 1663, 673 | ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE = 1664, 674 | ER_BINLOG_STMT_MODE_AND_ROW_ENGINE = 1665, 675 | ER_BINLOG_ROW_INJECTION_AND_STMT_MODE = 1666, 676 | ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE = 1667, 677 | ER_BINLOG_UNSAFE_LIMIT = 1668, 678 | ER_BINLOG_UNSAFE_INSERT_DELAYED = 1669, 679 | ER_BINLOG_UNSAFE_SYSTEM_TABLE = 1670, 680 | ER_BINLOG_UNSAFE_AUTOINC_COLUMNS = 1671, 681 | ER_BINLOG_UNSAFE_UDF = 1672, 682 | ER_BINLOG_UNSAFE_SYSTEM_VARIABLE = 1673, 683 | ER_BINLOG_UNSAFE_SYSTEM_FUNCTION = 1674, 684 | ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS = 1675, 685 | ER_MESSAGE_AND_STATEMENT = 1676, 686 | ER_SLAVE_CONVERSION_FAILED = 1677, 687 | ER_SLAVE_CANT_CREATE_CONVERSION = 1678, 688 | ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT = 1679, 689 | ER_PATH_LENGTH = 1680, 690 | ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT = 1681, 691 | ER_WRONG_NATIVE_TABLE_STRUCTURE = 1682, 692 | ER_WRONG_PERFSCHEMA_USAGE = 1683, 693 | ER_WARN_I_S_SKIPPED_TABLE = 1684, 694 | ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT = 1685, 695 | ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT = 1686, 696 | ER_SPATIAL_MUST_HAVE_GEOM_COL = 1687, 697 | ER_TOO_LONG_INDEX_COMMENT = 1688, 698 | ER_LOCK_ABORTED = 1689, 699 | ER_DATA_OUT_OF_RANGE = 1690, 700 | ER_WRONG_SPVAR_TYPE_IN_LIMIT = 1691, 701 | ER_BINLOG_UNSAFE_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE = 1692, 702 | ER_BINLOG_UNSAFE_MIXED_STATEMENT = 1693, 703 | ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN = 1694, 704 | ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN = 1695, 705 | ER_FAILED_READ_FROM_PAR_FILE = 1696, 706 | ER_VALUES_IS_NOT_INT_TYPE_ERROR = 1697, 707 | ER_ACCESS_DENIED_NO_PASSWORD_ERROR = 1698, 708 | ER_SET_PASSWORD_AUTH_PLUGIN = 1699, 709 | ER_GRANT_PLUGIN_USER_EXISTS = 1700, 710 | ER_TRUNCATE_ILLEGAL_FK = 1701, 711 | ER_PLUGIN_IS_PERMANENT = 1702, 712 | ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN = 1703, 713 | ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX = 1704, 714 | ER_STMT_CACHE_FULL = 1705, 715 | ER_MULTI_UPDATE_KEY_CONFLICT = 1706, 716 | ER_TABLE_NEEDS_REBUILD = 1707, 717 | WARN_OPTION_BELOW_LIMIT = 1708, 718 | ER_INDEX_COLUMN_TOO_LONG = 1709, 719 | ER_ERROR_IN_TRIGGER_BODY = 1710, 720 | ER_ERROR_IN_UNKNOWN_TRIGGER_BODY = 1711, 721 | ER_INDEX_CORRUPT = 1712, 722 | ER_UNDO_RECORD_TOO_BIG = 1713, 723 | ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT = 1714, 724 | ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE = 1715, 725 | ER_BINLOG_UNSAFE_REPLACE_SELECT = 1716, 726 | ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT = 1717, 727 | ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT = 1718, 728 | ER_BINLOG_UNSAFE_UPDATE_IGNORE = 1719, 729 | ER_PLUGIN_NO_UNINSTALL = 1720, 730 | ER_PLUGIN_NO_INSTALL = 1721, 731 | ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT = 1722, 732 | ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC = 1723, 733 | ER_BINLOG_UNSAFE_INSERT_TWO_KEYS = 1724, 734 | ER_TABLE_IN_FK_CHECK = 1725, 735 | ER_UNSUPPORTED_ENGINE = 1726, 736 | ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST = 1727, 737 | ER_CANNOT_LOAD_FROM_TABLE_V2 = 1728, 738 | ER_MASTER_DELAY_VALUE_OUT_OF_RANGE = 1729, 739 | ER_ONLY_FD_AND_RBR_EVENTS_ALLOWED_IN_BINLOG_STATEMENT = 1730, 740 | ER_PARTITION_EXCHANGE_DIFFERENT_OPTION = 1731, 741 | ER_PARTITION_EXCHANGE_PART_TABLE = 1732, 742 | ER_PARTITION_EXCHANGE_TEMP_TABLE = 1733, 743 | ER_PARTITION_INSTEAD_OF_SUBPARTITION = 1734, 744 | ER_UNKNOWN_PARTITION = 1735, 745 | ER_TABLES_DIFFERENT_METADATA = 1736, 746 | ER_ROW_DOES_NOT_MATCH_PARTITION = 1737, 747 | ER_BINLOG_CACHE_SIZE_GREATER_THAN_MAX = 1738, 748 | ER_WARN_INDEX_NOT_APPLICABLE = 1739, 749 | ER_PARTITION_EXCHANGE_FOREIGN_KEY = 1740, 750 | ER_NO_SUCH_KEY_VALUE = 1741, 751 | ER_RPL_INFO_DATA_TOO_LONG = 1742, 752 | ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE = 1743, 753 | ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE = 1744, 754 | ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX = 1745, 755 | ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT = 1746, 756 | ER_PARTITION_CLAUSE_ON_NONPARTITIONED = 1747, 757 | ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET = 1748, 758 | ER_NO_SUCH_PARTITION__UNUSED = 1749, 759 | ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE = 1750, 760 | ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CREATED_TEMP_TABLE = 1751, 761 | ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE = 1752, 762 | ER_MTS_FEATURE_IS_NOT_SUPPORTED = 1753, 763 | ER_MTS_UPDATED_DBS_GREATER_MAX = 1754, 764 | ER_MTS_CANT_PARALLEL = 1755, 765 | ER_MTS_INCONSISTENT_DATA = 1756, 766 | ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING = 1757, 767 | ER_DA_INVALID_CONDITION_NUMBER = 1758, 768 | ER_INSECURE_PLAIN_TEXT = 1759, 769 | ER_INSECURE_CHANGE_MASTER = 1760, 770 | ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO = 1761, 771 | ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO = 1762, 772 | ER_SQLTHREAD_WITH_SECURE_SLAVE = 1763, 773 | ER_TABLE_HAS_NO_FT = 1764, 774 | ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER = 1765, 775 | ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION = 1766, 776 | ER_GTID_NEXT_IS_NOT_IN_GTID_NEXT_LIST = 1767, 777 | ER_CANT_CHANGE_GTID_NEXT_IN_TRANSACTION_WHEN_GTID_NEXT_LIST_IS_NULL = 1768, 778 | ER_SET_STATEMENT_CANNOT_INVOKE_FUNCTION = 1769, 779 | ER_GTID_NEXT_CANT_BE_AUTOMATIC_IF_GTID_NEXT_LIST_IS_NON_NULL = 1770, 780 | ER_SKIPPING_LOGGED_TRANSACTION = 1771, 781 | ER_MALFORMED_GTID_SET_SPECIFICATION = 1772, 782 | ER_MALFORMED_GTID_SET_ENCODING = 1773, 783 | ER_MALFORMED_GTID_SPECIFICATION = 1774, 784 | ER_GNO_EXHAUSTED = 1775, 785 | ER_BAD_SLAVE_AUTO_POSITION = 1776, 786 | ER_AUTO_POSITION_REQUIRES_GTID_MODE_ON = 1777, 787 | ER_CANT_DO_IMPLICIT_COMMIT_IN_TRX_WHEN_GTID_NEXT_IS_SET = 1778, 788 | ER_GTID_MODE_2_OR_3_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON = 1779, 789 | ER_GTID_MODE_REQUIRES_BINLOG = 1780, 790 | ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF = 1781, 791 | ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON = 1782, 792 | ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF = 1783, 793 | ER_FOUND_GTID_EVENT_WHEN_GTID_MODE_IS_OFF = 1784, 794 | ER_GTID_UNSAFE_NON_TRANSACTIONAL_TABLE = 1785, 795 | ER_GTID_UNSAFE_CREATE_SELECT = 1786, 796 | ER_GTID_UNSAFE_CREATE_DROP_TEMPORARY_TABLE_IN_TRANSACTION = 1787, 797 | ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME = 1788, 798 | ER_MASTER_HAS_PURGED_REQUIRED_GTIDS = 1789, 799 | ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID = 1790, 800 | ER_UNKNOWN_EXPLAIN_FORMAT = 1791, 801 | ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION = 1792, 802 | ER_TOO_LONG_TABLE_PARTITION_COMMENT = 1793, 803 | ER_SLAVE_CONFIGURATION = 1794, 804 | ER_INNODB_FT_LIMIT = 1795, 805 | ER_INNODB_NO_FT_TEMP_TABLE = 1796, 806 | ER_INNODB_FT_WRONG_DOCID_COLUMN = 1797, 807 | ER_INNODB_FT_WRONG_DOCID_INDEX = 1798, 808 | ER_INNODB_ONLINE_LOG_TOO_BIG = 1799, 809 | ER_UNKNOWN_ALTER_ALGORITHM = 1800, 810 | ER_UNKNOWN_ALTER_LOCK = 1801, 811 | ER_MTS_CHANGE_MASTER_CANT_RUN_WITH_GAPS = 1802, 812 | ER_MTS_RECOVERY_FAILURE = 1803, 813 | ER_MTS_RESET_WORKERS = 1804, 814 | ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2 = 1805, 815 | ER_SLAVE_SILENT_RETRY_TRANSACTION = 1806, 816 | ER_DISCARD_FK_CHECKS_RUNNING = 1807, 817 | ER_TABLE_SCHEMA_MISMATCH = 1808, 818 | ER_TABLE_IN_SYSTEM_TABLESPACE = 1809, 819 | ER_IO_READ_ERROR = 1810, 820 | ER_IO_WRITE_ERROR = 1811, 821 | ER_TABLESPACE_MISSING = 1812, 822 | ER_TABLESPACE_EXISTS = 1813, 823 | ER_TABLESPACE_DISCARDED = 1814, 824 | ER_INTERNAL_ERROR = 1815, 825 | ER_INNODB_IMPORT_ERROR = 1816, 826 | ER_INNODB_INDEX_CORRUPT = 1817, 827 | ER_INVALID_YEAR_COLUMN_LENGTH = 1818, 828 | ER_NOT_VALID_PASSWORD = 1819, 829 | ER_MUST_CHANGE_PASSWORD = 1820, 830 | ER_FK_NO_INDEX_CHILD = 1821, 831 | ER_FK_NO_INDEX_PARENT = 1822, 832 | ER_FK_FAIL_ADD_SYSTEM = 1823, 833 | ER_FK_CANNOT_OPEN_PARENT = 1824, 834 | ER_FK_INCORRECT_OPTION = 1825, 835 | ER_FK_DUP_NAME = 1826, 836 | ER_PASSWORD_FORMAT = 1827, 837 | ER_FK_COLUMN_CANNOT_DROP = 1828, 838 | ER_FK_COLUMN_CANNOT_DROP_CHILD = 1829, 839 | ER_FK_COLUMN_NOT_NULL = 1830, 840 | ER_DUP_INDEX = 1831, 841 | ER_FK_COLUMN_CANNOT_CHANGE = 1832, 842 | ER_FK_COLUMN_CANNOT_CHANGE_CHILD = 1833, 843 | ER_FK_CANNOT_DELETE_PARENT = 1834, 844 | ER_MALFORMED_PACKET = 1835, 845 | ER_READ_ONLY_MODE = 1836, 846 | ER_GTID_NEXT_TYPE_UNDEFINED_GROUP = 1837, 847 | ER_VARIABLE_NOT_SETTABLE_IN_SP = 1838, 848 | ER_CANT_SET_GTID_PURGED_WHEN_GTID_MODE_IS_OFF = 1839, 849 | ER_CANT_SET_GTID_PURGED_WHEN_GTID_EXECUTED_IS_NOT_EMPTY = 1840, 850 | ER_CANT_SET_GTID_PURGED_WHEN_OWNED_GTIDS_IS_NOT_EMPTY = 1841, 851 | ER_GTID_PURGED_WAS_CHANGED = 1842, 852 | ER_GTID_EXECUTED_WAS_CHANGED = 1843, 853 | ER_BINLOG_STMT_MODE_AND_NO_REPL_TABLES = 1844, 854 | ER_ALTER_OPERATION_NOT_SUPPORTED = 1845, 855 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON = 1846, 856 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY = 1847, 857 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION = 1848, 858 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME = 1849, 859 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COLUMN_TYPE = 1850, 860 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_CHECK = 1851, 861 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_IGNORE = 1852, 862 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOPK = 1853, 863 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_AUTOINC = 1854, 864 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_HIDDEN_FTS = 1855, 865 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_CHANGE_FTS = 1856, 866 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS = 1857, 867 | ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE = 1858, 868 | ER_DUP_UNKNOWN_IN_INDEX = 1859, 869 | ER_IDENT_CAUSES_TOO_LONG_PATH = 1860, 870 | ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL = 1861, 871 | ER_MUST_CHANGE_PASSWORD_LOGIN = 1862, 872 | ER_ROW_IN_WRONG_PARTITION = 1863, 873 | ER_ERROR_LAST = 1863, 874 | } 875 | 876 | _M.COM_MAP = { 877 | COM_SLEEP = 0, 878 | COM_QUIT = 1, 879 | COM_INIT_DB = 2, 880 | COM_QUERY = 3, 881 | COM_FIELD_LIST = 4, 882 | COM_CREATE_DB = 5, 883 | COM_DROP_DB = 6, 884 | COM_REFRESH = 7, 885 | COM_SHUTDOWN = 8, 886 | COM_STATISTICS = 9, 887 | COM_PROCESS_INFO = 10, 888 | COM_CONNECT = 11, 889 | COM_PROCESS_KILL = 12, 890 | COM_DEBUG = 13, 891 | COM_PING = 14, 892 | COM_TIME = 15, 893 | COM_DELAYED_INSERT = 16, 894 | COM_CHANGE_USER = 17, 895 | COM_BINLOG_DUMP = 18, 896 | COM_TABLE_DUMP = 19, 897 | COM_CONNECT_OUT = 20, 898 | COM_REGISTER_SLAVE = 21, 899 | COM_STMT_PREPARE = 22, 900 | COM_STMT_EXECUTE = 23, 901 | COM_STMT_SEND_LONG_DATA = 24, 902 | COM_STMT_CLOSE = 25, 903 | COM_STMT_RESET = 26, 904 | COM_SET_OPTION = 27, 905 | COM_STMT_FETCH = 28, 906 | COM_DAEMON = 29, 907 | COM_BINLOG_DUMP_GTID = 30, 908 | COM_RESET_CONNECTION = 31, 909 | } 910 | 911 | _M.CHARSET_MAP = { 912 | _default = 0, 913 | big5 = 1, 914 | dec8 = 3, 915 | cp850 = 4, 916 | hp8 = 6, 917 | koi8r = 7, 918 | latin1 = 8, 919 | latin2 = 9, 920 | swe7 = 10, 921 | ascii = 11, 922 | ujis = 12, 923 | sjis = 13, 924 | hebrew = 16, 925 | tis620 = 18, 926 | euckr = 19, 927 | koi8u = 22, 928 | gb2312 = 24, 929 | greek = 25, 930 | cp1250 = 26, 931 | gbk = 28, 932 | latin5 = 30, 933 | armscii8 = 32, 934 | utf8 = 33, 935 | ucs2 = 35, 936 | cp866 = 36, 937 | keybcs2 = 37, 938 | macce = 38, 939 | macroman = 39, 940 | cp852 = 40, 941 | latin7 = 41, 942 | utf8mb4 = 45, 943 | cp1251 = 51, 944 | utf16 = 54, 945 | utf16le = 56, 946 | cp1256 = 57, 947 | cp1257 = 59, 948 | utf32 = 60, 949 | binary = 63, 950 | geostd8 = 92, 951 | cp932 = 95, 952 | eucjpms = 97, 953 | gb18030 = 248 954 | } 955 | 956 | _M.SERVER_STATUS_MAP = { 957 | SERVER_STATUS_IN_TRANS = 0x0001, 958 | SERVER_STATUS_AUTOCOMMIT = 0x0002, 959 | SERVER_MORE_RESULTS_EXISTS = 0x0008, 960 | SERVER_STATUS_NO_GOOD_INDEX_USED = 0x0010, 961 | SERVER_STATUS_NO_INDEX_USED = 0x0020, 962 | SERVER_STATUS_CURSOR_EXISTS = 0x0040, 963 | SERVER_STATUS_LAST_ROW_SEND = 0x0080, 964 | SERVER_STATUS_DB_DROPPED = 0x0100, 965 | SERVER_STATUS_NO_BACKSLASH_ESCAPED = 0x0200, 966 | SERVER_STATUS_METADATA_CHANGED = 0x0400, 967 | SERVER_QUERY_WAS_SLOW = 0x0800, 968 | SERVER_PS_OUT_PARAMS = 0x1000, 969 | } 970 | 971 | local CAPABILITY_MAP = { 972 | CLIENT_LONG_PASSWORD = 0x0001, 973 | CLIENT_FOUND_ROWS = 0x0002, 974 | CLIENT_LONG_FLAG = 0x0004, 975 | CLIENT_CONNECT_WITH_DB = 0x0008, 976 | CLIENT_NO_SCHEMA = 0x0010, 977 | CLIENT_COMPRESS = 0x0020, 978 | CLIENT_ODBC = 0x0040, 979 | CLIENT_LOCAL_FILES = 0x0080, 980 | CLIENT_IGNORE_SPACE = 0x0100, 981 | CLIENT_PROTOCOL_41 = 0x0200, 982 | CLIENT_INTERACTIVE = 0x0400, 983 | CLIENT_SSL = 0x0800, 984 | CLIENT_IGNORE_SIGPIPE = 0x1000, 985 | CLIENT_TRANSACTIONS = 0x2000, 986 | CLIENT_RESERVED = 0x4000, 987 | CLIENT_SECURE_CONNECTION = 0x8000, 988 | CLIENT_MULTI_STATEMENTS = 0x10000, 989 | CLIENT_MULTI_RESULTS = 0x20000, 990 | CLIENT_PS_MULTI_RESULTS = 0x40000, 991 | CLIENT_PLUGIN_AUTH = 0x80000, 992 | CLIENT_CONNECT_ATTRS = 0x100000, 993 | CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x200000, 994 | } 995 | _M.CAPABILITY_MAP = CAPABILITY_MAP 996 | 997 | _M.DEFAULT_CAPABILITY = bor( 998 | CAPABILITY_MAP.CLIENT_LONG_PASSWORD, CAPABILITY_MAP.CLIENT_LONG_FLAG, 999 | CAPABILITY_MAP.CLIENT_CONNECT_WITH_DB, CAPABILITY_MAP.CLIENT_PROTOCOL_41, 1000 | CAPABILITY_MAP.CLIENT_TRANSACTIONS, CAPABILITY_MAP.CLIENT_SECURE_CONNECTION 1001 | ) 1002 | 1003 | _M.MIN_PROTOCOL_VERISON = 10 1004 | _M.SERVER_VERISON = "5.6.20-myproxy" 1005 | _M.DEFAULT_CHARSET = "utf8" 1006 | _M.DEFAULT_COLLATION_ID = 33 1007 | _M.DEFAULT_COLLATION_NAME = "utf8_general_ci" 1008 | _M.BASE_CONN_ID = 10000 1009 | _M.MAX_PACKET_SIZE = 1024 * 1024 1010 | _M.OK_HEADER = 0x00 1011 | _M.ERR_HEADER = 0xff 1012 | _M.EOF_HEADER = 0xfe 1013 | _M.DATA_HEADER_UPPER = 250 1014 | _M.DEFAULT_MYSQL_STATE = "HY000" 1015 | _M.DEFAULT_MYSQL_ERRMESSAGE = "mysql error" 1016 | 1017 | return _M 1018 | -------------------------------------------------------------------------------- /lib/resty/mysql/packet.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2017 Libo Huang (huangnauh), UPYUN Inc. 2 | local bit = require "bit" 3 | local const = require "resty.mysql.const" 4 | 5 | local sub = string.sub 6 | local strlen = string.len 7 | local strbyte = string.byte 8 | local strchar = string.char 9 | local strfind = string.find 10 | local strsub = string.sub 11 | local format = string.format 12 | local strrep = string.rep 13 | local tcp = ngx.socket.tcp 14 | local null = ngx.null 15 | local ERR = ngx.ERR 16 | local WARN = ngx.WARN 17 | local INFO = ngx.INFO 18 | local log = ngx.log 19 | local band = bit.band 20 | local bxor = bit.bxor 21 | local bor = bit.bor 22 | local lshift = bit.lshift 23 | local rshift = bit.rshift 24 | local tohex = bit.tohex 25 | local sha1 = ngx.sha1_bin 26 | local concat = table.concat 27 | local unpack = unpack 28 | local setmetatable = setmetatable 29 | local error = error 30 | local tonumber = tonumber 31 | local tostring = tostring 32 | 33 | if not ngx.config 34 | or not ngx.config.ngx_lua_version 35 | or ngx.config.ngx_lua_version < 9011 36 | then 37 | error("ngx_lua 0.9.11+ required") 38 | end 39 | 40 | local STATE_CONNECTED = 1 41 | local STATE_COMMAND_SENT = 2 42 | 43 | local ok, new_tab = pcall(require, "table.new") 44 | if not ok then 45 | new_tab = function (narr, nrec) return {} end 46 | end 47 | 48 | local _M = { _VERSION = '0.01' } 49 | 50 | local mt = { __index = _M } 51 | 52 | -- mysql field value type converters 53 | local converters = new_tab(0, 9) 54 | 55 | for i = 0x01, 0x05 do 56 | -- tiny, short, long, float, double 57 | converters[i] = tonumber 58 | end 59 | converters[0x00] = tonumber -- decimal 60 | -- converters[0x08] = tonumber -- long long 61 | converters[0x09] = tonumber -- int24 62 | converters[0x0d] = tonumber -- year 63 | converters[0xf6] = tonumber -- newdecimal 64 | 65 | 66 | local function _get_byte2(data, i) 67 | local a, b = strbyte(data, i, i + 1) 68 | return bor(a, lshift(b, 8)), i + 2 69 | end 70 | 71 | 72 | local function _get_byte3(data, i) 73 | local a, b, c = strbyte(data, i, i + 2) 74 | return bor(a, lshift(b, 8), lshift(c, 16)), i + 3 75 | end 76 | 77 | 78 | local function _get_byte4(data, i) 79 | local a, b, c, d = strbyte(data, i, i + 3) 80 | return bor(a, lshift(b, 8), lshift(c, 16), lshift(d, 24)), i + 4 81 | end 82 | 83 | 84 | local function _get_byte8(data, i) 85 | local a, b, c, d, e, f, g, h = strbyte(data, i, i + 7) 86 | 87 | -- XXX workaround for the lack of 64-bit support in bitop: 88 | local lo = bor(a, lshift(b, 8), lshift(c, 16), lshift(d, 24)) 89 | local hi = bor(e, lshift(f, 8), lshift(g, 16), lshift(h, 24)) 90 | return lo + hi * 4294967296, i + 8 91 | 92 | -- return bor(a, lshift(b, 8), lshift(c, 16), lshift(d, 24), lshift(e, 32), 93 | -- lshift(f, 40), lshift(g, 48), lshift(h, 56)), i + 8 94 | end 95 | 96 | 97 | local function _set_byte2(n) 98 | return strchar(band(n, 0xff), band(rshift(n, 8), 0xff)) 99 | end 100 | 101 | 102 | local function _set_byte3(n) 103 | return strchar(band(n, 0xff), 104 | band(rshift(n, 8), 0xff), 105 | band(rshift(n, 16), 0xff)) 106 | end 107 | 108 | 109 | local function _set_byte4(n) 110 | return strchar(band(n, 0xff), 111 | band(rshift(n, 8), 0xff), 112 | band(rshift(n, 16), 0xff), 113 | band(rshift(n, 24), 0xff)) 114 | end 115 | 116 | 117 | local function _from_cstring(data, i) 118 | local last = strfind(data, "\0", i, true) 119 | if not last then 120 | return nil, nil 121 | end 122 | 123 | return sub(data, i, last-1), last + 1 124 | end 125 | 126 | 127 | local function _to_cstring(data) 128 | return data .. "\0" 129 | end 130 | 131 | 132 | local function _to_binary_coded_string(data) 133 | return strchar(#data) .. data 134 | end 135 | 136 | 137 | local function _dump(data) 138 | local len = #data 139 | local bytes = new_tab(len, 0) 140 | for i = 1, len do 141 | bytes[i] = format("%x", strbyte(data, i)) 142 | end 143 | return concat(bytes, " ") 144 | end 145 | 146 | 147 | local function _dumphex(data) 148 | local len = #data 149 | local bytes = new_tab(len, 0) 150 | for i = 1, len do 151 | bytes[i] = tohex(strbyte(data, i), 2) 152 | end 153 | return concat(bytes, " ") 154 | end 155 | 156 | 157 | local function _compute_token(password, scramble) 158 | if password == "" then 159 | return "" 160 | end 161 | 162 | local stage1 = sha1(password) 163 | local stage2 = sha1(stage1) 164 | local stage3 = sha1(scramble .. stage2) 165 | local n = #stage1 166 | local bytes = new_tab(n, 0) 167 | for i = 1, n do 168 | bytes[i] = strchar(bxor(strbyte(stage3, i), strbyte(stage1, i))) 169 | end 170 | 171 | return concat(bytes) 172 | end 173 | 174 | 175 | local function _send_packet(self, req, size) 176 | local sock = self.sock 177 | 178 | self.packet_no = self.packet_no + 1 179 | 180 | -- print("packet no: ", self.packet_no) 181 | 182 | local packet = _set_byte3(size) .. strchar(band(self.packet_no, 255)) .. req 183 | 184 | -- print("sending packet: ", _dump(packet)) 185 | -- 186 | -- print("sending packet... of size " .. #packet) 187 | 188 | return sock:send(packet) 189 | end 190 | _M.send_packet = _send_packet 191 | 192 | 193 | local function _recv_packet(self) 194 | local sock = self.sock 195 | 196 | local data, err = sock:receive(4) -- packet header 197 | if not data then 198 | return nil, "failed to receive packet header: " .. err 199 | end 200 | 201 | -- print("packet header: ", _dump(data)) 202 | 203 | local len, pos = _get_byte3(data, 1) 204 | 205 | -- print("packet length: ", len) 206 | 207 | if len == 0 then 208 | return nil, "empty packet" 209 | end 210 | 211 | if len > self.max_packet_size then 212 | return nil, "packet size too big: " .. len 213 | end 214 | 215 | local num = strbyte(data, pos) 216 | 217 | --print("recv packet: packet no: ", num) 218 | 219 | self.packet_no = num 220 | 221 | data, err = sock:receive(len) 222 | 223 | --print("receive returned") 224 | 225 | if not data then 226 | return nil, "failed to read packet content: " .. err 227 | end 228 | 229 | -- print("packet content: ", _dump(data)) 230 | -- print("packet content (ascii): ", data) 231 | return data 232 | end 233 | _M.recv_packet = _recv_packet 234 | 235 | 236 | local function _type(data) 237 | local field_count = strbyte(data, 1) 238 | local typ 239 | if field_count == const.OK_HEADER then 240 | typ = "OK" 241 | elseif field_count == const.ERR_HEADER then 242 | typ = "ERR" 243 | elseif field_count == const.EOF_HEADER then 244 | typ = "EOF" 245 | elseif field_count <= const.DATA_HEADER_UPPER then 246 | typ = "DATA" 247 | end 248 | return tostring(typ) 249 | end 250 | _M.type = _type 251 | 252 | 253 | function _M.cmd(data) 254 | return strbyte(data, 1) 255 | end 256 | 257 | 258 | local function _to_length_coded_bin(num) 259 | if num <= 250 then 260 | return strchar(num) 261 | end 262 | 263 | if num <= 0xffff then 264 | return strchar(252, band(num, 0xff), band(rshift(num, 8), 0xff)) 265 | end 266 | 267 | if num <= 0xffffff then 268 | return strchar(253, band(num, 0xff), band(rshift(num, 8), 0xff), 269 | band(rshift(num, 16), 0xff)) 270 | end 271 | 272 | if num <= 0xffffffffffffffff then 273 | return strchar(254, band(num, 0xff), band(rshift(num, 8), 0xff), 274 | band(rshift(num, 16), 0xff), band(rshift(num, 24), 0xff), 275 | band(rshift(num, 32), 0xff), band(rshift(num, 48), 0xff), 276 | band(rshift(num, 56), 0xff)) 277 | end 278 | return "" 279 | end 280 | _M.to_length_coded_bin = _to_length_coded_bin 281 | 282 | 283 | local function _to_length_coded_str(str) 284 | local len = #str 285 | return _to_length_coded_bin(len) .. str 286 | end 287 | 288 | 289 | local function _from_length_coded_bin(data, pos) 290 | local first = strbyte(data, pos) 291 | 292 | --print("LCB: first: ", first) 293 | 294 | if not first then 295 | return nil, pos 296 | end 297 | 298 | if first >= 0 and first <= 250 then 299 | return first, pos + 1 300 | end 301 | 302 | if first == 251 then 303 | return null, pos + 1 304 | end 305 | 306 | if first == 252 then 307 | pos = pos + 1 308 | return _get_byte2(data, pos) 309 | end 310 | 311 | if first == 253 then 312 | pos = pos + 1 313 | return _get_byte3(data, pos) 314 | end 315 | 316 | if first == 254 then 317 | pos = pos + 1 318 | return _get_byte8(data, pos) 319 | end 320 | 321 | return nil, pos + 1 322 | end 323 | 324 | 325 | local function _from_length_coded_str(data, pos) 326 | local len 327 | len, pos = _from_length_coded_bin(data, pos) 328 | if not len or len == null then 329 | return null, pos 330 | end 331 | 332 | return sub(data, pos, pos + len - 1), pos + len 333 | end 334 | 335 | 336 | function _M.parse_handshake_packet(self, packet) 337 | local capability, pos = _get_byte4(packet, 1) 338 | self.capability = capability 339 | -- print("capability (ascii): ", capability) 340 | -- print("pos:", pos) 341 | -- skip max packet size 342 | pos = pos + 4 343 | -- skip charset 344 | pos = pos + 1 345 | -- skip reserved 23[00] 346 | pos = pos + 23 347 | 348 | local user 349 | user, pos = _from_cstring(packet, pos) 350 | if not user then 351 | return "empty user" 352 | end 353 | 354 | log(INFO, "connect with user: ", user) 355 | if self.user ~= user then 356 | return "invalid user" 357 | end 358 | 359 | local auth_len = strbyte(strsub(packet, pos, pos + 1)) 360 | if auth_len == 0 then 361 | return "empty auth" 362 | end 363 | pos = pos + 1 364 | 365 | local auth = strsub(packet, pos, pos+auth_len-1) 366 | pos = pos + auth_len 367 | self.auth = auth 368 | 369 | local token = _compute_token(self.password, self.salt) 370 | -- print("auth_len:", _dump(auth), ",token:", _dump(token)) 371 | if token ~= auth then 372 | return "invalid auth" 373 | end 374 | 375 | if bor(self.capability, const.CAPABILITY_MAP.CLIENT_CONNECT_WITH_DB) == 0 then 376 | return "empty db" 377 | end 378 | 379 | local db, pos = _from_cstring(packet, pos) 380 | -- print("db:", db, ", len:", #db) 381 | if db == nil or strlen(db) == 0 then 382 | return "empty db" 383 | end 384 | self.db = db 385 | end 386 | 387 | 388 | local function send_ok_packet(self, res) 389 | local res = res or {} 390 | local insert_id = res.insert_id or 0 391 | local affected_rows = res.affected_rows or 0 392 | local data = strchar(const.OK_HEADER) 393 | .. _to_length_coded_bin(affected_rows) 394 | .. _to_length_coded_bin(insert_id) 395 | if band(self.capability, const.CAPABILITY_MAP.CLIENT_PROTOCOL_41) > 0 then 396 | data = data .. _set_byte2(self.status) .. strrep("\0", 2) 397 | end 398 | return _send_packet(self, data, #data) 399 | end 400 | _M.send_ok_packet = send_ok_packet 401 | 402 | 403 | local function _parse_ok_packet(packet) 404 | local res = new_tab(0, 5) 405 | local pos 406 | 407 | res.affected_rows, pos = _from_length_coded_bin(packet, 2) 408 | 409 | -- print("affected rows: ", res.affected_rows, ", pos:", pos) 410 | 411 | res.insert_id, pos = _from_length_coded_bin(packet, pos) 412 | 413 | -- print("insert id: ", res.insert_id, ", pos:", pos) 414 | 415 | res.server_status, pos = _get_byte2(packet, pos) 416 | 417 | -- print("server status: ", res.server_status, ", pos:", pos) 418 | 419 | res.warning_count, pos = _get_byte2(packet, pos) 420 | 421 | -- print("warning count: ", res.warning_count, ", pos: ", pos) 422 | 423 | local message = _from_length_coded_str(packet, pos) 424 | if message and message ~= null then 425 | res.message = message 426 | end 427 | 428 | -- print("message: ", res.message, ", pos:", pos) 429 | 430 | return res 431 | end 432 | 433 | 434 | local function _dump_eof_packet(self) 435 | local data = strchar(const.EOF_HEADER) 436 | if band(self.capability, const.CAPABILITY_MAP.CLIENT_PROTOCOL_41) > 0 then 437 | data = data .. strrep("\0", 2) .. _set_byte2(self.status) 438 | end 439 | return data 440 | end 441 | 442 | 443 | local function _send_eof_packet(self) 444 | local data = _dump_eof_packet(self) 445 | return _send_packet(self, data, #data) 446 | end 447 | _M.send_eof_packet = _send_eof_packet 448 | 449 | 450 | local function _parse_eof_packet(packet) 451 | local pos = 2 452 | 453 | local warning_count, pos = _get_byte2(packet, pos) 454 | local status_flags = _get_byte2(packet, pos) 455 | 456 | return warning_count, status_flags 457 | end 458 | 459 | 460 | function _M.send_error_packet(self, sql_err) 461 | local data = strchar(const.ERR_HEADER) 462 | .. _set_byte2(sql_err.errno) 463 | if band(self.capability, const.CAPABILITY_MAP.CLIENT_PROTOCOL_41) > 0 then 464 | data = data .. "#" .. sql_err.sqlstate 465 | end 466 | data = data .. sql_err.message 467 | return _send_packet(self, data, #data) 468 | end 469 | 470 | 471 | local function _parse_err_packet(packet) 472 | local errno, pos = _get_byte2(packet, 2) 473 | local marker = sub(packet, pos, pos) 474 | local sqlstate 475 | if marker == '#' then 476 | -- with sqlstate 477 | pos = pos + 1 478 | sqlstate = sub(packet, pos, pos + 5 - 1) 479 | pos = pos + 5 480 | end 481 | 482 | local message = sub(packet, pos) 483 | return errno, message, sqlstate 484 | end 485 | 486 | 487 | local function _parse_result_set_header_packet(packet) 488 | local field_count, pos = _from_length_coded_bin(packet, 1) 489 | 490 | local extra 491 | extra = _from_length_coded_bin(packet, pos) 492 | 493 | return field_count, extra 494 | end 495 | 496 | 497 | local function _parse_field_packet(data) 498 | local col = {} 499 | -- local catalog, db, table, orig_table, orig_name, charsetnr, length 500 | local pos 501 | col.catalog, pos = _from_length_coded_str(data, 1) 502 | 503 | -- print("catalog: ", col.catalog, ", pos:", pos) 504 | 505 | col.db, pos = _from_length_coded_str(data, pos) 506 | col.table, pos = _from_length_coded_str(data, pos) 507 | col.orig_table, pos = _from_length_coded_str(data, pos) 508 | col.name, pos = _from_length_coded_str(data, pos) 509 | 510 | col.orig_name, pos = _from_length_coded_str(data, pos) 511 | 512 | pos = pos + 1 -- ignore the filler 0x0c 513 | 514 | col.charsetnr, pos = _get_byte2(data, pos) 515 | 516 | col.length, pos = _get_byte4(data, pos) 517 | 518 | col.type = strbyte(data, pos) 519 | 520 | pos = pos + 1 521 | 522 | col.flags, pos = _get_byte2(data, pos) 523 | 524 | col.decimals = strbyte(data, pos) 525 | pos = pos + 1 526 | 527 | local default = sub(data, pos + 2) 528 | if default and default ~= "" then 529 | col.default = default 530 | end 531 | 532 | return col 533 | end 534 | 535 | 536 | local function _parse_row_data_packet(data, cols, compact) 537 | local pos = 1 538 | local ncols = #cols 539 | local row 540 | if compact then 541 | row = new_tab(ncols, 0) 542 | else 543 | row = new_tab(0, ncols) 544 | end 545 | for i = 1, ncols do 546 | local value 547 | value, pos = _from_length_coded_str(data, pos) 548 | local col = cols[i] 549 | local typ = col.type 550 | local name = col.name 551 | 552 | --print("row field value: ", value, ", type: ", typ) 553 | 554 | if value ~= null then 555 | local conv = converters[typ] 556 | if conv then 557 | value = conv(value) 558 | end 559 | end 560 | 561 | if compact then 562 | row[i] = value 563 | 564 | else 565 | row[name] = value 566 | end 567 | end 568 | 569 | return row 570 | end 571 | 572 | 573 | local function _recv_field_packet(self, raw) 574 | local packet, err = _recv_packet(self) 575 | if not packet then 576 | return nil, err 577 | end 578 | 579 | local typ = _type(packet) 580 | if typ == "ERR" then 581 | local errno, msg, sqlstate = _parse_err_packet(packet) 582 | return nil, msg, errno, sqlstate 583 | end 584 | 585 | if typ ~= 'DATA' then 586 | return nil, "bad field packet type: " .. typ 587 | end 588 | 589 | -- typ == 'DATA' 590 | if raw then 591 | return packet 592 | end 593 | 594 | return _parse_field_packet(packet) 595 | end 596 | 597 | function _M.set_timeout(self, timeout) 598 | local sock = self.sock 599 | if not sock then 600 | return nil, "not initialized" 601 | end 602 | 603 | return sock:settimeout(timeout) 604 | end 605 | 606 | 607 | function _M.connect(self, opts) 608 | local sock = self.sock 609 | if not sock then 610 | return nil, "not initialized" 611 | end 612 | 613 | local max_packet_size = opts.max_packet_size 614 | if not max_packet_size then 615 | max_packet_size = const.MAX_PACKET_SIZE 616 | end 617 | self.max_packet_size = max_packet_size 618 | 619 | local ok, err 620 | 621 | self.compact = opts.compact_arrays 622 | 623 | local database = opts.database or "" 624 | local user = opts.user or "" 625 | 626 | local charset = const.CHARSET_MAP[opts.charset or "_default"] 627 | if not charset then 628 | return nil, "charset '" .. opts.charset .. "' is not supported" 629 | end 630 | 631 | local pool = opts.pool 632 | 633 | local host = opts.host 634 | if host then 635 | local port = opts.port or 3306 636 | if not pool then 637 | pool = user .. ":" .. database .. ":" .. host .. ":" .. port 638 | end 639 | 640 | ok, err = sock:connect(host, port, { pool = pool }) 641 | 642 | else 643 | local path = opts.path 644 | if not path then 645 | return nil, 'neither "host" nor "path" options are specified' 646 | end 647 | 648 | if not pool then 649 | pool = user .. ":" .. database .. ":" .. path 650 | end 651 | 652 | ok, err = sock:connect("unix:" .. path, { pool = pool }) 653 | end 654 | 655 | if not ok then 656 | return nil, 'failed to connect: ' .. err 657 | end 658 | 659 | local reused = sock:getreusedtimes() 660 | -- print("reused:", reused) 661 | if reused and reused > 0 then 662 | self.state = STATE_CONNECTED 663 | return 1 664 | end 665 | 666 | local packet, err = _recv_packet(self) 667 | if not packet then 668 | return nil, err 669 | end 670 | 671 | local typ = _type(packet) 672 | if typ == "ERR" then 673 | local errno, msg, sqlstate = _parse_err_packet(packet) 674 | return nil, msg, errno, sqlstate 675 | end 676 | 677 | self.protocol_ver = strbyte(packet) 678 | 679 | --print("protocol version: ", self.protocol_ver) 680 | 681 | local server_ver, pos = _from_cstring(packet, 2) 682 | if not server_ver then 683 | return nil, "bad handshake initialization packet: bad server version" 684 | end 685 | 686 | -- print("server version: ", server_ver, ", len:", #server_ver) 687 | 688 | self._server_ver = server_ver 689 | 690 | local thread_id, pos = _get_byte4(packet, pos) 691 | 692 | --print("thread id: ", thread_id) 693 | 694 | local scramble = sub(packet, pos, pos + 8 - 1) 695 | if not scramble then 696 | return nil, "1st part of scramble not found" 697 | end 698 | 699 | pos = pos + 9 -- skip filler 700 | 701 | -- two lower bytes 702 | local capabilities -- server capabilities 703 | capabilities, pos = _get_byte2(packet, pos) 704 | 705 | -- print(format("server capabilities: %#x", capabilities)) 706 | 707 | self._server_lang = strbyte(packet, pos) 708 | pos = pos + 1 709 | 710 | --print("server lang: ", self._server_lang) 711 | 712 | self._server_status, pos = _get_byte2(packet, pos) 713 | 714 | --print("server status: ", self._server_status) 715 | 716 | local more_capabilities 717 | more_capabilities, pos = _get_byte2(packet, pos) 718 | 719 | capabilities = bor(capabilities, lshift(more_capabilities, 16)) 720 | 721 | --print("server capabilities: ", capabilities) 722 | 723 | -- local len = strbyte(packet, pos) 724 | local len = 21 - 8 - 1 725 | 726 | --print("scramble len: ", len) 727 | 728 | pos = pos + 1 + 10 729 | 730 | local scramble_part2 = sub(packet, pos, pos + len - 1) 731 | if not scramble_part2 then 732 | return nil, "2nd part of scramble not found" 733 | end 734 | 735 | scramble = scramble .. scramble_part2 736 | --print("scramble: ", _dump(scramble)) 737 | 738 | local client_flags = 0x3f7cf; 739 | 740 | local ssl_verify = opts.ssl_verify 741 | local use_ssl = opts.ssl or ssl_verify 742 | 743 | local ssl_cap = const.CAPABILITY_MAP.CLIENT_SSL 744 | if use_ssl then 745 | if band(capabilities, ssl_cap) == 0 then 746 | return nil, "ssl disabled on server" 747 | end 748 | 749 | -- send a SSL Request Packet 750 | local req = _set_byte4(bor(client_flags, ssl_cap)) 751 | .. _set_byte4(self.max_packet_size) 752 | .. strchar(charset) 753 | .. strrep("\0", 23) 754 | 755 | local packet_len = 4 + 4 + 1 + 23 756 | local bytes, err = _send_packet(self, req, packet_len) 757 | if not bytes then 758 | return nil, "failed to send client authentication packet: " .. err 759 | end 760 | 761 | local ok, err = sock:sslhandshake(false, nil, ssl_verify) 762 | if not ok then 763 | return nil, "failed to do ssl handshake: " .. (err or "") 764 | end 765 | end 766 | 767 | local password = opts.password or "" 768 | 769 | local token = _compute_token(password, scramble) 770 | 771 | -- print("token: ", _dump(token)) 772 | 773 | local req = _set_byte4(client_flags) 774 | .. _set_byte4(self.max_packet_size) 775 | .. strchar(charset) 776 | .. strrep("\0", 23) 777 | .. _to_cstring(user) 778 | .. _to_binary_coded_string(token) 779 | .. _to_cstring(database) 780 | 781 | local packet_len = 4 + 4 + 1 + 23 + #user + 1 782 | + #token + 1 + #database + 1 783 | 784 | -- print("packet content length: ", packet_len) 785 | -- print("packet content: ", _dump(req)) 786 | 787 | local bytes, err = _send_packet(self, req, packet_len) 788 | if not bytes then 789 | return nil, "failed to send client authentication packet: " .. err 790 | end 791 | 792 | -- print("packet sent ", bytes, " bytes") 793 | 794 | local packet, err = _recv_packet(self) 795 | if not packet then 796 | return nil, "failed to receive the result packet: " .. err 797 | end 798 | 799 | local typ = _type(packet) 800 | 801 | if typ == 'ERR' then 802 | local errno, msg, sqlstate = _parse_err_packet(packet) 803 | return nil, msg, errno, sqlstate 804 | end 805 | 806 | if typ == 'EOF' then 807 | return nil, "old pre-4.1 authentication protocol not supported" 808 | end 809 | 810 | if typ ~= 'OK' then 811 | return nil, "bad packet type: " .. typ 812 | end 813 | 814 | self.state = STATE_CONNECTED 815 | 816 | return 1 817 | end 818 | 819 | 820 | function _M.set_keepalive(self, ...) 821 | local sock = self.sock 822 | if not sock then 823 | return nil, "not initialized" 824 | end 825 | 826 | if self.state ~= STATE_CONNECTED then 827 | return nil, "cannot be reused in the current connection state: " 828 | .. (self.state or "nil") 829 | end 830 | 831 | self.state = nil 832 | return sock:setkeepalive(...) 833 | end 834 | 835 | 836 | function _M.get_reused_times(self) 837 | local sock = self.sock 838 | if not sock then 839 | return nil, "not initialized" 840 | end 841 | 842 | return sock:getreusedtimes() 843 | end 844 | 845 | 846 | function _M.close(self) 847 | local sock = self.sock 848 | if not sock then 849 | return nil, "not initialized" 850 | end 851 | 852 | self.state = nil 853 | 854 | local bytes, err = _send_packet(self, strchar(const.COM_MAP.COM_QUIT), 1) 855 | if not bytes then 856 | return nil, err 857 | end 858 | 859 | return sock:close() 860 | end 861 | 862 | 863 | function _M.server_ver(self) 864 | return self._server_ver 865 | end 866 | 867 | 868 | local function send_data(self, data) 869 | if self.state ~= STATE_CONNECTED then 870 | return nil, "cannot send data in the current context: " 871 | .. (self.state or "nil") 872 | end 873 | 874 | local sock = self.sock 875 | if not sock then 876 | return nil, "not initialized" 877 | end 878 | 879 | self.packet_no = -1 880 | 881 | local bytes, err = _send_packet(self, data, #data) 882 | if not bytes then 883 | return nil, err 884 | end 885 | 886 | self.state = STATE_COMMAND_SENT 887 | 888 | --print("packet sent ", bytes, " bytes") 889 | 890 | return bytes 891 | end 892 | _M.send_data = send_data 893 | 894 | 895 | local function send_query(self, query) 896 | if self.state ~= STATE_CONNECTED then 897 | return nil, "cannot send query in the current context: " 898 | .. (self.state or "nil") 899 | end 900 | 901 | local sock = self.sock 902 | if not sock then 903 | return nil, "not initialized" 904 | end 905 | 906 | self.packet_no = -1 907 | 908 | local cmd_packet = strchar(const.COM_MAP.COM_QUERY) .. query 909 | local packet_len = 1 + #query 910 | 911 | local bytes, err = _send_packet(self, cmd_packet, packet_len) 912 | if not bytes then 913 | return nil, err 914 | end 915 | 916 | self.state = STATE_COMMAND_SENT 917 | 918 | --print("packet sent ", bytes, " bytes") 919 | 920 | return bytes 921 | end 922 | _M.send_query = send_query 923 | 924 | 925 | local function send_result_rows(self, res) 926 | local ncols = #res.cols 927 | local nrows = #res 928 | -- local bytes = new_tab(n, 0) 929 | local total = 0 930 | 931 | local data = _to_length_coded_bin(ncols) 932 | local len = #data 933 | local _, err = _send_packet(self, data, len) 934 | if err then 935 | return nil, err 936 | end 937 | 938 | total = total + len 939 | 940 | -- send raw field 941 | for i = 1, ncols do 942 | data = res.cols[i] 943 | len = #data 944 | _, err = _send_packet(self, data, len) 945 | if err then 946 | return nil, err 947 | end 948 | total = total + len 949 | end 950 | 951 | len, err = _send_eof_packet(self) 952 | if err then 953 | return nil, err 954 | end 955 | total = total + len 956 | 957 | -- send raw data 958 | for i = 1, nrows do 959 | data = res[i] 960 | len = #data 961 | _, err = _send_packet(self, data, len) 962 | if err then 963 | return nil, err 964 | end 965 | total = total + len 966 | end 967 | 968 | len, err = _send_eof_packet(self) 969 | if err then 970 | return err 971 | end 972 | total = total + len 973 | return total, nil 974 | end 975 | 976 | 977 | function _M.send_result(self, res) 978 | if res[1] then 979 | return send_result_rows(self, res) 980 | else 981 | return send_ok_packet(self, res) 982 | end 983 | end 984 | 985 | 986 | local function read_result(self, raw, est_nrows) 987 | if self.state ~= STATE_COMMAND_SENT then 988 | return nil, "cannot read result in the current context: " 989 | .. (self.state or "nil") 990 | end 991 | 992 | local sock = self.sock 993 | if not sock then 994 | return nil, "not initialized" 995 | end 996 | 997 | local packet, err = _recv_packet(self) 998 | if not packet then 999 | return nil, err 1000 | end 1001 | 1002 | local typ = _type(packet) 1003 | 1004 | if typ == "ERR" then 1005 | self.state = STATE_CONNECTED 1006 | 1007 | local errno, msg, sqlstate = _parse_err_packet(packet) 1008 | return nil, msg, errno, sqlstate 1009 | end 1010 | 1011 | if typ == 'OK' then 1012 | local res = _parse_ok_packet(packet) 1013 | if res and band(res.server_status, const.SERVER_STATUS_MAP.SERVER_MORE_RESULTS_EXISTS) ~= 0 then 1014 | return res, "again" 1015 | end 1016 | 1017 | self.state = STATE_CONNECTED 1018 | return res 1019 | end 1020 | 1021 | if typ ~= 'DATA' then 1022 | self.state = STATE_CONNECTED 1023 | 1024 | return nil, "packet type " .. typ .. " not supported" 1025 | end 1026 | 1027 | -- typ == 'DATA' 1028 | 1029 | -- print("read the result set header packet") 1030 | 1031 | local field_count, extra = _parse_result_set_header_packet(packet) 1032 | 1033 | -- print("field count: ", field_count) 1034 | 1035 | local cols = new_tab(field_count, 0) 1036 | for i = 1, field_count do 1037 | local col, err, errno, sqlstate = _recv_field_packet(self, raw) 1038 | if not col then 1039 | return nil, err, errno, sqlstate 1040 | end 1041 | 1042 | cols[i] = col 1043 | end 1044 | 1045 | local packet, err = _recv_packet(self) 1046 | if not packet then 1047 | return nil, err 1048 | end 1049 | 1050 | local typ = _type(packet) 1051 | if typ ~= 'EOF' then 1052 | return nil, "unexpected packet type " .. typ .. " while eof packet is " 1053 | .. "expected" 1054 | end 1055 | 1056 | -- typ == 'EOF' 1057 | 1058 | local compact = self.compact 1059 | 1060 | local rows = new_tab(est_nrows or 4, 1) 1061 | if raw then 1062 | rows.cols = cols 1063 | end 1064 | 1065 | local i = 0 1066 | while true do 1067 | -- print("reading a row") 1068 | 1069 | packet, err = _recv_packet(self) 1070 | if not packet then 1071 | return nil, err 1072 | end 1073 | 1074 | typ = _type(packet) 1075 | if typ == 'EOF' then 1076 | local warning_count, status_flags = _parse_eof_packet(packet) 1077 | 1078 | -- print("status flags: ", status_flags) 1079 | 1080 | if band(status_flags, const.SERVER_STATUS_MAP.SERVER_MORE_RESULTS_EXISTS) ~= 0 then 1081 | return rows, "again" 1082 | end 1083 | 1084 | break 1085 | end 1086 | 1087 | -- if typ ~= 'DATA' then 1088 | -- return nil, 'bad row packet type: ' .. typ 1089 | -- end 1090 | 1091 | -- typ == 'DATA' 1092 | 1093 | i = i + 1 1094 | if raw then 1095 | rows[i] = packet 1096 | else 1097 | local row = _parse_row_data_packet(packet, cols, compact) 1098 | rows[i] = row 1099 | end 1100 | end 1101 | 1102 | self.state = STATE_CONNECTED 1103 | 1104 | return rows 1105 | end 1106 | _M.read_result = read_result 1107 | 1108 | 1109 | function _M.query(self, query, est_nrows) 1110 | local bytes, err = send_query(self, query) 1111 | if not bytes then 1112 | return nil, "failed to send query: " .. err 1113 | end 1114 | 1115 | return read_result(self, est_nrows) 1116 | end 1117 | 1118 | 1119 | function _M.set_compact_arrays(self, value) 1120 | self.compact = value 1121 | end 1122 | 1123 | 1124 | function _M.init_handshake(self) 1125 | local data = strchar(const.MIN_PROTOCOL_VERISON) 1126 | .. _to_cstring(const.SERVER_VERISON) 1127 | .. _set_byte4(self.conn_id) 1128 | .. _to_cstring(strsub(self.salt, 1, 8)) 1129 | .. _set_byte2(const.DEFAULT_CAPABILITY) 1130 | .. strchar(const.DEFAULT_COLLATION_ID) 1131 | .. _set_byte2(self.status) 1132 | .. strchar(band(rshift(const.DEFAULT_CAPABILITY, 16), 0xff)) 1133 | .. strchar(band(rshift(const.DEFAULT_CAPABILITY, 24), 0xff)) 1134 | .. strchar(0x15) 1135 | .. strrep("\0", 10) 1136 | .. _to_cstring(strsub(self.salt, 9, -1)) 1137 | 1138 | local len = 1 + strlen(const.SERVER_VERISON) + 1 + 4 + 9 + 1 + 2 + 1 + 2 + 3 + 10 1139 | + strlen(strsub(self.salt, 9, -1)) 1140 | -- print("##############", len, #data) 1141 | return data, #data 1142 | end 1143 | 1144 | 1145 | function _M.new(self, conn) 1146 | if not conn then 1147 | local sock, err = tcp() 1148 | if not sock then 1149 | return nil, err 1150 | end 1151 | conn = { sock = sock, packet_no = -1 } 1152 | end 1153 | return setmetatable(conn, mt) 1154 | end 1155 | 1156 | 1157 | return _M 1158 | -------------------------------------------------------------------------------- /lib/resty/mysql/proxy.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2017 Libo Huang (huangnauh), UPYUN Inc. 2 | local checkups = require "resty.checkups.api" 3 | local const = require "resty.mysql.const" 4 | local packet = require "resty.mysql.packet" 5 | 6 | local type = type 7 | local rawget = rawget 8 | local ipairs = ipairs 9 | local setmetatable = setmetatable 10 | local tostring = tostring 11 | local strbyte = string.byte 12 | local strchar = string.char 13 | local strfind = string.find 14 | local format = string.format 15 | local strrep = string.rep 16 | local rand = math.random 17 | local req_sock = ngx.req.socket 18 | local null = ngx.null 19 | local ERR = ngx.ERR 20 | local WARN = ngx.WARN 21 | local INFO = ngx.INFO 22 | local log = ngx.log 23 | local spawn = ngx.thread.spawn 24 | local wait = ngx.thread.wait 25 | local slardar = slardar 26 | 27 | local _M = { _VERSION = '0.01' } 28 | 29 | local mt = { __index = _M } 30 | 31 | local conn_id = const.BASE_CONN_ID 32 | 33 | local function rand_str(length) 34 | local s = "" 35 | for i=1, length do 36 | s = s .. strchar(rand(256)-1) 37 | end 38 | return s 39 | end 40 | 41 | function _M.new(self, config) 42 | local sock, err = req_sock(true) 43 | if not sock then 44 | log(ERR, "failed to get the request socket: ", err) 45 | return nil, err 46 | end 47 | 48 | conn_id = conn_id + 1 49 | local conn = { 50 | sock = sock, 51 | conn_id = conn_id, 52 | user = config.user, 53 | password = config.password, 54 | status = config.status or const.SERVER_STATUS_MAP.SERVER_STATUS_AUTOCOMMIT, 55 | salt = rand_str(20), 56 | packet_no = -1, 57 | capability = config.capability or 0, 58 | max_packet_size = config.max_packet_size or const.MAX_PACKET_SIZE, 59 | } 60 | 61 | local pkt = packet:new(conn) 62 | return setmetatable({pkt = pkt}, mt) 63 | end 64 | 65 | 66 | local function backend(self) 67 | local ups = slardar.mysql 68 | local db = packet:new() 69 | db:set_timeout(10000) 70 | 71 | local backend_connect = function(host, port) 72 | local ok, err, errno, sqlstate = db:connect{ 73 | host = host, 74 | port = port, 75 | database = ups.name, 76 | user = ups.user, 77 | password = ups.pass, 78 | max_packet_size = 1024 * 1024 } 79 | 80 | if not ok and err then 81 | log(WARN, "failed to connect: ", 82 | err, ": ", errno, " ", sqlstate) 83 | end 84 | return ok, err 85 | end 86 | 87 | local ok, err = checkups.ready_ok("mysql", backend_connect) 88 | if not ok then 89 | return err 90 | end 91 | self.bkd = db 92 | end 93 | 94 | 95 | function _M.handshake(self) 96 | local data, len = self.pkt:init_handshake() 97 | local _, err = self.pkt:send_packet(data, len) 98 | if err then 99 | log(ERR, "failed to send initial handshake, err=",err) 100 | return err 101 | end 102 | 103 | local data, err = self.pkt:recv_packet() 104 | if err then 105 | log(ERR, "failed to read handshake response, err=",err) 106 | return err 107 | end 108 | 109 | err = self.pkt:parse_handshake_packet(data) 110 | if err then 111 | log(ERR, "failed to parse handshake packet, err=",err) 112 | self.pkt:send_error_packet({ 113 | errno=const.ERROR.ER_HANDSHAKE_ERROR, 114 | message=const.DEFAULT_MYSQL_ERRMESSAGE, 115 | sqlstate=const.DEFAULT_MYSQL_STATE}) 116 | return err 117 | end 118 | 119 | err = backend(self) 120 | if err then 121 | log(ERR, "failed to connect mysql, err=",err) 122 | self.pkt:send_error_packet({ 123 | errno=const.ERROR.ER_ABORTING_CONNECTION, 124 | message=const.DEFAULT_MYSQL_ERRMESSAGE, 125 | sqlstate=const.DEFAULT_MYSQL_STATE}) 126 | return err 127 | end 128 | 129 | local _, err = self.pkt:send_ok_packet() 130 | if err then 131 | log(ERR, "send ok handshake failed, err=",err) 132 | return err 133 | end 134 | return nil 135 | end 136 | 137 | 138 | local function query(self, data) 139 | -- print("query bkd send_data") 140 | local _, err = self.bkd:send_data(data) 141 | if err then 142 | log(ERR, "bkd failed to send_packet, err=",err) 143 | return false, err 144 | end 145 | 146 | -- print("query bkd read_result") 147 | local res, err, errno, sqlstate = self.bkd:read_result(true) 148 | if errno then 149 | self.pkt:send_error_packet({ 150 | errno=errno, 151 | message=err, 152 | sqlstate=sqlstate}) 153 | return true, nil 154 | elseif err then 155 | log(ERR, "bkd failed to send_packet, err=",err) 156 | self.pkt:send_error_packet({ 157 | errno=const.ERROR.ER_ABORTING_CONNECTION, 158 | message=const.DEFAULT_MYSQL_ERRMESSAGE, 159 | sqlstate=const.DEFAULT_MYSQL_STATE}) 160 | return false, err 161 | end 162 | 163 | -- print("query pkt send_result") 164 | _, err = self.pkt:send_result(res) 165 | if err then 166 | return false, err 167 | else 168 | return true, nil 169 | end 170 | end 171 | 172 | 173 | local function quit(self, data) 174 | local _, err = self.bkd:set_keepalive(10000, 100) 175 | if err then 176 | log(WARN, "set_keepalive failed, err=",err) 177 | end 178 | return false, nil 179 | end 180 | 181 | 182 | local supported = { 183 | [const.COM_MAP.COM_QUERY] = query, 184 | [const.COM_MAP.COM_QUIT] = quit, 185 | } 186 | 187 | 188 | local function dispatch(self, data) 189 | local func = supported[packet.cmd(data)] 190 | if func then 191 | return func(self, data) 192 | else 193 | self.pkt:send_error_packet({ 194 | errno=const.ERROR.ER_UNKNOWN_ERROR, 195 | message=const.DEFAULT_MYSQL_ERRMESSAGE, 196 | sqlstate=const.DEFAULT_MYSQL_STATE}) 197 | return true, nil 198 | end 199 | end 200 | 201 | 202 | function _M.process(self) 203 | while true do 204 | -- print("pkt recv_packet") 205 | local data, err = self.pkt:recv_packet() 206 | if err then 207 | log(ERR, "pkt failed to recv_packet, err=",err) 208 | break 209 | end 210 | 211 | if data and data ~= "" then 212 | -- print("type:", data[1], data) 213 | local ok, err = dispatch(self, data) 214 | -- print("ok:", ok, ", err:", err) 215 | if err or not ok then 216 | break 217 | end 218 | end 219 | end 220 | end 221 | 222 | 223 | return _M 224 | -------------------------------------------------------------------------------- /lib/resty/test.lua: -------------------------------------------------------------------------------- 1 | local proxy = require "resty.mysql.proxy" 2 | 3 | local conn, err = proxy:new({user="runner", password="runner123456"}) 4 | if err then 5 | return 6 | end 7 | 8 | err = conn:handshake() 9 | if err then 10 | return 11 | end 12 | 13 | conn:process() 14 | --------------------------------------------------------------------------------