From: | Vladimir Kokovic <vladimir(dot)kokovic(at)gmail(dot)com> |
---|---|
To: | pgadmin-hackers(at)postgresql(dot)org |
Subject: | pg_scanner - patch no.1 |
Date: | 2012-10-21 08:08:53 |
Message-ID: | CAHsHPqckwX=zZ0mjBqcp3SDpN7xnejgz+ha17PpDXj4BcKubKQ@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgadmin-hackers |
Hi,
This patch is my try to add lexical scanner for PostgreSQL SQL
commands in Pgadmin source tree(prerequisite for patches no.2 and 3).
The main reason why that is done is to scan and parse a SQL command in
the same way
like PostgreSQL server, but for limited number of parse functions.
All scanner special cases are covered: TYPECAST(::), COLON_EQUALS(:=),
DOT_DOT(..) and $foo$.
Currently, three parsers implemented:
1. parse SQL command string for commands separated by ';'
returns single linked list of commands
struct myScannerNode *get_all_commands_cpp(const struct
myScannerNode *head);
2. parse RULE SQL command and substitute source schema with target schema
returns CREATE RULE SQL command with new schema name
char *parse_rule_cpp(const struct myScannerNode *head, const
char *rulename, const char *targetschema, const char *tablename);
3. parse TRIGGER SQL command and substitute source schema with target
schema (pgadmin/utils/pasteTables.cpp)
returns CREATE TRIGGER SQL command with new schema name
char *parse_trigger_cpp(const struct myScannerNode *head, const
char *targetschema);
For all parsers 'scan_SQL_cpp' method is prerequisite which scan SQL
command for tokens:
returns single linked list of scan results (tokens)
struct myScannerNode *scan_SQL_cpp(const char *command);
If some error occurred during scan process, variable
'pgadmin_scanner_last_error' contains diagnostic message.
*** This code snippet is from my pgadmin/frm/frmQuery.cpp ***
/*
* The scanner returns extra data about scanned tokens in this union type.
* Note that this is a subset of the fields used in YYSTYPE of the bison
* parsers built atop the scanner.
*/
typedef union core_YYSTYPE
{
int ival; /* for integer literals */
char *str; /* for identifiers and non-integer literals */
const char *keyword; /* canonical spelling of keywords */
} core_YYSTYPE;
/*
my token data struct
*/
struct myScannerData {
int loc;
int token;
core_YYSTYPE val;
};
/*
my single linked list for scan results
*/
struct myScannerNode {
struct myScannerData data;
struct myScannerNode *next;
};
//command offest from the beginning of SQL command string for each SQL command
wxArrayInt locs;
//SQL commands (queries)
wxArrayString queries;
//this is the first step which must be executed
//scan_SQL_cpp returns single linked list of scan results (tokens)
struct myScannerNode *head = scan_SQL_cpp(query.ToUTF8());
if (head)
{
//parse scan results
//get_all_commands_cpp returns single linked list of commands
struct myScannerNode *result = get_all_commands_cpp(head);
struct myScannerNode *current = result;
if (current)
{
do
{
wxString x = wxString(current->data.val.str, wxConvUTF8);
queries.Add(x);
locs.Add(current->data.loc);
current = current->next;
} while (current != result);
destroylist(result);
}
destroylist(head);
}
*** This code snippet is from my pgadmin/utils/pasteTables.cpp ***
struct myScannerNode *head =
scan_SQL_cpp(definition.mb_str(*srcrule->GetConnection()->GetConv()));
if (head)
{
char *rule = parse_rule_cpp(
head, qtname.ToAscii(), targetschema->GetIdentifier().ToAscii(),
newtablename.ToAscii());
if (rule)
{
newdefinition = wxString(rule, *targetschema->GetConnection()->GetConv());
free(rule);
}
destroylist_cpp(head);
}
Best regards
Vladimir Kokovic
Belgrade, Serbia, 21.October 2012
Attachment | Content-Type | Size |
---|---|---|
changes1.txt | text/plain | 2.5 KB |
pgadmin3-1.diff | application/octet-stream | 1.3 MB |
From | Date | Subject | |
---|---|---|---|
Next Message | Vladimir Kokovic | 2012-10-21 08:15:04 | frmQuery (multiple result sets support) - patch no.2 |
Previous Message | Jim Wilson | 2012-10-20 16:19:55 | Re: pgadmin crash - editing function body |