Einträge von badblock
badblocks
Kalender
|
|
März '10 | |||||
| Mo | Di | Mi | Do | Fr | Sa | So |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 | ||||
Suche
supersized.org
Blog abonnieren
Letzte Google Suche
Top Referers
www.bing.com (1)
www.google.at (1)
UPDATE
ja ich lebe und mir gehts gut. Desweiteren:
1) natürlich bekommen alle Interessenten der ETA-Datenvisualisierung meinen Quellcode und alles was dazugehört. Bitte einfach Email-Adresse hinterlassen. Weiteren Support dazu kann und will ich nicht leisten. Das Projekt ist für mich abgeschlossen (lange nicht perfekt, aber mit dem Status "worksforme" kann ich gut leben). Aber wenn ihr da draussen eigene ETA Tools/Visualisierungen entwickelt täte mich das aber schon interessieren.
2) das Projekt "Migration von uw-imapd nach scalix" erfolgreich beendet. Lief eigentlich ziemlich rund, aber speziell die Datenkonvertierung war ein eher unschönes Detail. Evtl. blogge ich dazu demnächst mehr.
3) das Projekt "Migration von Legacy-ERP nach SAP" ist in vollem Gange und die Details dazu sind bisher (zumindest aus der Sicht des EDV-Verantwortlichen) teilweise sehr ernüchternd. Auch dazu später (d.h. nach Projektende, was bei einem SAP Projekt nicht unbedingt "bald" heissen muss) mehr.
der sinn des lebens...
-rw-r--r-- 1 vdr vdr 0 2007-10-04 02:44 /srv/video/Der_Sinn_des_Lebens/2007-10-04.00.25.99.99.rec/001.vdr
Irgendwie hats linvdr drauf, alle Aufnahmen, die mir wirklich wichtig sind, zu versauen.
Keine Kommentare Trackbacks (0)
COMMENT eines PostgreSQL Typen ermitteln

In PostgreSQL kann ja mit COMMENT für jedes "Ding" (Typ, Tabelle, Schema etc.) eine Beschreibung gesetzt werden. Dies ist ganz nützlich, um z.B. in einer Eingabemaske dem User mitzuteilen, was das aktuelle Feld für einen Wertebereich etc. hat. Um an den Inhalt eines COMMENTs zu kommen, muss man in pg_description rumfingern. Etwas eleganter geht es z.B. mit so einer Funktion:
AS $_$
DECLARE
e TEXT;
BEGIN
e := NULL;
IF $2 IS NULL THEN
SELECT description
INTO e
FROM pg_description
JOIN pg_namespace ON (pg_description.objoid = pg_namespace.oid)
WHERE nspname = $1
AND objsubid = 0;
ELSIF $3 IS NULL THEN
SELECT description
INTO e
FROM pg_description
JOIN pg_class ON (pg_description.objoid = pg_class.oid)
JOIN pg_namespace ON (pg_class.relnamespace = pg_namespace.oid)
WHERE nspname = $1
AND relname = $2
AND objsubid = 0;
ELSE
SELECT description
INTO e
FROM pg_description
JOIN pg_class ON (pg_description.objoid = pg_class.oid)
JOIN pg_namespace ON (pg_class.relnamespace = pg_namespace.oid)
JOIN pg_attribute ON (pg_description.objsubid = pg_attribute.attnum AND pg_class.oid = pg_attribute.attrelid)
WHERE nspname = $1
AND relname = $2
AND attname = $3;
END IF;
RETURN e;
END;
$_$ LANGUAGE plpgsql IMMUTABLE;
Damit kann der COMMENT von Schemas, Tabellen und Attributen gelesen werden. Anwendung:
- COMMENT von Schema 'myschema':
CODE:SELECT get_comment('myschema', NULL, NULL)
- COMMENT von Tabelle 'mytab' im Schema 'myschema':
CODE:SELECT get_comment('myschema', 'mytab', NULL)
- COMMENT von Attribut 'mycol' in Tabelle 'mytab' im Schema 'myschema':
CODE:SELECT get_comment('myschema', 'mytab', 'mycol')
Keine Kommentare Trackbacks (0)
table-audit unter postgresql mit plperl

Eine Möglichkeit, einen Table-Audit unter PostgreSQL durchzuführen, ist hier beschrieben. Leider krankt diese Implementation an verschiedenen Stellen, z.b:
- ist sie in PL/TCL implementiert (naja, Geschmackfrage, ich mags nicht)
- loggt sie nur den Tabellennamen, nich das Schema.
- hat sie Probleme bei Tabellen mit zusammengesetzten Primary Keys
Deshalb hab ich mich mal hingesetzt und das ganze leicht abgewandelt in plperl implementiert:
CREATE TABLE public.audit_table (
ts TIMESTAMP default current_timestamp,
usr VARCHAR(10) default current_user,
sch VARCHAR(64),
tab VARCHAR(64),
fld VARCHAR(64),
pk_cols VARCHAR(128),
pk_vals VARCHAR(128),
event CHAR(1),
old_val VARCHAR,
new_val VARCHAR
);
GRANT INSERT ON public.audit_table TO PUBLIC;
CREATE OR REPLACE FUNCTION public.log_to_audit_table () RETURNS TRIGGER AS $body$
#
# Schema + Tabelle ermitteln
#
my $rv_tab = spi_exec_query(qq/
SELECT pg_class.relname AS tab,
pg_namespace.nspname AS sch
FROM pg_class
JOIN pg_namespace ON (pg_class.relnamespace = pg_namespace.oid)
WHERE pg_class.oid = $_TD->{relid}
/);
my $sch = $rv_tab->{rows}[0]->{sch};
my $tab = $rv_tab->{rows}[0]->{tab};
#
# Spalten des PK ermitteln
#
my $rv_pk = spi_exec_query(qq/
SELECT a.attname AS pk
FROM pg_class c, pg_attribute a, pg_index i
WHERE c.relname = '$_TD->{relname}'
AND c.oid = i.indrelid
AND a.attrelid = i.indexrelid
AND a.attnum > 0
AND i.indisprimary = 't'
/);
my @pk_cols = map { $rv_pk->{rows}[$_]->{pk} } (0 .. $rv_pk->{processed}-1);
my $pk_cols = join ',', @pk_cols;
#
# Attribute der Tabelle ermitteln
#
my $rv_att = spi_exec_query(qq/
SELECT attname
FROM pg_attribute
WHERE attnum > 0
AND attisdropped = 'f'
AND attrelid = $_TD->{relid}
ORDER BY attnum
/);
my @cols = map { $rv_att->{rows}[$_]->{attname} } (0 .. $rv_att->{processed}-1);
#
# Audit-Table fuellen
#
if ($_TD->{event} eq "INSERT") {
#
# PK Wert ermitteln
#
my $pk_vals = join ',', map { quote($_TD->{new}{$_}) } @pk_cols;
foreach (@cols) {
my $val = quote($_TD->{new}{$_});
spi_exec_query(qq/
INSERT INTO public.audit_table (
pk_cols, pk_vals, sch, tab, event, fld, new_val
) VALUES (
'$pk_cols', '$pk_vals', '$sch', '$tab', 'I', '$_', '$val'
)
/);
}
}
elsif ($_TD->{event} eq "UPDATE") {
#
# PK Wert ermitteln
#
my $pk_vals = join ',', map { quote($_TD->{new}{$_}) } @pk_cols;
foreach (@cols) {
my $val_old = quote($_TD->{old}{$_});
my $val_new = quote($_TD->{new}{$_});
if ($val_old ne $val_new) {
spi_exec_query(qq/
INSERT INTO public.audit_table (
pk_cols, pk_vals, sch, tab, event, fld, old_val, new_val
) VALUES (
'$pk_cols', '$pk_vals', '$sch', '$tab', 'U', '$_', '$val_old', '$val_new'
)
/);
}
}
}
elsif ($_TD->{event} eq "DELETE") {
#
# PK Wert ermitteln
#
my $pk_vals = join ',', map { quote($_TD->{old}{$_}) } @pk_cols;
foreach (@cols) {
my $val = quote($_TD->{old}{$_});
spi_exec_query(qq/
INSERT INTO public.audit_table (
pk_cols, pk_vals, sch, tab, event, fld, old_val
) VALUES (
'$pk_cols', '$pk_vals', '$sch', '$tab', 'D', '$_', '$val'
)
/);
}
}
return;
sub quote
{
my ($val) = @_;
$val =~ s/'/''/g;
return $val;
}
$body$ LANGUAGE 'plperl' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
DROP TRIGGER tg_audit_test1 ON public.test;
DROP table public.test;
CREATE table public.test (
id INTEGER NOT NULL,
nam CHAR(20) NOT NULL,
foo DATE,
bar FLOAT
);
ALTER TABLE public.test ADD CONSTRAINT pk_test PRIMARY KEY (id, nam);
CREATE TRIGGER "tg_audit_test1"
AFTER INSERT OR DELETE OR UPDATE ON public.test
FOR EACH ROW EXECUTE PROCEDURE public.log_to_audit_table();
INSERT INTO public.test (id, nam, foo, bar) VALUES (1, 'test1', '20070101', 123.4);
INSERT INTO public.test (id, nam) VALUES (2, 'test2');
UPDATE public.test SET nam = 'test zwei' WHERE id = 2;
DELETE FROM public.test WHERE id = 1;
UPDATE public.test SET nam = 'test''zwei' WHERE id = 2;
UPDATE public.test SET foo = current_date where id = 1;
UPDATE public.test SET bar = 1.234 where id = 1;
UPDATE public.test SET bar = NULL where id = 1;
SELECT * FROM public.audit_table;
Ab PostgreSQL 8.2 werden unter plperl auch Prepared Statements unterstützt, d.h. der Code könnte dann noch etwas eleganter und solider formulierrt werden.
Keine Kommentare Trackbacks (0)
PostgreSQL 8.2.4 RPMs für SuSE 9.0

Weils grad so lustig ist, hier auch gleich PostgreSQL 8.2.4 RPMs für ein brandaktuelles System: Suse 9.0
hier gehts zum download
Keine Kommentare Trackbacks (0)
PostgreSQL 8.2.4 RPMs für opensuse 10.2

Da ich nirgends fertige RPMs für PostgreSQL 8.2.4 auf opensuse 10.2 gefunden habe, hab ich kurzerhand selbst den Compiler angeworfen. Die RPMs gibts hier
Keine Kommentare Trackbacks (0)
webcam
wir bedanken uns für Ihre Nachricht, und möchten uns für die Dauer der Bearbeitung entschuldigen.
Wir haben leider nur Treiber für Windows. Wir haben weder für Linux noch für Mac-Rechner Treiber.
Keine Kommentare Trackbacks (0)
lacher des tages
Keine Kommentare Trackbacks (0)
webcam
Nachdem ich jetzt eine halbe Stunde mit EffectTV gespielt habe, denke ich jetzt über eine ernsthaftere Anwendung nach...


(hallo Google, es handelt sich um eine Typhoon Easycam 1.3 MPix, lsusb nennt das Ding "093a:2600 Pixart Imaging, Inc.")
Keine Kommentare Trackbacks (0)
mach's gut und danke für fred fish
Keine Kommentare Trackbacks (0)
schluckauf
Keine Kommentare Trackbacks (0)
vj badblock
Attwenger / Sun
Clinic / Harvest
NoMeansNo / The River (live)
Monster Magnet / Nod Scene
Ween / Buenos Tardes Amigo (live)
Radio Soulwax Nite Versions:
Keine Kommentare Trackbacks (0)
was haben die gerockt...
es gibt noch viel mehr Zeug davon bei youtube und natürlich diverse mp3s auf ihrer offizellen Webseite.
Warum ich das hier erwähne? Naja, als ich mich 1995 das erste mal mit HTML beschäftigte, hatte ich beschlossen, der besten Band der Welt (und noch ein paar anderen) eine Webseite zu widmen. "Walters Underground Pages" waren geboren. Leider ist die "Urform" von 1995 weder auf archive.org noch in meinen Backup-Archiv zu finden. Die älteste Version die ich auftreiben konnte, ist vom Januar '97, also immerhin auch schon über 10 Jahre alt. Und so sahs damals aus (Achtung: DSL Homeserver mit DynDNS, also langsam und nicht immer online). Übrigens: The internet is for porn. Wirlich, mein Provider bekam damals auf die erste Version meiner Seite mehr Hits, als er haben wollte: Die Leute haben mit Altavista (oder mit was man in der Prä-Google-Ära halt so suchte) nach schmutzigen Bildern gesucht und sind bei schmutziger Musik gelandet...
Keine Kommentare Trackbacks (0)
deduplicator
Die erste Implementierung dauerte nur ein paar Minuten. Nicht perfekt, aber les- und wartbar. Thats why I love Perl...
use warnings;
use strict;
use File::Find;
use File::Copy;
use Digest::MD5 'md5_hex';
my @queue = qw(/Linktest/Files /Linktest/Files_copy);
my $archiv = '/Linktest/Archive';
find(\&callback, @queue);
sub callback
{
return if ! -f;
my (undef, undef, undef, $links) = stat;
return if ($links > 1);
my $new = $archiv . "/" . md5_file($File::Find::name);
if (-f $new) {
unlink($_);
}
elsif (move($File::Find::name, $new) == 0) {
print "ERROR, can't move $File::Find::name to $new: $!\n";
return;
}
link $new, $File::Find::name;
}
sub md5_file
{
my ($filename) = @_;
open my $fh, '<', $filename or die $!;
binmode $fh;
my $md5 = Digest::MD5->new->addfile($fh)->hexdigest;
close $fh;
return $md5;
}
Keine Kommentare Trackbacks (0)
nur mal eben schnell...
erster Akt: Kamera angesteckt, /var/log/messages beobachtet und nach kurzem googeln festgestellt, daß ich natürlich genau die Kamera gekauft habe, die von Linux "not yet supported" ist. Zurückgeben? Nööö, jetzt schon aufgeben ist feige.
zweiter Akt: den Gedanken, selbst einen Treiber zu schreiben nach 1 Minute wieder verworfen.
dritter Akt: OK, ich hab mich damit abgefunden, daß die Kamera nur unter Windows tut. Aber hey: Wir leben im Zeitalter der virtualisierten Rechner. Soll die Kamera halt wegen meiner in einer einem virtuellen Windows arbeiten und mir die Bilddaten dort hin schaufeln, wo ich sie brauche. Also VMware-Server runtergeladen. Der Installer sagt mir, daß die CPU meines VIA EPIA die cmov Anweisung nicht unterstützt und ich mir VMware auf diesem Rechner in die Haare schmieren kann.
vierter Akt: Es gibt andere Virtualisierungslösungen. z.B. VirtualBox. Von eben diesen gibt es kein .deb für das auf meinem Server laufende Ubuntu 5.10. Aber hey, das wollte ich ja eh schon lange auf 6.06 LTS upgraden. Endlich ein Grund! dist-upgrade angeschmissen, 2 Stunden später schaut es ganz gut aus auf der Konsole, als ins neue System rebootet. Leider begrüsst mich Grub mit Error 18, er kann den Kernel nicht greifen, weil er ausserhalb seines vom BIOS beschränkten Horizonts liegt. F'ck, mit sowas hab ich mich zuletzt in den 90ern rumgeschlagen. Ich war mir eigentlich sicher, das Zeitalter der kranken 1024-Zylinder-Grenze längst überlebt zu haben.
fünfter Akt: Alte Probleme, alte Tools. Mit LILO hab ich 1994 mein erstes Linux gebootet, LILO soll auch heute mein Retter sein. Oder doch nicht? LI 99 99 99 99 99 99....das wars. Langsam beginne ich den Kauf der Webcam zu bereuen.
sechster Akt: Norton Partition Magic gebootet. Ich will eine /boot am Anfang der Platte einrichten, soll mein Kernel halt innerhalb dieser @!#*%!!-1024-Zylinder leben. Dazu muss ich meine hda1, die bisher fast die ganze Platte einnahm, verkleinern. Nach einer halben Stunde bekomme ich Error #1212: "Inode 0 has an illegal block 0". Und einen Error #1201: "EXT2 superblock contains illegal information". Illegal information? Nope, alles legal hier. Langsam entwickeln sich in mir leichte Gewaltphantasien gegen den Hersteller der Webcam.
sieber Akt: zwischendurch mal ein Knoppix booten, um zu sehen, ob mir der liebe Norton mein Platte jetzt total zerschossen hat, oder ob noch was zu retten ist.
achter Akt: ein Seufzer der Erleichterung: hda1 is alive and well. Auch ein explizit angestossener fsck bestätigt mir das nochmal. Also, es ist spät, ich will langsam ins Bett. Aber vorher muss die Kiste booten. Also mit mkisofs schnell (naja) ein bootbares CD-Image vom Kernel erstellt, dieses dann auf einen Rechner mit Brenner kopiert, CD gebrannt und was soll ich sagen: Die Kiste fährt hoch, alle Dienste laufen, mysql, postgres, cyrus-imapd, cacti... alles grün!
neunter Akt: ich geh' ins Bett. Wollte ich eigentlich schon vor 2 Stunden machen, aber... Hey da war doch noch was. Ach ja, genau, die Webcam. Darum kümmere ich mich nächstes mal, versprochen.
Ich wollt ja nur mal eben schnell...
Keine Kommentare Trackbacks (0)
Owner login
