6
# Code still has to be documented
9
#load /usr/local/pgsql/lib/libpgtcl.so
14
# Check for minimum arguments
18
puts stderr "usage: pltcl_loadmod dbname \[options\] file \[...\]"
20
puts stderr "options:"
21
puts stderr " -host hostname"
22
puts stderr " -port portnumber"
28
# Remember database name and initialize options
30
set dbname [lindex $argv 0]
38
if {[string compare [string index [lindex $argv $i] 0] "-"] != 0} {
42
set opt [lindex $argv $i]
45
puts stderr "no value given for option $opt"
49
set val [lindex $argv $i]
54
append options "-host \"$val\" "
57
append options "-port $val "
60
puts stderr "unknown option '$opt'"
69
if {$i >= $argc || $errors > 0} {
71
puts stderr "usage: pltcl_loadmod dbname \[options\] file \[...\]"
73
puts stderr "options:"
74
puts stderr " -host hostname"
75
puts stderr " -port portnumber"
81
proc __PLTcl_loadmod_check_table {conn tabname expnames exptypes} {
82
set attrs [expr [llength $expnames] - 1]
86
pg_select $conn "select C.relname, A.attname, A.attnum, T.typname \
87
from pg_catalog.pg_class C, pg_catalog.pg_attribute A, pg_catalog.pg_type T \
88
where C.relname = '$tabname' \
89
and A.attrelid = C.oid \
91
and T.oid = A.atttypid \
92
order by attnum" tup {
98
puts stderr "Table $tabname has extra field '$tup(attname)'"
103
set xname [lindex $expnames $i]
104
set xtype [lindex $exptypes $i]
106
if {[string compare $tup(attname) $xname] != 0} {
107
puts stderr "Attribute $i of $tabname has wrong name"
108
puts stderr " got '$tup(attname)' expected '$xname'"
111
if {[string compare $tup(typname) $xtype] != 0} {
112
puts stderr "Attribute $i of $tabname has wrong type"
113
puts stderr " got '$tup(typname)' expected '$xtype'"
122
if {$found < $attrs} {
124
set miss [lrange $expnames $found end]
125
puts "Table $tabname doesn't have field(s) $miss"
137
proc __PLTcl_loadmod_check_tables {conn} {
138
upvar #0 __PLTcl_loadmod_status status
142
set names {{} modname modseq modsrc}
143
set types {{} name int2 text}
145
switch [__PLTcl_loadmod_check_table $conn pltcl_modules $names $types] {
147
set status(create_table_modules) 1
150
set status(create_table_modules) 0
153
puts "Error(s) in table pltcl_modules"
158
set names {{} funcname modname}
159
set types {{} name name}
161
switch [__PLTcl_loadmod_check_table $conn pltcl_modfuncs $names $types] {
163
set status(create_table_modfuncs) 1
166
set status(create_table_modfuncs) 0
169
puts "Error(s) in table pltcl_modfuncs"
174
if {$status(create_table_modfuncs) && !$status(create_table_modules)} {
175
puts stderr "Table pltcl_modfuncs doesn't exist but pltcl_modules does"
176
puts stderr "Either both tables must be present or none."
180
if {$status(create_table_modules) && !$status(create_table_modfuncs)} {
181
puts stderr "Table pltcl_modules doesn't exist but pltcl_modfuncs does"
182
puts stderr "Either both tables must be present or none."
192
if {!$status(create_table_modules)} {
193
__PLTcl_loadmod_read_current $conn
198
proc __PLTcl_loadmod_read_current {conn} {
199
upvar #0 __PLTcl_loadmod_status status
200
upvar #0 __PLTcl_loadmod_modsrc modsrc
201
upvar #0 __PLTcl_loadmod_funclist funcs
202
upvar #0 __PLTcl_loadmod_globlist globs
207
pg_select $conn "select distinct modname from pltcl_modules" mtup {
208
set mname $mtup(modname);
209
lappend curmodlist $mname
212
foreach mname $curmodlist {
214
pg_select $conn "select * from pltcl_modules \
215
where modname = '$mname' \
216
order by modseq" tup {
217
append srctext $tup(modsrc)
221
__PLTcl_loadmod_analyze \
224
$srctext new_globals new_functions
228
set modsrc($mname) $srctext
229
set funcs($mname) $new_functions
230
set globs($mname) $new_globals
241
proc __PLTcl_loadmod_analyze {modinfo modname srctext v_globals v_functions} {
242
upvar 1 $v_globals new_g
243
upvar 1 $v_functions new_f
244
upvar #0 __PLTcl_loadmod_allfuncs allfuncs
245
upvar #0 __PLTcl_loadmod_allglobs allglobs
249
set old_g [info globals]
250
set old_f [info procs]
255
uplevel #0 "$srctext"
257
puts "$modinfo: $msg"
261
set cur_g [info globals]
262
set cur_f [info procs]
264
foreach glob $cur_g {
265
if {[lsearch -exact $old_g $glob] >= 0} {
268
if {[info exists allglobs($glob)]} {
269
puts stderr "$modinfo: Global $glob previously used in module $allglobs($glob)"
272
set allglobs($glob) $modname
275
uplevel #0 unset $glob
277
foreach func $cur_f {
278
if {[lsearch -exact $old_f $func] >= 0} {
281
if {[info exists allfuncs($func)]} {
282
puts stderr "$modinfo: Function $func previously defined in module $allfuncs($func)"
285
set allfuncs($func) $modname
294
#puts "globs in $modname: $new_g"
295
#puts "funcs in $modname: $new_f"
299
proc __PLTcl_loadmod_create_tables {conn} {
300
upvar #0 __PLTcl_loadmod_status status
302
if {$status(create_table_modules)} {
304
set res [pg_exec $conn \
305
"create table pltcl_modules ( \
310
puts stderr "Error creating table pltcl_modules"
315
set res [pg_exec $conn \
316
"create index pltcl_modules_i \
317
on pltcl_modules using btree \
318
(modname name_ops);"]
320
puts stderr "Error creating index pltcl_modules_i"
324
puts "Table pltcl_modules created"
325
pg_result $res -clear
328
if {$status(create_table_modfuncs)} {
330
set res [pg_exec $conn \
331
"create table pltcl_modfuncs ( \
335
puts stderr "Error creating table pltcl_modfuncs"
340
set res [pg_exec $conn \
341
"create index pltcl_modfuncs_i \
342
on pltcl_modfuncs using hash \
343
(funcname name_ops);"]
345
puts stderr "Error creating index pltcl_modfuncs_i"
349
puts "Table pltcl_modfuncs created"
350
pg_result $res -clear
355
proc __PLTcl_loadmod_read_new {conn} {
356
upvar #0 __PLTcl_loadmod_status status
357
upvar #0 __PLTcl_loadmod_modsrc modsrc
358
upvar #0 __PLTcl_loadmod_funclist funcs
359
upvar #0 __PLTcl_loadmod_globlist globs
360
upvar #0 __PLTcl_loadmod_allfuncs allfuncs
361
upvar #0 __PLTcl_loadmod_allglobs allglobs
362
upvar #0 __PLTcl_loadmod_modlist modlist
367
foreach modfile $modlist {
368
set modname [file rootname [file tail $modfile]]
370
set fid [open $modfile "r"]
376
set srctext [read $fid]
379
if {[info exists modsrc($modname)]} {
380
if {[string compare $modsrc($modname) $srctext] == 0} {
381
puts "Module $modname unchanged - ignored"
384
foreach func $funcs($modname) {
385
unset allfuncs($func)
387
foreach glob $globs($modname) {
388
unset allglobs($glob)
390
unset funcs($modname)
391
unset globs($modname)
392
set modsrc($modname) $srctext
393
lappend new_modlist $modname
395
set modsrc($modname) $srctext
396
lappend new_modlist $modname
400
__PLTcl_loadmod_analyze "New/updated $modname" \
401
$modname $srctext new_globals new_funcs
406
set funcs($modname) $new_funcs
407
set globs($modname) $new_globals
416
set modlist $new_modlist
420
proc __PLTcl_loadmod_load_modules {conn} {
421
upvar #0 __PLTcl_loadmod_modsrc modsrc
422
upvar #0 __PLTcl_loadmod_funclist funcs
423
upvar #0 __PLTcl_loadmod_modlist modlist
427
foreach modname $modlist {
428
set xname [__PLTcl_loadmod_quote $modname]
430
pg_result [pg_exec $conn "begin;"] -clear
432
pg_result [pg_exec $conn \
433
"delete from pltcl_modules where modname = '$xname'"] -clear
434
pg_result [pg_exec $conn \
435
"delete from pltcl_modfuncs where modname = '$xname'"] -clear
437
foreach func $funcs($modname) {
438
set xfunc [__PLTcl_loadmod_quote $func]
440
pg_exec $conn "insert into pltcl_modfuncs values ( \
441
'$xfunc', '$xname')" \
445
set srctext $modsrc($modname)
446
while {[string compare $srctext ""] != 0} {
447
set xpart [string range $srctext 0 3999]
448
set xpart [__PLTcl_loadmod_quote $xpart]
449
set srctext [string range $srctext 4000 end]
452
pg_exec $conn "insert into pltcl_modules values ( \
453
'$xname', $i, '$xpart')" \
458
pg_result [pg_exec $conn "commit;"] -clear
460
puts "Successfully loaded/updated module $modname"
465
proc __PLTcl_loadmod_quote {s} {
466
regsub -all {\\} $s {\\\\} s
467
regsub -all {'} $s {''} s
472
set __PLTcl_loadmod_modlist [lrange $argv $i end]
473
set __PLTcl_loadmod_modsrc(dummy) ""
474
set __PLTcl_loadmod_funclist(dummy) ""
475
set __PLTcl_loadmod_globlist(dummy) ""
476
set __PLTcl_loadmod_allfuncs(dummy) ""
477
set __PLTcl_loadmod_allglobs(dummy) ""
479
unset __PLTcl_loadmod_modsrc(dummy)
480
unset __PLTcl_loadmod_funclist(dummy)
481
unset __PLTcl_loadmod_globlist(dummy)
482
unset __PLTcl_loadmod_allfuncs(dummy)
483
unset __PLTcl_loadmod_allglobs(dummy)
488
set __PLTcl_loadmod_conn [eval pg_connect $dbname $options]
490
unset i dbname options errors opt val
492
__PLTcl_loadmod_check_tables $__PLTcl_loadmod_conn
494
__PLTcl_loadmod_read_new $__PLTcl_loadmod_conn
496
__PLTcl_loadmod_create_tables $__PLTcl_loadmod_conn
497
__PLTcl_loadmod_load_modules $__PLTcl_loadmod_conn
499
pg_disconnect $__PLTcl_loadmod_conn