10bet网址
MySQL内部手册


23.10.6实现rnd_next()方法

在表初始化之后,MySQL服务器将调用处理程序的[custom-engine.html#custom-engine-api-reference-rnd_nextrnd_next ()方法,直到满足服务器的搜索条件或到达文件的末尾,在这种情况下,处理程序返回HA_ERR_END_OF_FILE

rnd_next ()方法的参数为*缓冲区.的*缓冲区参数必须用MySQL内部格式的表行内容填充。

服务器使用三种数据格式:定长行、变长行和带有BLOB指针的变长行。在每种格式中,列都按照CREATE TABLE语句定义的顺序出现。表定义存储在.frm文件,优化器和处理程序都能够访问来自同一个源的表元数据表格结构)。

每一种格式都以一个NULL位图开始,每一列为空。有8个可空列的表将有一个单字节位图;有9到16个可空列的表将有一个两字节的位图,依此类推。一个例外是固定宽度的表,它有一个额外的起始位,这样一个有8个可空列的表将有一个两个字节的位图。

在NULL位图之后是列,一个接一个。每一列的大小为数据类型.在服务器中,列数据类型定义在sql / field.cc文件。在固定长度的行格式中,列只是一个接一个地排列。在一个变长行中,VARCHAR列编码为一个或两个字节的长度,后面跟着一个字符串。在一个变长行与列中,每个blob由两部分表示:第一部分是表示对象实际大小的整数的指针在内存中。

行转换(或打包)的示例可以从rnd_next ()在任何表处理程序中。在ha_tina.cc,例如,代码在find_current_row ()说明了表格结构(由表指向)和字符串对象(命名为buffer)可以用来打包CSV文件中的字符数据。将一行写回磁盘需要相反的转换,即从内部格式解压缩。

下面的示例来自CSV存储引擎:

int ha_tina::rnd_next(字节*buf) {DBUG_ENTER("ha_tina::rnd_next");statistic_increment(表- > in_use - > status_var。ha_read_rnd_next_count &LOCK_status);current_position = next_position;if (!share->mapped_file) DBUG_RETURN(HA_ERR_END_OF_FILE);if (HA_ERR_END_OF_FILE == find_current_row(buf)) DBUG_RETURN(HA_ERR_END_OF_FILE);记录+ +;DBUG_RETURN (0);}

内部行格式到CSV行格式的转换在find_current_row ()方法:

Int ha_tina::find_current_row(byte *buf) {byte *mapped_ptr= (byte *)share->mapped_file + current_position;字节* end_ptr;DBUG_ENTER(“ha_tina:: find_current_row”);/* EOF应该算作新行*/ if ((end_ptr= find_eoln(share->mapped_file, current_position, share->file_stat.st_size)) == 0) DBUG_RETURN(HA_ERR_END_OF_FILE);for(字段**字段=table->字段;*字段;字段++){buffer.length(0);mapped_ptr + +;//从(;mapped_ptr != end_ptr;mapped_ptr++){//需要转换换行! if (*mapped_ptr == '"' && (((mapped_ptr[1] == ',') && (mapped_ptr[2] == '"')) || (mapped_ptr == end_ptr -1 ))) { mapped_ptr += Move past the , and the " break; } if (*mapped_ptr == '\\' && mapped_ptr != (end_ptr - 1)) { mapped_ptr++; if (*mapped_ptr == 'r') buffer.append('\r'); else if (*mapped_ptr == 'n' ) buffer.append('\n'); else if ((*mapped_ptr == '\\') || (*mapped_ptr == '"')) buffer.append(*mapped_ptr); else /* This could only happed with an externally created file */ { buffer.append('\\'); buffer.append(*mapped_ptr); } } else buffer.append(*mapped_ptr); } (*field)->store(buffer.ptr(), buffer.length(), system_charset_info); } next_position= (end_ptr - share->mapped_file)+1; /* Maybe use \N for null? */ memset(buf, 0, table->s->null_bytes); /* We do not implement nulls! */ DBUG_RETURN(0); }