- how to implement dynamically adjusting views based
on total number of result records??
- sqlite with_v3=yes
perl
perl-dbi with_dbd_sqlite=yes
perl-www
perl-xml
perl-util
apache
- apache.conf:
Alias /quos/ /u/rse/wrk/ossp/quos/
Options +ExecCGI
- prepare:
- purpose of all files
- OpenPKG RDF as example
- perldoc IO::File
- perldoc CGI
- perldoc String::Divert
- perldoc DBI
- design for HTML form for boolean expression based query!
(RT, perldoc DBIx::SearchBuilder)
- UI Query Part (boolean expression to HTML form):
Boolean Expression:
expr ::= field op value
| "!" expr
| expr "||" expr
| expr "&&" expr
| "(" expr ")"
field ::= /^[A-Z]+$/
op ::= "==" | "!=" | "<" | "<=" | ">" | ">=" | "=~" | "!~"
value ::= /^.*$/
HTML Form:
------------------------------
( field op value
& field op value )
& ( | field op value
& field op value
| ! field op value
& ! field op value )
------------------------------
<:NN V:NN UPDATE CLEAR SUBMIT
------------------------------
NAME LOAD DELETE
NAME SAVE HYPERLINK
------------------------------
- modules:
* transformation module:
- format 1: 2d form elements (input after submit of web form)
lo2 lo1 lo0 fn fo fv
+---+ +---+ +---+ +---------+ +---+ +---------+
0 ...| | | | | | | grp | |== | | Mail |
+---+ +---+ +---+ +---------+ +---+ +---------+
+---+ +---+ +---+ +---------+ +---+ +---------+
1 ...| | | | ||| | | desc | |=~ | | \bMTA\b |
+---+ +---+ +---+ +---------+ +---+ +---------+
+---+ +---+ +---+ +---------+ +---+ +---------+
2 ...| | |&& | | | | class | |== | | CORE |
+---+ +---+ +---+ +---------+ +---+ +---------+
+---+ +---+ +---+ +---------+ +---+ +---------+
3 ...| | | | ||| | | class | |== | | BASE |
+---+ +---+ +---+ +---------+ +---+ +---------+
: : : : : :
fn-0="grp"&fo-0="=="&fv-0="Mail"&lo0-1="||"&fn-1="desc"&fo-1="=~"&fv-1="\bMTA\b"
lo1-2="&&"&fn-2="class"&fo-2="=="&fv-2="CORE"&lo0-3="||"&fn-3="class"&fo-3="=="&fv-3="BASE"
- format 2a: astract syntax tree for query expression (internal representation)
function-style:
AND( OR( EQ(grp,"Mail"),
RE(desc,"\bMTA\b") ),
OR( EQ(class,"CORE"),
EQ(class,"BASE") ) )
in-core-style:
my $expr =
[ "AND", [ "OR", [ "EQ", "grp", "Mail" ],
[ "RE", "desc", "\bMTA\b"] ],
[ "OR", [ "EQ", "class", "CORE" ],
[ "EQ", "class", "BASE" ] ] ];
"print $expr->[2]->[1]->[2];" -> "CORE"
my $format2b = &transform_tree($expr, \&transform_style_perl);
my $format2c = &transform_tree($expr, \&transform_style_sql);
sub transform_tree {
my ($expr, $style) = @_;
my $str = '';
my ($op, $a1, $a2) = @{$expr};
$op = &style($op);
$a1 = ref($a1) ? &style(&transform_tree($a1, $style)) : &style($a1);
$a2 = ref($a2) ? &style(&transform_tree($a2, $style)) : &style($a2);
$str = "$a1 $op $a2";
return $str;
}
sub transform_style_perl {
my ($token) = @_;
$token =~ s/^AND$/&&/;
$token =~ s/^OR$/||/;
$token =~ s/^EQ$/==/;
$token =~ s/^RE$/=~/;
return $token;
}
sub transform_style_sql {
my ($token) = @_;
$token =~ s/^EQ$/=/;
$token =~ s/^RE$/MATCH/;
return $token;
}
- format 2b: C-style query expression (input after hyperlink in web page)
(grp == "Mail" || desc =~ "\bMTA\b") &&
(class == "CORE || class == "BASE")
- format 2c: SQL-style query expression (output for database query)
(quos.q_grp = 'Mail' OR quos.q_desc MATCH? '\bMTA\b') AND
(quos.q_class = 'CORE' OR quos.q_class = 'BASE')
* creation of web formular (render query)
sub_render_form (cgi-Object | expression, row, column
- Parsing CFG:
OSSP shiela (with tricks)
OSSP ac (uses Parse::RecDescent)
Parse::RecDescent (full featured recursive-descend parsing)
GENERAL:
config ::= directive(s)
directive ::= word arg ";"
arg ::= "{" config "}"
| word
word ::= m/"[^"]*"/
| m/'[^']*'/
| m/[^\s+;]+/
SPECIAL:
config ::= directive(s)
directive ::= options
| queries
| views
options ::= "option" "{" options-directive(s) "}" ";"
options-directive ::= webpage
| database
webpage ::= "webpage" word word ";"
database ::= "database" "{" database-directive(s) "}" ";"
database-directive ::= ...
...
queries ::= group(s)
...
views ::= view(s)
...
word ::= m/"[^"]*"/
| m/'[^']*'/
| m/[^\s+;]+/
- Parsing RDF:
my $str = ...; # string representation
my $rdf = {}; # AST representation
$str =~ s/]+)>(.+?)<\/Repository>/&do_repository($rdf, $1, $2)/sge;
sub do_repository {
my ($rdf, $attr, $str) = @_;
my ($name) = ($attr =~ m/rdf:resource="([^"]+)"/s);
$rdf->{$name} = {};
$str =~ s/]+)>(.+?)<\/rdf:Description>/&do_destription($rdf->{$name}, $1, $2)/sge;
sub do_description {
my ($rdf, $attr, $str) = @_;
$rdf->{...} = ...;
}
}
1. geht nur, wenn die Sprache keine rekursiven Elemente enthält, d.h. ein
Element kann nicht in sich selber (in beliebiger Tiefe) vorkommen
(Hinweis: Für Compilerbauer uninteressant)
2. Blockstruktur der Sprache wird direkt Substitution+Funktionsaufruf umgesetzt
3. Auf jeder Ebene wird die bereits erkannte Information in einer internen
Datenstruktur aufgesammelt ($rdf)
- Next Steps:
- openpkg-rdf2sql.pl:
. rdf to AST parsing (subst+func) (1)
. AST to SQL mapping (INSERT...) (2)
- quos.cgi:
. AST to SQL mapping (WHERE....) (3)
. view part
. result part