Wrapping MYSQL_FIELD in a class

The MySQL Connector/C framework uses the MYSQL_FIELD (the actual name of the structure is st_mysql_field) to store the information for any column in a SQL table, such like the column name, type, and size.

Here we are about to describe a simple class, Field, that would provide an object-oriented wrapper to the raw C structure. Here we'll just provide access just for the more commonly used properties for a SQL column, it would be easy to extend the interface in the future.

Here is the Field class declaration:

class Field
{
private:
MYSQL_FIELD* field_; // 1.
public:
Field() : field_(0) {} // 2.
Field(MYSQL_FIELD* field) : field_(field) {}

_OPERATOR_BOOL() const { return (field_ != 0 ? _CONVERTIBLE_TO_TRUE : 0); } // 3.

const char* getName() const;
const int getType() const;
const int getSize() const;

void dumpDetails(std::ostream& os);
};

std::ostream& operator<<(std::ostream& os, const Field& fld); // 4.

1. pointer to the raw structure
2. ctor for dummy object
3. allow to use objects of this class in boolean context
4. convenience global function for putting the field name on a output stream

The getter functions are easy to be implemented:

const char* Field::getName() const
{
return field_ ? field_->name : "Dummy";
}

const int Field::getType() const
{
return field_ ? field_->type : MYSQL_TYPE_NULL; // 1.
}

const int Field::getSize() const
{
return field_ ? field_->name_length : 0;
}

1. for the dummy field I guess the best choice to represent its type is MYSQL_TYPE_NULL.

The "put to" global operator on the ostream is easy to implement, too:

std::ostream& operator<<(std::ostream& os, const Field& fld)
{
os << fld.getName();
return os;
}

Finally the dumpDetails() function, that is just meant to give an overview of the many internal details available on a MYSQL_FIELD object:

void Field::dumpDetails(std::ostream& os)
{
if(field_ == 0)
{
os << "Dummy" << std::endl;
return;
}

os << "Database name: " << field_->db << std::endl;
os << "Table name (or alias): " << field_->table << std::endl;
os << "Table name: " << field_->org_table << std::endl;
os << "Field name (or alias): " << field_->name << std::endl;
os << "Field name (or alias) length: " << field_->name_length << std::endl;
os << "Field name: " << field_->org_name << std::endl;
os << "Field name length: " << field_->org_name_length << std::endl;
os << "Field length: " << field_->length << std::endl;
os << "Current RS field max length: " << field_->max_length << std::endl;
os << "Default field value: " << (field_->def ? field_->def : "Not set") << std::endl;

os << "Field decimals: " << field_->decimals << std::endl;
os << "Field charset: " << field_->charsetnr << std::endl;
if(field_->charsetnr == 63)
os << "Field is binary (charsetnr == 63)" << std::endl;
os << "Field type: " << field_->type << std::endl;

if(IS_NUM(field_->type))
os << "Field is numeric" << std::endl;

os << "Field is ";
switch(field_->type)
{
case MYSQL_TYPE_DECIMAL:
os << "decimal" << std::endl;
break;
case MYSQL_TYPE_TINY:
os << "tiny" << std::endl;
break;
case MYSQL_TYPE_SHORT:
os << "short";
break;
case MYSQL_TYPE_LONG:
os << "long";
break;
case MYSQL_TYPE_FLOAT:
os << "float";
break;
case MYSQL_TYPE_DOUBLE:
os << "double";
break;
case MYSQL_TYPE_NULL:
os << "null";
break;
case MYSQL_TYPE_TIMESTAMP:
os << "timestamp";
break;
case MYSQL_TYPE_LONGLONG:
os << "long long";
break;
case MYSQL_TYPE_INT24:
os << "int24";
break;
case MYSQL_TYPE_DATE:
os << "date";
break;
case MYSQL_TYPE_TIME:
os << "time";
break;
case MYSQL_TYPE_DATETIME:
os << "datetime";
break;
case MYSQL_TYPE_YEAR:
os << "year";
break;
case MYSQL_TYPE_NEWDATE:
os << "(new) date";
break;
case MYSQL_TYPE_VARCHAR:
os << "varchar";
break;
case MYSQL_TYPE_BIT:
os << "bit";
break;
case MYSQL_TYPE_NEWDECIMAL:
os << "(new) decimal";
break;
case MYSQL_TYPE_ENUM:
os << "enum";
break;
case MYSQL_TYPE_SET:
os << "set";
break;
case MYSQL_TYPE_TINY_BLOB:
os << "tiny blob";
break;
case MYSQL_TYPE_MEDIUM_BLOB:
os << "medium blob";
break;
case MYSQL_TYPE_LONG_BLOB:
os << "long blob";
break;
case MYSQL_TYPE_BLOB:
os << "blob";
break;
case MYSQL_TYPE_VAR_STRING:
os << "var string";
break;
case MYSQL_TYPE_STRING:
os << "string";
break;
case MYSQL_TYPE_GEOMETRY:
os << "geometry";
break;
default:
os << "an unexpected type";
break;
}
os << std::endl;

if(field_->flags & NOT_NULL_FLAG)
os << "Field can't be NULL" << std::endl;
if(field_->flags & PRI_KEY_FLAG)
os << "Field part of a PK" << std::endl;
if(field_->flags & UNIQUE_KEY_FLAG)
os << "Field part of a Unique Key" << std::endl;
if(field_->flags & MULTIPLE_KEY_FLAG)
os << "Field part of a Multiple Key" << std::endl;
if(field_->flags & UNSIGNED_FLAG)
os << "Field is unsigned" << std::endl;
if(field_->flags & ZEROFILL_FLAG)
os << "Field is zero-filled" << std::endl;
if(field_->flags & BINARY_FLAG)
os << "Field is binary" << std::endl;
if(field_->flags & AUTO_INCREMENT_FLAG)
os << "Field is auto-incrementing" << std::endl;
if(field_->flags & NO_DEFAULT_VALUE_FLAG)
os << "Field has no default value" << std::endl;
}

No comments:

Post a Comment