 4985bf9b6e
			
		
	
	4985bf9b6e
	
	
	
		
			
			Regexp functions were not listed among the builtin read-only functions and consequently any SELECT using one of those was routed to master.
		
			
				
	
	
		
			420 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			420 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * @licence@
 | |
|  */
 | |
| 
 | |
| #include "builtin_functions.h"
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <maxscale/debug.h>
 | |
| 
 | |
| static struct
 | |
| {
 | |
|     bool inited;
 | |
| } unit = { false };
 | |
| 
 | |
| // The functions have been taken from:
 | |
| // https://mariadb.com/kb/en/mariadb/functions-and-operators/
 | |
| 
 | |
| static const char* BUILTIN_FUNCTIONS[] =
 | |
| {
 | |
|     /*
 | |
|      * Bit Functions and Operators
 | |
|      * https://mariadb.com/kb/en/mariadb/bit-functions-and-operators
 | |
|      */
 | |
|     "bit_count",
 | |
| 
 | |
|     /*
 | |
|      * Control Flow Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/control-flow-functions/
 | |
|      */
 | |
|     "if",
 | |
|     "ifnull",
 | |
|     "nullif",
 | |
| 
 | |
|     /*
 | |
|      * Date and Time Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/date-and-time-functions/
 | |
|      */
 | |
|     "adddate",
 | |
|     "addtime",
 | |
|     "convert_tz",
 | |
|     "curdate",
 | |
|     "current_date",
 | |
|     "current_time",
 | |
|     "current_timestamp",
 | |
|     "curtime",
 | |
|     "date",
 | |
|     "datediff",
 | |
|     "date_add",
 | |
|     "date_format",
 | |
|     "date_sub",
 | |
|     "day",
 | |
|     "dayname",
 | |
|     "dayofmonth",
 | |
|     "dayofweek",
 | |
|     "dayofyear",
 | |
|     "extract",
 | |
|     "from_days",
 | |
|     "from_unixtime",
 | |
|     "get_format",
 | |
|     "hour",
 | |
|     "last_day",
 | |
|     "localtime",
 | |
|     "localtimestamp",
 | |
|     "makedate",
 | |
|     "maketime",
 | |
|     "microsecond",
 | |
|     "minute",
 | |
|     "month",
 | |
|     "monthname",
 | |
|     "now",
 | |
|     "period_add",
 | |
|     "period_diff",
 | |
|     "quarter",
 | |
|     "second",
 | |
|     "sec_to_time",
 | |
|     "str_to_date",
 | |
|     "subdate",
 | |
|     "subtime",
 | |
|     "sysdate",
 | |
|     "time",
 | |
|     "timediff"
 | |
|     "timestamp",
 | |
|     "timestampadd",
 | |
|     "timestampdiff",
 | |
|     "time_format",
 | |
|     "time_to_sec",
 | |
|     "to_days",
 | |
|     "to_seconds",
 | |
|     "unix_timestamp",
 | |
|     "utc_date",
 | |
|     "utc_time",
 | |
|     "week",
 | |
|     "weekday",
 | |
|     "weekofyear",
 | |
|     "year",
 | |
|     "yearweek",
 | |
| 
 | |
|     /*
 | |
|      * Columns Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/dynamic-columns-functions/
 | |
|      */
 | |
|     "column_check",
 | |
|     "column_exists",
 | |
|     "column_get",
 | |
|     "column_json",
 | |
|     "column_list",
 | |
| 
 | |
|     /*
 | |
|      * Encryption, Hashing and Compression Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/encryption-hashing-and-compression-functions/
 | |
|      */
 | |
|     "aes_decrypt",
 | |
|     "aes_encrypt",
 | |
|     "compress",
 | |
|     "decode",
 | |
|     "des_decrypt",
 | |
|     "des_encrypt",
 | |
|     "encode",
 | |
|     "encrypt",
 | |
|     "md5",
 | |
|     "old_password",
 | |
|     "password",
 | |
|     "sha1",
 | |
|     "sha2",
 | |
|     "uncompress",
 | |
|     "uncompressed_length",
 | |
| 
 | |
|     /*
 | |
|      * Comparison Operators
 | |
|      * https://mariadb.com/kb/en/mariadb/comparison-operators/
 | |
|      */
 | |
|     "coalesce",
 | |
|     "greatest",
 | |
|     "interval",
 | |
|     "isnull",
 | |
|     "least",
 | |
| 
 | |
|     /*
 | |
|      * Functions and Modifiers for use with GROUP BY
 | |
|      * https://mariadb.com/kb/en/mariadb/functions-and-modifiers-for-use-with-group-by/
 | |
|      */
 | |
|     "avg",
 | |
|     "bit_and",
 | |
|     "bit_or",
 | |
|     "bit_xor",
 | |
|     "count",
 | |
|     "group_concat",
 | |
|     "max",
 | |
|     "min",
 | |
|     "std",
 | |
|     "stddev",
 | |
|     "stddev_pop",
 | |
|     "stddev_samp",
 | |
|     "sum",
 | |
|     "variance",
 | |
|     "var_pop",
 | |
|     "var_samp",
 | |
| 
 | |
|     /*
 | |
|      * Geographic Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/geographic-functions/
 | |
|      */
 | |
| 
 | |
|     // Geometry Constructors
 | |
|     // https://mariadb.com/kb/en/mariadb/geometry-constructors/
 | |
|     "geometrycollection",
 | |
|     "linestring",
 | |
|     "multilinestring",
 | |
|     "multipoint",
 | |
|     "point",
 | |
|     "polygon",
 | |
|     "st_buffer",
 | |
|     "st_convexhull",
 | |
|     "st_intersection",
 | |
|     "st_pointonsurface",
 | |
|     "st_symdifference",
 | |
|     "std_union",
 | |
| 
 | |
|     // Geometry Properties
 | |
|     // https://mariadb.com/kb/en/mariadb/geometry-properties/
 | |
|     // TODO
 | |
| 
 | |
|     // Geometry Relations
 | |
|     // TODO
 | |
| 
 | |
|     // LineString Properties
 | |
|     // TODO
 | |
| 
 | |
|     // MBR
 | |
|     // TODO
 | |
| 
 | |
|     // Point Propertoes
 | |
|     // TODO
 | |
| 
 | |
|     // Polygon Properties
 | |
|     // TODO
 | |
| 
 | |
|     // WKB
 | |
|     // TODO
 | |
| 
 | |
|     // WKT
 | |
|     // https://mariadb.com/kb/en/mariadb/wkt/
 | |
|     "MLineFromText",
 | |
|     "MPointFromText",
 | |
|     "MPolyFromText",
 | |
|     "ST_AsText",
 | |
|     "ST_ASWKT",
 | |
|     "ST_GeomCollFromText",
 | |
|     "ST_GeometryFromText",
 | |
|     "ST_LineFromText",
 | |
|     "ST_PointFromText",
 | |
|     "ST_PolyFromText",
 | |
|     // Deprecated
 | |
|     "geomfromtext",
 | |
| 
 | |
|     /*
 | |
|      * Information Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/information-functions/
 | |
|      */
 | |
|     "benchmark",
 | |
|     "binlog_gtid_pos",
 | |
|     "charset",
 | |
|     "coercibility",
 | |
|     "collation",
 | |
|     "connection_id",
 | |
|     "current_role",
 | |
|     "current_user",
 | |
|     "database",
 | |
|     "decode_histogram",
 | |
|     "found_rows",
 | |
|     "last_insert_id",
 | |
|     "row_count",
 | |
|     "schema",
 | |
|     "session_user",
 | |
|     "system_user",
 | |
|     "user",
 | |
|     "version",
 | |
| 
 | |
|     /*
 | |
|      * Miscellanesous Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/miscellaneous-functions/
 | |
|      */
 | |
|     "default",
 | |
|     "get_lock",
 | |
|     "inet6_aton",
 | |
|     "inet6_ntoa",
 | |
|     "inet_aton",
 | |
|     "inet_ntoa",
 | |
|     "is_free_lock",
 | |
|     "is_ipv4",
 | |
|     "is_ipv4_compat",
 | |
|     "is_ipv4_mapped",
 | |
|     "is_ipv6",
 | |
|     "is_used_lock",
 | |
|     "last_value",
 | |
|     "master_gtid_wait",
 | |
|     "master_pos_wait",
 | |
|     "name_const",
 | |
|     "release_lock",
 | |
|     "sleep",
 | |
|     "uuid",
 | |
|     "uuid_short",
 | |
|     "values",
 | |
| 
 | |
|     /*
 | |
|      * Numeric Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/numeric-functions/
 | |
|      */
 | |
|     "abs",
 | |
|     "acos",
 | |
|     "asin",
 | |
|     "atan",
 | |
|     "atan2",
 | |
|     "ceil",
 | |
|     "ceiling",
 | |
|     "conv",
 | |
|     "cos",
 | |
|     "cot",
 | |
|     "crc32",
 | |
|     "degrees",
 | |
|     "div",
 | |
|     "exp",
 | |
|     "floor",
 | |
|     "greatest",
 | |
|     "least",
 | |
|     "ln",
 | |
|     "log",
 | |
|     "log10",
 | |
|     "log2",
 | |
|     "mod",
 | |
|     "oct",
 | |
|     "pi",
 | |
|     "pow",
 | |
|     "power",
 | |
|     "radians",
 | |
|     "rand",
 | |
|     "round",
 | |
|     "sign",
 | |
|     "sin",
 | |
|     "sqrt",
 | |
|     "tan",
 | |
|     "truncate",
 | |
| 
 | |
|     /*
 | |
|      * String Functions
 | |
|      * https://mariadb.com/kb/en/mariadb/string-functions/
 | |
|      */
 | |
|     "ascii",
 | |
|     "bin",
 | |
|     "bit_length",
 | |
|     "cast",
 | |
|     "char",
 | |
|     "character_length",
 | |
|     "char_length",
 | |
|     "concat",
 | |
|     "concat_ws",
 | |
|     "convert",
 | |
|     "elt",
 | |
|     "export_set",
 | |
|     "extractvalue",
 | |
|     "field",
 | |
|     "find_in_set",
 | |
|     "format",
 | |
|     "hex",
 | |
|     "insert",
 | |
|     "instr",
 | |
|     "lcase",
 | |
|     "left",
 | |
|     "length",
 | |
|     "like",
 | |
|     "load_file",
 | |
|     "locate",
 | |
|     "lower",
 | |
|     "lpad",
 | |
|     "ltrim",
 | |
|     "make_set",
 | |
|     "mid",
 | |
|     "octet_length",
 | |
|     "ord",
 | |
|     "position",
 | |
|     "quote",
 | |
|     "repeat",
 | |
|     "replace",
 | |
|     "reverse",
 | |
|     "right",
 | |
|     "rpad",
 | |
|     "rtrim",
 | |
|     "soundex",
 | |
|     "space",
 | |
|     "strcmp",
 | |
|     "substr",
 | |
|     "substring",
 | |
|     "substring_index",
 | |
|     "trim",
 | |
|     "ucase",
 | |
|     "unhex",
 | |
|     "updatexml",
 | |
|     "upper",
 | |
|     "from_base64",
 | |
|     "to_base64",
 | |
|     "weight_string",
 | |
| 
 | |
|     /*
 | |
|      * Regex functions
 | |
|      * https://mariadb.com/kb/en/mariadb/regular-expressions-functions/
 | |
|      */
 | |
|     "regexp",
 | |
|     "regexp_instr",
 | |
|     "regexp_replace",
 | |
|     "regexp_substr",
 | |
|     "rlike",
 | |
| 
 | |
|     /*
 | |
|      * http://dev.mysql.com/doc/refman/5.7/en/row-subqueries.html
 | |
|      */
 | |
|     "row"
 | |
| };
 | |
| 
 | |
| const size_t N_BUILTIN_FUNCTIONS = sizeof(BUILTIN_FUNCTIONS) / sizeof(BUILTIN_FUNCTIONS[0]);
 | |
| 
 | |
| // NOTE: sort_compare and search_compare are not identical, so don't
 | |
| // NOTE: optimize either of them away.
 | |
| static int sort_compare(const void* key, const void* value)
 | |
| {
 | |
|     return strcasecmp(*(const char**) key, *(const char**) value);
 | |
| }
 | |
| 
 | |
| static int search_compare(const void* key, const void* value)
 | |
| {
 | |
|     return strcasecmp((const char*) key, *(const char**) value);
 | |
| }
 | |
| 
 | |
| //
 | |
| // API
 | |
| //
 | |
| 
 | |
| void init_builtin_functions()
 | |
| {
 | |
|     ss_dassert(!unit.inited);
 | |
| 
 | |
|     qsort(BUILTIN_FUNCTIONS, N_BUILTIN_FUNCTIONS, sizeof(char*), sort_compare);
 | |
| 
 | |
|     unit.inited = true;
 | |
| }
 | |
| 
 | |
| void finish_builtin_functions()
 | |
| {
 | |
|     ss_dassert(unit.inited);
 | |
|     unit.inited = false;
 | |
| }
 | |
| 
 | |
| bool is_builtin_readonly_function(const char* key)
 | |
| {
 | |
|     ss_dassert(unit.inited);
 | |
| 
 | |
|     char* value = bsearch(key, BUILTIN_FUNCTIONS, N_BUILTIN_FUNCTIONS, sizeof(char*), search_compare);
 | |
| 
 | |
|     return value ? true : false;
 | |
| }
 |