pg_scanner - patch no.1

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

Responses

Browse pgadmin-hackers by date

  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