## GdaSqlParser

GdaSqlParser — SQL parser

## Synopsis

    #include <sql-parser/gda-sql-parser.h>

                        GdaSqlParser;
    enum                GdaSqlParserMode;
    GdaSqlParser *      gda_sql_parser_new                  (void);
    GdaStatement *      gda_sql_parser_parse_string         (GdaSqlParser *parser,
                                                             const gchar *sql,
                                                             const gchar **remain,
                                                             GError **error);
    GdaBatch *          gda_sql_parser_parse_string_as_batch
                                                            (GdaSqlParser *parser,
                                                             const gchar *sql,
                                                             const gchar **remain,
                                                             GError **error);
    GdaBatch *          gda_sql_parser_parse_file_as_batch  (GdaSqlParser *parser,
                                                             const gchar *filename,
                                                             GError **error);

    gchar *             gda_sql_identifier_quote            (const gchar *id,
                                                             GdaConnection *cnc,
                                                             GdaServerProvider *prov,
                                                             gboolean meta_store_convention,
                                                             gboolean force_quotes);
    gboolean            gda_sql_identifier_needs_quotes     (const gchar *str);
    gchar *             gda_sql_identifier_add_quotes       (const gchar *str);
    gchar *             gda_sql_identifier_remove_quotes    (gchar *str);
    gchar **            gda_sql_identifier_split            (const gchar *id);

## Object Hierarchy

      GObject
       +----GdaSqlParser

## Implemented Interfaces

GdaSqlParser implements GdaLockable.

## Properties

      "column-error"             gint                  : Read
      "debug"                    gboolean              : Write
      "line-error"               gint                  : Read
      "mode"                     gint                  : Read / Write
      "tokenizer-flavour"        gint                  : Read / Write

## Description

The GdaSqlParser is an object dedicated to creating GdaStatement and GdaBatch objects from SQL strings. The actual contents of the parsed statements is represented as GdaSqlStatement structures (which can be obtained from any GdaStatement through the "structure" property).

GdaSqlParser parsers can be created by calling `gda_server_provider_create_parser()` for a provider adapted SQL parser, or using `gda_sql_parser_new()` for a general purpose SQL parser.

The GdaSqlParser can either work in "parse" mode where it will try to parse the SQL string, or in "delimiter" mode where it will only attempt at delimiting SQL statements in a string which may contain several SQL statements (usually separated by a semi column). If operating in "parser" mode, and the parser can't correctly parse the string, then it will switch to the "delimiter" mode for the next statement in the string to parse (and create a GDA_SQL_STATEMENT_UNKNOWN statement).

The GdaSqlParser object parses and analyzes SQL statements and reports the following statement types:

- SELECT (and COMPOUND select), INSERT, UPDATE and DELETE SQL statements should be completely parsed.

- Transaction related statements (corresponding to the BEGIN, COMMIT, ROLLBACK, SAVEPOINT, ROLLBACK SAVEPOINT and DELETE SAVEPOINT) are parsed and a minimalist structure is created to extract some information (that structure is not enough per-se to re-create the complete SQL statement).

- Any other type of SQL statement (CREATE TABLE, ...) creates a GdaStatement of type GDA_SQL_STATEMENT_UNKNOWN, and it only able to locate place holders (variables) and end of statement marks.

NOTE: Any SQL of a type which should be parsed which but which creates a GdaStatement of type GDA_SQL_STATEMENT_UNKNOWN (check with `gda_statement_get_statement_type()`) should be reported as a bug.

The GdaSqlParser object recognizes place holders (variables), which can later be queried and valued using `gda_statement_get_parameters()`. The following syntax are recognized (other syntaxes might be recognized for specific database providers if the GdaSqlParser is created using `gda_server_provider_create_parser()` but for portability reasons it's better to avoid them):

- ##NAME[::TYPE[::NULL]]: for a variable named NAME with the optional type TYPE (which can be a GType name or a custom database type name), and with the optional "::NULL" to instruct that the variable can be NULL.

- ## /* name:NAME [type:TYPE] [nullok:[TRUE|FALSE]] [descr:DESCR] */ for a variable named NAME with the optional type TYPE (which can be a GType name or a custom database type name), with the optional "nullok" attribute and an optional description DESCR. Note that the NAME, TYPE and DESCR literals here must be quoted (simple or double quotes) if they include non alphanumeric characters, and that there must always be at least a space between the ## and the /* ... */.

Note that the type string must be a type recognized by the `gda_g_type_from_string()` function (all valid GType names plus a few synonyms). Examples of correct place holders definitions are:

    ## /* name:"+0" type:gchararray */
    ## /* name:'-5' type:string */
    ## /*name:myvar type:gint descr:ToBeDefined nullok:FALSE*/
    ## /*name:myvar type:int descr:"A long description"*/
    ##+0::gchararray
    ##-5::timestamp

Also note that variables should not be used when an SQL identifier is expected. For example the following examples should be avoided because they may not work properly (depending on the database being used):

    SELECT * FROM #tablename::string;
    DELETE FROM mytable WHERE #tcol::string = 5;
    ALTER GROUP mygroup ADD USER #name::gchararray;

The GdaSqlParser object internally uses a LEMON generated parser (the same as the one used by SQLite).

The GdaSqlParser object implements its own locking mechanism so it is thread-safe.

## Details

### GdaSqlParser

    typedef struct _GdaSqlParser GdaSqlParser;

### enum GdaSqlParserMode

    typedef enum {
            GDA_SQL_PARSER_MODE_PARSE,
            GDA_SQL_PARSER_MODE_DELIMIT
    } GdaSqlParserMode;

`GDA_SQL_PARSER_MODE_PARSE` | Parse mode, the parser tries to parse and build a structure representing the SQL statement
`GDA_SQL_PARSER_MODE_DELIMIT` | Delimit mode, the parser only tries to identify variables, will always return a statement of type GDA_SQL_STATEMENT_UNKNOWN.

### gda_sql_parser_new ()

    GdaSqlParser *      gda_sql_parser_new                  (void);

Creates a new GdaSqlParser object

Returns : | the new object

### gda_sql_parser_parse_string ()

    GdaStatement *      gda_sql_parser_parse_string         (GdaSqlParser *parser,
                                                             const gchar *sql,
                                                             const gchar **remain,
                                                             GError **error);

Parses `sql` and creates a GdaStatement statement from the first SQL statement contained in `sql`: if `sql` contains more than one statement, then the remaining part of the string is not parsed at all, and `remain` (if not `NULL`) will point at the first non parsed character.

To include variables in the `sql` string, see the GdaSqlParser's object description.

`parser` : | a GdaSqlParser object
`sql` : | the SQL string to parse
`remain` : | location to store a pointer to remaining part of `sql` in case `sql` has multiple statement, or `NULL`. [out][allow-none]
`error` : | location to store error, or `NULL`
Returns : | a new GdaStatement object, or `NULL` if an error occurred. [transfer full][allow-none]

### gda_sql_parser_parse_string_as_batch ()

    GdaBatch *          gda_sql_parser_parse_string_as_batch
                                                            (GdaSqlParser *parser,
                                                             const gchar *sql,
                                                             const gchar **remain,
                                                             GError **error);

Parse `sql` and creates a GdaBatch object which contains all the GdaStatement objects created while parsing (one object per SQL statement). Empty statements (composed of spaces only) do not appear in the resulting object.

`sql` is parsed and GdaStatement objects are created as long as no error is found in `sql`. If an error is found at some point, then the parsing stops and `remain` may contain a non `NULL` pointer, `error` may be set, and `NULL` is returned.

if `sql` is `NULL`, then the returned GdaBatch object will contain no statement.

To include variables in the `sql` string, see the GdaSqlParser's object description.

`parser` : | a GdaSqlParser object
`sql` : | the SQL string to parse
`remain` : | location to store a pointer to remaining part of `sql` in case an error occurred while parsing `sql`, or `NULL`. [out][allow-none]
`error` : | location to store error, or `NULL`
Returns : | a new GdaBatch object, or `NULL` if an error occurred. [transfer full][allow-none]

### gda_sql_parser_parse_file_as_batch ()

    GdaBatch *          gda_sql_parser_parse_file_as_batch  (GdaSqlParser *parser,
                                                             const gchar *filename,
                                                             GError **error);

Parse `filename`'s contents and creates a GdaBatch object which contains all the GdaStatement objects created while parsing (one object per SQL statement).

`filename`'s contents are parsed and GdaStatement objects are created as long as no error is found. If an error is found at some point, then the parsing stops, `error` may be set and `NULL` is returned

if `sql` is `NULL`, then the returned GdaBatch object will contain no statement.

`parser` : | a GdaSqlParser object
`filename` : | name of the file to parse
`error` : | location to store error, or `NULL`
Returns : | a new GdaBatch object, or `NULL` if an error occurred. [transfer full][allow-none]

### gda_sql_identifier_quote ()

    gchar *             gda_sql_identifier_quote            (const gchar *id,
                                                             GdaConnection *cnc,
                                                             GdaServerProvider *prov,
                                                             gboolean meta_store_convention,
                                                             gboolean force_quotes);

Use this function for any SQL identifier to make sure that:

- it is correctly formatted to be used with `cnc` (if `cnc` is `NULL`, then some default SQL quoting rules will be applied, similar to PostgreSQL's way) if `for_meta_store` is `FALSE`;

- it is correctly formatted to be used with the GdaMetaStore's object associated to `cnc` is `for_meta_store` is `TRUE`.

The `force_quotes` allow some control of how to interpret `id`: if `FALSE`, then `id` will be left unchanged most of the time (except for example if it's a reserved keyword), otherwise if `force_quotes` is `TRUE`, then the returned string will most probably have quotes around it to request that the database keep the case sensitiveness (but again, this may vary depending on the database being accessed through `cnc`).

For example, the following table gives the result of this function depending on the arguments when `cnc` is `NULL` (and `prov` is also `NULL`):

Table 3.

id | for_meta_store=`FALSE`, force_quotes=`FALSE` | for_meta_store=`TRUE`, force_quotes=`FALSE` | for_meta_store=`FALSE`, force_quotes=`TRUE` | for_meta_store=`TRUE`, force_quotes=`TRUE` | remark
--- | --- | --- | --- | --- | ---
"double word" | "double word" | "double word" | "double word" | "double word" | non allowed character in SQL identifier
"CapitalTest" | "CapitalTest" | "CapitalTest" | "CapitalTest" | "CapitalTest" | Mixed case SQL identifier, already quoted
CapitalTest | CapitalTest | capitaltest | "CapitalTest" | "CapitalTest" | Mixed case SQL identifier, non quoted
"mytable" | "mytable" | mytable | "mytable" | mytable | All lowser case, quoted
mytable | mytable | mytable | "mytable" | mytable | All lowser case
MYTABLE | MYTABLE | mytable | "MYTABLE" | "MYTABLE" | All upper case
"MYTABLE" | "MYTABLE" | "MYTABLE" | "MYTABLE" | "MYTABLE" | All upper case, quoted
desc | "desc" | "desc" | "desc" | "desc" | SQL reserved keyword
5ive | "5ive" | "5ive" | "5ive" | "5ive" | SQL identifier starting with a digit

Here are a few examples of when and how to use this function:

- When creating a table, the user has entered the table name, this function can be used to create a valid SQL identifier from the user provided table name:

      gchar *user_sqlid=...
      gchar *valid_sqlid = gda_sql_identifier_quote (user_sqlid, cnc, NULL, FALSE, FALSE);
      gchar *sql = g_strdup_printf ("CREATE TABLE %s ...", valid_sqlid);
      g_free (valid_sqlid);

  Note that this is an illustration and creating a table should be sone using a GdaServerOperation object.

- When updating the meta data associated to a table which has been created with the code above:

      GValue table_name_value = { 0 };
      gchar* column_names[] = { (gchar*)"table_name" };
      GValue* column_values[] = { &table_name_value };
      GdaMetaContext mcontext = { (gchar*)"_tables", 1, column_names, column_values };
      g_value_init (&table_name_value, G_TYPE_STRING);
      g_value_take_string (&table_name_value, gda_sql_identifier_quote (user_sqlid, cnc, NULL, TRUE, FALSE);
      gda_connection_update_meta_store (cnc, &mcontext, NULL);
      g_value_reset (&table_name_value);

- When using a GdaMetaStruct object to fetch information about a table (which has been created with the code above):

      GValue table_name_value = { 0 };
      g_value_init (&table_name_value, G_TYPE_STRING);
      g_value_take_string (&table_name_value, gda_sql_identifier_quote (user_sqlid, cnc, NULL, TRUE, FALSE);
      GdaMetaDbObject *dbo;
      dbo = gda_meta_struct_complement (mstruct, GDA_META_DB_TABLE, NULL, NULL, &table_name_value, NULL);
      g_value_reset (&table_name_value);

Note that `id` must not be a composed SQL identifier (such as "mytable.mycolumn" which should be treated as the "mytable" and "mycolumn" SQL identifiers). If unsure, use `gda_sql_identifier_split()`.

Also note that if `cnc` is `NULL`, then it's possible to pass an non `NULL` `prov` to have a result specific to `prov`.

For more information, see the SQL identifiers and abstraction and SQL identifiers in meta data sections.

`id` : | an SQL identifier
`cnc` : | a GdaConnection object, or `NULL`. [allow-none]
`prov` : | a GdaServerProvider object, or `NULL` `for_meta_store` set to `TRUE` if the returned string will be used in a GdaMetaStore. [allow-none]
`force_quotes` : | set to `TRUE` to force the returned string to be quoted
Returns : | the representation of `id` ready to be used in SQL statement, as a new string, or `NULL` if `id` is in a wrong format

Since 4.0.3

### gda_sql_identifier_needs_quotes ()

    gboolean            gda_sql_identifier_needs_quotes     (const gchar *str);

### Warning

`gda_sql_identifier_needs_quotes` has been deprecated since version 4.0.3 and should not be used in newly-written code. Not needed anymore because of the `gda_sql_identifier_quote()` function.

Tells if `str` needs to be quoted before using it in an SQL statement. To actually add quotes, use `gda_sql_identifier_add_quotes()`.

To determine if quotes are needed: the following rules are applied:

- If the 1st character is a digit, then `TRUE` is returned

- If there are mixed lower and upper case letters, then `TRUE` is returned

- If there are other characters than digits, letters and the '_', '$' and '#', then `TRUE` is returned

- Otherwise `FALSE` is returned

`str` : | an SQL identifier
Returns : | TRUE if `str` needs some quotes

### gda_sql_identifier_add_quotes ()

    gchar *             gda_sql_identifier_add_quotes       (const gchar *str);

### Warning

`gda_sql_identifier_add_quotes` has been deprecated since version 4.0.3 and should not be used in newly-written code. Use `gda_sql_identifier_quote()` instead.

Add double quotes around the `str` identifier. Use the `gda_sql_identifier_needs_quotes()` function to tell if an identifier needs to be quoted.

`str` : | an SQL identifier
Returns : | a new string

### gda_sql_identifier_remove_quotes ()

    gchar *             gda_sql_identifier_remove_quotes    (gchar *str);

### Warning

`gda_sql_identifier_remove_quotes` has been deprecated since version 4.0.3 and should not be used in newly-written code. Not needed anymore because of the `gda_sql_identifier_quote()` function.

Prepares `str` to be compared:

- if surrounded by double quotes or single quotes, then just remove the quotes

- otherwise convert to lower case

The quoted string:

- must start and finish with the same single or double quotes character

- can contain the delimiter character (the single or double quotes) in the string if every instance of it is preceeded with a backslash character or with the delimiter character itself

WARNING: `str` must NOT be a composed identifier (<part1>."<part2>" for example)

`str` : | a quoted string
Returns : | `str`

### gda_sql_identifier_split ()

    gchar **            gda_sql_identifier_split            (const gchar *id);

Splits `id` into an array of it sub parts. `id`'s format has to be "<part>[.<part>[...]]" where each part is either a text surrounded by double quotes which can contain upper and lower cases or an SQL identifier in lower case.

For example the "test.\"ATable\"" string will result in the array: {"test", "\"ATable\"", NULL}

`id` : | an SQL identifier
Returns : | a new `NULL`-terminated array of strings, or NULL (use `g_strfreev()` to free the returned array). [transfer full][array zero-terminated=1][allow-none]

## Property Details

### The `"column-error"` property

      "column-error"             gint                  : Read

Internal usage only.

Allowed values: >= 0

Default value: 0

### The `"debug"` property

      "debug"                    gboolean              : Write

Default value: FALSE

### The `"line-error"` property

      "line-error"               gint                  : Read

Internal usage only.

Allowed values: >= 0

Default value: 0

### The `"mode"` property

      "mode"                     gint                  : Read / Write

Controls the parsing mode determining how the parser operates.

Allowed values: [0,1]

Default value: 0

### The `"tokenizer-flavour"` property

      "tokenizer-flavour"        gint                  : Read / Write

Modifies the behaviour of the tokenizer, reserved for GdaServerProvider implementations

Allowed values: [0,4]

Default value: 0