Sites are unlikely to have over 2 billion active users
[lhc/web/wiklou.git] / maintenance / postgres / compare_schemas.pl
index 4f73137..144663d 100644 (file)
@@ -2,10 +2,14 @@
 
 ## Rough check that the base and postgres "tables.sql" are in sync
 ## Should be run from maintenance/postgres
+## Checks a few other things as well...
 
 use strict;
 use warnings;
 use Data::Dumper;
+use Cwd;
+
+check_valid_sql();
 
 my @old = ('../tables.sql');
 my $new = 'tables.sql';
@@ -44,7 +48,7 @@ $datatype = qr{($datatype)};
 
 my $typeval = qr{(\(\d+\))?};
 
-my $typeval2 = qr{ unsigned| binary| NOT NULL| NULL| auto_increment| default ['\-\d\w"]+| REFERENCES .+CASCADE};
+my $typeval2 = qr{ signed| unsigned| binary| NOT NULL| NULL| auto_increment| default ['\-\d\w"]+| REFERENCES .+CASCADE};
 
 my $indextype = join '|' => qw(INDEX KEY FULLTEXT), 'PRIMARY KEY', 'UNIQUE INDEX', 'UNIQUE KEY';
 $indextype = qr{$indextype};
@@ -64,7 +68,7 @@ my ($table,%old);
 my %xinfo;
 for my $xfile (@xfile) {
        print "Loading $xfile\n";
-       my $info = &parse_sql($xfile);
+       my $info = parse_sql($xfile);
        for (keys %$info) {
                $xinfo{$_} = $info->{$_};
        }
@@ -72,7 +76,7 @@ for my $xfile (@xfile) {
 
 for my $oldfile (@old) {
        print "Loading $oldfile\n";
-       my $info = &parse_sql($oldfile);
+       my $info = parse_sql($oldfile);
        for (keys %xinfo) {
                $info->{$_} = $xinfo{$_};
        }
@@ -97,8 +101,8 @@ sub parse_sql {
                        $table = $1;
                        $info{$table}{name}=$table;
                }
-               elsif (m#^\) /\*\$wgDBTableOptions\*/#) {
-                       $info{$table}{engine} = 'TYPE';
+               elsif (m{^\) /\*\$wgDBTableOptions\*/}) {
+                       $info{$table}{engine} = 'ENGINE';
                        $info{$table}{type} = 'variable';
                }
                elsif (/^\) ($engine)=($tabletype);$/) {
@@ -124,12 +128,53 @@ sub parse_sql {
                }
 
        }
-       close $oldfh;
+       close $oldfh or die qq{Could not close "$oldfile": $!\n};
 
        return \%info;
 
 } ## end of parse_sql
 
+## Read in the parser test information
+my $parsefile = '../parserTests.inc';
+open my $pfh, '<', $parsefile or die qq{Could not open "$parsefile": $!\n};
+my $stat = 0;
+my %ptable;
+while (<$pfh>) {
+       if (!$stat) {
+               if (/function listTables/) {
+                       $stat = 1;
+               }
+               next;
+       }
+       $ptable{$1}=2 while m{'(\w+)'}g;
+       last if /\);/;
+}
+close $pfh or die qq{Could not close "$parsefile": $!\n};
+
+my $OK_NOT_IN_PTABLE = '
+filearchive
+logging
+profiling
+querycache_info
+searchindex
+trackbacks
+transcache
+user_newtalk
+updatelog
+';
+
+## Make sure all tables in main tables.sql are accounted for in the parsertest.
+for my $table (sort keys %{$old{'../tables.sql'}}) {
+       $ptable{$table}++;
+       next if $ptable{$table} > 2;
+       next if $OK_NOT_IN_PTABLE =~ /\b$table\b/;
+       print qq{Table "$table" is in the schema, but not used inside of parserTest.inc\n};
+}
+## Any that are used in ptables but no longer exist in the schema?
+for my $table (sort grep { $ptable{$_} == 2 } keys %ptable) {
+       print qq{Table "$table" ($ptable{$table}) used in parserTest.inc, but not found in schema\n};
+}
+
 for my $oldfile (@old) {
 
 ## Begin non-standard indent
@@ -137,9 +182,7 @@ for my $oldfile (@old) {
 ## MySQL sanity checks
 for my $table (sort keys %{$old{$oldfile}}) {
        my $t = $old{$oldfile}{$table};
-       if (($oldfile =~ /5/ and $t->{engine} ne 'ENGINE')
-               or
-               ($oldfile !~ /5/ and $t->{engine} ne 'TYPE')) {
+       if ($t->{engine} eq 'TYPE') {
                die "Invalid engine for $oldfile: $t->{engine}\n" unless $t->{name} eq 'profiling';
        }
        my $charset = $t->{charset} || '';
@@ -221,6 +264,7 @@ real NUMERIC
 float NUMERIC
 
 ## TEXT:
+varchar(15) TEXT
 varchar(32) TEXT
 varchar(70) TEXT
 varchar(255) TEXT
@@ -239,7 +283,7 @@ timestamp TIMESTAMPTZ
 mediumblob BYTEA
 
 ## OTHER:
-bool CHAR # Sigh
+bool SMALLINT # Sigh
 
 };
 ## Allow specific exceptions to the above
@@ -274,6 +318,8 @@ oi_minor_mime     varbinary(32)  TEXT
 oi_sha1           varbinary(32)  TEXT
 old_flags         tinyblob       TEXT
 old_text          mediumblob     TEXT
+pp_propname       varbinary(60)  TEXT
+pp_value          blob           TEXT
 page_restrictions tinyblob       TEXT # CSV string
 pf_server         varchar(30)    TEXT
 pr_level          varbinary(60)  TEXT
@@ -284,6 +330,7 @@ qc_type           varbinary(32)  TEXT
 qcc_type          varbinary(32)  TEXT
 qci_type          varbinary(32)  TEXT
 rc_params         blob           TEXT
+rlc_to_blob       blob           TEXT
 ug_group          varbinary(16)  TEXT
 user_email_token  binary(32)     TEXT
 user_ip           varbinary(40)  TEXT
@@ -318,32 +365,21 @@ math_inputhash  varbinary(16) BYTEA
 math_outputhash varbinary(16) BYTEA
 
 ## Namespaces: not need for such a high range
-ar_namespace   int SMALLINT
-job_namespace  int SMALLINT
-log_namespace  int SMALLINT
-page_namespace int SMALLINT
-pl_namespace   int SMALLINT
-pt_namespace   int SMALLINT
-qc_namespace   int SMALLINT
-rc_namespace   int SMALLINT
-rd_namespace   int SMALLINT
-tl_namespace   int SMALLINT
-wl_namespace   int SMALLINT
-
-## "Bools"
-ar_minor_edit    tinyint CHAR
-iw_trans         tinyint CHAR
-page_is_new      tinyint CHAR
-page_is_redirect tinyint CHAR
-rc_bot           tinyint CHAR
-rc_deleted       tinyint CHAR
-rc_minor         tinyint CHAR
-rc_new           tinyint CHAR
-rc_patrolled     tinyint CHAR
-rev_deleted      tinyint CHAR
-rev_minor_edit   tinyint CHAR
+ar_namespace     int SMALLINT
+job_namespace    int SMALLINT
+log_namespace    int SMALLINT
+page_namespace   int SMALLINT
+pl_namespace     int SMALLINT
+pt_namespace     int SMALLINT
+qc_namespace     int SMALLINT
+rc_namespace     int SMALLINT
+rd_namespace     int SMALLINT
+rlc_to_namespace int SMALLINT
+tl_namespace     int SMALLINT
+wl_namespace     int SMALLINT
 
 ## Easy enough to change if a wiki ever does grow this big:
+ss_active_users  bigint INTEGER
 ss_good_articles bigint INTEGER
 ss_total_edits   bigint INTEGER
 ss_total_pages   bigint INTEGER
@@ -423,6 +459,67 @@ for (sort keys %new) {
 } ## end each file to be parsed
 
 
+sub check_valid_sql {
+
+       ## Check for a few common problems in most php files
+
+       my $olddir = getcwd();
+       chdir("../..");
+       for my $basedir (qw/includes extensions/) {
+               scan_dir($basedir);
+       }
+       chdir $olddir;
+
+       return;
+
+} ## end of check_valid_sql
+
+
+sub scan_dir {
+
+       my $dir = shift;
+
+       opendir my $dh, $dir or die qq{Could not opendir $dir: $!\n};
+       #print "Scanning $dir...\n";
+       for my $file (grep { -f "$dir/$_" and /\.php$/ } readdir $dh) {
+               find_problems("$dir/$file");
+       }
+       rewinddir $dh;
+       for my $subdir (grep { -d "$dir/$_" and ! /\./ } readdir $dh) {
+               scan_dir("$dir/$subdir");
+       }
+       closedir $dh or die qq{Closedir failed: $!\n};
+       return;
+
+} ## end of scan_dir
+
+sub find_problems {
+
+       my $file = shift;
+       open my $fh, '<', $file or die qq{Could not open "$file": $!\n};
+       while (<$fh>) {
+               if (/FORCE INDEX/ and $file !~ /Database\w*\.php/) {
+                       warn "Found FORCE INDEX string at line $. of $file\n";
+               }
+               if (/REPLACE INTO/ and $file !~ /Database\w*\.php/) {
+                       warn "Found REPLACE INTO string at line $. of $file\n";
+               }
+               if (/\bIF\s*\(/ and $file !~ /DatabaseMySQL\.php/) {
+                       warn "Found IF string at line $. of $file\n";
+               }
+               if (/\bCONCAT\b/ and $file !~ /Database\w*\.php/) {
+                       warn "Found CONCAT string at line $. of $file\n";
+               }
+               if (/\bGROUP\s+BY\s*\d\b/i and $file !~ /Database\w*\.php/) {
+                       warn "Found GROUP BY # at line $. of $file\n";
+               }
+       }
+       close $fh or die qq{Could not close "$file": $!\n};
+       return;
+
+} ## end of find_problems
+
+
 __DATA__
 ## Known exceptions
 OLD: searchindex          ## We use tsearch2 directly on the page table instead