#!/usr/bin/perl use strict; use Data::Dump qw(dump); my $pathdir_help="."; my @files; my @stak; my %function_help; my %useref; my %section; my %my_help=( '@gen' =>' Скрипт генерации указывается в однострочном коментарии. Можно записать несколько скриптов для запроса.
--@gen:Имя для генерации:@Колонка1@,@Колонка2[-1],ae@,@Колонка3[0],e@\tcol4=@col4@\n

Имена колонок заключаются в "@" после имени, через запятую можно указать флаги. Значения колонок подставляются с учётом форматирования.
Глобальный флаг можно указать один раз в любой колонке. Разрешены спецпоследовательности \n,\t,\r.
Если все имена колонок присутсвуют в результате запроса то в контекстное меню результата добавляется имя генерации.
Генерация работает для выделенных строк либо для всех строк.
Можно ссылать на предудущие строки если индекс в квадратных скобках отрицательный или абсолютно если положительный. Первая строка имеет индекс 0.
Для первых двух скриптов можно применить быстрые клавиши Ctrl+1, Ctrl+2.

Флаги:

a → глобальный флаг включающий выравнивание. Учитываются все переводы строк, первая строка как образец (см. Ctrl+Shift+A).
e → отключить форматирование. Значение колонки выводиться как есть.

' ); my %ignorehtml=( 'pgbench.html', ); my @keys_name=( '' ,'overlaps' ); my @keys=( "" ,"" ,'

true' #overlaps end ); my %others_func=( 'FUNCTIONS-DATETIME-DELAY'=>'pg_sleep' ,'FUNCTIONS-CASE'=>'case' ,'FUNCTIONS-COMPARISONS-IN-SCALAR'=>'in' ,'id-1.5.8.30.15'=>'not in' ,'FUNCTIONS-NULLIF'=>'nullif' ,'FUNCTIONS-COALESCE-NVL-IFNULL'=>'coalesce' ,'FUNCTIONS-GREATEST-LEAST'=>'greatest' ,'greatest'=>'least' ,'FUNCTIONS-LIKE'=>'like' ,'FUNCTIONS-SIMILARTO-REGEXP'=>'similar to' ,'id-1.5.8.30.16' => 'any' ,'id-1.5.8.30.17' => 'all' ,'FUNCTIONS-SUBQUERY-EXISTS'=>'exists' ,'FUNCTIONS-SUBQUERY-IN'=>'in' ,'FUNCTIONS-SUBQUERY-NOTIN'=>'not in' ,'FUNCTIONS-SUBQUERY-ALL'=>'all' ,'FUNCTIONS-SUBQUERY-ANY-SOME'=>'some' ,'some'=>'any' ,'ROW-WISE-COMPARISON' => 'is distinct from' ,'SQL-SYNTAX-TYPE-CASTS' => 'cast' ,'SQL-SYNTAX-COLLATE-EXPRS' => 'collate' ,'SQL-SYNTAX-ARRAY-CONSTRUCTORS' => 'array' ,'SQL-SYNTAX-ROW-CONSTRUCTORS' => 'row' ,'SYNTAX-WINDOW-FUNCTIONS' => 'filter' ,'filter' => 'over' ); my %keys_to_file=( 'order' => '@queries-order.html' ,'limit' => '@queries-limit.html' ,'offset' => '@queries-limit.html' ,'values' => '@queries-values.html' ,'with' => '@queries-with.html' ,'union' => '@queries-union.html' ,'from' => '@queries-table-expressions.html#QUERIES-FROM' ,'where' => '@queries-table-expressions.html#QUERIES-WHERE' ,'group' => '@queries-table-expressions.html#QUERIES-GROUP' ,'having' => '@queries-table-expressions.html#QUERIES-GROUP' ,'cube' => '@queries-table-expressions.html#QUERIES-GROUPING-SETS' ,'rollup' => '@queries-table-expressions.html#QUERIES-GROUPING-SETS' ); my %tags=( 'pclass="func_signature"' => '', 'pclass="func_signature"/p' => '', 'codeclass="token"' => '', 'codeclass="token"/code' => '', 'p' => '

', 'p/p' => '
', 'ul' => '', 'liclass="listitem"' => '
  • ', 'liclass="listitem"/li' => '
  • ', 'divclass="itemizedlist"' => '', 'divclass="itemizedlist"/div' => '', 'divclass="titlepage"' => '', 'divclass="titlepage"/div' => '', 'divclass="note"' => '
    ',
    'divclass="note"/div'             => '
    ', 'divclass="warning"' => '
    ',
    'divclass="warning"/div'             => '
    ', 'divclass="tip"'=>'', 'divclass="tip"/div'=>'', 'div' => '', 'div/div' => '', 'h3class="title"' =>'

    ', 'h3class="title"/h3' =>'

    ', 'a' => '
    ', 'a/a' => '', 'sup' => '', 'sup/sup' => '', 'em' => '', 'em/em' => '', 'emclass="replaceable"' => '', 'emclass="replaceable"/em' => '', 'emclass="lineannotation"' => '', 'emclass="lineannotation"/em' => '', 'spanclass="lineannotation"' => '', 'spanclass="lineannotation"/span' => '', 'acronymclass="acronym"' => '', 'acronymclass="acronym"/acronym' => '', 'spanclass="quote"' => '', 'spanclass="quote"/span' => '', 'spanclass="productname"' => '', 'spanclass="productname"/span' => '', 'spanclass="emphasis"' => '', 'spanclass="emphasis"/span' => '', 'spanclass="refentrytitle"' => '', 'spanclass="refentrytitle"/span' => '', 'spanclass="symbol_font"' => '', 'spanclass="symbol_font"/span' => '', 'code' => '', 'code/code' => '', 'preclass="programlisting"' => '
    ',
    'preclass="programlisting"/pre'                 => '
    ', 'preclass="screen"' => '
    ',
    'preclass="screen"/pre'                 => '
    ', 'preclass="synopsis"' => '', 'preclass="synopsis"/pre' => '', 'spanclass="optional"' => '', 'spanclass="optional"/span' => '', 'spanclass="systemitem"' => '', 'spanclass="systemitem"/span' => '', 'spanclass="application"' => '', 'spanclass="application"/span' => '', 'codeclass="filename"' => '', 'codeclass="filename"/code' => '', 'codeclass="computeroutput"' => '', 'codeclass="computeroutput"/code' => '', 'emclass="parameter"' => '', 'emclass="parameter"/em' => '', 'emclass="firstterm"' => '', 'emclass="firstterm"/em' => '', 'codeclass="varname"' => '', 'codeclass="varname"/code' => '', 'codeclass="structname"' => '', 'codeclass="structname"/code' => '', 'codeclass="structfield"' => '', 'codeclass="structfield"/code' => '', 'codeclass="literal"' => '', 'codeclass="literal"/code' => '', 'codeclass="function"' => '', 'codeclass="function"/code' => '', 'codeclass="returnvalue"' => '', 'codeclass="returnvalue"/code' => '', 'codeclass="type"' => '', 'codeclass="type"/code' => '', 'codeclass="command"' => '', 'codeclass="command"/code' => '', ); opendir(DIR, $pathdir_help) or die "can't opendir $pathdir_help: $!"; while (defined(my $file = readdir(DIR))) { next if (!($file =~ /html$/)); push @files, $file; } closedir(DIR); my $TDcount=0; foreach my $file (sort @files) { #open my $info, $file or die "Could not open $file: $!"; if (exists $ignorehtml{$file}) {next;} my $fileContent; open(my $F, '<', $file) or die $!; binmode($F); { local $/; $fileContent = <$F>; } close($F); my $pos=0; my $lvl=0; my $cc=0; my $val=""; my $se="div"; #div id=href $pos=0; while ($pos>-1) { my $n1=index($fileContent,"id=\"",$pos); if ($n1 > -1) { my $n2=index($fileContent,"\"",$n1+4); my $id_name=substr($fileContent,$n1+4,$n2-$n1-4); my $nn=$n1; while (substr($fileContent,$nn,1) ne "<") { $nn--; } $nn++; ($se)= substr($fileContent,$nn,40) =~ /(\S+)/; #print "se=$se id_name=$id_name tag=\n40 sim=".substr($fileContent,$nn,40); $n2++; $pos=$n2; #if (exists $ref{$id_name}) if (uc($id_name) eq $id_name || (exists $others_func{$id_name} && $se ne "a")) { my @st=(); my $n3=$pos; while ($n1 > -1) { $n1=$pos; $n1=index($fileContent,$se,$pos); if ($n1 >-1) { #print "$n1\n"; if (substr($fileContent,$n1-1,1) eq "<") { #
    push @st, $n1; #print "+".substr($fileContent,$n1,20)."\n"; $n1=$n1+3; $pos=$n1; next; } if (substr($fileContent,$n1-1,1) eq "/" && substr($fileContent,$n1-2,1) eq "<") { ## close tag #print "-".substr($fileContent,$n1,20)."\n"; if (scalar @st == 0) { if ($se eq "dt") { $n1=index($fileContent,"",$n1); $n1=$n1+7; #print "".substr($fileContent,$n3+1,$n1-$n3-length($se)-1); } my $r=substr($fileContent,$n3+1,$n1-$n3-length($se)); #if (index($id_name,"FUNCTIONS-",0)==0 && $se ne "a") { my $ee=substr($fileContent,$nn,40); print " ->$id_name\n";} if (exists $others_func{$id_name}) { my $id_index=$others_func{$id_name}; print "====> other function $id_name add <=====\n"; while (exists $others_func{$id_index}) { $id_index=$others_func{$id_index}; parseTag($r,$id_index); } $id_index=$others_func{$id_name}; parseTag($r,$id_index); } else { $section{$id_name}=$r; } #print "$r \n$id_name\n"; #exit; $n1=-1; next; } #0 level end my $nnn=pop @st; $pos=$n1+length($se); next; } $pos=$n1+length($se); } } $n2=$n2+1; print ""; } $pos=$n2; } else { $pos=$n1;} } #td func #print "file $file\n"; $pos=0; while( $pos > -1) { #td function my $ist=index($fileContent,$keys[$lvl],$pos); if ($ist > -1) { my $ien=index($fileContent,$keys[$lvl+1],$ist); if ($ien >-1) { print "Read file $file .. " if $cc==0; my $posval=$ist+length($keys[$lvl]); if ($lvl>1) { $val=substr($fileContent,$ist,$ien-$ist+length($keys[$lvl+1])); } else { $val=substr($fileContent,$posval,$ien-$posval); } my $idx_name=$lvl/2; my $name_sec=$keys_name[$idx_name]; parseTag($val,$name_sec); $pos=$ien+length($keys[$lvl+1]); if ($lvl==2) { #print " kes idx==2 name_sec=$name_sec \n"; } $cc++; } else { die "Not closed string $keys[$lvl+1] . File : $file position : $ist\n"; } } else { $lvl=$lvl+2; if (scalar @keys > $lvl) { $pos=0; # new keys } else { $pos=$ist; } } } print " Ok.\n" if $cc > 0; } print " TD count $TDcount\n"; open(F, '>', "_func.txt") or die $!; my $c0=0; #append my help # foreach my $key (sort keys %my_help) { $function_help{$key}=$my_help{$key}; } foreach my $key (sort keys %useref) { $function_help{$key}=$section{$key}; #print "section $key\n"; $c0++; } my $c1=0; foreach my $key (sort keys %keys_to_file) { $function_help{$key}=$keys_to_file{$key}; #print "section $key\n"; $c1++; } print "Add section $c0 add file link $c1\n"; foreach my $key (sort keys %function_help) { #print "$key: $function_help{$key}\n"; print F "#".$key."\n".$function_help{$key}."\n"; } close(F); exit; ################################################################### sub parseTag { my $s=shift; my $defname=shift; $TDcount++; my $text; my $tagname; my $attr; my $vv; my $pos=0; my $repl; my $pc; my $pre=0; my $fn=0; my $flit=0; my $fname; my $fliteral; my $href; my @t=(); while ($pos 0 ) {print "close $tagname\n";} my $tmp=substr($s,$pos); # print "CLOSE TAG=$tagname pos=$pos\n"; my ($tagnameC) = $tmp =~ m/<(\/\w+)>/g; if (substr($tagname,0,3) eq "pre") {$pre=0;} my $startp=$pos; $pos=index($s,'>',$pos); if ($pos<0) { die "$s\n NOT CLOSE SIBOL > for tag ${tagname} last=$tmp\n"; } $pos++; if (exists $tags{$tagname.$tagnameC}) { $repl=$tags{$tagname.$tagnameC}; push @stak, $text, $repl; } else { if ($href ne "") { push @stak, $text, ""; $useref{$href}=1; $href=""; } else { die "$s\n NOT DEFINE REPALCE CLOSE TAG ${tagname}${tagnameC} pos=$pos\n"; } } if ($tagname eq "codeclass=\"function\"" && $fn == 1 ) { $fn=0; $fname=$text; } if ($tagname eq "codeclass=\"literal\"" && $flit == 1 ) { $fliteral=$text; } $text=""; next; #end close } my $tmp=substr($s,$pos); ($tagname,$attr) = $tmp =~ m/<(\w+)\s*(.*?)>/g; # if (length($defname)>0 ) {print "open $tagname pos=$pos\n";} my $pp=$pos; $pos=index($s,'>',$pos); if ($pos<0) { die "$s\n NOT CLOSE TAG ${tagname} pos=$pp\n"; } $pos++; $href=""; if ($tagname eq "a" ) {($href) = $attr =~ m/href=".*?#(.*?)"/; $attr=""; } if ($tagname eq "sup" ) {$attr="";} if ($tagname eq "ul" ) {$attr="";} if ($tagname eq "pre" ) {$pre=1;} if ($tagname eq "code" && $attr =~ /literal/ ) {$flit++;} if ($attr =~ /func_signature/ ) {$fn=1;} die "$s TAG NAME EMPTY\n" if $tagname eq "" ; if (exists $tags{$tagname.$attr}) { $repl=$tags{$tagname.$attr}; if ($href ne "") { $repl=""; $useref{$href}=1; #print "$repl\n"; } push @stak, $text , $repl; $text=""; } else { die "$s\n NOT DEFINE REPALCE OPEN TAG ${tagname}${attr}\n"; } #print substr($s,$pos)."\n =============== tag=$tagname, attr=$attr\n"; push @t, $tagname.$attr; # print "TAG=${tagname}${attr} pos=$pos prev=$pp\n"; next; } else { my $c=substr($s,$pos,1); if ($pc eq $c && $c eq " " && $pre == 0) { } else { if ($pre == 1 && $c eq "\n") {$c="
    ";} $text.=$c; $pc=$c; } } $pos++; } my $rez; # dump(@stak); foreach my $t (@stak) { next if $t eq ""; $rez.=$t; } if (!defined $fname && defined $fliteral) { $fname=lc($fliteral); #print "Literal function define $fname\n"; } if (defined $fname) { $fname =~ s/>/>/g; $fname =~ s/</0) { $fname=$defname; } if (defined $fname && exists $function_help{$fname}) { #print "Dublicate function define $text .Append help\n"; my $v=$function_help{$fname}; $function_help{$fname}=$v."
    ".$rez; if ($fname =~ /\||\[/ && length($fname)>3) { print "Bad name $fname \n"; } #print "$s\nAppend REZ: $function_help{$fname}\n"; } if (defined $fname && !exists $function_help{$fname}) { if ($fname =~ /\||\[/ && length($fname)>3) { print "Bad name $fname \n"; } $function_help{$fname}=$rez; } # print "$s\nREZ: $rez\n"; @stak=(); #exit; }