db-table-data.tcl

Location:
/packages/acs-subsite/www/admin/system/db-table-data.tcl
Author:
Guenter Ernst guenter.ernst@wu-wien.ac.at
Created:
14.09.2007

Related Files

[ hide source ] | [ make this the default ]

File Contents

ad_page_contract {
    @author Guenter Ernst guenter.ernst@wu-wien.ac.at
    @creation-date 14.09.2007
} {
    t:notnull
    {c:optional}
    {orderby:optional {}}
    {where:optional,allhtml {}}
    {offset:integer,optional {0}}
    {limit:optional {100}}
} -validate {
    table_exists -requires {t:notnull} {
        
        if {![regexp {^(.*?)\.(.*)$} $t _ namespace table]} {
            set namespace "public"
            set table $table
        } 
        
        set sql {
            select
                c.oid,
                c.relname,
                n.nspname,
                Case when c.relkind = 'r' then 'Table'
                else 'View'
                end as relkind_pretty
            from pg_class c inner join pg_namespace n on c.relnamespace = n.oid
            where n.nspname=:namespace and c.relname=:table and c.relkind in ('r','v')
        }
        
        if {![db_0or1row check_table $sql]} {
            ad_complain "Table $t not found"
            return
        }
    }
    where_has_no_double_quotes -requires {where} {
        if {[regexp {\"} $where]} {
            ad_complain "No Double Quotes in WHERE-Clause"
            return
        }
        if {$where ne ""} {
            set where " where $where"
        }
    }
}

# source table selector
set options [list]
db_foreach get_tables {select
            n.nspname || '.' || c.relname  as fq_table_name,
            relkind 
            from pg_catalog.pg_class c inner join pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
            where relkind in ('r','v') 
            order by fq_table_name} {
    lappend options [list ${fq_table_name}[expr {$relkind eq "v"?" (View)":""}] $fq_table_name]
}

# einschränken der ergebnisse
ad_form \
    -name restrictions \
    -mode edit \
    -form {
        {orderby:text(hidden)
            {value $orderby}
        }
        {t:text(select) 
            {label "Select Table/View"}
            {options $options}
            {html {onchange "document.getElementById('restrictions_where').value='';"}}
            {value $t}
            
        }
        {where:text(text),optional
            {label "Where clause"}
            {value $where}
            {help_text {Without 'WHERE'}}
        }
        {limit:text(text),optional
            {label "Limit"}
            {html {size 5}}
            {value $limit}
            {help_text {Default: 100; Use 'ALL' to remove limit}}
        }
        {offset:integer(text),optional
            {label "Offset"}
            {html {size 5}}
            {value $offset}
        }
    } -on_submit {
        if {$limit eq ""} {set limit all}
        if {$offset eq ""} {set offset 0}
        if {[string trim $where] ne ""} {
            set where "where $where"
        }
    }


# count all row

set table_rows [lc_numeric num [db_string count_rows "select count(*) from $t" -default 0]]


set columns [list]

set cols_sql {select
                attname,
                attnum,
                (select count(*) > 0 from pg_constraint r where r.conrelid = :oid and r.contype='f' and attnum = any (r.conkey)) as foreign_key_p
            from pg_attribute 
            where 
                 attnum > 0 
                 and NOT attisdropped
                 and attrelid = :oid
            order by attnum}

set columns_list [db_list_of_lists get_columns $cols_sql]

db_foreach get_columns_list $cols_sql {
    lappend columns $attname
    set attnum_attname_map($attnum$attname
    set f_key_map($attnum$foreign_key_p 
}


# get the foreign key constraints for this table 
# and map them to the corresponding colums

set sql "select
            (select n.nspname || '.' || c.relname as table_name 
                from pg_catalog.pg_class c inner join pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
                where c.oid = con.confrelid) as fq_target_fk_table_name,
            (select at.attname from pg_attribute at where at.attrelid = con.confrelid and at.attnum = con.confkey\[1\]) as fk_column_name,
            con.conkey\[1\]::integer
        from pg_constraint con    
        where con.conrelid = :oid and con.confkey is not null"


db_foreach get_fk_list $sql {
    set fk_target_map($conkey) [list $fq_target_fk_table_name $fk_column_name]
    set f_key($conkey) 1
}

# get all tables that have a foreign-key relation to this table 
set sql {SELECT
            r.confkey[1]::integer,
            (select at.attname from pg_attribute at where 
                at.attrelid = r.conrelid and at.attnum = r.conkey[1]) as ref_fk_column_name,
              (select n.nspname || '.' || c.relname as table_name 
                from pg_catalog.pg_class c inner join pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
                where c.oid = r.conrelid) as ref_fk_table_name
        FROM pg_catalog.pg_constraint r WHERE r.confrelid = :oid and r.contype='f'
        order by ref_fk_table_name, ref_fk_column_name}


::template::multirow create fk_references column ref_table ref_column

db_foreach get_ref_fks $sql {
    ::template::multirow append fk_references $attnum_attname_map($confkey) $ref_fk_table_name $ref_fk_column_name
    set ref_fk_p($confkey) 1
}


########################

set filters [list]

set order_by [list]

foreach column $columns {
    lappend order_by $column [list label "$column" orderby $column]
} 

if {([info exists orderby] && $orderby ne "") && [lsearch $columns [lindex [split $orderby ","] 0]] == -1} {
    set orderby [lindex $columns 0]
}

if {(![info exists orderby] || $orderby eq "")} {set orderby [lindex $columns 0]}


######################################################
### Create the list template
######################################################

# create list elements

set elements [list]
set idx 1
foreach element $columns {
    lappend elements $element [list label "$element" \
                                    sub_class "narrow" \
                                    html {style "border-right:1px solid #A0BDEB;border-left:1px solid #A0BDEB;"} \
                                    display_template "@table.$element@[expr {[info exists f_key($idx)] && $f_key_map($idx)==t?"<if @table.$element@ ne \"\"><sup><b>\
                                                            <a href='db-table-data?t=[lindex $fk_target_map($idx) 0]\&where=[lindex $fk_target_map($idx) 1]%3d%27@table.$element@%27' \
                                                            title='Foreign-key from [lindex $fk_target_map($idx) 0]([lindex $fk_target_map($idx) 1])'>FK</a></b></sup></if>":""}]\
                                                            [expr {[info exists ref_fk_p($idx)]==1?"<sup><span style='color:blue;cursor:pointer;' title='This value is used as a foreign-key in an other table. Click for a list of all tables using this value' id='$element@table.rownum@' onclick=\"show_${element}Menu(@table.$element@,'$element@table.rownum@');\">RFK</span></sup>":""}]
                                                            " \
                                ]
    incr idx
}


list::create \
    -name "table" \
    -multirow "table" \
    -no_data "Keine Daten vorhanden" \
    -pass_properties {t c return_url} \
    -pass_to_urls {t where offset limit} \
    -page_flush_p t \
    -elements $elements \
    -filters $filters \
    -orderby $order_by


# ######################################################
# ###### Create the sql query string (for the data)
# ######################################################


set sql_str "select [join $columns ,] from ${namespace}.${table} $where [template::list::orderby_clause -orderby -name "table"] limit $limit offset $offset"

db_multirow table get_data $sql_str

ad_return_template