ljr/livejournal/htdocs/admin/schema/index.bml

279 lines
9.3 KiB
Plaintext
Executable File

<?_code
use strict;
$title = "Schema Browser";
$body = "";
my $dbh = LJ::get_db_writer();
my $sth;
my $remote = LJ::get_remote();
my $can_doc = 0;
if (LJ::remote_has_priv($remote, "schemadoc")) { $can_doc = 1; }
unless ($can_doc) {
my $url = "/doc/server/ljp.dbschema.ref.html";
$body = "This page is for editing <a href=\"$url\">schema documentation</a>, ";
$body .= "but you don't have the 'schemadoc' priv.";
return;
}
sub magic_links
{
my $des = shift;
$$des =~ s!\[dbtable\[(\w+?)\]\]!<a href="./?mode=viewtable&amp;table=$1">$1</a>!g;
}
if ($FORM{'mode'} eq "")
{
my %table;
$sth = $dbh->prepare("SELECT tablename, public_browsable, des FROM schematables");
$sth->execute;
while (my ($name, $public, $des) = $sth->fetchrow_array) {
$table{$name} = { 'public' => $public, 'des' => $des };
}
$body .= "<?h1 Tables h1?><?p Click a table for more information. p?><p><table cellpadding=4><tr bgcolor=<?emcolor?>><td><b>Table</b></td><td><b>Description</b></td></tr>\n";
$sth = $dbh->prepare("SHOW TABLES");
$sth->execute;
while (my ($table) = $sth->fetchrow_array) {
my $des = $table{$table}->{'des'} || "<i>no description, yet</i>";
magic_links(\$des);
$body .= "<tr valign=top><td nowrap><b><a href=\"./?mode=viewtable&amp;table=$table\">$table</a></b>";
if ($table{$table}->{'public'}) {
$body .= " (<a href=\"./?mode=viewdata&amp;table=$table\">data</a>)";
}
$body .= "</td><td>$des</td></tr>\n";
}
$body .= "</table>\n";
return;
}
if ($FORM{'mode'} eq "viewtable")
{
my $table = $FORM{'table'};
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
my $qtable = $dbh->quote($table);
$sth = $dbh->prepare("SELECT des, public_browsable FROM schematables WHERE tablename=$qtable");
$sth->execute;
my ($tabledes, $browsable) = $sth->fetchrow_array;
$body .= "<a href=\"./\">&lt;&lt; Tables</a>";
if ($browsable) {
$body .= " | <a href=\"./?mode=viewdata&amp;table=$table\">View Data</a>";
}
if ($can_doc) {
$body .= " | <a href=\"./?mode=doc&amp;table=$table\">Edit Documentation</a>";
}
$body .= "<?h1 Table: $table h1?><?p ";
if ($tabledes) {
&magic_links(\$tabledes);
$body .= $tabledes;
} else {
$body .= "Below are the columns and descriptions for the <b>$table</b> table.";
}
$body .= " p?><p>\n";
my %coldes;
$sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable");
$sth->execute;
while (my ($col, $des) = $sth->fetchrow_array) { $coldes{$col} = $des; }
$sth = $dbh->prepare("DESCRIBE $table");
$sth->execute;
$body .= "<table cellpadding=3><tr bgcolor=<?emcolor?>>";
$body .= "<td><b>Key?</b></td>";
$body .= "<td><b>Column</b></td>";
$body .= "<td><b>Type</b></td>";
$body .= "<td><b>Null</b></td>";
$body .= "<td><b>Default</b></td>";
$body .= "<td><b>Description</b></td>";
$body .= "</tr>\n";
while (my $row = $sth->fetchrow_hashref)
{
my $name = $row->{'Field'};
my $type = $row->{'Type'};
my $key = $row->{'Key'};
my $null = $row->{'Null'};
my $def = $row->{'Default'};
my $des = BML::eall($coldes{$name});
magic_links(\$des);
$type =~ s/int\(\d+\)/int/g;
$body .= "<tr valign=top>";
$body .= "<td align=center>$key</td>";
$body .= "<td><b>$name</b></td>";
$body .= "<td>$type</td>";
$body .= "<td align=center>$null</td>";
$body .= "<td align=center>$def</td>";
$body .= "<td>$des</td>";
$body .= "</tr>\n";
}
$body .= "</table>\n";
return;
}
if ($FORM{'mode'} eq "viewdata") {
my $table = $FORM{'table'};
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
my $MAX_ROWS = 100;
$body .= "<a href=\"./\">&lt;&lt; Tables</a><br><a href=\"./?mode=viewtable&amp;table=$table\">&lt;&lt; Table: $table</a><?h1 Data: $table h1?><?p Below are the rows in the <b>$table</b> table. If the table has more than $MAX_ROWS records, only the top $MAX_ROWS are shown. p?><p>\n";
$sth = $dbh->prepare("SELECT tablename, public_browsable, des FROM schematables WHERE tablename='$table'");
$sth->execute;
my ($tablename, $public, $des) = $sth->fetchrow_array;
unless ($public) { $body .= "This table's data is not public.\n"; return; }
$sth = $dbh->prepare("SELECT * FROM $table LIMIT $MAX_ROWS");
$sth->execute;
$body .= "<table cellpadding=3><tr bgcolor=<?emcolor?>>";
foreach my $col (@{$sth->{'NAME'}}) {
$body .= "<td><b>$col</b></td>\n";
}
$body .= "</tr>\n";
while (my $row = $sth->fetchrow_arrayref) {
$body .= "<tr valign=top>\n";
foreach my $val (@$row) {
$body .= "<td>$val</td>\n";
}
$body .= "</tr>\n";
}
$body .= "</table>\n";
return;
}
# show form to enter documentation
if ($FORM{'mode'} eq "doc")
{
unless ($can_doc) { $body .= "You don't have permissions to document the schema."; return; }
my $table = $FORM{'table'};
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
$body .= "<a href=\"./\">&lt;&lt; Tables</a><?h1 Document Table: $table h1?>";
my $qtable = $dbh->quote($table);
my $sth;
$sth = $dbh->prepare("SELECT des FROM schematables WHERE tablename=$qtable");
$sth->execute;
my ($tabledes) = $sth->fetchrow_array;
my %coldes;
$sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable");
$sth->execute;
while (my ($col, $des) = $sth->fetchrow_array) { $coldes{$col} = $des; }
$body .= "<form method=post action=\"./\">\n";
$body .= "<input type=hidden name=table value=\"$table\">\n";
$body .= "<input type=hidden name=mode value=\"docsave\">\n";
$body .= "<p><b>Description:</b><br><textarea name=\"table-des\" rows=10 cols=40 wrap=soft>";
$body .= BML::eall($tabledes) . "</textarea>";
$sth = $dbh->prepare("DESCRIBE $table");
$sth->execute;
$body .= "<p><table cellpadding=3><tr bgcolor=<?emcolor?>>";
$body .= "<td><b>Column</b></td>";
$body .= "<td><b>Type</b></td>";
$body .= "<td><b>Description</b></td>";
$body .= "</tr>\n";
while (my $row = $sth->fetchrow_hashref)
{
my $name = $row->{'Field'};
my $type = $row->{'Type'};
$type =~ s/int\(\d+\)/int/g;
$body .= "<tr valign=top>";
$body .= "<td><b>$name</b></td>";
$body .= "<td>$type</td>";
$body .= "<td><input name=\"col-$name\" size=60 maxlength=255 value=\"" . BML::eall($coldes{$name}) . "\"></td>";
$body .= "</tr>\n";
}
$body .= "</table>\n";
$body .= "<p><input type=submit value=\"Save Changes\"></form>";
return;
}
# save documentation
if ($FORM{'mode'} eq "docsave")
{
unless ($can_doc) { $body .= "You don't have permissions to document the schema."; return; }
my $table = $FORM{'table'};
if ($table !~ /^\w+$/) { $body = "Invalid table name!\n"; return; }
$body .= "<a href=\"./\">&lt;&lt; Tables</a><?h1 Document Table: $table h1?>";
my $qtable = $dbh->quote($table);
my $sth;
$sth = $dbh->prepare("SELECT tablename, des FROM schematables WHERE tablename=$qtable");
$sth->execute;
my ($tablename, $tabledes) = $sth->fetchrow_array;
$FORM{'table-des'} =~ s/\r//;
my $qdes = $dbh->quote($FORM{'table-des'});
if ($tablename) {
# row exists, update.
$dbh->do("UPDATE schematables SET des=$qdes WHERE tablename=$qtable");
} else {
# no row exists, so insert
$dbh->do("INSERT INTO schematables (tablename, public_browsable, des) VALUES ($qtable, '0', $qdes)");
}
if ($dbh->err) { $body .= $dbh->errstr; return; }
my %olddes;
my %newdes;
### load old descriptions
$sth = $dbh->prepare("SELECT colname, des FROM schemacols WHERE tablename=$qtable");
$sth->execute;
while (my ($col, $des) = $sth->fetchrow_array) { $olddes{$col} = $des; }
### check new descriptions (only for valid columns)
$sth = $dbh->prepare("DESCRIBE $table");
$sth->execute;
if ($dbh->err) { $body .= $dbh->errstr; return; }
while (my $row = $sth->fetchrow_hashref)
{
my $name = $row->{'Field'};
my $type = $row->{'Type'};
$FORM{"col-$name"} =~ s/\r//;
if ($FORM{"col-$name"} ne $olddes{$name}) {
$newdes{$name} = $FORM{"col-$name"};
}
}
if (%newdes) {
my $sql = "REPLACE INTO schemacols (tablename, colname, des) VALUES ";
foreach my $col (keys %newdes) {
my $qcol = $dbh->quote($col);
my $qdes = $dbh->quote($newdes{$col});
$sql .= "($qtable, $qcol, $qdes),";
}
chop $sql;
$dbh->do($sql);
if ($dbh->err) { $body .= "[3] ($sql)<p>" . $dbh->errstr; return; }
}
$body .= "<?h1 Success h1?><?p Documentation saved. <a href=\"./?mode=viewtable&amp;table=$table\">View</a>. p?>";
return;
}
return;
_code?><?page
title=><?_code return $title; _code?>
body=><?_code return $body; _code?>
page?><?_c <LJDEP>
link: htdocs/admin/scheme/index.bml
</LJDEP> _c?>