In the previous article, we wrote, compiled, and tested our first custom data type for MariaDB using the Type_handler framework.
But currently, aside from allowing the use of its new name (MONEY) and listing it in the metadata, our new data type behaves exactly like a DOUBLE, the class it inherits from.
In this article, we will extend our data type just a bit by transforming the result into a VARCHAR and adding a currency sign to it: the dollar sign, ($).
This is the expected result:
MariaDB [test]> insert into t1 (amount) values (41578.4);
Query OK, 1 row affected (0.016 sec)
MariaDB [test]> insert into t1 (amount) values (15678.309);
Query OK, 1 row affected (0.006 sec)
MariaDB [test]> select * from t1 order by amount desc;
+----+-----------+
| id | amount |
+----+-----------+
| 1 | $41578.40 |
| 2 | $15678.31 |
+----+-----------+
2 rows in set (0.006 sec)
As you can see, we just added the dollar sign to the value.
Protocol
To control how our data type sends the data, we need to override another method from Type_handler_double: protocol_send_type().
In sql_type_money.h, in our class Type_handler_money, we add in the public method the following definition:
protocol_send_type_t protocol_send_type() const override
{
return PROTOCOL_SEND_STRING;
}
We also add in the other class, Field_money, the following override:
bool send(Protocol *protocol) override;
Make Send Field
In plugin.cc, we had defined Field_money::make_send_field(), which sent the field as a double. But now we need to change that and send more specifications:
void Field_money::make_send_field(Send_field *field)
{
Field::make_send_field(field);
field->set_handler(&type_handler_varchar);
field->set_data_type_name(LEX_CSTRING{STRING_WITH_LEN("money")});
field->length= MY_MAX(field->length, (ulong) (field_length + 32));
field->decimals= 0;
}
Here, we call the base Field class implementation, skipping Field_double entirely. This fills in basic metadata such as column name, null-bit, flags, etc.
The next line instructs the protocol to send the column as VARCHAR(string). We need this because our custom method emits text with a ‘$’ prefix. The client must interpret those bytes as a string, not as a double.
The next line is obvious; it sets the extended metadata type name to “money”. This is for clients that support this feature, such as mariadb-connector-j.
Then we adjust the display width and the last line, and we tell the client that this is not a decimal number but a string.
And then we specify the override for Field_money::send():
bool Field_money::send(Protocol *protocol)
{
DBUG_ASSERT(marked_for_read());
String numeric_buf;
String money_buf;
String *numeric= Field_double::val_str(&numeric_buf, &numeric_buf);
money_buf.set_charset(numeric->charset());
if (money_buf.append('$') || money_buf.append(*numeric))
return true;
return protocol->store(&money_buf);
}
This is where we retrieve the value and append the $ sign.
The plugin’s actual code is in the part3 branch.
In the next article, we will extend our data type a bit more and override another method just for fun.
Meanwhile, happy coding!
- Adding a New Data Type to MariaDB with Type_handler – Part 0
- Adding a New Data Type to MariaDB with Type_handler – Part 1
- Adding a New Data Type to MariaDB with Type_handler – Part 2
- Adding a New Data Type to MariaDB with Type_handler – Part 3