pgadmin3/utils/_extract_func_help.pl
2026-02-18 16:10:47 +05:00

500 lines
16 KiB
Perl
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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' =>'
Скрипт генерации указывается в однострочном коментарии. Можно записать несколько скриптов для запроса.<br>
<b>--@gen:Имя для генерации:@Колонка1@,@Колонка2[-1],ae@,@Колонка3[0],e@\tcol4=@col4@\n</b><br>
<p>Имена колонок заключаются в "@" после имени, через запятую можно указать флаги.
Значения колонок подставляются с учётом форматирования.<br>
Глобальный флаг можно указать один раз в любой колонке. Разрешены спецпоследовательности <b>\n,\t,\r</b>.<br>
Если все имена колонок присутсвуют в результате запроса то в контекстное меню результата добавляется
имя генерации.<br>
Генерация работает для выделенных строк либо для всех строк.<br>
Можно ссылать на предудущие строки если индекс в квадратных скобках отрицательный или
абсолютно если положительный. Первая строка имеет индекс 0.<br>
Для первых двух скриптов можно применить быстрые клавиши <b>Ctrl+1</b>, <b>Ctrl+2</b>.<br>
</p>
<p>Флаги:<br>
<blockquote>
<b>a</b> → глобальный флаг включающий выравнивание. Учитываются все переводы строк, первая строка как образец (см. Ctrl+Shift+A).<br>
<b>e</b> → отключить форматирование. Значение колонки выводиться как есть.<br>
</blockquote>
</p>
'
);
my %ignorehtml=(
'pgbench.html',
);
my @keys_name=(
''
,'overlaps'
);
my @keys=(
"<td class=\"func_table_entry\">"
,"</td>"
,'<p><a id="id-1.5.8.15.7.1"' #overlaps
,'ass="computeroutput">true</code></pre>' #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"' => '<span style="font-size: 11pt;">',
'pclass="func_signature"/p' => '</span>',
'codeclass="token"' => '<span style="fgcolor: #0000ff;">',
'codeclass="token"/code' => '</span>',
'p' => '<blockquote>',
'p/p' => '</blockquote>',
'ul' => '<ul>',
'ul/ul' => '</ul>',
'liclass="listitem"' => '<li>',
'liclass="listitem"/li' => '</li>',
'divclass="itemizedlist"' => '',
'divclass="itemizedlist"/div' => '',
'divclass="titlepage"' => '',
'divclass="titlepage"/div' => '',
'divclass="note"' => '<pre>',
'divclass="note"/div' => '</pre>',
'divclass="warning"' => '<pre>',
'divclass="warning"/div' => '</pre>',
'divclass="tip"'=>'',
'divclass="tip"/div'=>'',
'div' => '',
'div/div' => '',
'h3class="title"' =>'<h3>',
'h3class="title"/h3' =>'</h3>',
'a' => '<a>',
'a/a' => '</a>',
'sup' => '<sup>',
'sup/sup' => '</sup>',
'em' => '<em>',
'em/em' => '</em>',
'emclass="replaceable"' => '<b>',
'emclass="replaceable"/em' => '</b>',
'emclass="lineannotation"' => '',
'emclass="lineannotation"/em' => '',
'spanclass="lineannotation"' => '<small>',
'spanclass="lineannotation"/span' => '</small>',
'acronymclass="acronym"' => '',
'acronymclass="acronym"/acronym' => '',
'spanclass="quote"' => '',
'spanclass="quote"/span' => '',
'spanclass="productname"' => '<b>',
'spanclass="productname"/span' => '</b>',
'spanclass="emphasis"' => '<b>',
'spanclass="emphasis"/span' => '</b>',
'spanclass="refentrytitle"' => '<b>',
'spanclass="refentrytitle"/span' => '</b>',
'spanclass="symbol_font"' => '<b>',
'spanclass="symbol_font"/span' => '</b>',
'code' => '',
'code/code' => '',
'preclass="programlisting"' => '<pre>',
'preclass="programlisting"/pre' => '</pre>',
'preclass="screen"' => '<pre>',
'preclass="screen"/pre' => '</pre>',
'preclass="synopsis"' => '',
'preclass="synopsis"/pre' => '',
'spanclass="optional"' => '<i>',
'spanclass="optional"/span' => '</i>',
'spanclass="systemitem"' => '<i>',
'spanclass="systemitem"/span' => '</i>',
'spanclass="application"' => '<i>',
'spanclass="application"/span' => '</i>',
'codeclass="filename"' => '<b>',
'codeclass="filename"/code' => '</b>',
'codeclass="computeroutput"' => '<i>',
'codeclass="computeroutput"/code' => '</i>',
'emclass="parameter"' => '',
'emclass="parameter"/em' => '',
'emclass="firstterm"' => '',
'emclass="firstterm"/em' => '',
'codeclass="varname"' => '',
'codeclass="varname"/code' => '',
'codeclass="structname"' => '<b>',
'codeclass="structname"/code' => '</b>',
'codeclass="structfield"' => '<b>',
'codeclass="structfield"/code' => '</b>',
'codeclass="literal"' => '<b>',
'codeclass="literal"/code' => '</b>',
'codeclass="function"' => '<b>',
'codeclass="function"/code' => '</b>',
'codeclass="returnvalue"' => '<b>',
'codeclass="returnvalue"/code' => '</b>',
'codeclass="type"' => '<b>',
'codeclass="type"/code' => '</b>',
'codeclass="command"' => '<b>',
'codeclass="command"/code' => '</b>',
);
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 "<") {
# <div>
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,"</dd>",$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 <length($s) && $s ne "") {
if (substr($s,$pos,1) eq "<") {
if (substr($s,$pos,2) eq "</") {
# close tag
$tagname = pop @t;
#if (length($defname)>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, "</a>";
$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="<a href=\"".$href."\">";
$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="<br>";}
$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/&gt;/>/g;
$fname =~ s/&lt;/</g;
$fname =~ s/&amp;/&/g;
$fname=lc($fname);
}
if (length($defname)>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."<hr>".$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;
}