Table of Contents
Flex 2.5.33 or later is required.
You need to use FlexLexer.h
provided with your Flex
distribution: copy this file into lib/include/pgscript
.
For MinGW you can download flex-2.5.33 from MinGW Supplementary
Tools download section. regex-0.12 is also required. Unzip the archives
in msys/1.0
directory and then:
flex --version
This must print 2.5.33 or later.
Bison 2.3 or later is required.
For MinGW you can download bison-2.3 from MinGW Supplementary
Tools download section. regex-0.12 is also required. Unzip the archives
in msys/1.0
directory and then:
bison --version
This must print 2.3 or later.
pgadmin/include/pgscript
pgScript engine header files .
pgadmin/pgscript
pgScript engine source files .
xtra/pgscript/bin
Source files for pgScript command-line interface: it relies on pgadmin/include/pgscript
and pgadmin/pgscript
.
xtra/pgscript/doc
Contains files related to the application documentation.
xtra/pgscript/file
Contains sample input files and test files.
xtra/pgscript/file/input
Sample pgScript scripts.
xtra/pgscript/file/test
Integration test suite.
execute.sh executes this integration test suite.
xtra/pgscript/file/test/dictionary
Sample dictionaries for the dictionary generator.
xtra/pgscript/file/test/source
Input scripts used by execute.sh
xtra/pgscript/lib
padmin/pgscript
source files are compiled to this directory first when compiling the command-line interface (bin
) or the unit test suite (test
). This creates a libpgs.a
.
xtra/pgscript/test
Source files for pgScript unit test suite : it relies on pgadmin/include/pgscript
and pgadmin/pgscript
.
This section describes the pgadmin/pgscript
folder, which is
very like pgadmin/
include/pgscript
.
pgadmin/pgscript
pgsParser.yy
and pgsScanner.ll
: Bison
and Flex parser for the T-SQL syntax (use parser.sh to generate
source and header files).
parser.tab.cc
and lex.pgs.cc
: Bison
and Flex generated files.
The parser goes through the to-be-parsed script and builds a
statement tree (made of pgsStmt
and its children). A
statement can be based on an expression (made of pgsExpression
and its children). Once the whole script
is parsed the tree is evaluated with the common eval(...)
method.
pgsApplication
: interface of the pgScript engine with the
outside world. It allows users to parse a file or a string.
pgadmin/pgscript/exceptions
Contains pgScript exceptions which inherits from pgsException
.
pgsArithmeticException
: when an operation
cannot be performed because of incompatible types for
example.pgsAssertException
: when pgsAssertStmt
detects an assertion failure.pgsBreakException
: when a break instruction
is found, must be caught by the enclosing pgsWhileStmt
.pgsCastException
: when a type conversion
cannot be performed (string 'abc'
to number for
example).pgsContinueException
: when a continue
instruction is found, must be caught by the enclosing pgsWhileStmt
.pgsInterruptException
: when the program is
stopped as it is running.pgsParameterException
: when the type of a
parameter of a function or a generator is not valid.pgadmin/pgscript/expressions
Contains r-values. This means
expressions that return something that can
be assigned to a variable. pgsExpression
is the
common parent class.
The common interface implies that the children must
implement a copy constructor, the assignment operator and a clone()
method which does a deep copy and which is
based on the copy constructor.
The eval(pgsVarMap &)
method is crucial.
During evaluation of the statement tree it performs the
operation associated to an expression and returns its values as
an r-value (value which can be used in an assignment). This
r-value isa pgsOperand
. Its parameter pgsVarMap
is a map of pgsOperand
: this is the symbol table (the program memory).
pgsOperand
is simply a smart pointer on a pgsObject
(see objects
).
pgadmin/pgscript/generators
Contains random data
generators. pgsObjectGen
is the common
parent. The wxString random()
method returns the
random object as a string.
A lot of generators use a pgsIntegerGen
through a smart pointer.
pgadmin/pgscript/objects
pgsObject
is the common parent class: a smart
pointer to a pgsObject
(pgsOperand
) is the data that is used in
pgScriptpgsGenerator
: container for the
generators.pgsNumber
: represents a number, either a real
number or an integer.pgsRecord
: represents a record set, which is
composed of pgsGenerator
, pgsNumber
and pgsString
.pgsString
: represents a string. The eval(...)
method returns in general a
string representation of the object or the object itself. This is
something that is used in expressions to perform
operations. Each object must implement some operations. Operations
should only be possible between operands of the same
type.
The type of an object is known either by a dynamic cast or
by the is_xxx()
methods, which use the type
specified in the object constructor (pgsTReal
, pgsTInt
, ...).
pgadmin/pgscript/statements
Similar to expressions, they perform operation but do not
return anything. pgsStmt
is the common parent
class.
Those classes do not require copy constructor, assignment
operator, clone()
method as they are never
copied.
pgsStmtList
is a list of statements and
therefore owns additional methods: push_xxx()
.pgsProgram
is not really a statement: it is
the program the root statement that contains the first statement
list.pgadmin/pgscript/utilities
pgsAlloc
: when configured with the PGSDEBUG symbol it tracks each new
or delete
that occur and at the
end of the program execution it shows what new
operations have not been deleted. pnew
pdelete
and pdeletea
must be used instead of new
delete
and delete[]
in order to enable those
features.pgsContext
: utilities for script parsing in pgsParser.yy
.pgsDriver
: manages Bison and Flex
files.pgsScanner
: Flex header.pgsMapm
: conversion utilities for the MAPM
library which is the big number library used in pgScript.pgsThread
: pgScript runs in a detached (auto
delete) thread that can be interrupted.pgsUtilities
: various utilities.pgsCopiedPtr
and pgsSharedPtr
:
smart pointers whose names are explicit.There are two steps: unit tests on classes and integration tests on pgScript executable.
Go to the root directory of pgAdmin and enter the following command:
./configure
Go to the xtra/pgscript
directory and enter the following
command:
make
This should compile both the pgScript command-line interface (bin
) and the unit test suite (test
).
Go to the xtra/pgscript
directory and enter the following
command:
./test/pgsTest
There should be no assertion failure otherwise there is a bug.
Go to the xtra/pgscript
and enter the following
command:
./file/test/execute.sh -h 192.168.190.1 -p 5432 -U postgres -W postgres -d testbase
The string -h 192.168.190.1 -p 5432 -U postgres -W postgres
-d testbase
are the parameters for pgScript. Replace them with
your database parameters.
There should be no error during this process. An error is a line in the output that begins with [EXCEPT]
or [ERROR]
or a segmentation fault.
Note: use a LOG_ERRORS
log level in main()
in order not to display too many things on the screen, otherwise it
would be hard to see if there was a failure.
Automatically defined when compiling the command-line interface. PGSCLI
stands for pgScript Command-Line Interface. This
means not to compile specific parts of pgAdmin and pgScript code because the command-line interface does need them: this is mainly GUI code that is ignored.
Along with PGSCLI
PGADMIN3_H
is also defined because the command-line must not include pgAdmin3.h
.
When compiled normally with pgAdmin this symbol is not defined.
Compiles pgScript command-line interface or unit test suite with
memory tracking features. At the end of the program undeallocated memory
blocks are displayed. Use pnew
instead of new
, pdelete(x)
instead of delete x
and pdeletea(x)
instead of delete[] x
when
programming pgScript in order to be able to use those features.
pgadmin/pgscript/parser.sh
parser.sh must be called for regenerating Flex and Bison source files because it does some more processing that just executing bison and flex: it replaces some headers and adds other ones.
xtra/pgscript/file/test/execute.sh
See the Directory structure section. Runs the integration test suite.
Header file is in pgadmin/include/pgscript/expressions
and source file is in pgadmin/pgscript/expressions
.
It returns a value (pgsOperand
) once it has been
evaluated.
It is a pgsExpression
child.
The header file must be included in pgsExpressions.h
.
A pgsOperand
is a smart pointer to a pgs
Variable (pgsGenerator
, pgsNumber
, pgsRecord
and pgsString
).
To declare a pgsOperand
:
pgsOperand operand(pnew pgsNumber(wxT("1")));
Then a pgsOperand
is copied, duplicated and deleted
automatically. In the example above there is no need to delete the new pgsNumber
: the destructor is called automatically when operand
is deleted.
pgsOperand copy(operand); operand = copy;
To duplicate and retrieve the pgsNumber
:
pgsNumber * number = operand->clone();
Even if copy and deletion are handled automatically, pgsOperand
is accessed like a regular pointer with ->
:
cout << operand->value() << endl; return operand->eval(vars);
Duplicate pgsAssign
(header and source) and
rename the files: pgsMyExpression
for example.
Replace each occurrence of pgsAssign
with pgsMyExpression
.
Replace the protected data and the constructor with what you want.
Do not forget to modify the destructor, the copy constructor and the assignment operator according to your new data.
The value()
method must return the not evaluated expression.
The eval(vars)
method must return the evaluated
expression.
Note. The vars
parameter is the symbol table: this is a
map whose key is the variable name and whose value is a pgsOperand
.
Add pgsMyExpression.h
in pgsExpressions.h
.
Modify pgscript/pgsScanner.ll
(Flex) and pgscript/pgsParser.yy
(Bison) to take into account this
new expression.
Note. Use parser.sh to regenerate the Flex/Bison parser.
The protected data is most of the time string identifiers and
pointers to pgsExpression
expressions that are used
(evaluated) for evaluating the expression.
Header file is in pgadmin/include/pgscript/statements
and source file is in pgadmin/pgscript/statements
.
It returns nothing: this is kind of an expression that returns nothing.
It is a pgsStmt
child.
The header file must be included in pgsStatements.h
.
Duplicate pgsPrint
(header and source) and rename
the files: pgsMyStmt
for example.
Replace each occurrence of pgsPrint
with pgsMyStmt
.
Replace the protected data and the constructor with what you want.
Do not forget to make the copy constructor and the assignment operator private (not allowed).
The value()
method must return the not evaluated statement.
The eval(vars)
method evaluate the statement (it
returns nothing).
Add pgsMyStmt.h
in pgsStatements.h
.
Modify pgscript/pgsScanner.ll
(Flex) and pgscript/pgsParser.yy
(Bison) to take into account this
new statement.