pg_scanner - patch no.1 - Mailing list pgadmin-hackers
From | Vladimir Kokovic |
---|---|
Subject | pg_scanner - patch no.1 |
Date | |
Msg-id | CAHsHPqckwX=zZ0mjBqcp3SDpN7xnejgz+ha17PpDXj4BcKubKQ@mail.gmail.com Whole thread Raw |
Responses |
Re: pg_scanner - patch no.1
Re: pg_scanner - patch no.1 |
List | 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
pgadmin-hackers by date: