SILVERCODERS®
In EnglishPo polsku

SqlUnify Dokumentacja

Menu

Features

Implemented:

  • SELECT without UNIONs
  • INSERT
  • UPDATE
  • DELETE
  • comments

TODO:

  • SELECT with UNIONs
  • subqueries
  • complex JOINs
  • CREATE TABLE
  • ALTER TABLE
  • strings written as $$string$$

MySQL transformations

TRUE
1
FALSE
0
UNKNOW
NULL
SELECT * FROM table LIMIT 20 OFFSET 10
SELECT * FROM table LIMIT 10,20
SELECT * FROM table OFFSET 10
FAIL
SELECT * FROM table LIMIT 10,-1
INTERVAL "1 day"
INTERVAL 1 day
INTERVAL "2 days"
INTERVAL 2 day
INTERVAL "2 days 1 hour 15 minutes"
INTERVAL 2 day + INTERVAL 1 hour + INTERVAL 15 minute
expression::type
CASE(expression AS type)
CAST(expression AS INT2)
CAST(expression AS INT4)
CAST(expression AS INT8)
CAST(expression AS SERIAL4)
CAST(expression AS SERIAL8)
CASE(expression AS SIGNED INTEGER)
expression::BOOL
CASE(expression AS UNSIGNED INTEGER)
CAST(expression AS VARCHAR)
CAST(expression AS CAHR)
CAST(expression AS TEXT)
CASE(expression AS BINARY)
CAST(expression AS TIMEZ)
CASE(expression AS TIME)
CAST(expression AS TIMESTAMP)
CAST(expression AS TIMESTAMPZ)
CASE(expression AS DATETIME)
SELECT boolean_expression FROM table
SELECT IF(boolean_expression IS NULL, 'UNKNOW', IF(boolean_expression, 'TRUE', 'FALSE'))
SELECT '2005-01-01'::DATETIME AT TIMEZONE '+01:00'
FAIL
INSERT INTO table VALUES(DEFAULT
FAIL
INSERT INTO table (field) VALUES(DEFAULT)
INSERT INTO table (field) VALUES(DEFAULT(field))
SELECT "field" FROM "table"
SELECT `field` FROM `table`
SELECT |/a FROM table
SELECT SQRT(a) FROM table
SELECT ||/a FROM table
SELECT POWER(a, 1/3) FROM table
SELECT a ^ b FROM table
SELECT POWER(a, b) FROM table
SELECT @a FROM table
SELECT ABS(a) FROM table
SELECT a IS TRUE FROM table
SELECT IF(a IS NULL, 0, a != 0) FROM table
SELECT a IS FALSE FROM table
SELECT IF(a IS NULL, 0, a = 0) FROM table
SELECT a IS UNKOW FROM table
SELECT a IS NULL FROM table
SELECT a IS NOT TRUE FROM table
SELECT IF(a IS NULL, 1, a = 0) FROM table
SELECT a IS NOT FALSE FROM table
SELECT IF(a IS NULL, 1, a != 0) FROM table
SELECT a IS NOT UNKOW FROM table
SELECT a IS NOT NULL FROM table
SELECT a IS DISTINCT FROM b FROM table
SELECT IF(a IS NULL, IF(b IS NULL, 0, 1), IF(b IS NULL, 1, a != b)) FROM table
SELECT a # b FROM table
SELECT a ^ b FROM table
SELECT ~a FROM table
SELECT ~(~(~(a) - 1)) FROM table
SELECT a || b FROM table
SELECT CONCAT(a, b) FROM table
SELECT a LIKE b FROM table
SELECT a LIKE BINARY b FROM table
SELECT a ~~ b FROM table
SELECT a LIKE BINARY b FROM table
SELECT a NOT LIKE b FROM table
SELECT a NOT LIKE BINARY b FROM table
SELECT a !~~ b FROM table
SELECT a NOT LIKE BINARY b FROM table
SELECT a ILIKE b FROM table
SELECT a LIKE b FROM table
SELECT a ~~* b FROM table
SELECT a LIKE b FROM table
SELECT a NOT ILIKE b FROM table
SELECT a NOT LIKE b FROM table
SELECT a !~~* b FROM table
SELECT a NOT LIKE b FROM table
SELECT a SIMILAR TO b FROM table
FAIL
SELECT a NOT SIMILAR TO b FROM table
FAIL
SELECT a ~ b FROM table
SELECT BINARY(a) REGEXP b FROM table
SELECT a ~* b FROM table
SELECT a REGEXP b FROM table
SELECT a !~ b FROM table
SELECT NOT (BINARY(a) REGEXP b ) FROM table
SELECT a !~* b FROM table
SELECT NOT(a REGEXP b) FROM table
SELECT date + integer FROM table
SELECT date + INTERVAL integer DAY FROM talbe
SELECT date + time FROM table
SELECT ADDTIME(date, time) FROM table
SELECT time + date FROM table
SELECT ADDTIME(date, time) FROM table
SELECT interval + interval FROM table
FAIL
SELECT time + interval FROM table
FAIL
SELECT interval + time FROM table
FAIL
SELECT date - date FROM table
SELECT TO_DAYS(date) - TO_DAYS(date)
SELECT time - time FROM table
FAIL
SELECT date - integer FROM table
SELECT date - INTERVAL integer DAY FROM talbe
SELECT interval - interval FROM table
FAIL
SELECT time - interval FROM table
FAIL
SELECT interval - time FROM table
FAIL
SELECT timestamp - timestamp FROM table
FAIL
SELECT -INTERVAL "1 day" FROM table
SELECT INTERVAL -1 DAY FROM table
SELECT interval * float FROM table
FAIL
SELECT interval / float FROM table
FAIL
SELECT (date1, date2) OVERLAPS (date3, date4) FROM table
SELECT (NOT((date4 < date1) OR (date3 > date2))) FROM table
SELECT (date1, interval1) OVERLAPS (date2, interval2) FROM table
SELECT (NOT((date2 + interval2 < date1) OR (date2 > date1 + interval1))) FROM table
SELECT CBRT(a) FROM table
SELECT POWER(a, 1/3) FROM table
SELECT LOG(a) FROM table
SELECT LOG(10, a) FROM table
SELECT RANDOM()
SELECT RAND()
SELECT SETSEED()
FAIL
SELECT TRUNC(a) FROM table
SELECT TRUNCATE(a, 0) FROM talbe
SELECT WIDTH_BUCKET()
FAIL
SELECT CONVERT()
FAIL
SELECT OVERLAY(expression1 PLACING expression2 FROM expression3 FOR expression4 FROM table
SELECT CONCAT(SUBSTR(expression1, 1, expression3 - 1), expression2, SUBSTR(expression1, expression3 + expression4)) FROM table
SELECT OVERLAY(expression1 PLACING expression2 FOR expression4) FROM table
FAIL
SELECT OVERLAY(expression1 PLACING expression2 FROM expression3) FROM table
FAIL
SELECT OVERLAY(expression1 PLACING expression2) FROM table
FAIL
SUBSTRING with regular expression
FAIL
SELECT CHR(a) FROM table
SELECT CHAR(a) FROM talbe
SELECT DECODE()
FAIL
SELECT ENCODE()
FAIL
SELECT INITCAP()
FAIL
SELECT LTRIM(string, ' ') FROM table
SELECT LTRIM(string) FROM table
SELECT LTRIM(string, char) FROM table
SELECT TRIM(LEADING char FROM string) FROM table
SELECT LTRIM(string, string)
FAIL
SELECT PG_CLIENT_ENCODING()
FAIL
SELECT QUOTE_IDENT()
FAIL
SELECT QUOTE_LITERAL()
FAIL
SELECT RTRIM(string, string)
FAIL
SELECT RTRIM(string, ' ') FROM table
SELECT RTRIM(string) FROM table
SELECT RTRIM(string, char) FROM table
SELECT TRIM(TRAILING char FROM string) FROM table
SELECT RTRIM(string, string)
FAIL
SELECT SPLIT_PART()
FAIL
SELECT STRPOS(string1, string2) FROM table
SELECT POSITION(string2 IN string1) FROM table
SELECT TO_ASCII()
FAIL
SELECT TO_HEX()
FAIL
SELECT TRANSLATE()
FAIL
SELECT AGE()
FAIL
SELECT DATE_PART("CENTURY", date) FROM table
SELECT FLOOR((EXTRACT(YEAR FROM date) + 99) / 100) FROM table
SELECT DATE_PART("CENTURY", interval) FROM table
SELECT FLOOR((EXTRACT(YEAR FROM '0000-01-01 00:00:00' interval - INTERVAL 1 month - INTERRVAL 1 day) + 99) / 100) FROM table
SELECT DATE_PART("DAY", date) FROM table
SELECT DAYOFMONTH(date) FROM table
SELECT DATE_PART("DAY", interval) FROM table
SELECT DAYOFMONTH('0000-01-01 00:00:00' + interval) FROM table
SELECT DATE_PART("DECADE", date) FROM table
SELECT FLOOR(EXTRACT(YEAR FROM date) / 10) FROM table
SELECT DATE_PART("DECADE", interval) FROM table
SELECT FLOOR(EXTRACT(YAR FROM '0000-01-01 00:00:00' + interval - INTERVAL 1 month - INTERVAL 1 day) / 10) FROM table
SELECT DATE_PART("DOW", date) FROM table
SELECT (DAYOFWEEK(date) -1) FROM table
SELECT DATE_PART("DOW", interval) FROM table
FAIL
SELECT DATE_PART("DOY", date) FROM table
SELECT DAYOFYEAR(date) FROM table
SELECT DATE_PART("DOY", interval) FROM table
FAIL
SELECT DATE_PART("EPOCH", date) FROM table
SELECT UNIX_TIMESTAMP(date) FROM table
SELECT DATE_PART("EPOCH", interval) FROM table
SELECT UNIX_TIMESTAMP('1970-01-01 00:00:00' + interval) FROM table
SELECT DATE_PART("HOUR", date) FROM table
SELECT HOUR(date) FROM table
SELECT DATE_PART("HOUR", interval) FROM table
SELECT HOUR('0000-01-01 00:00:00' + interval) FROM table
SELECT DATE_PART("MICROSECONDS", date) FROM table
SELECT (MICROSECOND(date) + 1000000 * SECOND(date)) FROM table
SELECT DATE_PART("MICROSECONDS", interval) FROM table
SELECT (MICROSECOND('0000-01-01 00:00:00' + interval) + 1000000 * SECOND('000-01-01 00:00:00' + interval)) FROM table
SELECT DATE_PART("MILLENIUM", date) FROM table
SELECT FLOOR((EXTRACT(YEAR FROM date) + 999) / 1000) FROM table
SELECT DATE_PART("MILLENIUM", interval) FROM table
SELECT FLOOR((EXTRACt(YEAR FROM '0000-01-01 00:00:00') + 999) / 1000) FROM table
SELECT DATE_PART("MILISECONDS", date) FROM table
SELECT (FLOOR(MICROSECONDS(date)) / 1000 + 1000 * SECOND(date)) FROM table
SELECT DATE_PART("MILISECONDS", interval) FROM table
SELECT (FLOOR(MILISECONDS('0000-01-01 00:00:00' + interval)) / 1000 + 1000 * SECOND('0000-01-01 00:00:00' + interval)) FROM table
SELECT DATE_PART("MINUTE", date) FROM table
SELECT MINUTE(date) FROM table
SELECT DATE_PART("MINUTE", interval) FROM table
SELECT MINUTE('0000-01-01 00:00:00' + interval) FROM table
SELECT DATE_PART("MONTH", date) FROM table
SELECT MONTH(date) FROM table
SELECT DATE_PART("MONTH", interval) FROM table
SELECT (MONTH('0000-01-01 00:00:00' + interval) - 1) FROM table
SELECT DATE_PART("QUARTER", date) FROM table
SELECT FLOOR((MONTH(date) - 2 / 3)) FROM table
SELECT DATE_PART("QUARTER", interval) FROM table
SELECT FLOOR((MONTH('0000-01-01 00:00:00' + interval) - 1) / 3) FROM table
SELECT DATE_PART("SECOND", date) FROM table
SELECT (SECOND(date) + MICROSECOND(date) / 1000000) FROM table
SELECT DATE_PART("SECOND", interval) FROM table
SELECT (SECOND('0000-01-01 00:00:00' + interval) + MICROSECOND('0000-01-01 00:00:00' + interval) / 1000000) FROM table
SELECT DATE_PART("WEEK", date) FROM table
SELECT WEEK(date, 7) FROM table
SELECT DATE_PART("WEEK", interval) FROM table
FAIL
SELECT DATE_PART("YEAR", date) FROM table
SELECT YEAR(date) FROM table
SELECT DATE_PART("YEAR", interval) FROM table
SELECT YEAR('0000-01-01' + interval - INTERVAL 1 month - INTERVAL 1 day) FROM table
SELECT EXTRACT("CENTURY", date) FROM table
SELECT FLOOR((EXTRACT(YEAR FROM date) + 99) / 100) FROM table
SELECT EXTRACT("CENTURY", interval) FROM table
SELECT FLOOR((EXTRACT(YEAR FROM '0000-01-01 00:00:00' + interval - INTERVAL 1 month - INTERRVAL 1 day) + 99) / 100) FROM table
SELECT EXTRACT(DAY FROM date) FROM table
SELECT DAYOFMONTH(date) FROM table
SELECT EXTRACT(DAY FROM interval) FROM table
SELECT DAYOFMONTH('0000-01-01 00:00:00' + interval) FROM table
SELECT EXTRACT(DECADE FROM date) FROM table
SELECT FLOOR(EXTRACT(YEAR FROM date) / 10) FROM table
SELECT EXTRACT(DECADE FROM interval) FROM table
SELECT FLOOR(EXTRACT(YAR FROM '0000-01-01 00:00:00' + interval - INTERVAL 1 month - INTERVAL 1 day) / 10) FROM table
SELECT EXTRACT(DOW FROM date) FROM table
SELECT (DAYOFWEEK(date) -1) FROM table
SELECT EXTRACT(DOW FROM interval) FROM table
FAIL
SELECT EXTRACT(DOY FROM date) FROM table
SELECT DAYOFYEAR(date) FROM table
SELECT EXTRACT(DOY FROM interval) FROM table
FAIL
SELECT EXTRACT(EPOCH FROM date) FROM table
SELECT UNIX_TIMESTAMP(date) FROM table
SELECT EXTRACT(EPOCH FROM interval) FROM table
SELECT UNIX_TIMESTAMP('1970-01-01 00:00:00' + interval) FROM table
SELECT EXTRACT(HOUR FROM date) FROM table
SELECT HOUR(date) FROM table
SELECT EXTRACT(HOUR FROM interval) FROM table
SELECT HOUR('0000-01-01 00:00:00' + interval) FROM table
SELECT EXTRACT(MICROSECONDS FROM date) FROM table
SELECT (MICROSECOND(date) + 1000000 * SECOND(date)) FROM table
SELECT EXTRACT(MICROSECONDS FROM interval) FROM table
SELECT (MICROSECOND('0000-01-01 00:00:00' + interval) + 1000000 * SECOND('000-01-01 00:00:00' + interval)) FROM table
SELECT EXTRACT(MILLENIUM FROM date) FROM table
SELECT FLOOR((EXTRACT(YEAR FROM date) + 999) / 1000) FROM table
SELECT EXTRACT(MILLENIUM FROM interval) FROM table
SELECT FLOOR((EXTRACY(YEAR FROM '0000-01-01 00:00:00' + FROM table
SELECT EXTRACT(MILISECONDS FROM date) FROM table
SELECT (FLOOR(MILISECONDS(date)) / 1000 + 1000 * SECOND(date)) FROM table
SELECT EXTRACT(MILISECONDS FROM interval) FROM table
SELECT (FLOOR(MILISECONDS('0000-01-01 00:00:00' + interval)) / 1000 + 1000 * SECOND('0000-01-01 00:00:00' + interval)) FROM table
SELECT EXTRACT(MINUTE FROM date) FROM table
SELECT MINUTE(date) FROM table
SELECT EXTRACT(MINUTE FROM interval) FROM table
SELECT MINUTE('0000-01-01 00:00:00' + interval) FROM table
SELECT EXTRACT(MONTH FROM date) FROM table
SELECT MONTH(date) FROM table
SELECT EXTRACT(MONTH FROM interval) FROM table
SELECT (MONTH('0000-01-01 00:00:00' + interval) - 1) FROM table
SELECT EXTRACT(QUARTER FROM date) FROM table
SELECT FLOOR((MONTH(date) - 2 / 3)) FROM table
SELECT EXTRACT(QUARTER FROM interval) FROM table
SELECT FLOOR((MONTH('0000-01-01 00:00:00' + interval) - 1) / 3) FROM table
SELECT EXTRACT(SECOND FROM date) FROM table
SELECT (SECOND(date) + MICROSECOND(date) / 1000000) FROM table
SELECT EXTRACT(SECOND FROM interval) FROM table
SELECT (SECOND('0000-01-01 00:00:00' + interval) + MICROSECOND('0000-01-01 00:00:00' + interval) / 1000000) FROM table
SELECT EXTRACT(WEEK FROM date) FROM table
SELECT WEEK(date, 7) FROM table
SELECT EXTRACT(WEEK FROM interval) FROM table
FAIL
SELECT EXTRACT(YEAR FROM date) FROM table
SELECT YEAR(date) FROM table
SELECT EXTRACT(YEAR FROM interval) FROM table
SELECT YEAR('0000-01-01' + interval - INTERVAL 1 month - INTERVAL 1 day) FROM table
SELECT DATE_TRUNC("CENTURY", date) FROM table
FAIL
SELECT DATE_TRUNC("CENTURY", interval) FROM table
FAIL
SELECT DATE_TRUNC("DAY", date) FROM table
SELECT DATE_FORMAT(date, "%Y-%m-%d 00:00:00") FROM table
SELECT DATE_TRUNC("DAY", interval) FROM table
FAIL
SELECT DATE_TRUNC("DECADE", date) FROM table
FAIL
SELECT DATE_TRUNC("DECADE", interval) FROM table
FAIL
SELECT DATE_TRUNC("HOUR", date) FROM table
SELECT DATE_FORMAT(date, "%Y-%m-%d %H:00:00") FROM table
SELECT DATE_TRUNC("HOUR", interval) FROM table
FAIL
SELECT DATE_TRUNC("MICROSECONDS", date) FROM table
SELECT DATE_FORMAT(date, "%Y-%m-%d %H:%i%s.%f") FROM table
SELECT DATE_TRUNC("MICROSECONDS", interval) FROM table
FAIL
SELECT DATE_TRUNC("MILISECONDS", date) FROM table
FAIL
SELECT DATE_TRUNC("MILISECONDS", interval) FROM table
FAIL
SELECT DATE_TRUNC("MILLENNIUM", date) FROM table
FAIL
SELECT DATE_TRUNC("MILLENNIUM", interval) FROM table
FAIL
SELECT DATE_TRUNC("MINUTE", date) FROM table
SELECT DATE_FORMAT(date, "%Y-%m-%d %H:%i:00") FROM table
SELECT DATE_TRUNC("MINUTE", interval) FROM table
FAIL
SELECT DATE_TRUNC("MONTH", date) FROM table
SELECT DATE_FORMAT(date, "%Y-%m-01 00;00:00") FROM table
SELECT DATE_TRUNC("MONTH", interval) FROM table
FAIL
SELECT DATE_TRUNC("SECOND", date) FROM table
SELECT DATE_FORMAT(date, "%Y-%m-%d %H:%i:%s") FROM table
SELECT DATE_TRUNC("SECOND", interval) FROM table
FAIL
SELECT DATE_TRUNC("YEAR", date) FROM table
SELECT DATE_FORMAT(date, "%Y-01-01 00:00:00") FROM table
SELECT DATE_TRUNC("YEAR", interval) FROM table
FAIL
SELECT ISFINITE() FROM table
FAIL
SELECT TIMEOFDAY() FROM table
FAIL
SELECT TIMEZONE() FROM table
FAIL
SELECT BIT_AND(expression)
SELECT IF(COUNT(expression) = 0, NULL, BIT_AND(expression))
SELECT BIT_OR(expression)
SELECT IF(COUNT(expression) = 0, NULL, BIT_OR(expression))
SELECT BOOL_AND(expression)
SELECT IF(COUNT(expression) = 0, NULL, BIT_AND(expression != 0))
SELECT BOOL_OR(expression)
SELECT IF(COUNT(expression) = 0, NULL, BIT_OR(expression != 0))
SELECT EVERY(expression)
SELECT IF(COUNT(expression) = 0, NULL, BIT_AND(expression != 0))
SELECT TO_DATE() FROM table
FAIL
SELECT DATE_FORMAT() FROM table
FAIL
SELECT TO_TIMESTAMP() FROM table
FAIL
SELECT TO_NUMBER() FROM table
FAIL
SELECT TO_CHAR(date, '%') FROM table
SELECT DATE_FORMAT(date, '%%') FROM table
SELECT TO_CHAR(date, '"anytext %"') FROM table
SELECT DATE_FORMAT(date, 'anytext %%') FROM table
SELECT TO_CHAR(date, 'FMHH') FROM table
SELECT DATE_FORMAT(date, '%l') FROM table
SELECT TO_CHAR(date, 'HH') FROM table
SELECT DATE_FORMAT(date, '%I') FROM table
SELECT TO_CHAR(date, 'FMHH12') FROM table
SELECT DATE_FORMAT(date, '%l') FROM table
SELECT TO_CHAR(date, 'HH12') FROM table
SELECT DATE_FORMAT(date, '%I') FROM table
SELECT TO_CHAR(date, 'FMHH24') FROM table
SELECT DATE_FORMAT(date, '%k') FROM table
SELECT TO_CHAR(date, 'HH24') FROM table
SELECT DATE_FORMAT(date, '%H') FROM table
SELECT TO_CHAR(date, 'MI') FROM table
SELECT DATE_FORMAT(date, '%i') FROM table
SELECT TO_CHAR(date, 'SS') FROM table
SELECT DATE_FORMAT(date, '%s') FROM table
SELECT TO_CHAR(date, 'US') FROM table
SELECT DATE_FORMAT(date, '%f') FROM table
SELECT TO_CHAR(date, 'AM') FROM table
SELECT DATE_FORMAT(date, '%p') FROM table
SELECT TO_CHAR(date, 'PM') FROM table
SELECT DATE_FORMAT(date, '%p') FROM table
SELECT TO_CHAR(date, 'YYYY') FROM table
SELECT DATE_FORMAT(date, '%Y') FROM table
SELECT TO_CHAR(date, 'IYYY') FROM table
SELECT DATE_FORMAT(date, '%Y') FROM table
SELECT TO_CHAR(date, 'YY') FROM table
SELECT DATE_FORMAT(date, '%Y') FROM table
SELECT TO_CHAR(date, 'IY') FROM table
SELECT DATE_FORMAT(date, '%Y') FROM table
SELECT TO_CHAR(date, 'Month') FROM table
SELECT DATE_FORMAT(date, '%M') FROM table
SELECT TO_CHAR(date, 'Mon') FROM table
SELECT DATE_FORMAT(date, '%b') FROM table
SELECT TO_CHAR(date, 'FMMM') FROM table
SELECT DATE_FORMAT(date, '%c') FROM table
SELECT TO_CHAR(date, 'MM') FROM table
SELECT DATE_FORMAT(date, '%M') FROM table
SELECT TO_CHAR(date, 'Day') FROM table
SELECT DATE_FORMAT(date, '%W') FROM table
SELECT TO_CHAR(date, 'Dy') FROM table
SELECT DATE_FORMAT(date, '%a') FROM table
SELECT TO_CHAR(date, 'DDD') FROM table
SELECT DATE_FORMAT(date, '%j') FROM table
SELECT TO_CHAR(date, 'FMDD') FROM table
SELECT DATE_FORMAT(date, '%e') FROM table
SELECT TO_CHAR(date, 'DD') FROM table
SELECT DATE_FORMAT(date, '%d') FROM table

HOWTO write builder

Structure of SqlUnify:

flex tokenizer and bison parser
they creates tree of nodes from string, the three descibes structure of query
helper tokenizers
they are used for tokenize date-format in some functions and used with own simple parser written in C
string module
contains function for easy concatenating and extracting strings
builders
builders are used to create SQL statements (or equivalent data) from tree created by parser

The best way to create a new builder is to use templates, copy them to lib/sqlunify_BUILDER_NAME_builder.* and register these files in lib/Makefile. Next replace BUILDER_NAME string with your builder short name. Register new functions in lib/sqlunify.c file (INC BUILDER_COUNT const and add entry in sqlunify_init() function).

Now you can override some methods from general "default" builder (which outputs PostgreSQL statements). There are three kinds of methods:

  1. structure methods (S prefix) - used to output structures' tranlations (like SELECT query, FROM part, WHERE clausule)
  2. function methods (F prefix) - used to output functions' tranlations (like CEIL, RANDOM)
  3. operator methods (O prefix) - used to output operators' translations (like +, -, !~*)

To override a method you have to:

  1. define it with prefix_PROTO(name) { statements } form (list of all names for S prefix are in lib/sqlunify_structure.h file, you have to look at *.y file to learn more about means of them; for O and F prefix you have lib/sqlunify_structure_operators.h and lib/sqlunify_structure_functions.h files)
  2. use it with adding prefix_ASSIGN(name) statement to sqlunify_BUILDER_builder_create function

Methods definitions:

  • begins with prefix_PROTO(name)
  • in every function you have access to predefinied node variable, with corresponds to structures in lib/sqlunify_struscture.h (for S, for O node is of type expression and for F - function_call) - it is pointer to C struct
  • first line of every function is:
    struct build_result *result = sqlunify_build_result_create();
  • you can add REQUIRE(member) statement to ensure that member is present in children of current node, if not - function will return CANNOT_TRANSLATE
  • you can add BUILD(member) to get char *member variable which is SQL statement part createt from member
  • next you use sqlunify_.concat_... function to concat received and hardcoded string into SQL statement part, the result is assigned to result->query)
  • at the end you return result;

BUILD macros

BUILD macros are used to create part of SQL statement from a node of pars-tree. The most general macro is BUILD_PATH_COND_DATA(type, name, path, cond, data).

type
type of node to parse
name
name of result variable (char * type)
path
path to node to parse (relative to current node)
condition
boolean expression, if evaluated to true - result variable will contains string, if evaluated to false - nothing will be done (result variable will be null)
data
any data passed verbatim to builder method
  • BUILD_PATH_COND(type, name, path, cond) = BUILD_PATH_COND_DATA(type, name, path, cond, 0)
  • BUILD_PATH_DATA(type, name, path, data) = BUILD_PATH_COND_DATA(type, name, path, 1, data)
  • BUILD_PATH(type, name, path) = BUILD_PATH_COND_DATA(type, name, path, 1, 0)
  • BUILD_NAME_DATA(type, name, data) = BUILD_PATH_COND_DATA(type, name, name, 1, data)
  • BUILD_NAME(type, name) = BUILD_PATH_COND_DATA(type, name, name, 1, 0)
  • BUILD_DATA(type, data) = BUILD_PATH_COND_DATA(type, name, name, 1, data)
  • BUILD(type) = BUILD_PATH_COND_DATA(type, type, type, 1, 0)

Some examples of use:

  • BUILD_PATH_COND(expression, exp_1, expression_1->expression, expression_1 != NULL, 0) - writes to variable char *exp_1 result of generating node->expression_1->expression (of type expression) only if expression_1 is not null
  • BUILD_NAME(expression, expression_2); BUILD_NAME(expression, expression_2) - writes to variables char *expression_1 and char *expression_2 results of generating node->expression_1 and node->expresion_2 (of type expresion)
  • BUILD(identifier) - writes to char *identifier results of generating node->idenifier (of type identified)

REQUIRE macros

REQUIRE macros are used to ensure that some subnodes of current node are not null (like parameters of some functions). If require condition is false, then we return immediately with some error code.

REQUIRE_FAIL_ERR(path, fail_code, err)

path
path to checked node, relative to current node
fail_code
code invoked when path is not available (should only contains FREE's)
err
error code returned to builder:
  • SQLUNIFY_ERR_INVALID_QUERY - query is invalid (does not contains all required tokens)
  • SQLUNIFY_ERR_CAN_NOT_TRANSLATE - querry cannot be translated (for example: backend requires 4 parameters for some function, but postgresql does not)
  • REQUIRE_ERR(path, err) = REQUIRE_FAIL_ERR(path,, err)
  • REQUIRE_FAIL(path, fail_code) = REQUIRE_FAIL_ERR(path, fail_code, SQLUNIFY_ERR_INVALID_QUERY)
  • REQUIRE(path) = REQUIRE_FAIL_ERR(path,, SQLUNIFY_ERR_INVALID_QUERY)

If you require some deep node to exists (like: expression_1->expression_1->expression->const_integer) you should make four calls of macro:

        REQUIRE(expression_1);
        REQUIRE(expression_1->expression_1);
        REQUIRE(expression_1->expression_1->expression);
        REQUIRE(expression_1->expression_1->expression->const_integer);
    

Builder macros

Each builder containts its own set of helper macros:

#define ASSIGN(name, type) BUILDER_NAME_builder->build_##type##name = sqlunify_##type##name##_BUILDER_NAME_builder;
#define S_ASSIGN(name) ASSIGN(name, )
#define O_ASSIGN(name) ASSIGN(name, operator_)
#define F_ASSIGN(name) ASSIGN(name, function_)
    

These macros allows you to fast override default implementations by putting them in constructor.

#define PROTO(name, type, node_type) struct build_result * sqlunify_##type##name##_BUILDER_NAME_builder(struct builder *this,\
    struct node_type *node, void *data)
#define S_PROTO(name) PROTO(name,, node_##name)
#define O_PROTO(name) PROTO(name, operator_, node_expression)
#define F_PROTO(name) PROTO(name, function_, node_function_call)
    

These macros allows you to fast create methods that override default implementations.

#define FAIL(name, type, node_type) PROTO(name, type, node_type)\
{\
    struct build_result *result = sqlunify_build_result_create();\
\
    BUILDER_NAME_error_code = -SQLUNIFY_BUILDER_NAME_ERR_NOT_IMPLEMENTED_##type##name;\
    result->build_result = -SQLUNIFY_ERR_CAN_NOT_TRANSLATE;\
\
    return result;\
}
#define S_FAIL(name) FAIL(name,, node_##name)
#define O_FAIL(name) FAIL(name, operator_, node_expression)
#define F_FAIL(name) FAIL(name, function_, node_function_call)

These macros allows for fast implementations of not-translatable nodes - translation just fails. For each call of FAIL macro you should provide const of name -SQLUNIFY_BUILDER_NAME_ERR_NOT_IMPLEMENTED_type_name (type is one of: '' for S_FAIL, 'operator' for O_FAIL, 'function' for F_FAIL, name is first parameter of macro) and corresponding entry in BUILDER_NAME_error_descriptions array.

FREE macro

FREE(x) is just:

      if (x)
        FREE(x);
    

Needed functions

sqlunify_XXX_builder_get_info

This function returns a pointer to sqlunify_builder_info which contains info about builder. This info is static and is used (in example application) to recognize builder by command line parameters and to create builders (it contains pointer to constructors).

Fields of sqlunify_builder_info:

  • char *builder_name - short name of builder, like postgresql, mysql
  • char *builder_description - long description of builder
  • int builder_id - id of builder (index in builders' table)
  • struct builder * (*constructor) (void) - pointer to sqlunify_XXX_builder_create function - constructor
  • int (* get_error_code) (void) - pointer to function that returns deailed error code
  • char * (* get_error_description) (void - pointer to function that returns deailed error desctiprion

Memory management in builders

In builders macros like BUILD creates new dynamic string and returns them (sometimes they resurns null). After creating result string these temporary strings should be fried. You can do it manually, or free them by sqlunify_concat_free_XXX functions. You should avoid using first option - it is neccesary only when some strings are used more than once.


numer9.pl webdesign