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.
doc
Contains files related to the application documentation.
HTML files are packaged with the application. generate.sh and XML (DocBook) files are used for generating those HTML files.
etc
Contains scripts that are used occasionally.
files
Contains sample input files and test files.
inputs
Sample pgScript scripts.
tests
Integration test suite.
execute.sh executes this integration test
suite. It must be executed from the files/tests
folder and pgScript must be compiled. Once executed no warning and
no exception should appear.
dictionaries
Sample dictionaries for the dictionary generator.
sources
Input scripts used by execute.sh
lib
Source files and header files for building
libpgs
.
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 add other ones.
src
Source files for pgScript main program: this is a simple
main()
command-line interface that relies on
libpgs
.
test
Unit test suite.
Contains a main()
in pgsTestSuite.cpp
that runs a test suite on libpgs
.
Either src
is built or test
is built
but both cannot be built at the same time: configure
takes care of that. Use --enable-tests to compile
test and nothing or --disable-tests to compile
src
. src
must be compiled to run the
integration test suite.
This section focuses on the libpgs
architecture and
therefore the files contained in the lib
folder.
db
Source files imported from pgAdmin and used for connecting to a database and executing queries. This code was a bit modified to suit pgScript.
include
Header files of db
, pgscript
and
utils
.
pgscript
Source files and header files for building
libpgs
.
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 add other ones.
utils
Source files imported from pgAdmin and used by db
and log functions. This code was a bit modified to suit
pgScript.
When exporting pgScript to pgAdmin it is only necessary to export
include/pgscript
and pgscript
directories
because the code of pgScript is fully compatible with pgAdmin without any modification. The opposite is not
true and this explains why db
and utils
code
was a bit modified to suit pgScript.
This section describes the pgscript
folder, which is
very like include/pgscript
.
pgscript
pgsParser.yy
, pgsScanner.ll
: Bison
& Flex parser for the T-SQL syntax (use parser.sh to generate
source and header files).
parser.tab.cc
, lex.pgs.cc
: Bison
& 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 libpgs with the
outside world, allows users to parse a file or a string.
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.
expressions
Contains r-values, i.e
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). It
returns a pgsOperand
. Its parameter
pgsVarMap
is a map of
pgsOperand
.
pgsOperand
is simply a smart pointer on a
pgsObject
(see objects
).
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.
objects
pgsObject
is the common parent class: a smart
pointer to a pgsObject
(pgsOperand
) is
the data that is used in
pgScript.
pgsGenerator
: 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, i.e
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
, ...).
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.
utilities
pgsAlloc
: when configured with --enable-debug 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 & Flex
files.
pgsScanner
: Flex header.
pgsMapm
: conversion utilities for the MAPM
library, the big number library used in pgScript.
pgsThread
: pgScript runs in a detached (auto
delete) thread that can be interrupted, this is the
thread.
pgsUtilities
: various utilities.
pgsCopiedPtr
, pgsSharedPtr
:
smart pointers, their names are explicit.
There are two steps: unit tests on classes and integration tests on pgScript executable.
Go to the pgScript directory and enter the following commands:
./configure --enable-debug --enable-tests make ./test/pgsTest
There should be no assertion failure, otherwise there is a bug.
Go to the pgScript directory and enter the following commands:
./configure --enable-debug --disable-tests cd files/tests/ ./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.
-d testbase
implies pgScript will write to a
database called testbase
. Be sure it is not a production
database.
There should be no error during this process.
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 in the standalone version.
NPGADMIN
stands for Not pgAdmin. This
means:
Not to create the set_caller
method in
pgsApplication
. Its goal is to provide
pgsApplication
with the window and the event to
dispatch once a pgsThread
is done, in order to notify
pgAdmin that pgScript has completed his job and that pgAdmin can
disable the stop button and enable the run button again.
To use a wxTextOutputStream
instead of a
wxTextCtrl
for outputting data. wxTextCtrl
is good for interfacing with pgAdmin and its msgResult
box. wxTextOutputStream
is better for pgScript
standalone version so that users could provide it with whatever
output stream they want.
When compiled with pgAdmin this symbol is not defined. Therefore
set_caller
is defined an a wxTextCtrl
is used
for output.
./configure --enable-tests
Compiles tests in the test
folder instead of the main
program in src
folder. Use ./test/pgsTest
to
run the unit test suite.
./configure --enable-debug
Compiles pgScript (test
or src
) 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.
autoclean.sh
Cleans every generated file by autogen.sh
and object
files (*.o). See the source to know the files that are deleted.
Explores ./files
, ./lib
and
./test
. The ./src/Makefile.am
is not generated
and ./src/configure.ac
is not updated with this
script.
autogen.sh
Runs aclocal
, autoheader
,
automake
and autoconf
in ./
,
./lib
, ./src
and ./test
.
windows.sh
Generates a Windows binary distribution. pgScript must have been compiled before with MinGW.
lib/parser.sh
See the Directory structure section.
lib/pgadmin.sh
Generates a tar
that can be deployed in pgAdmin. This
only contains source files: modules.mk
files and
vcproj
file need to be updated if new files are added or some
are removed.
doc/generate.sh
See the Directory structure section. Generates documentation.
files/tests/execute.sh
See the Directory structure section. Runs the integration test suite.
The pgScript project on the CVS repository is an Eclipse CDT project. This is configured for a Windows & MinGW platform.
Project -> Properties -> C/C++ Build ->
Environment
or Settings
You can configure paths to wxWidgets and libpq in GCC C++
Compiler -> Directories
and in C++ Linker ->
Libraries
. You can use the MINGWDIR
environment
variable in order to achieve that.
Header file is in
lib/include/pgscript/expressions
, source file is in
lib/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.
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.
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
lib/include/pgscript/statements
, source file is in
lib/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.