remove outdated reports
authorRogan Hamby <rhamby@esilibrary.com>
Tue, 14 Jan 2020 14:27:42 +0000 (09:27 -0500)
committerRogan Hamby <rhamby@esilibrary.com>
Tue, 14 Jan 2020 14:27:42 +0000 (09:27 -0500)
18 files changed:
fingerprinter
mandarin/clean_mandarin_fine_list_report.pl [new file with mode: 0755]
mandarin/clean_mandarin_hold_list_by_patron.pl [new file with mode: 0755]
mandarin/clean_mandarin_loan_list_report.pl [new file with mode: 0755]
match_fingerprints
mig-bin/mig-stagebibs
mig-sql/init/020_common_tables.sql
mig-xml/evergreen_staged_report.xml
mig-xml/mapping_reports.xml
sql/base/00-infrastructure.sql
sql/base/07-eg-specific.sql
sql/base/09-misc.sql
sql/base/99-deprecated.sql
sql/base/MANIFEST
sql/base/base.sql
sql/base/base_replacement.sql [deleted file]
text/clean_csv
text/csv2sql

index f388174..8442970 100755 (executable)
@@ -75,7 +75,7 @@ for my $file (@ARGV) {
 
         # if everything looks good, score it and dump fingerprints
         score_marc($marc, $record);
-        dump_fingerprints($marc);
+        dump_fingerprints_score_id($marc);
         $scount++; progress_ticker();
     }
 }
@@ -102,6 +102,8 @@ sub populate_marc {
 
     # date1, date2
     my $my_008 = $record->field('008');
+    my @my_007 = $record->field('007');
+    my $my_006 = $record->field('006');
     $marc{tag008} = $my_008->as_string() if ($my_008);
     if (defined $marc{tag008}) {
         unless (length $marc{tag008} == 40) {
@@ -123,12 +125,35 @@ sub populate_marc {
             }
         }
     }
+    $marc{tag006} = $my_006->as_string() if ($my_006);
+    $marc{tag007} = \@my_007 if (@my_007);
+    $marc{audioformat}='';
+    $marc{videoformat}='';
+    foreach(@my_007)
+    {
+        if(substr($_->data(),0,1) eq 's' && $marc{audioformat} eq '')
+        {
+            $marc{audioformat} = substr($_->data(),3,1) unless (length $_->data() < 4);
+        }
+        elsif(substr($_->data(),0,1) eq 'v' && $marc{videoformat} eq '')
+        {
+            $marc{videoformat} = substr($_->data(),4,1) unless (length $_->data() < 5);
+        }
+    }
+    #print "$marc{audioformat}\n";
+    #print "$marc{videoformat}\n";
 
     # item_form
+    $marc{item_form}='';
     if ( $marc{record_type} =~ /[gkroef]/ ) { # MAP, VIS
-        $marc{item_form} = substr($marc{tag008},29,1) if ($marc{tag008});
+        $marc{item_form} = substr($marc{tag008},29,1) if ($marc{tag008} && (length $marc{tag008} > 29 ));
     } else {
-        $marc{item_form} = substr($marc{tag008},23,1) if ($marc{tag008});
+        $marc{item_form} = substr($marc{tag008},23,1) if ($marc{tag008} && (length $marc{tag008} > 23 ));
+    }
+    #fall through to 006 if 008 doesn't have info for item form
+    if ($marc{item_form} eq '|')
+    {
+        $marc{item_form} = substr($marc{tag006},6,1) if ($marc{tag006} && (length $marc{tag006} > 6 ));
     }
 
     # isbns
@@ -419,6 +444,227 @@ sub dump_fingerprints {
     }
 }
 
+sub dump_fingerprints_score_id {
+    my ($marc) = @_;
+
+    if ($conf->{fingerprints}{baseline}) {
+        print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, 'baseline',
+                      $marc->{item_form}, $marc->{date1}, $marc->{record_type},
+                      $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat}, $marc->{title}), "\n";
+    }
+
+    if ($conf->{fingerprints}{oclc} and scalar @{$marc->{oclc} }) {
+        for (@{$marc->{oclc} }) {
+            print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "oclc",
+                          $marc->{item_form}, $marc->{date1},
+                          $marc->{record_type}, $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat},
+                          $marc->{title}, $_, "\n");
+        }
+    }
+
+    if ($conf->{fingerprints}{koha_bib_id} and exists $marc->{koha_bib_id}) {
+        print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "z_koha_bib_id",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type},
+                      $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat}, $marc->{title},
+                      $marc->{koha_bib_id}), "\n";
+    }
+
+    if ($conf->{fingerprints}{isbn}) {
+        if ((scalar @{ $marc->{isbns} } > 0) and $marc->{pages}) {
+            foreach my $isbn ( @{ $marc->{isbns}} ) {
+                print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "isbn",
+                              $marc->{item_form}, $marc->{date1},
+                              $marc->{record_type},
+                              $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat}, $marc->{title},
+                              $isbn, $marc->{pages}), "\n";
+            }
+        }
+    }
+
+    if ($conf->{fingerprints}{edition} and $marc->{edition} and $marc->{author}) {
+        print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "edition",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat},
+                      $marc->{title}, $marc->{author}, $marc->{edition}), "\n";
+    }
+
+    if ($conf->{fingerprints}{issn} and $marc->{issn}) {
+        print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "issn",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat},
+                      $marc->{title}, $marc->{issn}), "\n";
+    }
+
+    if ($conf->{fingerprints}{lccn} and $marc->{lccn}) {
+        print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "lccn",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat},
+                      $marc->{title}, $marc->{lccn}) ,"\n";
+    }
+
+    if ($conf->{fingerprints}{accomp} and $marc->{accomp}) {
+        print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "accomp",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat},
+                      $marc->{title}, $marc->{accomp}) ,"\n";
+    }
+
+    if ($conf->{fingerprints}{authpub} and $marc->{author} and
+        $marc->{publisher} and $marc->{pubyear} and $marc->{pages}) {
+        print OF join("\t", sortvalfromid($marc->{id}),"json", $marc->{id}, "authpub",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},$marc->{audioformat},$marc->{videoformat},
+                      $marc->{title}, $marc->{author},
+                      $marc->{publisher}, $marc->{pubyear},
+                      $marc->{pages}), "\n";
+    }
+}
+
+sub sortvalfromid
+{
+    my $sortval = shift;
+    while(length($sortval)<17)
+    {
+        $sortval = '0'.$sortval;
+    }
+    return $sortval;
+}
+
+sub dump_fingerprints_hash_score {
+    my ($marc) = @_;
+
+    if ($conf->{fingerprints}{baseline}) {
+        my $string = join("", 'baseline',
+                      $marc->{item_form}, $marc->{date1}, $marc->{record_type},
+                      $marc->{bib_lvl}, $marc->{title});
+        $string =~ s/[^A-Za-z0-9]//g;
+        $string = sha1_base64($string);
+        print OF join("\t", $string,"json", $marc->{id}, 'baseline',
+                      $marc->{item_form}, $marc->{date1}, $marc->{record_type},
+                      $marc->{bib_lvl}, $marc->{title}), "\n";
+    }
+
+    if ($conf->{fingerprints}{oclc} and scalar @{$marc->{oclc} }) {
+        for (@{$marc->{oclc} }) {
+            my $string = join("", "oclc",
+                          $marc->{item_form}, $marc->{date1},
+                          $marc->{record_type}, $marc->{bib_lvl},
+                          $marc->{title}, $_);
+            $string =~ s/[^A-Za-z0-9]//g;
+            $string = sha1_base64($string);
+            print OF join("\t", $string,"json", $marc->{id}, "oclc",
+                          $marc->{item_form}, $marc->{date1},
+                          $marc->{record_type}, $marc->{bib_lvl},
+                          $marc->{title}, $_, "\n");
+        }
+    }
+
+    if ($conf->{fingerprints}{koha_bib_id} and exists $marc->{koha_bib_id}) {
+        my $string = join("", "z_koha_bib_id",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type},
+                      $marc->{bib_lvl}, $marc->{title},
+                      $marc->{koha_bib_id});
+        $string =~ s/[^A-Za-z0-9]//g;
+        $string = sha1_base64($string);
+        print OF join("\t", $string,"json", $marc->{id}, "z_koha_bib_id",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type},
+                      $marc->{bib_lvl}, $marc->{title},
+                      $marc->{koha_bib_id}), "\n";
+    }
+
+    if ($conf->{fingerprints}{isbn}) {
+        if ((scalar @{ $marc->{isbns} } > 0) and $marc->{pages}) {
+            foreach my $isbn ( @{ $marc->{isbns}} ) {
+                my $string = join("", "isbn",
+                              $marc->{item_form}, $marc->{date1},
+                              $marc->{record_type},
+                              $marc->{bib_lvl}, $marc->{title},
+                              $isbn, $marc->{pages});
+                $string =~ s/[^A-Za-z0-9]//g;
+                $string = sha1_base64($string);
+                print OF join("\t", $string,"json", $marc->{id}, "isbn",
+                              $marc->{item_form}, $marc->{date1},
+                              $marc->{record_type},
+                              $marc->{bib_lvl}, $marc->{title},
+                              $isbn, $marc->{pages}), "\n";
+            }
+        }
+    }
+
+    if ($conf->{fingerprints}{edition} and $marc->{edition} and $marc->{author}) {
+        my $string = join("", "edition",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{author}, $marc->{edition});
+        $string =~ s/[^A-Za-z0-9]//g;
+        $string = sha1_base64($string);
+        print OF join("\t", $string,"json", $marc->{id}, "edition",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{author}, $marc->{edition}), "\n";
+    }
+
+    if ($conf->{fingerprints}{issn} and $marc->{issn}) {
+        my $string = join("", "issn",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{issn});
+        $string =~ s/[^A-Za-z0-9]//g;
+        $string = sha1_base64($string);
+        print OF join("\t", $string,"json", $marc->{id}, "issn",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{issn}), "\n";
+    }
+
+    if ($conf->{fingerprints}{lccn} and $marc->{lccn}) {
+        my $string = join("", "lccn",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{lccn});
+        $string =~ s/[^A-Za-z0-9]//g;
+        $string = sha1_base64($string);
+        print OF join("\t", $string,"json", $marc->{id}, "lccn",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{lccn}) ,"\n";
+    }
+
+    if ($conf->{fingerprints}{accomp} and $marc->{accomp}) {
+        my $string = join("", "accomp",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{accomp});
+        $string =~ s/[^A-Za-z0-9]//g;
+        $string = sha1_base64($string);
+        print OF join("\t", $string,"json", $marc->{id}, "accomp",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{accomp}) ,"\n";
+    }
+
+    if ($conf->{fingerprints}{authpub} and $marc->{author} and
+        $marc->{publisher} and $marc->{pubyear} and $marc->{pages}) {
+        my $string = join("", "authpub",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{author},
+                      $marc->{publisher}, $marc->{pubyear},
+                      $marc->{pages});
+        $string =~ s/[^A-Za-z0-9]//g;
+        $string = sha1_base64($string);
+        print OF join("\t", $string,"json", $marc->{id}, "authpub",
+                      $marc->{item_form}, $marc->{date1},
+                      $marc->{record_type}, $marc->{bib_lvl},
+                      $marc->{title}, $marc->{author},
+                      $marc->{publisher}, $marc->{pubyear},
+                      $marc->{pages}), "\n";
+    }
+}
+
 
 
 =head2 dump_exception
diff --git a/mandarin/clean_mandarin_fine_list_report.pl b/mandarin/clean_mandarin_fine_list_report.pl
new file mode 100755 (executable)
index 0000000..6efc323
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# copy and paste raw text from acrobat reader to .txt file
+
+my $filename = $ARGV[0];
+open(my $fh, '<:encoding(UTF-8)', $filename)
+  or die "Could not open file '$filename' $!";
+
+my $user;
+while (my $row = <$fh>) {
+  chomp $row;
+  if ($row =~ m/Fines Due by patron/) { next; }
+  if ($row =~ m/Patron Title Barcode Date Due Fine/) { next; }
+  if ($row =~ m/Page: /) { next; }
+  if ($row =~ m/Program Files \(x86\)/) { next; }
+  if ($row =~ m/End Of Report/) { next; }
+  if ($row =~ m/Fines Due by Patron/) { next; }
+
+  my @str = split / /, $row;
+  my $str_length = scalar(@str);
+  if ($str[1] eq 'AM' or $str[1] eq 'PM') {
+    if ($str[2] =~ m/2019/) { next; }  
+  }
+
+  if ($str[$str_length -1] !~ m/^\d*\.?\d*$/) {
+    $user = $str[$str_length -1];
+    next;
+  }
+
+  #print "$row\n";
+  if ($str[$str_length -1] =~  m/^\d*\.?\d*$/) {
+    my $f = $str[$str_length -1];  #fine
+    my $i = $str[$str_length -3];  #item barcode 
+    print "$user\t$i\t$f\n";
+  } 
+}
diff --git a/mandarin/clean_mandarin_hold_list_by_patron.pl b/mandarin/clean_mandarin_hold_list_by_patron.pl
new file mode 100755 (executable)
index 0000000..2ad084b
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# copy and paste raw text from acrobat reader to .txt file
+
+my $filename = $ARGV[0];
+open(my $fh, '<:encoding(UTF-8)', $filename)
+  or die "Could not open file '$filename' $!";
+
+my $user;
+while (my $row = <$fh>) {
+  chomp $row;
+  if ($row =~ m/Items On Hold by Patron/) { next; }
+  if ($row =~ m/Patron Title Barcode /) { next; }
+  if ($row =~ m/Page: /) { next; }
+  if ($row =~ m/Program Files \(x86\)/) { next; }
+  if ($row =~ m/End Of Report/) { next; }
+
+  my @str = split / /, $row;
+  my $str_length = scalar(@str);
+  if ($str[1] eq 'AM' or $str[1] eq 'PM') {
+    if ($str[2] =~ m/2019/) { next; }  
+  }
+
+  if ($str[$str_length -1] !~ m/\d\d\/\d\d\/\d\d\d\d/) {
+    $user = $str[$str_length -1];
+    next;
+  }
+
+  #print "$row\n";
+  if ($str[$str_length -1] =~  m/\d\d\/\d\d\/\d\d\d\d/) {
+    my $posted    = $str[$str_length -1];  
+    my $expire    = $str[$str_length -2];  
+    my $item      = $str[$str_length -3];  #item
+    print "$user\t$item\t$posted\t$expire\n";
+  } 
+}
diff --git a/mandarin/clean_mandarin_loan_list_report.pl b/mandarin/clean_mandarin_loan_list_report.pl
new file mode 100755 (executable)
index 0000000..b19c1c6
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# copy and paste raw text from acrobat reader to .txt file
+
+my $filename = $ARGV[0];
+open(my $fh, '<:encoding(UTF-8)', $filename)
+  or die "Could not open file '$filename' $!";
+
+my $user;
+while (my $row = <$fh>) {
+  chomp $row;
+  if ($row =~ m/Items On Loan by Patron/) { next; }
+  if ($row =~ m/Patron Title Barcode /) { next; }
+  if ($row =~ m/Page: /) { next; }
+  if ($row =~ m/Program Files \(x86\)/) { next; }
+  if ($row =~ m/End Of Report/) { next; }
+
+  my @str = split / /, $row;
+  my $str_length = scalar(@str);
+  if ($str[1] eq 'AM' or $str[1] eq 'PM') {
+    if ($str[2] =~ m/2019/) { next; }  
+  }
+
+  if ($str[$str_length -1] !~ m/\d\d\/\d\d\/\d\d\d\d/) {
+    $user = $str[$str_length -1];
+    next;
+  }
+
+  #print "$row\n";
+  if ($str[$str_length -1] =~  m/\d\d\/\d\d\/\d\d\d\d/) {
+    my $due       = $str[$str_length -1];  
+    my $borrowed  = $str[$str_length -2];  
+    my $item      = $str[$str_length -3];  #item
+    print "$user\t$item\t$due\t$borrowed\n";
+  } 
+}
index 4c77480..8f0d485 100755 (executable)
@@ -62,7 +62,7 @@ sub populate_fingerprint {
     $fp{sha1}    = sha1_base64($stripped);
 
     # make sure file is sorted properly
-    if ($lastscore and ($fp{compact} > $lastscore)) {
+    if ($lastscore and ($fp{compact} < $lastscore)) {
         print "Input file is sorted improperly or unsorted.\n";
         die "Sort descending (sort -r) and rerun this script.\n";
     }
@@ -79,7 +79,7 @@ sub rank_fingerprint {
     my $id   = $fp->{id};
 
     # only process records which haven't already been seen
-    unless (defined $seen{$id}) {
+    #unless (defined $seen{$id}) {
         unless (defined $fps{$sha1}) {
             # haven't seen this fp before. create a new listref to hold subs
             # and stow the hash of the fingerprint that we're lead of
@@ -90,7 +90,7 @@ sub rank_fingerprint {
             push @{ $fps{$sha1} }, $id;
         }
         $seen{$id} = 1;
-    }
+    #}
 }
 
 
@@ -107,16 +107,38 @@ sub dump_records {
     for my $rec (@recs) {
         for ( @{ $fps{ $rec->{sha1} } } ) {
             # check for dupes and die if they exist
-            die "Collision: dupe sub record $_\n" if $subs{$_};
-            $subs{$_} = 1;
-            die "Collision: lead in sub list ", $rec->{id}, "\n"
-              if $subs{ $rec->{id} };
-
-            # we don't want subs below threshold
-            next if ($_ < $conf->{threshold});
-
-            # still here? output.
-            print OUT $rec->{id}, "\t$_\n"
+            #die "Collision: dupe sub record $_\n" if $subs{$_};
+            if( not exists ($subs{$_}) ) {
+                #die "Collision: lead in sub list ", $rec->{id}, "\n"
+                #  if $subs{ $rec->{id} };
+                my $lead = $rec->{id};
+
+                # we don't need to match onto itself
+                next if ($lead eq $_);
+
+                if ($subs{ $rec->{id} })
+                {
+                    print "moving ".$lead." to ".$subs{$rec->{id}}."\n";
+                    $lead = $subs{$rec->{id}};
+                }
+
+                if($_ eq '1459051')
+                {
+                    print "looking at ".$rec->{sha1};
+                }
+
+                # we don't want subs below threshold
+                next if ($_ < $conf->{threshold});
+
+                # we don't need to match onto itself
+                next if ($lead eq $_);
+
+                # record this sub having this leader
+                $subs{$_} = $lead;
+
+                # still here? output.
+                print OUT $lead, "\t$_\n"
+            }
         }
     }
 }
index e64fd82..95a678b 100755 (executable)
@@ -11,7 +11,13 @@ so records should be checked before hand and cleaned.
 
 Takes three optional arguments:
 
---source
+
+--source 
+
+Takes a numeric value and set the x_source of the bib record to that.  Defaults to 
+2 which is local system.
+
+--x_source
 
 Sets an x_source value on the staging table to the one supplied instead of the 
 default of none.
@@ -54,11 +60,12 @@ pod2usage(-verbose => 2) if defined $ARGV[0] && $ARGV[0] eq '--help';
 pod2usage(-verbose => 1) if ! $ARGV[1];
 
 my $append = 0;
-my $base_table = 'biblio_record_entry';
-my $stage_table = 'biblio_record_entry_legacy';
+my $base_table = 'm_biblio_record_entry';
+my $stage_table = 'm_biblio_record_entry_legacy';
 my $auth = '';
 my $serial = '';
-my $source = 'default';
+my $source = 2;
+my $x_source = 'default';
 my $dbh = Mig::db_connect();
 my $infile;
 my $i = 0;
@@ -69,7 +76,8 @@ my $ret = GetOptions(
     'file:s'              => \$infile,
     'serial:s'            => \$serial,
     'auth:s'              => \$auth,
-    'source:s'            => \$source,
+    'x_source:s'          => \$x_source,
+    'source:i'            => \$source,
     'base_table:s'        => \$base_table,
     'stage_table:s'       => \$stage_table
 );
@@ -78,13 +86,13 @@ my $ret = GetOptions(
 #if auth and serial = 1 fail 
 
 if ($serial == 1) { 
-    $base_table = 'authority_record_entry';
-    $stage_table = 'authority_record_entry_legacy';
+    $base_table = 'm_authority_record_entry';
+    $stage_table = 'm_authority_record_entry_legacy';
 }
 
 if ($auth == 1) {
-    $base_table = 'serial_record_entry';
-    $stage_table = 'serial_record_entry_legacy';       
+    $base_table = 'm_serial_record_entry';
+    $stage_table = 'm_serial_record_entry_legacy';     
 }
 
 if ($auth == 1 and $serial == 1) { abort('are you sure you want to load these as authorities and serials?'); }
@@ -97,8 +105,8 @@ if ($bre_test == 1 and $bre_legacy_test == 0 ) { create_child_bre($dbh); }
 my $xmig_test = check_for_column($dbh,$stage_table,'x_migrate');
 if ($xmig_test == 0) { add_column($dbh,$stage_table,'x_migrate','BOOLEAN DEFAULT TRUE'); }
 
-my $xsource_test = check_for_column($dbh,$stage_table,'x_source');
-if ($xsource_test == 0) { add_column($dbh,$stage_table,'x_source','TEXT'); }
+my $xx_source_test = check_for_column($dbh,$stage_table,'x_source');
+if ($xx_source_test == 0) { add_column($dbh,$stage_table,'x_source','TEXT'); }
 
 #flatten out MARC XML FILE
 open my $xml, "<:encoding(utf8)", $infile or abort('could not open MARC XML file');
@@ -109,7 +117,7 @@ while(my $line = <$xml>) {
        chomp $line;
        $record = $record . $line;
        if ($line =~ /<\/record>$/) {
-               stage_record($dbh,$record,$source); 
+               stage_record($dbh,$record,$x_source,$source); 
                $record = '';
                $i++;
                if (($i % 100) == 0) { report_progress('Records stage', $i); }
@@ -165,12 +173,13 @@ sub report_progress {
 sub stage_record {
     my $dbh = shift;
     my $record = shift;
-       my $source = shift;
+       my $x_source = shift;
+    my $source = shift;
        my $last_xact = "'$MIGSCHEMA'";
        $record = '$_$' . $record . '$_$';
        my $sql;
-       if ($source eq 'default') { $sql = "INSERT INTO $MIGSCHEMA.$stage_table (last_xact_id,marc) VALUES ($last_xact,$record);"; }
-               else { $sql = "INSERT INTO $MIGSCHEMA.$stage_table (last_xact_id,marc,x_source) VALUES ($last_xact,$record,'$source');";  }
+       if ($x_source eq 'default') { $sql = "INSERT INTO $MIGSCHEMA.$stage_table (last_xact_id,marc,source) VALUES ($last_xact,$record,$source);"; }
+               else { $sql = "INSERT INTO $MIGSCHEMA.$stage_table (last_xact_id,marc,x_source,source) VALUES ($last_xact,$record,'$x_source',$source);";  }
     my $sth = $dbh->prepare($sql);
     $sth->execute();
        return;
index 1ad339d..99b3ce4 100644 (file)
@@ -158,7 +158,7 @@ CREATE TABLE map_create_shelving_location (
     ,l_note               TEXT
     ,x_migrate            BOOLEAN NOT NULL DEFAULT TRUE
     ,x_shelf              INTEGER
-) INHERITS (asset_copy_location);
+) INHERITS (m_asset_copy_location);
 
 INSERT INTO gsheet_tracked_table 
     (sheet_name,table_name,tab_name,created)
index a796a67..e42125a 100644 (file)
@@ -34,7 +34,7 @@
         <tag>money</tag>  arbitrary tags, each should go in separate tag
         <report_title>Migrated Billings</report_title>  title used in the asciidoc output
         <heading column='1'>Number of Billings.Migrated.Total</heading> period delimited 
-        <query>SELECT COUNT(id),x_migrate::TEXT,SUM(amount) FROM money_billing_legacy GROUP BY 2;</query>  query itself, will be replaced
+        <query>SELECT COUNT(id),x_migrate::TEXT,SUM(amount) FROM m_money_billing_legacy GROUP BY 2;</query>  query itself, will be replaced
         <note>Arbitrary note that can be included in the entries.</note>
     </report>
 -->
@@ -46,8 +46,8 @@
         <iteration>0</iteration>
         <report_title>Migrated Circulations</report_title>
         <heading>Circulation Status.Count of Circs</heading>
-        <query>SELECT 'Closed Circulations', COUNT(id) FROM action_circulation_legacy WHERE xact_finish IS NOT NULL AND x_migrate 
-            UNION ALL SELECT 'Open Circulations', COUNT(id) FROM action_circulation_legacy WHERE xact_finish IS NULL AND x_migrate</query>
+        <query>SELECT 'Closed Circulations', COUNT(id) FROM m_action_circulation_legacy WHERE xact_finish IS NOT NULL AND x_migrate 
+            UNION ALL SELECT 'Open Circulations', COUNT(id) FROM m_action_circulation_legacy WHERE xact_finish IS NULL AND x_migrate</query>
     </report>
 
     <report>
@@ -56,8 +56,8 @@
         <iteration>0</iteration>
         <report_title>Open Un-migrated Circulations</report_title>
         <heading>Circulation Status.Count of Circs</heading>
-        <query>SELECT 'No Matching User', COUNT(id) FROM action_circulation_legacy WHERE xact_finish IS NULL AND x_migrate = FALSE AND usr IS NULL 
-                UNION ALL SELECT 'No Matching Item', COUNT(id) FROM action_circulation_legacy WHERE xact_finish IS NULL AND x_migrate = FALSE AND target_copy IS NULL </query>
+        <query>SELECT 'No Matching User', COUNT(id) FROM m_action_circulation_legacy WHERE xact_finish IS NULL AND x_migrate = FALSE AND usr IS NULL 
+                UNION ALL SELECT 'No Matching Item', COUNT(id) FROM m_action_circulation_legacy WHERE xact_finish IS NULL AND x_migrate = FALSE AND target_copy IS NULL </query>
     </report>
 
     <report>
@@ -66,7 +66,7 @@
         <iteration>1</iteration>
         <report_title>Open Circulations</report_title>
         <heading>Circulation Status.Count of Circs</heading>
-        <query>SELECT 'Closed Circulations', COUNT(id) FROM action_circulation WHERE xact_finish IS NOT NULL UNION ALL SELECT 'Open Circulations', COUNT(id) FROM action_circulation WHERE xact_finish IS NULL</query>
+        <query>SELECT 'Closed Circulations', COUNT(id) FROM m_action_circulation WHERE xact_finish IS NOT NULL UNION ALL SELECT 'Open Circulations', COUNT(id) FROM m_action_circulation WHERE xact_finish IS NULL</query>
     </report>
 <!-- intent is to add a report by circulated and item status
     <report>
@@ -75,7 +75,7 @@
         <iteration>0</iteration>
         <report_title>Open Circulations</report_title>
         <heading>Circulation Status.Migrated.Count of Circs</heading>
-        <query>SELECT 'Closed Circulations', x_migrate::TEXT, COUNT(id) FROM action_circulation_legacy WHERE xact_finish IS NOT NULL GROUP BY 2 UNION ALL SELECT 'Open Circulations', x_migrate::TEXT, COUNT(id) FROM action_circulation_legacy WHERE xact_finish IS NULL GROUP BY 2</query>
+        <query>SELECT 'Closed Circulations', x_migrate::TEXT, COUNT(id) FROM m_action_circulation_legacy WHERE xact_finish IS NOT NULL GROUP BY 2 UNION ALL SELECT 'Open Circulations', x_migrate::TEXT, COUNT(id) FROM m_action_circulation_legacy WHERE xact_finish IS NULL GROUP BY 2</query>
     </report>
 -->
      <report>
@@ -84,7 +84,7 @@
         <iteration>0</iteration>
         <report_title>Circulations by Org Unit</report_title>
         <heading>Circulations Count.Migrated.Org Unit</heading>
-        <query>SELECT COUNT(acirc.id), acirc.x_migrate::TEXT, aou.name FROM action_circulation_legacy acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib WHERE acirc.xact_finish IS NULL GROUP BY 2, 3</query>
+        <query>SELECT COUNT(acirc.id), acirc.x_migrate::TEXT, aou.name FROM m_action_circulation_legacy acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib WHERE acirc.xact_finish IS NULL GROUP BY 2, 3</query>
     </report>
 
      <report>
@@ -93,7 +93,7 @@
         <iteration>1</iteration>
         <report_title>Circulations by Org Unit</report_title>
         <heading>Circulations Count.Org Unit</heading>
-        <query>SELECT COUNT(acirc.id), aou.name FROM action_circulation acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib WHERE acirc.xact_finish IS NULL GROUP BY 2</query>
+        <query>SELECT COUNT(acirc.id), aou.name FROM m_action_circulation acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib WHERE acirc.xact_finish IS NULL GROUP BY 2</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>Migrated Circulations by Duration, Fine and Max Fine</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine.Migrated</heading>
-        <query>SELECT COUNT(id), duration_rule, recurring_fine_rule, max_fine_rule, x_migrate::TEXT FROM action_circulation_legacy WHERE x_migrate = TRUE GROUP BY 2, 3, 4, 5</query>
+        <query>SELECT COUNT(id), duration_rule, recurring_fine_rule, max_fine_rule, x_migrate::TEXT FROM m_action_circulation_legacy WHERE x_migrate = TRUE GROUP BY 2, 3, 4, 5</query>
     </report>
 
      <report>
         <iteration>1</iteration>
         <report_title>Circulations by Duration, Fine and Max Fine</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine</heading>
-        <query>SELECT COUNT(id), duration_rule, recurring_fine_rule, max_fine_rule FROM action_circulation GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
+        <query>SELECT COUNT(id), duration_rule, recurring_fine_rule, max_fine_rule FROM m_action_circulation GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>Circulations by Rules and Patron Group</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine.User Group.Matchpoints</heading>
-        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, pgt.name, x.buildrows FROM action_circulation_legacy acirc JOIN actor.usr au ON au.id = acirc.usr JOIN permission.grp_tree pgt ON pgt.id = au.profile JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM action_circulation_legacy acirc WHERE acirc.x_migrate = TRUE) x ON x.id = acirc.id WHERE acirc.x_migrate = TRUE GROUP BY 2, 3, 4, 5, 6 ORDER BY 2, 3, 4, 5, 6</query>
+        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, pgt.name, x.buildrows FROM m_action_circulation_legacy acirc JOIN actor.usr au ON au.id = acirc.usr JOIN permission.grp_tree pgt ON pgt.id = au.profile JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM m_action_circulation_legacy acirc WHERE acirc.x_migrate = TRUE) x ON x.id = acirc.id WHERE acirc.x_migrate = TRUE GROUP BY 2, 3, 4, 5, 6 ORDER BY 2, 3, 4, 5, 6</query>
     </report>
 
      <report>
         <iteration>1</iteration>
         <report_title>Circulations by Rules and Patron Group</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine.User Group.Matchpoints</heading>
-        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, pgt.name, x.buildrows FROM action_circulation acirc JOIN actor.usr au ON au.id = acirc.usr JOIN permission.grp_tree pgt ON pgt.id = au.profile JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM action_circulation acirc) x ON x.id = acirc.id GROUP BY 2, 3, 4, 5, 6 ORDER BY 2, 3, 4, 5, 6</query>
+        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, pgt.name, x.buildrows FROM m_action_circulation acirc JOIN actor.usr au ON au.id = acirc.usr JOIN permission.grp_tree pgt ON pgt.id = au.profile JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM m_action_circulation acirc) x ON x.id = acirc.id GROUP BY 2, 3, 4, 5, 6 ORDER BY 2, 3, 4, 5, 6</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>Circulations by Rules and Circulation Modifier</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine.Circulation Modifier.Matchpoints</heading>
-        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, ac.circ_modifier, x.buildrows FROM action_circulation_legacy acirc JOIN asset.copy ac ON ac.id = acirc.target_copy JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM action_circulation_legacy acirc WHERE acirc.x_migrate = TRUE) x ON x.id = acirc.id WHERE acirc.x_migrate = TRUE GROUP BY 2, 3, 4, 5, 6 ORDER BY 2, 3, 4, 5, 6</query>
+        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, ac.circ_modifier, x.buildrows FROM m_action_circulation_legacy acirc JOIN asset.copy ac ON ac.id = acirc.target_copy JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM m_action_circulation_legacy acirc WHERE acirc.x_migrate = TRUE) x ON x.id = acirc.id WHERE acirc.x_migrate = TRUE GROUP BY 2, 3, 4, 5, 6 ORDER BY 2, 3, 4, 5, 6</query>
     </report>
 
      <report>
         <iteration>1</iteration>
         <report_title>Circulations by Rules and Circulation Modifier</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine.Circulation Modifier.Matchpoints</heading>
-        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, ac.circ_modifier, x.buildrows FROM action_circulation acirc JOIN asset.copy ac ON ac.id = acirc.target_copy JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM action_circulation acirc) x ON x.id = acirc.id
+        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, ac.circ_modifier, x.buildrows FROM m_action_circulation acirc JOIN asset.copy ac ON ac.id = acirc.target_copy JOIN (SELECT acirc.id, ARRAY_TO_STRING(find_cmm(acirc.id),',') AS buildrows FROM m_action_circulation acirc) x ON x.id = acirc.id
              GROUP BY 2, 3, 4, 5, 6 ORDER BY 2, 3, 4, 5, 6</query>
     </report>
 
         <iteration>0</iteration>
         <report_title>Circulations by Rules and Org Unit</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine.Library Branch</heading>
-        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, aou.name FROM action_circulation_legacy acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib WHERE acirc.x_migrate = TRUE GROUP BY 2, 3, 4, 5 ORDER BY 2, 3, 4, 5</query>
+        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, aou.name FROM m_action_circulation_legacy acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib WHERE acirc.x_migrate = TRUE GROUP BY 2, 3, 4, 5 ORDER BY 2, 3, 4, 5</query>
     </report>
 
      <report>
         <iteration>1</iteration>
         <report_title>Circulations by Rules and Org Unit</report_title>
         <heading>Count of Circs.Duration.Fine.Max Fine.Library Branch</heading>
-        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, aou.name FROM action_circulation acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib GROUP BY 2, 3, 4, 5 ORDER BY 2, 3, 4, 5</query>
+        <query>SELECT COUNT(acirc.id), acirc.duration_rule, acirc.recurring_fine_rule, acirc.max_fine_rule, aou.name FROM m_action_circulation acirc JOIN actor.org_unit aou ON aou.id = acirc.circ_lib GROUP BY 2, 3, 4, 5 ORDER BY 2, 3, 4, 5</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>Non-Cataloged Circulation</report_title>
         <heading>Circulations Count.Migrated</heading>
-        <query>SELECT COUNT(id), x_migrate::TEXT FROM action_non_cataloged_circulation_legacy GROUP BY 2</query>
+        <query>SELECT COUNT(id), x_migrate::TEXT FROM m_action_non_cataloged_circulation_legacy GROUP BY 2</query>
     </report>
 
      <report>
         <iteration>1</iteration>
         <report_title>Non-Cataloged Circulation</report_title>
         <heading>Circulations Count</heading>
-        <query>SELECT COUNT(id) FROM action_non_cataloged_circulation</query>
+        <query>SELECT COUNT(id) FROM m_action_non_cataloged_circulation</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>In House Use</report_title>
         <heading>In House Use Records.Migrated</heading>
-        <query>SELECT COUNT(id), x_migrate::TEXT FROM action_in_house_use_legacy GROUP BY 2</query>
+        <query>SELECT COUNT(id), x_migrate::TEXT FROM m_action_in_house_use_legacy GROUP BY 2</query>
     </report>
 
      <report>
         <iteration>1</iteration>
         <report_title>In House Use</report_title>
         <heading>In House Use Records</heading>
-        <query>SELECT COUNT(id) FROM action_in_house_use</query>
+        <query>SELECT COUNT(id) FROM m_action_in_house_use</query>
     </report>
 
      <report>
         <iteration>1</iteration>
         <report_title>Circs Missing Rules</report_title>
         <heading>Count.Field Missing</heading>
-        <query>SELECT COUNT(id), 'Duration Rule Value' FROM action_circulation WHERE duration IS NULL 
-            UNION ALL SELECT COUNT(id), 'Recurring Fine Rule Value' FROM action_circulation WHERE recurring_fine IS NULL 
-            UNION ALL SELECT COUNT(id), 'Max Fine Rule Value' FROM action_circulation WHERE max_fine IS NULL
-            UNION ALL SELECT COUNT(id), 'Duration Rule' FROM action_circulation WHERE duration_rule IS NULL       
-            UNION ALL SELECT COUNT(id), 'Recurring Fine Rule' FROM action_circulation WHERE recurring_fine_rule IS NULL      
-            UNION ALL SELECT COUNT(id), 'Max Fine Rule' FROM action_circulation WHERE max_fine_rule IS NULL
+        <query>SELECT COUNT(id), 'Duration Rule Value' FROM m_action_circulation WHERE duration IS NULL 
+            UNION ALL SELECT COUNT(id), 'Recurring Fine Rule Value' FROM m_action_circulation WHERE recurring_fine IS NULL 
+            UNION ALL SELECT COUNT(id), 'Max Fine Rule Value' FROM m_action_circulation WHERE max_fine IS NULL
+            UNION ALL SELECT COUNT(id), 'Duration Rule' FROM m_action_circulation WHERE duration_rule IS NULL       
+            UNION ALL SELECT COUNT(id), 'Recurring Fine Rule' FROM m_action_circulation WHERE recurring_fine_rule IS NULL      
+            UNION ALL SELECT COUNT(id), 'Max Fine Rule' FROM m_action_circulation WHERE max_fine_rule IS NULL
         </query>
     </report>
 
         <iteration>0</iteration>
         <report_title>Open Circulation and Status of Linked Items</report_title>
         <heading>Count.Status</heading>
-        <query>SELECT COUNT(acirc.id), ccs.name FROM action.circulation acirc JOIN asset.copy ac ON ac.id = acirc.target_copy JOIN config.copy_status ccs ON ccs.id = ac.status WHERE acirc.xact_finish IS NULL AND acirc.checkin_time IS NULL AND acirc.id IN (SELECT id FROM action_circulation) GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(acirc.id), ccs.name FROM action.circulation acirc JOIN asset.copy ac ON ac.id = acirc.target_copy JOIN config.copy_status ccs ON ccs.id = ac.status WHERE acirc.xact_finish IS NULL AND acirc.checkin_time IS NULL AND acirc.id IN (SELECT id FROM m_action_circulation) GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <!-- HOLDS REPORTS -->
         <iteration>0</iteration>
         <report_title>Migrated Holds</report_title>
         <heading>Hold Type.Hold Count.Migrated</heading>
-        <query>SELECT 'Closed Holds', COUNT(id), x_migrate::TEXT FROM action_hold_request_legacy WHERE (expire_time::TIMESTAMP &lt; now()) OR cancel_time IS NOT NULL OR fulfillment_time IS NOT NULL GROUP BY 3 UNION ALL SELECT 'Open Holds', COUNT(id), x_migrate::TEXT FROM action_hold_request_legacy WHERE (expire_time IS NULL OR expire_time::TIMESTAMP &gt; now()) AND cancel_time IS NULL AND fulfillment_time IS NULL GROUP BY 3</query>
+        <query>SELECT 'Closed Holds', COUNT(id), x_migrate::TEXT FROM m_action_hold_request_legacy WHERE (expire_time::TIMESTAMP &lt; now()) OR cancel_time IS NOT NULL OR fulfillment_time IS NOT NULL GROUP BY 3 UNION ALL SELECT 'Open Holds', COUNT(id), x_migrate::TEXT FROM m_action_hold_request_legacy WHERE (expire_time IS NULL OR expire_time::TIMESTAMP &gt; now()) AND cancel_time IS NULL AND fulfillment_time IS NULL GROUP BY 3</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>Migrated Holds By Type</report_title>
         <heading>Hold Type.Hold Count.Migrated</heading>
-        <query>SELECT hold_type as "Hold Type", COUNT(id), x_migrate::TEXT FROM action_hold_request_legacy GROUP BY 1, 3</query>
+        <query>SELECT hold_type as "Hold Type", COUNT(id), x_migrate::TEXT FROM m_action_hold_request_legacy GROUP BY 1, 3</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>Transit Copy Records and Status of Linked Items</report_title>
         <heading>Count.Status</heading>
-        <query>SELECT COUNT(atc.id), ccs.name FROM action.transit_copy atc JOIN asset.copy ac ON ac.id = atc.target_copy JOIN config.copy_status ccs ON ccs.id = ac.status WHERE atc.id IN (SELECT id FROM action_transit_copy) AND atc.dest_recv_time IS NULL GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(atc.id), ccs.name FROM action.transit_copy atc JOIN asset.copy ac ON ac.id = atc.target_copy JOIN config.copy_status ccs ON ccs.id = ac.status WHERE atc.id IN (SELECT id FROM m_action_transit_copy) AND atc.dest_recv_time IS NULL GROUP BY 2 ORDER BY 2</query>
     </report>
 
      <report>
         <iteration>0</iteration>
         <report_title>Status of Items with Count of Open In Transits</report_title>
         <heading>Count.Status.Count of Open Transits</heading>
-        <query>SELECT COUNT(ac.id), ccs.name, SUM(CASE WHEN atc.id IS NULL THEN 0 ELSE 1 END) FROM asset.copy ac JOIN config.copy_status ccs ON ccs.id = ac.status LEFT JOIN (SELECT * FROM action.transit_copy WHERE id IN (SELECT id FROM action_transit_copy) AND dest_recv_time IS NULL) atc ON atc.target_copy = ac.id WHERE ac.id IN (SELECT id from asset_copy) GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(ac.id), ccs.name, SUM(CASE WHEN atc.id IS NULL THEN 0 ELSE 1 END) FROM asset.copy ac JOIN config.copy_status ccs ON ccs.id = ac.status LEFT JOIN (SELECT * FROM action.transit_copy WHERE id IN (SELECT id FROM m_action_transit_copy) AND dest_recv_time IS NULL) atc ON atc.target_copy = ac.id WHERE ac.id IN (SELECT id from m_asset_copy) GROUP BY 2 ORDER BY 2</query>
     </report>
     
      <report>
         <iteration>0</iteration>
         <report_title>Captured Holds with Status of Items</report_title>
         <heading>Count of Captured Hold.Status of Item</heading>
-        <query>SELECT COUNT(ahr.id), ccs.name FROM action.hold_request ahr JOIN asset.copy ac ON ac.id = ahr.current_copy JOIN config.copy_status ccs ON ccs.id = ac.status WHERE ahr.capture_time IS NOT NULL AND ahr.fulfillment_time IS NULL and ahr.cancel_time IS NULL AND ahr.id IN (SELECT id FROM action_hold_request) GROUP BY 2 ORDER By 2</query>
+        <query>SELECT COUNT(ahr.id), ccs.name FROM action.hold_request ahr JOIN asset.copy ac ON ac.id = ahr.current_copy JOIN config.copy_status ccs ON ccs.id = ac.status WHERE ahr.capture_time IS NOT NULL AND ahr.fulfillment_time IS NULL and ahr.cancel_time IS NULL AND ahr.id IN (SELECT id FROM m_action_hold_request) GROUP BY 2 ORDER By 2</query>
     </report>
 
       <report>
         <iteration>0</iteration>
         <report_title>Depth of Unfilled Holds</report_title>
         <heading>Count.Depth</heading>
-        <query>SELECT COUNT(ahr.id), ahr.selection_depth FROM action.hold_request ahr WHERE ahr.id IN (SELECT id FROM action_hold_request) AND ahr.cancel_time IS NULL AND ahr.capture_time IS NULL AND ahr.fulfillment_time IS NULL GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(ahr.id), ahr.selection_depth FROM action.hold_request ahr WHERE ahr.id IN (SELECT id FROM m_action_hold_request) AND ahr.cancel_time IS NULL AND ahr.capture_time IS NULL AND ahr.fulfillment_time IS NULL GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <!-- ASSET REPORTS -->
     
     <report>
-        <name>asset_copy_count</name>
+        <name>m_asset_copy_count</name>
         <report_title>Count of Copies by Library</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Copy Count.Library.Migrated</heading>
-        <query>SELECT COUNT(ac.id), aou.name, ac.x_migrate::TEXT FROM asset_copy_legacy ac JOIN actor.org_unit aou ON aou.id = ac.circ_lib GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(ac.id), aou.name, ac.x_migrate::TEXT FROM m_asset_copy_legacy ac JOIN actor.org_unit aou ON aou.id = ac.circ_lib GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
-        <name>asset_deleted_copies</name>
+        <name>m_asset_deleted_copies</name>
         <report_title>Deleted Copies</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Copy Count.Deleted.Migrated</heading>
-        <query>SELECT COUNT(ac.id), ac.deleted::TEXT, ac.x_migrate::TEXT FROM asset_copy_legacy ac GROUP BY 2, 3</query>
+        <query>SELECT COUNT(ac.id), ac.deleted::TEXT, ac.x_migrate::TEXT FROM m_asset_copy_legacy ac GROUP BY 2, 3</query>
     </report>
 
     <report>
-        <name>asset_copies_by_status</name>
+        <name>m_asset_copies_by_status</name>
         <report_title>Copies by Status</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Copy Count.Status.Migrated</heading>
-        <query>SELECT COUNT(ac.id), cs.name, ac.x_migrate::TEXT FROM asset_copy_legacy ac JOIN config.copy_status cs ON cs.id = ac.status GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(ac.id), cs.name, ac.x_migrate::TEXT FROM m_asset_copy_legacy ac JOIN config.copy_status cs ON cs.id = ac.status GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
-        <name>asset_circ_mod_copies_count</name>
+        <name>m_asset_circ_mod_copies_count</name>
         <report_title>Copies by Circulation Modifier</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Copy Count.Circulation Modifier.Migrated</heading>
-        <query>SELECT COUNT(ac.id), ac.circ_modifier, ac.x_migrate::TEXT FROM asset_copy_legacy ac GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(ac.id), ac.circ_modifier, ac.x_migrate::TEXT FROM m_asset_copy_legacy ac GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
-        <name>asset_copy_notes</name>
+        <name>m_asset_copy_notes</name>
         <report_title>Copy Notes</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Note Count.Public.Migrated</heading>
-        <query>SELECT COUNT(acnote.id), acnote.pub::TEXT, acnote.x_migrate::TEXT FROM asset_copy_note_legacy acnote GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(acnote.id), acnote.pub::TEXT, acnote.x_migrate::TEXT FROM m_asset_copy_note_legacy acnote GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
-        <name>asset_copy_notes</name>
+        <name>m_asset_copy_notes</name>
         <report_title>Copy Notes</report_title>
         <tag>assets</tag>
         <iteration>1</iteration>
         <heading>Note Count.Public</heading>
-        <query>SELECT COUNT(acnote.id), acnote.pub::TEXT FROM asset_copy_note acnote GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(acnote.id), acnote.pub::TEXT FROM m_asset_copy_note acnote GROUP BY 2 ORDER BY 2</query>
     </report>
 
    <report>
-        <name>asset_vols_by_lib</name>
+        <name>m_asset_vols_by_lib</name>
         <report_title>Volumes by Library</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Volume Count.Library.Migrated</heading>
-        <query>SELECT COUNT(acn.id), aou.name, acn.x_migrate::TEXT FROM asset_call_number_legacy acn JOIN actor_org_unit_legacy aou ON aou.id = acn.owning_lib GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(acn.id), aou.name, acn.x_migrate::TEXT FROM m_asset_call_number_legacy acn JOIN m_actor_org_unit_legacy aou ON aou.id = acn.owning_lib GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
    <report>
-        <name>asset_vols_by_lib</name>
+        <name>m_asset_vols_by_lib</name>
         <report_title>Volumes by Library</report_title>
         <tag>assets</tag>
         <iteration>1</iteration>
         <heading>Volume Count.Library</heading>
-        <query>SELECT COUNT(acn.id), aou.name FROM asset_call_number acn JOIN actor.org_unit aou ON aou.id = acn.owning_lib GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(acn.id), aou.name FROM m_asset_call_number acn JOIN actor.org_unit aou ON aou.id = acn.owning_lib GROUP BY 2 ORDER BY 2</query>
     </report>
-    <!--
-   <report>
-        <name>asset_cops_by_loc</name>
-        <report_title>Copies by Location</report_title>
-        <tag>assets</tag>
-        <iteration>0</iteration>
-        <heading>Copy Count.Library.Migrated</heading>
-        <query>SELECT COUNT(ac.id), acl.name, ac.x_migrate::TEXT FROM asset_copy_legacy ac JOIN asset.copy_location acl ON acl.id = ac.location GROUP BY 2, 3 ORDER BY 2, 3</query>
-    </report>
-   -->
+
    <report>
-        <name>asset_cops_by_loc_and_org</name>
+        <name>m_asset_cops_by_loc_and_org</name>
         <report_title>Copies by Location</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Copy Count.Library.Circ Library.Migrated</heading>
-        <query>SELECT COUNT(ac.id), acl.name, aou.name, ac.x_migrate::TEXT FROM asset_copy_legacy ac JOIN asset.copy_location acl ON acl.id = ac.location JOIN actor.org_unit aou ON aou.id = ac.circ_lib GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
+        <query>SELECT COUNT(ac.id), acl.name, aou.name, ac.x_migrate::TEXT FROM m_asset_copy_legacy ac JOIN asset.copy_location acl ON acl.id = ac.location JOIN actor.org_unit aou ON aou.id = ac.circ_lib GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
     </report>
 
    <report>
-        <name>asset_cops_w_loc_one</name>
+        <name>m_asset_cops_w_loc_one</name>
         <report_title>Copies with a Location of Stacks</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Barcode</heading>
-        <query>SELECT barcode FROM asset_copy_legacy WHERE location = 1 AND x_migrate</query>
+        <query>SELECT barcode FROM m_asset_copy_legacy WHERE location = 1 AND x_migrate</query>
     </report>
 
-    <!-- report>
-        <name>asset_barcode_lengths</name>
-        <report_title>Barcode Lengths by Library</report_title>
-        <tag>assets</tag>
-        <iteration>0</iteration>
-        <heading>Count of Barcode.Barcode Length.Library</heading>
-        <query>SELECT COUNT(ac.id), LENGTH(ac.barcode), aou.name FROM asset_copy_legacy ac JOIN actor.org_unit aou ON aou.id = ac.circ_lib WHERE ac.x_migrate = TRUE GROUP BY 2, 3 ORDER BY 3, 2</query>
-    </report -->
-
     <report>
-        <name>asset_no_barcode</name>
+        <name>m_asset_no_barcode</name>
         <report_title>Items Without Barcodes</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Assigned Barcode</heading>
-        <query>SELECT barcode FROM asset_copy_legacy WHERE barcode ~* 'no_barocde' AND x_migrate</query>
+        <query>SELECT barcode FROM m_asset_copy_legacy WHERE barcode ~* 'no_barocde' AND x_migrate</query>
     </report>
 
     <report>
-        <name>asset_barcode_patterns</name>
+        <name>m_asset_barcode_patterns</name>
         <report_title>Common Barcode Starting Patterns</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Count of Barcodes (greater than 10).Left 60% of Characters</heading>
-        <query>SELECT COUNT(ac.id), LEFT(ac.barcode,(ROUND(LENGTH(ac.barcode)*.6))::INT) FROM asset_copy_legacy ac WHERE ac.x_migrate = TRUE GROUP BY 2 HAVING COUNT(ac.id) > 10 ORDER BY 2</query>
+        <query>SELECT COUNT(ac.id), LEFT(ac.barcode,(ROUND(LENGTH(ac.barcode)*.6))::INT) FROM m_asset_copy_legacy ac WHERE ac.x_migrate = TRUE GROUP BY 2 HAVING COUNT(ac.id) > 10 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>asset_barcode_incumbent_collisions</name>
-        <report_title>Copy Barcode Incumbent Collisions</report_title>
+        <name>m_asset_barcode_collisions</name>
+        <report_title>Copy Barcode Collisions</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Collision Count</heading>
-        <query>SELECT COUNT(id) FROM asset_copy_legacy WHERE x_migrate = TRUE AND barcode ~* 'collision' and barcode ~* 'incumbent'</query>
+        <query>SELECT COUNT(id) FROM m_asset_copy_legacy WHERE x_migrate = TRUE AND barcode LIKE 'x_%'</query>
         <note>Incumbent collisions are those where the migrated barcodes collide with existing barcodes in the database.</note>
     </report>
 
     <report>
-        <name>asset_barcode_incumbent_collisions</name>
-        <report_title>Copy Barcode Incumbent Collisions</report_title>
+        <name>m_asset_barcode_collisions</name>
+        <report_title>Copy Barcode Collisions</report_title>
         <tag>assets</tag>
         <iteration>1</iteration>
         <heading>Collision Count</heading>
-        <query>SELECT COUNT(id) FROM asset_copy WHERE barcode ~* 'collision' and barcode ~* 'incumbent'</query>
+        <query>SELECT COUNT(id) FROM m_asset_copy WHERE barcode LIKE 'x_%'</query>
         <note>Incumbent collisions are those where the migrated barcodes collide with existing barcodes in the database.</note>
     </report>
 
     <report>
-        <name>asset_barcode_internal_collisions</name>
-        <report_title>Copy Barcode Internal Collisions</report_title>
-        <tag>assets</tag>
-        <iteration>0</iteration>
-        <heading>Collision Count</heading>
-        <query>SELECT COUNT(id) FROM asset_copy_legacy WHERE x_migrate = TRUE AND barcode ~* 'collision' and barcode ~* 'internal'</query>
-        <note>Internal collisions are those where the migrated barcodes have conflicts within their list of barcodes.</note>
-    </report>
-
-    <report>
-        <name>asset_barcode_internal_collisions</name>
-        <report_title>Copy Barcode Internal Collisions</report_title>
-        <tag>assets</tag>
-        <iteration>1</iteration>
-        <heading>Collision Count</heading>
-        <query>SELECT COUNT(id) FROM asset_copy WHERE barcode ~* 'collision' and barcode ~* 'internal'</query>
-        <note>Internal collisions are those where the migrated barcodes have conflicts within their list of barcodes.</note>
-    </report>
-
-    <report>
-        <name>asset_barcode_collisions_shortlist</name>
+        <name>m_asset_barcode_collisions_shortlist</name>
         <report_title>Copy Barcode Collisions (first 20)</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Collision List</heading>
-        <query>SELECT ac.barcode FROM asset_copy_legacy ac WHERE ac.barcode ~* 'collision' ORDER BY 1 LIMIT 20</query>
+        <query>SELECT ac.barcode FROM m_asset_copy_legacy ac WHERE ac.barcode LIKE 'x_%' ORDER BY 1 LIMIT 20</query>
         <note>This is a shortlist of copy barcode collisions that maxes out at 20.  If there are more collisions we will need to run a custom report.</note>
     </report>
 
     <report>
-        <name>asset_barcode_collisions_shortlist</name>
+        <name>m_asset_barcode_collisions_shortlist</name>
         <report_title>Copy Barcode Collisions (first 20)</report_title>
         <tag>assets</tag>
         <iteration>1</iteration>
         <heading>Collision List</heading>
-        <query>SELECT ac.barcode FROM asset_copy ac WHERE ac.barcode ~* 'collision' ORDER BY 1 LIMIT 20</query>
+        <query>SELECT ac.barcode FROM m_asset_copy ac WHERE ac.barcode LIKE 'x_%' ORDER BY 1 LIMIT 20</query>
         <note>This is a shortlist of patron barcode collisions that maxes out at 20.  If there are more collisions we will need to run a custom report.</note>
     </report>
 
     <report>
-        <name>asset_barcode_collision_patterns</name>
+        <name>m_asset_barcode_collision_patterns</name>
         <report_title>Common Copy Barcode Collision Patterns</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Number of Barcodes Matching Pattern Greater than 10.Left 60% of Characters</heading>
-        <query>SELECT COUNT(ac.id), LEFT(ac.barcode,(ROUND(LENGTH(ac.barcode)*.6))::INT) FROM asset_copy_legacy ac WHERE barcode ~* 'collision' GROUP BY 2 HAVING COUNT(ac.id) > 10 ORDER BY 2</query>
+        <query>SELECT COUNT(ac.id), LEFT(ac.barcode,(ROUND(LENGTH(ac.barcode)*.6))::INT) FROM m_asset_copy_legacy ac WHERE barcode LIKE 'x_%' GROUP BY 2 HAVING COUNT(ac.id) > 10 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>asset_barcode_collision_patterns</name>
+        <name>m_asset_barcode_collision_patterns</name>
         <report_title>Common Copy Barcode Collision Patterns</report_title>
         <tag>assets</tag>
         <iteration>1</iteration>
         <heading>Number of Barcodes Matching Pattern Greater than 10.Left 60% of Characters</heading>
-        <query>SELECT COUNT(ac.id), LEFT(ac.barcode,(ROUND(LENGTH(ac.barcode)*.6))::INT) FROM asset_copy ac WHERE barcode ~* 'collision' GROUP BY 2 HAVING COUNT(ac.id) > 10 ORDER BY 2</query>
+        <query>SELECT COUNT(ac.id), LEFT(ac.barcode,(ROUND(LENGTH(ac.barcode)*.6))::INT) FROM m_asset_copy ac WHERE barcode LIKE 'x_%' GROUP BY 2 HAVING COUNT(ac.id) > 10 ORDER BY 2</query>
     </report>
 
     <report>
-         <name>asset_stat_cats</name>
+         <name>m_asset_stat_cats</name>
         <report_title>Copy Statistical Categories</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Stat Cat Count.Library.Statistical Category</heading>
-        <query>SELECT COUNT(ac_sc.id), aou.name, ac_sc.name FROM asset_stat_cat_legacy ac_sc JOIN actor.org_unit aou ON aou.id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
+        <query>SELECT COUNT(ac_sc.id), aou.name, ac_sc.name FROM m_asset_stat_cat_legacy ac_sc JOIN actor.org_unit aou ON aou.id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
     </report>
 
     <report>
-         <name>asset_stat_cats</name>
+         <name>m_asset_stat_cats</name>
         <report_title>Copy Statistical Categories</report_title>
         <tag>assets</tag>
         <iteration>1</iteration>
         <heading>Stat Cat Count.Library.Statistical Category</heading>
-        <query>SELECT COUNT(ac_sc.id), aou.name, ac_sc.name FROM asset_stat_cat ac_sc JOIN actor.org_unit aou ON aou.id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
+        <query>SELECT COUNT(ac_sc.id), aou.name, ac_sc.name FROM m_asset_stat_cat ac_sc JOIN actor.org_unit aou ON aou.id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
     </report>
 
     <report>
-        <name>asset_stat_cat_entries</name>
+        <name>m_asset_stat_cat_entries</name>
         <report_title>Copy Stat Cat User Entries</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Copy Stat Count.Library.Statistical Category</heading>
-        <query>SELECT COUNT(map.id), aou.name, ac_sc.name FROM asset_stat_cat_entry_copy_map_legacy map JOIN asset_stat_cat_legacy ac_sc ON ac_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
+        <query>SELECT COUNT(map.id), aou.name, ac_sc.name FROM m_asset_stat_cat_entry_copy_map_legacy map JOIN m_asset_stat_cat_legacy ac_sc ON ac_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
     </report>
 
     <report>
-        <name>asset_stat_cat_entries</name>
+        <name>m_asset_stat_cat_entries</name>
         <report_title>Copy Stat Cat User Entries</report_title>
         <tag>assets</tag>
         <iteration>1</iteration>
         <heading>Copy Stat Count.Library.Statistical Category</heading>
-        <query>SELECT COUNT(map.id), aou.name, ac_sc.name FROM asset_stat_cat_entry_copy_map map JOIN asset_stat_cat ac_sc ON ac_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.
+        <query>SELECT COUNT(map.id), aou.name, ac_sc.name FROM m_asset_stat_cat_entry_copy_map map JOIN m_asset_stat_cat ac_sc ON ac_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.
 id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
     </report>
 
     <report>
-         <name>asset_copy_tags</name>
+         <name>m_asset_copy_tags</name>
         <report_title>Copy Tags</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Tag Count.Copy Tag Type.Copy Tag Label.Staff Note.Public</heading>
-        <query>SELECT COUNT(map.id), tag.tag_type, tag.label, tag.staff_note, tag.pub FROM asset_copy_tag tag JOIN asset_copy_tag_copy_map map ON map.tag = tag.id GROUP BY 2,3,4,5 ORDER BY 2,3</query>
+        <query>SELECT COUNT(map.id), tag.tag_type, tag.label, tag.staff_note, tag.pub FROM m_asset_copy_tag tag JOIN m_asset_copy_tag_copy_map map ON map.tag = tag.id GROUP BY 2,3,4,5 ORDER BY 2,3</query>
     </report>
 
     <report>
-         <name>asset_copy_alerts</name>
+         <name>m_asset_copy_alerts</name>
         <report_title>Copy Alerts</report_title>
         <tag>assets</tag>
         <iteration>0</iteration>
         <heading>Alert Count.Alert Type</heading>
-               <query>SELECT COUNT(*), cat.name FROM asset_copy_alert aca JOIN config.copy_alert_type cat ON cat.id = aca.alert_type GROUP BY 2</query>
+               <query>SELECT COUNT(*), cat.name FROM m_asset_copy_alert aca JOIN config.copy_alert_type cat ON cat.id = aca.alert_type GROUP BY 2</query>
     </report>
 
     <!-- MONEY REPORTS -->
 
     <report>
-        <name>money_billing_voided</name>
+        <name>m_money_billing_voided</name>
         <report_title>Bills Voided And Not</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_billing_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_billing_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
     <report>
-        <name>money_billing_voided</name>
+        <name>m_money_billing_voided</name>
         <report_title>Bills Voided And Not</report_title>
         <tag>money</tag>
         <iteration>1</iteration>
         <heading>Count.Voided.Sum</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount) FROM money_billing a GROUP BY 2 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount) FROM m_money_billing a GROUP BY 2 ORDER BY 2, 3</query>
     </report>
 
     <report>
-        <name>money_billing_by_type</name>
+        <name>m_money_billing_by_type</name>
         <report_title>Bills by Type</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Billing Type.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.billing_type, a.x_migrate::TEXT FROM money_billing_legacy a GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(a.id), a.billing_type, a.x_migrate::TEXT FROM m_money_billing_legacy a GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
-        <name>money_billing_by_type</name>
+        <name>m_money_billing_by_type</name>
         <report_title>Bills by Type</report_title>
         <tag>money</tag>
         <iteration>1</iteration>
         <heading>Count.Billing Type</heading>
-        <query>SELECT COUNT(a.id), a.billing_type FROM money_billing a GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(a.id), a.billing_type FROM m_money_billing a GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>money_cash_payment</name>
+        <name>m_money_cash_payment</name>
         <report_title>Cash Payments</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_cash_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_cash_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
     <report>
-        <name>money_cash_payment</name>
+        <name>m_money_cash_payment</name>
         <report_title>Cash Payments</report_title>
         <tag>money</tag>
         <iteration>1</iteration>
         <heading>Count.Voided.Sum</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount) FROM money_cash_payment a GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount) FROM m_money_cash_payment a GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>money_check_payment</name>
+        <name>m_money_check_payment</name>
         <report_title>Check Payments</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_check_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_check_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
     <report>
-        <name>money_forgive_payment</name>
+        <name>m_money_forgive_payment</name>
         <report_title>Forgive Payments</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_forgive_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_forgive_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
     <report>
-        <name>money_forgive_payment</name>
+        <name>m_money_forgive_payment</name>
         <report_title>Forgive Payments</report_title>
         <tag>money</tag>
         <iteration>1</iteration>
         <heading>Count.Voided.Sum</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount) FROM money_forgive_paymen a GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount) FROM m_money_forgive_paymen a GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>money_goods_payment</name>
+        <name>m_money_goods_payment</name>
         <report_title>Goods Payments</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_goods_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_goods_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
     <report>
-        <name>money_work_payment</name>
+        <name>m_money_work_payment</name>
         <report_title>Work Payments</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_work_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_work_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
     <report>
-        <name>money_credit_card_payment</name>
+        <name>m_money_credit_card_payment</name>
         <report_title>Credit Card Payments</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_credit_card_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_credit_card_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
     <report>
-        <name>money_credit_payment</name>
+        <name>m_money_credit_payment</name>
         <report_title>Credit Payments</report_title>
         <tag>money</tag>
         <iteration>0</iteration>
         <heading>Count.Voided.Sum.Migrated</heading>
-        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM money_credit_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
+        <query>SELECT COUNT(a.id), a.voided::TEXT, SUM(a.amount), a.x_migrate::TEXT FROM m_money_credit_payment_legacy a GROUP BY 2, 4 ORDER BY 2, 4</query>
     </report>
 
 
@@ -674,7 +636,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(bre.id) FROM biblio_record_entry_legacy bre WHERE id IN (SELECT id FROM biblio.record_entry) ORDER BY 1</query>
+        <query>SELECT COUNT(bre.id) FROM m_biblio_record_entry_legacy bre WHERE id IN (SELECT id FROM biblio.record_entry) ORDER BY 1</query>
     </report>
 
     <report>
@@ -683,7 +645,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>1</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(bre.id) FROM biblio_record_entry bre WHERE id IN (SELECT id FROM biblio.record_entry) ORDER BY 1</query>
+        <query>SELECT COUNT(bre.id) FROM m_biblio_record_entry bre WHERE id IN (SELECT id FROM biblio.record_entry) ORDER BY 1</query>
     </report>
 
     <report>
@@ -692,7 +654,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(id) FROM biblio_record_entry where id NOT IN (SELECT DISTINCT record FROM asset_call_number)</query>
+        <query>SELECT COUNT(id) FROM m_biblio_record_entry where id NOT IN (SELECT DISTINCT record FROM m_asset_call_number)</query>
                <note>These records would not have been loaded.</note>
     </report>
 
@@ -702,7 +664,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(id) FROM biblio_record_entry where id IN (SELECT record FROM asset.call_number WHERE label ~* '##URI##')</query>
+        <query>SELECT COUNT(id) FROM m_biblio_record_entry where id IN (SELECT record FROM asset.call_number WHERE label ~* '##URI##')</query>
     </report>
 
        <report>
@@ -711,7 +673,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
                <tag>bibs</tag>
                <iteration>0</iteration>
                <heading>Count.Original Search Format.New Search Format</heading>
-               <query>SELECT COUNT(*), ARRAY_TO_STRING(x_search_format,','), ARRAY_TO_STRING(x_after_search_format,',') FROM biblio_record_entry_legacy WHERE x_migrate AND x_after_search_format IS NOT NULL GROUP BY 2, 3 ORDER BY 3,2</query>
+               <query>SELECT COUNT(*), ARRAY_TO_STRING(x_search_format,','), ARRAY_TO_STRING(x_after_search_format,',') FROM m_biblio_record_entry_legacy WHERE x_migrate AND x_after_search_format IS NOT NULL GROUP BY 2, 3 ORDER BY 3,2</query>
        </report>
 
     <report>
@@ -720,7 +682,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>0</iteration>
         <heading>Count.Migrated</heading>
-        <query>SELECT COUNT(b.id), b.x_migrate::TEXT FROM biblio_record_note_legacy b GROUP BY 2</query>
+        <query>SELECT COUNT(b.id), b.x_migrate::TEXT FROM m_biblio_record_note_legacy b GROUP BY 2</query>
     </report>
 
     <report>
@@ -729,7 +691,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>1</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(b.id) FROM biblio_record_note b</query>
+        <query>SELECT COUNT(b.id) FROM m_biblio_record_note b</query>
     </report>
 
     <report>
@@ -738,7 +700,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>0</iteration>
         <heading>Count.Migrated</heading>
-        <query>SELECT COUNT(b.id), b.x_migrate::TEXT FROM biblio_peer_bib_copy_map_legacy b GROUP BY 2</query>
+        <query>SELECT COUNT(b.id), b.x_migrate::TEXT FROM m_biblio_peer_bib_copy_map_legacy b GROUP BY 2</query>
     </report>
 
     <report>
@@ -747,7 +709,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>1</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(b.id) FROM biblio_peer_bib_copy_map b</query>
+        <query>SELECT COUNT(b.id) FROM m_biblio_peer_bib_copy_map b</query>
     </report>
 
     <report>
@@ -756,7 +718,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>0</iteration>
         <heading>Count.Migrated</heading>
-        <query>SELECT COUNT(b.id), b.x_migrate::TEXT FROM biblio_monograph_part_legacy b GROUP BY 2</query>
+        <query>SELECT COUNT(b.id), b.x_migrate::TEXT FROM m_biblio_monograph_part_legacy b GROUP BY 2</query>
     </report>
 
     <report>
@@ -765,7 +727,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>bibs</tag>
         <iteration>1</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(b.id) FROM biblio_monograph_part b</query>
+        <query>SELECT COUNT(b.id) FROM m_biblio_monograph_part b</query>
     </report>
 
     <report>
@@ -785,7 +747,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count.Library.Deleted.Migrated</heading>
-        <query>SELECT COUNT(au.id), aou.name, au.deleted::TEXT, au.x_migrate::TEXT FROM actor_usr_legacy au JOIN actor.org_unit aou ON aou.id = au.home_ou GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
+        <query>SELECT COUNT(au.id), aou.name, au.deleted::TEXT, au.x_migrate::TEXT FROM m_actor_usr_legacy au JOIN actor.org_unit aou ON aou.id = au.home_ou GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
     </report>
 
     <report>
@@ -794,7 +756,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count.Permission Group.Migrated</heading>
-        <query>SELECT COUNT(au.id), pgt.name, au.x_migrate::TEXT FROM actor_usr_legacy au JOIN permission.grp_tree pgt ON pgt.id = au.profile GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(au.id), pgt.name, au.x_migrate::TEXT FROM m_actor_usr_legacy au JOIN permission.grp_tree pgt ON pgt.id = au.profile GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
@@ -803,7 +765,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count of Users.Active.Migrated</heading>
-        <query>SELECT COUNT(id), active::TEXT, x_migrate::TEXT FROM actor_usr_legacy GROUP BY 2, 3</query>
+        <query>SELECT COUNT(id), active::TEXT, x_migrate::TEXT FROM m_actor_usr_legacy GROUP BY 2, 3</query>
     </report>
 
     <report>
@@ -812,7 +774,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Count of Users.Active</heading>
-        <query>SELECT COUNT(id), active::TEXT FROM actor_usr GROUP BY 2</query>
+        <query>SELECT COUNT(id), active::TEXT FROM m_actor_usr GROUP BY 2</query>
     </report>
 
     <report>
@@ -821,7 +783,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count of Barcodes.Active.Migrated</heading>
-        <query>SELECT COUNT(id), active::TEXT, x_migrate::TEXT FROM actor_card_legacy GROUP BY 2, 3</query>
+        <query>SELECT COUNT(id), active::TEXT, x_migrate::TEXT FROM m_actor_card_legacy GROUP BY 2, 3</query>
     </report>
 
     <report>
@@ -830,34 +792,16 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Count of Barcodes.Active</heading>
-        <query>SELECT COUNT(id), active::TEXT FROM actor_card GROUP BY 2</query>
+        <query>SELECT COUNT(id), active::TEXT FROM m_actor_card GROUP BY 2</query>
     </report>
 
-    <!-- report>
-        <name>usr_barcode_lengths</name>
-        <report_title>Barcode Lengths by Library</report_title>
-        <tag>actors</tag>
-        <iteration>0</iteration>
-        <heading>Count of Barcode.Barcode Length.Library</heading>
-        <query>SELECT COUNT(acard.id), LENGTH(acard.barcode), aou.name FROM actor_card_legacy acard JOIN actor_usr_legacy au ON au.id = acard.usr JOIN actor.org_unit aou ON aou.id = au.home_ou WHERE acard.x_migrate = TRUE GROUP BY 2, 3 ORDER BY 3, 2</query>
-    </report -->
-
-    <!-- report>
-        <name>usr_barcode_lengths</name>
-        <report_title>Barcode Lengths by Library</report_title>
-        <tag>actors</tag>
-        <iteration>1</iteration>
-        <heading>Count of Barcode.Barcode Length.Library</heading>
-        <query>SELECT COUNT(acard.id), LENGTH(acard.barcode), aou.name FROM actor_card acard JOIN actor_usr au ON au.id = acard.usr JOIN actor.org_unit aou ON aou.id = au.home_ou GROUP BY 2, 3 ORDER BY 3, 2</query>
-    </report -->
-
     <report>
         <name>usr_barcode_patterns</name>
         <report_title>Common Barcode Starting Patterns</report_title>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count of Barcodes (greater than 10).Left 60% of Characters</heading>
-        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM actor_card_legacy acard WHERE acard.x_migrate = TRUE GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
+        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM m_actor_card_legacy acard WHERE acard.x_migrate = TRUE GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
     </report>
 
     <report>
@@ -866,52 +810,34 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Count of Barcodes (greater than 10).Left 60% of Characters</heading>
-        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM actor_card acard GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
+        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM m_actor_card acard GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
     </report>
  
    <report>
-        <name>usr_barcode_incoming_collisions</name>
-        <report_title>Incoming Patron Barcode Collisions</report_title>
+        <name>usr_barcode_collisions</name>
+        <report_title>Patron Barcode Collisions</report_title>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Collision Count</heading>
-        <query>SELECT COUNT(acard.id) FROM actor_card_legacy acard WHERE barcode ~* 'collision' AND x_migrate = TRUE</query>
+        <query>SELECT COUNT(acard.id) FROM m_actor_card_legacy acard WHERE barcode LIKE 'x_%' AND x_migrate = TRUE</query>
     </report>
 
     <report>
-        <name>usr_barcode_incoming_collisions</name>
-        <report_title>Incoming Patron Barcode Collisions</report_title>
+        <name>usr_barcode_collisions</name>
+        <report_title>Patron Barcode Collisions</report_title>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Collision Count</heading>
-        <query>SELECT COUNT(acard.id) FROM actor_card acard WHERE barcode ~* 'collision'</query>
+        <query>SELECT COUNT(acard.id) FROM m_actor_card acard WHERE barcode LIKE 'x_%'</query>
     </report>
 
-       <report>
-       <name>usr_barcode_incumbent_collisions</name>
-       <report_title>Incumbent Patron Barcode Collisions</report_title>
-       <tag>actors</tag>
-       <iteration>0</iteration>
-       <heading>Collision Count</heading>
-       <query>SELECT COUNT(acard.id) FROM actor_card_legacy acard WHERE barcode ~* '^x_' AND x_migrate = TRUE</query>
-       </report>
-
-       <report>
-       <name>usr_barcode_incumbent_collisions</name>
-       <report_title>Incumbent Patron Barcode Collisions</report_title>
-       <tag>actors</tag>
-       <iteration>1</iteration>
-       <heading>Collision Count</heading>
-       <query>SELECT COUNT(acard.id) FROM actor_card acard WHERE barcode ~* '^x_'</query>
-       </report>
-
     <report>
         <name>usr_barcode_collision_shortlist</name>
         <report_title>Patron Barcode Collisions (first 20)</report_title>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Collision List</heading>
-        <query>SELECT acard.barcode FROM actor_card_legacy acard WHERE (acard.barcode ~* 'collision' OR acard.barcode ~* '^x_') AND acard.x_migrate = TRUE ORDER BY 1 LIMIT 20</query>
+        <query>SELECT acard.barcode FROM m_actor_card_legacy acard WHERE acard.barcode LIKE 'x_' AND acard.x_migrate = TRUE ORDER BY 1 LIMIT 20</query>
         <note>This is a shortlist of patron barcode collisions that maxes out at 20.  If there are more collisions we will need to run a custom report.  In some cases we may flag individual accounts to not migrate.</note>
     </report>
 
@@ -921,7 +847,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Collision List</heading>
-        <query>SELECT acard.barcode FROM actor_card acard WHERE (acard.barcode ~* 'collision' OR acard.barcode ~* '^x_') ORDER BY 1 LIMIT 20</query>
+        <query>SELECT acard.barcode FROM m_actor_card acard WHERE acard.barcode LIKE 'x_%' ORDER BY 1 LIMIT 20</query>
         <note>This is a shortlist of patron barcode collisions that maxes out at 20.  If there are more collisions we will need to run a custom report.  In some cases we may flag individual accounts to not migrate.</note>
     </report>
 
@@ -931,7 +857,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Number of Barcodes Matching Pattern Greater than 10.Left 60% of Characters</heading>
-        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM actor_card_legacy acard WHERE (acard.barcode ~* 'collision' OR acard.barcode ~* '^x_') AND acard.x_migrate = TRUE GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
+        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM m_actor_card_legacy acard WHERE (acard.barcode ~* 'collision' OR acard.barcode ~* '^x_') AND acard.x_migrate = TRUE GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
     </report>
 
     <report>
@@ -940,7 +866,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Number of Barcodes Matching Pattern Greater than 10.Left 60% of Characters</heading>
-        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM actor_card acard WHERE (acard.barcode ~* 'collision' OR acard.barcode ~* '^x_') GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
+        <query>SELECT COUNT(acard.id), LEFT(acard.barcode,(ROUND(LENGTH(acard.barcode)*.6))::INT) FROM m_actor_card acard WHERE (acard.barcode ~* 'collision' OR acard.barcode ~* '^x_') GROUP BY 2 HAVING COUNT(acard.id) > 10 ORDER BY 2</query>
     </report>
 
     <report>
@@ -949,7 +875,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count.Valid.Migrated</heading>
-        <query>SELECT COUNT(aua.id), valid::TEXT, x_migrate::TEXT FROM actor_usr_address_legacy aua GROUP BY 2, 3</query>
+        <query>SELECT COUNT(aua.id), valid::TEXT, x_migrate::TEXT FROM m_actor_usr_address_legacy aua GROUP BY 2, 3</query>
     </report>
 
     <report>
@@ -958,7 +884,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Count.Valid</heading>
-        <query>SELECT COUNT(aua.id), valid::TEXT FROM actor_usr_address aua GROUP BY 2</query>
+        <query>SELECT COUNT(aua.id), valid::TEXT FROM m_actor_usr_address aua GROUP BY 2</query>
     </report>
 
     <report>
@@ -967,7 +893,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count of Addresses.Pending.Migrated</heading>
-        <query>SELECT COUNT(aua.id), pending::TEXT, x_migrate::TEXT FROM actor_usr_address_legacy aua GROUP BY 2, 3</query>
+        <query>SELECT COUNT(aua.id), pending::TEXT, x_migrate::TEXT FROM m_actor_usr_address_legacy aua GROUP BY 2, 3</query>
     </report>
 
     <report>
@@ -976,7 +902,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Count of Addresses.Pending</heading>
-        <query>SELECT COUNT(aua.id), pending::TEXT FROM actor_usr_address aua GROUP BY 2</query>
+        <query>SELECT COUNT(aua.id), pending::TEXT FROM m_actor_usr_address aua GROUP BY 2</query>
     </report>
 
     <report>
@@ -985,7 +911,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count.Deleted.Migrated</heading>
-        <query>SELECT COUNT(aum.id), deleted::TEXT, x_migrate::TEXT FROM actor_usr_message_legacy aum GROUP BY 2, 3</query>
+        <query>SELECT COUNT(aum.id), deleted::TEXT, x_migrate::TEXT FROM m_actor_usr_message_legacy aum GROUP BY 2, 3</query>
     </report>
 
     <report>
@@ -994,7 +920,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Count.Deleted</heading>
-        <query>SELECT COUNT(aum.id), deleted::TEXT FROM actor_usr_message_legacy aum GROUP BY 2</query>
+        <query>SELECT COUNT(aum.id), deleted::TEXT FROM m_actor_usr_message_legacy aum GROUP BY 2</query>
     </report>
 
     <report>
@@ -1003,7 +929,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count.Public.Migrated</heading>
-        <query>SELECT COUNT(aun.id), pub::TEXT, x_migrate::TEXT FROM actor_usr_note_legacy aun GROUP BY 2, 3</query>
+        <query>SELECT COUNT(aun.id), pub::TEXT, x_migrate::TEXT FROM m_actor_usr_note_legacy aun GROUP BY 2, 3</query>
     </report>
 
     <report>
@@ -1012,7 +938,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Count.Public</heading>
-        <query>SELECT COUNT(aun.id), pub::TEXT FROM actor_usr_note aun GROUP BY 2</query>
+        <query>SELECT COUNT(aun.id), pub::TEXT FROM m_actor_usr_note aun GROUP BY 2</query>
     </report>
 
     <report>
@@ -1021,7 +947,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Stat Cat Count.Library.Statistical Category.Migrated</heading>
-        <query>SELECT COUNT(au_sc.id), aou.name, au_sc.name, au_sc.x_migrate::TEXT FROM actor_stat_cat_legacy au_sc JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
+        <query>SELECT COUNT(au_sc.id), aou.name, au_sc.name, au_sc.x_migrate::TEXT FROM m_actor_stat_cat_legacy au_sc JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3, 4 ORDER BY 2, 3, 4</query>
     </report>
 
     <report>
@@ -1030,7 +956,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Stat Cat Count.Library.Statistical Category</heading>
-        <query>SELECT COUNT(au_sc.id), aou.name, au_sc.name FROM actor_stat_cat au_sc JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(au_sc.id), aou.name, au_sc.name FROM m_actor_stat_cat au_sc JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
@@ -1039,7 +965,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Patron Stat Count.Library.Statistical Category.Migrated</heading>
-        <query>SELECT COUNT(map.id), aou.name, au_sc.name, map.x_migrate::TEXT FROM actor_stat_cat_entry_usr_map_legacy map JOIN actor_stat_cat_legacy au_sc ON au_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3, 4 ORDER BY 2,3, 4</query>
+        <query>SELECT COUNT(map.id), aou.name, au_sc.name, map.x_migrate::TEXT FROM m_actor_stat_cat_entry_usr_map_legacy map JOIN m_actor_stat_cat_legacy au_sc ON au_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3, 4 ORDER BY 2,3, 4</query>
     </report>
 
     <report>
@@ -1048,7 +974,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>1</iteration>
         <heading>Patron Stat Count.Library.Statistical Category</heading>
-        <query>SELECT COUNT(map.id), aou.name, au_sc.name FROM actor_stat_cat_entry_usr_map map JOIN actor_stat_cat au_sc ON au_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3 ORDER BY 2,3</query>
+        <query>SELECT COUNT(map.id), aou.name, au_sc.name FROM m_actor_stat_cat_entry_usr_map map JOIN m_actor_stat_cat au_sc ON au_sc.id = map.stat_cat JOIN actor.org_unit aou ON aou.id = au_sc.owner GROUP BY 2, 3 ORDER BY 2,3</query>
     </report>
 
     <report>
@@ -1068,9 +994,9 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>actors</tag>
         <iteration>0</iteration>
         <heading>Count.Setting.Value</heading>
-        <query>SELECT COUNT(*), name, 'User''s Phone' FROM actor_usr_setting WHERE name IN ('opac.default_phone') GROUP BY 2, 3 
-                       UNION ALL SELECT COUNT(*), name, value FROM actor_usr_setting WHERE name IN ('opac.hold_notify') GROUP BY 2, 3 
-                       UNION ALL SELECT COUNT(*), a.name, aou.shortname FROM actor_usr_setting a JOIN actor.org_unit aou ON aou.id = REPLACE(a.value,'"','')::INTEGER 
+        <query>SELECT COUNT(*), name, 'User''s Phone' FROM m_actor_usr_setting WHERE name IN ('opac.default_phone') GROUP BY 2, 3 
+                       UNION ALL SELECT COUNT(*), name, value FROM m_actor_usr_setting WHERE name IN ('opac.hold_notify') GROUP BY 2, 3 
+                       UNION ALL SELECT COUNT(*), a.name, aou.shortname FROM m_actor_usr_setting a JOIN actor.org_unit aou ON aou.id = REPLACE(a.value,'"','')::INTEGER 
                                WHERE a.name IN ('opac.default_pickup_location','opac.default_search_location') GROUP BY 2, 3 ORDER BY 2, 3;</query>
     </report>
 
@@ -1081,7 +1007,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>acq</tag>
         <report_title>Migrated Funds</report_title>
         <heading>Number of Funds.Migrated</heading>
-        <query>SELECT COUNT(id), x_migrate::TEXT FROM acq_fund_legacy GROUP BY 2;</query>
+        <query>SELECT COUNT(id), x_migrate::TEXT FROM m_acq_fund_legacy GROUP BY 2;</query>
     </report>
 
     <report>                                                                        
@@ -1090,7 +1016,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>acq</tag>
         <report_title>Migrated Funds</report_title>
         <heading>Number of Funds</heading>
-        <query>SELECT COUNT(id) FROM acq_fund;</query>
+        <query>SELECT COUNT(id) FROM m_acq_fund;</query>
     </report>
 
     <report>
@@ -1099,7 +1025,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>acq</tag>
         <report_title>Migrated Invoices</report_title>
         <heading>Number of Invoices.Migrated</heading>
-        <query>SELECT COUNT(id), x_migrate::TEXT FROM acq_invoice_legacy GROUP BY 2;</query>
+        <query>SELECT COUNT(id), x_migrate::TEXT FROM m_acq_invoice_legacy GROUP BY 2;</query>
     </report>
 
     <report>
@@ -1108,7 +1034,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <tag>acq</tag>
         <report_title>Migrated Invoices</report_title>
         <heading>Number of Funds</heading>
-        <query>SELECT COUNT(id) FROM acq_invoice;</query>
+        <query>SELECT COUNT(id) FROM m_acq_invoice;</query>
     </report>    
 
     <!-- SERIALS REPORTS -->
@@ -1118,7 +1044,7 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <iteration>0</iteration>
         <report_title>Migrated Serial MFHDs</report_title>
         <heading>Number of MFHDs</heading>
-        <query>SELECT COUNT(id) FROM serial_record_entry</query>
+        <query>SELECT COUNT(id) FROM m_serial_record_entry</query>
     </report>
 
     <!-- DEDUPE REPORTS -->
@@ -1186,10 +1112,10 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <report_title>Action Triggers Setup for Notices</report_title>
         <heading>ID.Active.Owner.Name</heading>
         <query>SELECT ed.id, ed.active, aou.shortname, ed.name
-            FROM action_trigger.event_definition ed 
+            FROM m_action_trigger.event_definition ed 
             JOIN actor.org_unit aou ON aou.id = ed.owner 
-            WHERE ed.owner IN (SELECT DISTINCT home_ou FROM actor_usr)
-            OR ed.owner IN (SELECT DISTINCT parent_ou FROM actor.org_unit WHERE id in (SELECT DISTINCT home_ou FROM actor_usr));
+            WHERE ed.owner IN (SELECT DISTINCT home_ou FROM m_actor_usr)
+            OR ed.owner IN (SELECT DISTINCT parent_ou FROM actor.org_unit WHERE id in (SELECT DISTINCT home_ou FROM m_actor_usr));
         </query>
     </report>
 
@@ -1200,11 +1126,11 @@ id = ac_sc.owner GROUP BY 2,3 ORDER BY 2,3</query>
         <report_title>Count of Notices Run with State</report_title>
         <heading>Count of Notices.State.ID.Owner.Name</heading>
         <query>SELECT COUNT(ate.id), ate.state, ed.id, aou.shortname, ed.name 
-            FROM action_trigger.event_definition ed 
+            FROM m_action_trigger.event_definition ed 
             JOIN actor.org_unit aou ON aou.id = ed.owner 
-            JOIN action_trigger.event ate ON ate.event_def = ed.id 
-            WHERE ed.owner IN (SELECT DISTINCT home_ou FROM actor_usr)
-            OR ed.owner IN (SELECT DISTINCT parent_ou FROM actor.org_unit WHERE id in (SELECT DISTINCT home_ou FROM actor_usr))
+            JOIN m_action_trigger.event ate ON ate.event_def = ed.id 
+            WHERE ed.owner IN (SELECT DISTINCT home_ou FROM m_actor_usr)
+            OR ed.owner IN (SELECT DISTINCT parent_ou FROM actor.org_unit WHERE id in (SELECT DISTINCT home_ou FROM m_actor_usr))
             GROUP BY 2,3,4;
         </query>
     </report>
index 55c12be..47f07e6 100644 (file)
@@ -6,7 +6,7 @@
         <tag>money</tag>  arbitrary tags, each should go in separate tag
         <report_title>Migrated Billings</report_title>  title used in the asciidoc output
         <heading column='1'>Number of Billings.Migrated.Total</heading> period delimited 
-        <query>SELECT COUNT(id),x_migrate,SUM(amount) FROM money_billing_legacy GROUP BY 2;</query>  query itself, will be replaced
+        <query>SELECT COUNT(id),x_migrate,SUM(amount) FROM m_money_billing_legacy GROUP BY 2;</query>  query itself, will be replaced
         <note>Arbitrary note that can be included in the entries.</note>
     </report>
 -->
    <!-- evergreen -->
 
     <report>
-        <name>evg_asset_copy_statuses</name>
+        <name>evg_m_asset_copy_statuses</name>
         <report_title>Statuses</report_title>
         <tag>evergreen</tag>
         <iteration>0</iteration>
         <heading>Copy Count.Migrating Status.New Evergreen Status.Notes</heading>
-        <query>SELECT COUNT(ac.l_id), cs.l_name FROM asset_copy_legacy ac JOIN config_copy_status_legacy cs ON cs.l_id = ac.l_status GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(ac.l_id), cs.l_name FROM m_asset_copy_legacy ac JOIN config_copy_status_legacy cs ON cs.l_id = ac.l_status GROUP BY 2 ORDER BY 2</query>
         <note>You only need to fill this sheet out if you use custom statuses that need to be migrated.</note>
     </report>
 
     <report>
-        <name>evg_asset_circ_mods</name>
+        <name>evg_m_asset_circ_mods</name>
         <report_title>Circulation Modifiers</report_title>
         <tag>evergreen</tag>
         <iteration>0</iteration>
         <heading>Copy Count.Migrating Circ Mod.New Circ Mod.Notes</heading>
-        <query>SELECT COUNT(ac.l_id), ac.l_circ_modifier FROM asset_copy_legacy ac GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(ac.l_id), ac.l_circ_modifier FROM m_asset_copy_legacy ac GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>evg_asset_copy_locs</name>
+        <name>evg_m_asset_copy_locs</name>
         <report_title>Copy Locations</report_title>
         <tag>evergreen</tag>
         <iteration>0</iteration>
         <heading>Count.Library.Migrating Copy Location.New Copy Location.Notes</heading>
-        <query>SELECT COUNT(ac.l_id), aou.l_name, acl.l_name FROM asset_copy_location_legacy acl JOIN actor_org_unit_legacy aou ON aou.l_id = acl.l_owning_lib JOIN asset_copy_legacy ac ON ac.l_location = acl.l_id GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(ac.l_id), aou.l_name, acl.l_name FROM m_asset_copy_location_legacy acl JOIN m_actor_org_unit_legacy aou ON aou.l_id = acl.l_owning_lib JOIN m_asset_copy_legacy ac ON ac.l_location = acl.l_id GROUP BY 2, 3 ORDER BY 2, 3</query>
         <note>Any locations not mapped can be moved over as their existing locations.</note>
     </report>
 
@@ -48,7 +48,7 @@
         <tag>evergreen</tag>
         <iteration>0</iteration>
         <heading>Count.Migrating Permission Group.New Permission Group.Notes</heading>
-        <query>SELECT COUNT(au.l_id), pgt.l_name FROM actor_usr_legacy au JOIN permission_grp_tree_legacy pgt ON pgt.l_id = au.l_profile GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(au.l_id), pgt.l_name FROM m_actor_usr_legacy au JOIN permission_grp_tree_legacy pgt ON pgt.l_id = au.l_profile GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <!-- tlc -->
@@ -62,7 +62,7 @@
     </report>
 
     <report>
-        <name>tlc_load_asset_notes</name>
+        <name>tlc_load_m_asset_notes</name>
         <report_title>Item Notes</report_title>
         <tag>tlc</tag>
         <iteration>0</iteration>
@@ -77,7 +77,7 @@
     </report>
 
     <report>
-        <name>tlc_load_asset_holdings_codes</name>
+        <name>tlc_load_m_asset_holdings_codes</name>
         <report_title>Holdings Codes</report_title>
         <tag>tlc</tag>
         <iteration>0</iteration>
@@ -86,7 +86,7 @@
     </report>
 <!--
     <report>
-        <name>tlc_load_asset_callnumbertype</name>
+        <name>tlc_load_m_asset_callnumbertype</name>
         <report_title>Call Number Types</report_title>
         <tag>tlc</tag>
         <iteration>0</iteration>
@@ -97,7 +97,7 @@
 -->
 <!-- 
     <report>
-        <name>tlc_load_asset_callnumberparts</name>
+        <name>tlc_load_m_asset_callnumberparts</name>
         <report_title>Call Number Parts</report_title>
         <tag>tlc</tag>
         <iteration>0</iteration>
     </report>
 -->
     <report>
-        <name>tlc_load_money_migrating_bills</name>
+        <name>tlc_load_m_money_migrating_bills</name>
         <report_title>Migrating Bills By Bill Type</report_title>
         <tag>tlc</tag>
         <iteration>0</iteration>
     </report>
     
     <report>
-        <name>destiny_load_asset_categories</name>
+        <name>destiny_load_m_asset_categories</name>
         <report_title>Count of Categories</report_title>
         <tag>destiny</tag>
         <iteration>0</iteration>
     </report>
     
     <report>
-        <name>destiny_load_asset_notes</name>
+        <name>destiny_load_m_asset_notes</name>
         <report_title>Copies by Note Types</report_title>
         <tag>destiny</tag>
         <iteration>0</iteration>
     </report>
     
         <report>
-        <name>destiny_load_asset_sublocation</name>
+        <name>destiny_load_m_asset_sublocation</name>
         <report_title>Copies by Sub Location</report_title>
         <tag>destiny</tag>
         <iteration>0</iteration>
     </report>
     
     <report>
-        <name>destiny_load_asset_vendor</name>
+        <name>destiny_load_m_asset_vendor</name>
         <report_title>Copies by Vendor</report_title>
         <tag>destiny</tag>
         <iteration>0</iteration>
     </report>
     
     <report>
-        <name>destiny_load_asset_descriptions</name>
+        <name>destiny_load_m_asset_descriptions</name>
         <report_title>Copies with Description Fields</report_title>
         <tag>destiny</tag>
         <iteration>0</iteration>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Status.Type</heading>
-        <query>SELECT COUNT(id), l_status, l_type FROM action_circulation_legacy GROUP BY 2, 3</query>
+        <query>SELECT COUNT(id), l_status, l_type FROM m_action_circulation_legacy GROUP BY 2, 3</query>
         <note>Circulations will only not be migrated if they can't be attached to a migrated patron and holding.</note>
     </report>
 
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Status</heading>
-        <query> SELECT COUNT(id), l_status FROM action_hold_request_legacy GROUP BY 2</query>
+        <query> SELECT COUNT(id), l_status FROM m_action_hold_request_legacy GROUP BY 2</query>
         <note>Only unfilled holds are being migrated.</note>
     </report>
 
     <report>
-        <name>asset_pending_bibs</name>
+        <name>m_asset_pending_bibs</name>
         <report_title>Pending Records</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Year of Last Edit.Count of Copies Attached</heading>
-        <query>SELECT COUNT(bre.id), CASE WHEN LENGTH(bre.l_edited) > 1 THEN EXTRACT(YEAR FROM bre.l_edited::TIMESTAMP) ELSE '1900' END, COUNT(ac.id) FROM biblio_record_entry_legacy bre LEFT JOIN asset_copy_legacy ac ON ac.l_biblio = bre.l_id WHERE bre.l_status = 'pending' GROUP BY 2 ORDER BY 2
+        <query>SELECT COUNT(bre.id), CASE WHEN LENGTH(bre.l_edited) > 1 THEN EXTRACT(YEAR FROM bre.l_edited::TIMESTAMP) ELSE '1900' END, COUNT(ac.id) FROM m_biblio_record_entry_legacy bre LEFT JOIN m_asset_copy_legacy ac ON ac.l_biblio = bre.l_id WHERE bre.l_status = 'pending' GROUP BY 2 ORDER BY 2
 </query>
     </report>
 
     <report>
-        <name>asset_copies_by_status</name>
+        <name>m_asset_copies_by_status</name>
         <report_title>Copies by Status</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Status</heading>
-        <query>SELECT COUNT(id), l_status FROM asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(id), l_status FROM m_asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
         <note>Deleted copies with a delete date were not exported additionally those with the deleted status won't get loaded.</note>
     </report>
 
     <report>
-        <name>asset_pending_copies</name>
+        <name>m_asset_pending_copies</name>
         <report_title>Pending Copies by Last Edit</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Last Edited</heading>
-        <query>SELECT COUNT(id), CASE WHEN LENGTH(l_edited) > 1 THEN EXTRACT(YEAR FROM l_edited::TIMESTAMP) ELSE '1900' END FROM asset_copy_legacy WHERE l_status = 'pending' GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(id), CASE WHEN LENGTH(l_edited) > 1 THEN EXTRACT(YEAR FROM l_edited::TIMESTAMP) ELSE '1900' END FROM m_asset_copy_legacy WHERE l_status = 'pending' GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <report>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Membership Number.Membership Name</heading>
-        <query>SELECT COUNT(ac.id), acl.l_membership_number, acl.l_membership_name FROM asset_copy_legacy ac JOIN asset_copy_location_legacy acl ON acl.l_membership_name = ac.l_memberships GROUP BY 2,3 ORDER BY 2
+        <query>SELECT COUNT(ac.id), acl.l_membership_number, acl.l_membership_name FROM m_asset_copy_legacy ac JOIN m_asset_copy_location_legacy acl ON acl.l_membership_name = ac.l_memberships GROUP BY 2,3 ORDER BY 2
 </query>
     </report>
 
    <report>
-        <name>money_bills</name>
+        <name>m_money_bills</name>
         <report_title>Bills</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Status</heading>
-        <query>SELECT COUNT(id), l_status FROM money_billing_legacy GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(id), l_status FROM m_money_billing_legacy GROUP BY 2 ORDER BY 2</query>
         <note>Unless there is a good reason to do so forgiven and paid bills will not be migrated.</note>
     </report>
 
    <report>
-        <name>actor_groups</name>
+        <name>m_actor_groups</name>
         <report_title>Patron Membership Groups</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Membership List Name.Membership List ID.Membership Number.Membership Name.Membership Length in Monthst</heading>
-        <query>SELECT l_membership_list_name, l_membership_list_id, l_membership_number, l_membership_name, l_membership_length_months FROM actor_usr_legacy_groups_tsv ORDER BY 1, 3</query>
+        <query>SELECT l_membership_list_name, l_membership_list_id, l_membership_number, l_membership_name, l_membership_length_months FROM m_actor_usr_legacy_groups_tsv ORDER BY 1, 3</query>
         <note>Age looks like a good target for a stat cat and / or juvenile setting while the patron type can map to profiles.</note>
     </report>
 
     <report>
-        <name>actor_by_groups</name>
+        <name>m_actor_by_groups</name>
         <report_title>Patrons by Membership Groups</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Membership List Name.Membership Number</heading>
-        <query>SELECT COUNT(*), l_membership_list_name, l_membership_number FROM (SELECT id, UNNEST(STRING_TO_ARRAY(l_memberships,'|')) AS m FROM actor_usr_legacy ) x JOIN actor_usr_legacy_groups_tsv t ON t.l_membership_name = x.m GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(*), l_membership_list_name, l_membership_number FROM (SELECT id, UNNEST(STRING_TO_ARRAY(l_memberships,'|')) AS m FROM m_actor_usr_legacy ) x JOIN m_actor_usr_legacy_groups_tsv t ON t.l_membership_name = x.m GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
-        <name>actor_addresses_nulls</name>
+        <name>m_actor_addresses_nulls</name>
         <report_title>Patron Addresses</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Address Field.Nulls</heading>
-        <query>SELECT 'Street Address', COUNT(id) FROM actor_usr_address_legacy WHERE l_lines IS NULL UNION ALL SELECT 'City', COUNT(id) FROM actor_usr_address_legacy UNION ALL SELECT 'State', COUNT(id) FROM actor_usr_address_legacy WHERE l_country_division IS NULL UNION ALL SELECT 'Postal Code', COUNT(id) FROM actor_usr_address_legacy WHERE l_postal_code IS NULL </query>
+        <query>SELECT 'Street Address', COUNT(id) FROM m_actor_usr_address_legacy WHERE l_lines IS NULL UNION ALL SELECT 'City', COUNT(id) FROM m_actor_usr_address_legacy UNION ALL SELECT 'State', COUNT(id) FROM m_actor_usr_address_legacy WHERE l_country_division IS NULL UNION ALL SELECT 'Postal Code', COUNT(id) FROM m_actor_usr_address_legacy WHERE l_postal_code IS NULL </query>
         <note>If any of these fields are null then we need defaults to fill in, note the extract had no city data.</note>
     </report>
 
     <report>
-        <name>actor_phones</name>
+        <name>m_actor_phones</name>
         <report_title>Patron Phones</report_title>
         <tag>apollo</tag>
         <iteration>0</iteration>
         <heading>Count.Type</heading>
-        <query>SELECT COUNT(*), l_type FROM actor_usr_phones_tsv GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(*), l_type FROM m_actor_usr_phones_tsv GROUP BY 2 ORDER BY 2</query>
         <note>These need to be mapped to Evergreen phone types.</note>
     </report>
 
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count.Borrower Type</heading>
-        <query>SELECT COUNT(id), l_borrower_btype FROM actor_usr_legacy GROUP BY 2 ORDER BY 2;</query>
+        <query>SELECT COUNT(id), l_borrower_btype FROM m_actor_usr_legacy GROUP BY 2 ORDER BY 2;</query>
     </report>
 
     <report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count of Migratable Passwords / PINs</heading>
-        <query>SELECT COUNT(l_borrower_pin) FROM actor_usr_legacy WHERE LENGTH(l_borrower_pin) > 1;</query>
+        <query>SELECT COUNT(l_borrower_pin) FROM m_actor_usr_legacy WHERE LENGTH(l_borrower_pin) > 1;</query>
     </report>
 
     <report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Sample of Migratable Notes</heading>
-        <query>SELECT l_borrower_borrower_note FROM actor_usr_legacy WHERE LENGTH(l_borrower_borrower_note) > 1 LIMIT 20;</query>
+        <query>SELECT l_borrower_borrower_note FROM m_actor_usr_legacy WHERE LENGTH(l_borrower_borrower_note) > 1 LIMIT 20;</query>
     </report>
 
     <report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(l_borrower_borrower_note) FROM actor_usr_legacy WHERE LENGTH(l_borrower_borrower_note) > 1;</query>
+        <query>SELECT COUNT(l_borrower_borrower_note) FROM m_actor_usr_legacy WHERE LENGTH(l_borrower_borrower_note) > 1;</query>
     </report>
 
     <report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT l_borrower_note2 FROM actor_usr_legacy WHERE LENGTH(l_borrower_note2) > 1 LIMIT 20;</query>
+        <query>SELECT l_borrower_note2 FROM m_actor_usr_legacy WHERE LENGTH(l_borrower_note2) > 1 LIMIT 20;</query>
     </report>
 
     <report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT l_borrower_note3 FROM actor_usr_legacy WHERE LENGTH(l_borrower_note3) > 1 LIMIT 20;</query>
+        <query>SELECT l_borrower_note3 FROM m_actor_usr_legacy WHERE LENGTH(l_borrower_note3) > 1 LIMIT 20;</query>
     </report>
 
     <report>
         <heading>Count.Borrower Phone Type</heading>
         <query>
         SELECT COUNT(*), b 
-        FROM (SELECT l_borrower_phone_1_phone_type AS b FROM actor_usr_legacy
-        UNION ALL SELECT l_borrower_phone_2_phone_type AS b FROM actor_usr_legacy
-        UNION ALL SELECT l_borrower_phone_3_phone_type AS b FROM actor_usr_legacy
-        UNION ALL SELECT l_borrower_phone_4_phone_type AS b FROM actor_usr_legacy) x 
+        FROM (SELECT l_borrower_phone_1_phone_type AS b FROM m_actor_usr_legacy
+        UNION ALL SELECT l_borrower_phone_2_phone_type AS b FROM m_actor_usr_legacy
+        UNION ALL SELECT l_borrower_phone_3_phone_type AS b FROM m_actor_usr_legacy
+        UNION ALL SELECT l_borrower_phone_4_phone_type AS b FROM m_actor_usr_legacy) x 
         GROUP BY 2 ORDER BY 2
         </query>
     </report>
         <iteration>0</iteration>
         <heading>Count.BStat</heading>
         <query>SELECT COUNT(*), b 
-        FROM (SELECT l_borrower_bstat_1_bstat AS b FROM actor_usr_legacy
+        FROM (SELECT l_borrower_bstat_1_bstat AS b FROM m_actor_usr_legacy
         UNION ALL
-        SELECT l_borrower_bstat_2_bstat AS b FROM actor_usr_legacy
+        SELECT l_borrower_bstat_2_bstat AS b FROM m_actor_usr_legacy
         UNION ALL
-        SELECT l_borrower_bstat_3_bstat AS b FROM actor_usr_legacy) x
+        SELECT l_borrower_bstat_3_bstat AS b FROM m_actor_usr_legacy) x
         GROUP BY 2 ORDER BY 1;
         </query>
     </report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count.Collection</heading>
-        <query>SELECT COUNT(id), l_collection FROM asset_copy_legacy GROUP BY 2 ORDER BY 2;</query>
+        <query>SELECT COUNT(id), l_collection FROM m_asset_copy_legacy GROUP BY 2 ORDER BY 2;</query>
     </report>
 
        <report>    
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count.Item Type (itype)</heading>
-        <query>SELECT COUNT(id), l_itype FROM asset_copy_legacy GROUP BY 2 ORDER BY 2;</query>
+        <query>SELECT COUNT(id), l_itype FROM m_asset_copy_legacy GROUP BY 2 ORDER BY 2;</query>
     </report>
   
     <report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT COUNT(l_internal_note) FROM asset_copy_legacy WHERE LENGTH(l_internal_note) > 1;</query>
+        <query>SELECT COUNT(l_internal_note) FROM m_asset_copy_legacy WHERE LENGTH(l_internal_note) > 1;</query>
     </report>
 
     <report>
         <tag>horizon</tag>
         <iteration>0</iteration>
         <heading>Count</heading>
-        <query>SELECT l_internal_note FROM asset_copy_legacy WHERE LENGTH(l_internal_note) > 1 LIMIT 20;</query>
+        <query>SELECT l_internal_note FROM m_asset_copy_legacy WHERE LENGTH(l_internal_note) > 1 LIMIT 20;</query>
     </report>
 
     <report>
         <iteration>0</iteration>
         <report_title>Circs by Status</report_title>
         <heading>Count of Circs.Status</heading>
-        <query>SELECT COUNT(id), l_is_checked_out FROM asset_copy_legacy GROUP BY 2</query>
+        <query>SELECT COUNT(id), l_is_checked_out FROM m_asset_copy_legacy GROUP BY 2</query>
     </report>
 
    <report>
-        <name>rm_load_asset_by_resource_type</name>
+        <name>rm_load_m_asset_by_resource_type</name>
         <report_title>Resource Type</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Resource Type</heading>
-        <query>SELECT COUNT(*), l_resource_type FROM asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(*), l_resource_type FROM m_asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
     </report>
 
    <report>
-        <name>rm_load_asset_by_location</name>
+        <name>rm_load_m_asset_by_location</name>
         <report_title>Copies by Location</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Location</heading>
-        <query>SELECT COUNT(*), l_location FROM asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(*), l_location FROM m_asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>rm_load_asset_by_category</name>
+        <name>rm_load_m_asset_by_category</name>
         <report_title>Copies by Category</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Category</heading>
-        <query>SELECT COUNT(*), l_category FROM asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(*), l_category FROM m_asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
     </report>
    
     <report>
-        <name>rm_load_asset_by_status</name>
+        <name>rm_load_m_asset_by_status</name>
         <report_title>Copies by Status</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Status</heading>
-        <query>SELECT COUNT(*), l_status FROM asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
+        <query>SELECT COUNT(*), l_status FROM m_asset_copy_legacy GROUP BY 2 ORDER BY 2</query>
     </report>
 
     <report>
-        <name>rm_actor_groups</name>
+        <name>rm_m_actor_groups</name>
         <report_title>Patrons by User Groups</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Group</heading>
-        <query>SELECT COUNT(id), l_user_group FROM actor_usr_legacy GROUP BY 2 ORDER BY 2;
+        <query>SELECT COUNT(id), l_user_group FROM m_actor_usr_legacy GROUP BY 2 ORDER BY 2;
         </query>
     </report>
 
     <report>
-        <name>rm_actor_access</name>
+        <name>rm_m_actor_access</name>
         <report_title>Patrons by Access Field</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Access</heading>
-        <query>SELECT COUNT(id), l_access_if_applicable FROM actor_usr_legacy GROUP BY 2 ORDER BY 2;
+        <query>SELECT COUNT(id), l_access_if_applicable FROM m_actor_usr_legacy GROUP BY 2 ORDER BY 2;
         </query>
     </report>
 
     <report>
-        <name>rm_actor_comments</name>
+        <name>rm_m_actor_comments</name>
         <report_title>Patron Comments</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Sample</heading>
-        <query>SELECT COUNT(id), 'All Comments' FROM actor_usr_legacy WHERE LENGTH(l_comments) > 1
-            UNION ALL SELECT NULL, l_comments FROM  actor_usr_legacy WHERE LENGTH(l_comments) > 1 LIMIT 10
+        <query>SELECT COUNT(id), 'All Comments' FROM m_actor_usr_legacy WHERE LENGTH(l_comments) > 1
+            UNION ALL SELECT NULL, l_comments FROM  m_actor_usr_legacy WHERE LENGTH(l_comments) > 1 LIMIT 10
         </query>
     </report>
 
     <report>
-        <name>rm_actor_circulation_note</name>
+        <name>rm_m_actor_circulation_note</name>
         <report_title>Patron Circ Notes</report_title>
         <tag>rm</tag>
         <iteration>0</iteration>
         <heading>Count.Sample</heading>
-        <query>SELECT COUNT(id), 'All Notes' FROM actor_usr_legacy WHERE LENGTH(l_circulation_note) > 1
-            UNION ALL SELECT NULL, l_circulation_note FROM  actor_usr_legacy WHERE LENGTH(l_circulation_note) > 1 LIMIT 10
+        <query>SELECT COUNT(id), 'All Notes' FROM m_actor_usr_legacy WHERE LENGTH(l_circulation_note) > 1
+            UNION ALL SELECT NULL, l_circulation_note FROM  m_actor_usr_legacy WHERE LENGTH(l_circulation_note) > 1 LIMIT 10
         </query>
     </report>
 
 <!-- tlc reports 
 
     <report>
-        <name>tlc_reports_load_asset_holdings_codes</name>
+        <name>tlc_reports_load_m_asset_holdings_codes</name>
         <report_title>Holdings Codes</report_title>
         <tag>tlc_reports</tag>
         <iteration>0</iteration>
         <heading>Count.Library.Holdings Codes.Evergreen Circulation Modifier.Evergreen Shelving Locatione</heading>
-        <query>SELECT COUNT(id), x_source, l_holdingscode FROM asset_copy_legacy GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(id), x_source, l_holdingscode FROM m_asset_copy_legacy GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
         <tag>tlc_reports</tag>
         <iteration>0</iteration>
         <heading>Count.Library.Permission Group.Evergreen Permission Group</heading>
-        <query>SELECT COUNT(id), l_location, l_borrower_type FROM actor_usr_legacy GROUP BY 2, 3 ORDER BY 2, 3</query>
+        <query>SELECT COUNT(id), l_location, l_borrower_type FROM m_actor_usr_legacy GROUP BY 2, 3 ORDER BY 2, 3</query>
     </report>
 
     <report>
         <tag>tlc_reports</tag>
         <iteration>0</iteration>
         <heading>Count.SUM.Migrate?</heading>
-        <query>SELECT COUNT(id), SUM(l_current_fine_balance::NUMERIC(6,2)) FROM actor_usr_address_legacy WHERE l_current_fine_balance != '0' AND l_current_fine_balance IS NOT NULL</query>
+        <query>SELECT COUNT(id), SUM(l_current_fine_balance::NUMERIC(6,2)) FROM m_actor_usr_address_legacy WHERE l_current_fine_balance != '0' AND l_current_fine_balance IS NOT NULL</query>
     </report>
 
     <report>
         <tag>tlc_reports</tag>
         <iteration>0</iteration>
         <heading>Count.Blocked.Migrate?</heading>
-        <query>SELECT COUNT(id), l_blocked FROM actor_usr_address_legacy GROUP BY 2</query>
+        <query>SELECT COUNT(id), l_blocked FROM m_actor_usr_address_legacy GROUP BY 2</query>
     </report>
 
     <report>
         <tag>tlc_reports</tag>
         <iteration>0</iteration>
         <heading>Count.Phone Type.Phone Type</heading>
-        <query>SELECT COUNT(id), 'Phone 1' FROM actor_usr_address_legacy WHERE l_phone_1 IS NOT NULL GROUP BY 2 UNION ALL SELECT COUNT(id), 'Phone 2' FROM actor_usr_address_legacy WHERE l_phone_2 IS NOT NULL GROUP BY 2</query>
+        <query>SELECT COUNT(id), 'Phone 1' FROM m_actor_usr_address_legacy WHERE l_phone_1 IS NOT NULL GROUP BY 2 UNION ALL SELECT COUNT(id), 'Phone 2' FROM m_actor_usr_address_legacy WHERE l_phone_2 IS NOT NULL GROUP BY 2</query>
     </report>
 -->
 </reports_file>
index c0953c6..4bd25cf 100644 (file)
@@ -62,13 +62,13 @@ CREATE OR REPLACE FUNCTION migration_tools.build (TEXT) RETURNS VOID AS $$
     BEGIN
         SELECT migration_tools.production_tables(migration_schema) INTO STRICT production_tables;
         PERFORM migration_tools.build_base_staging_tables(migration_schema,production_tables);
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_barcode_key ON ' || migration_schema || '.actor_card ( barcode );';
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_usrname_key ON ' || migration_schema || '.actor_usr ( usrname );';
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_barcode_key ON ' || migration_schema || '.asset_copy ( barcode );';
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_id_key ON ' || migration_schema || '.asset_copy ( id );';
-        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_record_idx ON ' || migration_schema || '.asset_call_number ( record );';
-        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_upper_label_id_lib_idx ON ' || migration_schema || '.asset_call_number ( UPPER(label),id,owning_lib );';
-        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_callnum_label_once_per_lib ON ' || migration_schema || '.asset_call_number ( record,owning_lib,label,prefix,suffix );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_barcode_key ON ' || migration_schema || '.m_actor_card ( barcode );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_usrname_key ON ' || migration_schema || '.m_actor_usr ( usrname );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_barcode_key ON ' || migration_schema || '.m_asset_copy ( barcode );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_id_key ON ' || migration_schema || '.m_asset_copy ( id );';
+        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_record_idx ON ' || migration_schema || '.m_asset_call_number ( record );';
+        EXECUTE 'CREATE INDEX ' || migration_schema || '_callnum_upper_label_id_lib_idx ON ' || migration_schema || '.m_asset_call_number ( UPPER(label),id,owning_lib );';
+        EXECUTE 'CREATE UNIQUE INDEX ' || migration_schema || '_callnum_label_once_per_lib ON ' || migration_schema || '.m_asset_call_number ( record,owning_lib,label,prefix,suffix );';
     END;
 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
 
@@ -90,7 +90,7 @@ CREATE OR REPLACE FUNCTION migration_tools.build_specific_base_staging_table (TE
         base_staging_table TEXT;
         columns RECORD;
     BEGIN
-        base_staging_table = REPLACE( production_table, '.', '_' );
+        base_staging_table = REPLACE( 'm_' || production_table, '.', '_' );
         EXECUTE 'CREATE TABLE ' || migration_schema || '.' || base_staging_table || ' ( LIKE ' || production_table || ' INCLUDING DEFAULTS EXCLUDING CONSTRAINTS );';
         FOR columns IN 
             SELECT table_schema, table_name, column_name, data_type
@@ -115,7 +115,7 @@ CREATE OR REPLACE FUNCTION migration_tools.create_linked_legacy_table_from (TEXT
     BEGIN
         create_sql := 'CREATE TABLE ' || migration_schema || '.' || parent_table || '_legacy ( ';
         FOR columns IN
-            SELECT table_schema, table_name, column_name, data_type
+            SELECT table_schema, table_name, column_name, data_type, numeric_precision, numeric_scale
             FROM information_schema.columns
             WHERE table_schema = migration_schema AND table_name = source_table
         LOOP
@@ -127,6 +127,8 @@ CREATE OR REPLACE FUNCTION migration_tools.create_linked_legacy_table_from (TEXT
             create_sql := create_sql || columns.column_name || ' ';
             if columns.data_type = 'ARRAY' then
                 create_sql := create_sql || 'TEXT[]';
+            elsif columns.data_type = 'numeric' then
+                create_sql := create_sql || 'NUMERIC('||columns.numeric_precision||','||columns.numeric_scale||')';
             else
                 create_sql := create_sql || columns.data_type;
             end if;
@@ -141,3 +143,67 @@ CREATE OR REPLACE FUNCTION migration_tools.create_linked_legacy_table_from (TEXT
     END;
 $$ LANGUAGE PLPGSQL STRICT VOLATILE;
 
+-- creates other child table so you can have more than one child table in a schema from a base table 
+CREATE OR REPLACE FUNCTION migration_tools.build_variant_staging_table(text, text, text)
+ RETURNS void
+ LANGUAGE plpgsql
+ STRICT
+AS $function$
+    DECLARE
+        migration_schema ALIAS FOR $1;
+        production_table ALIAS FOR $2;
+        base_staging_table ALIAS FOR $3;
+        columns RECORD;
+    BEGIN
+        --RAISE INFO 'In migration_tools.build_specific_base_staging_table(%,%) -> %', migration_schema, production_table, base_staging_table;
+        EXECUTE 'CREATE TABLE ' || migration_schema || '.' || base_staging_table || ' ( LIKE ' || production_table || ' INCLUDING DEFAULTS EXCLUDING CONSTRAINTS );';
+        EXECUTE '
+            INSERT INTO ' || migration_schema || '.fields_requiring_mapping
+                SELECT table_schema, table_name, column_name, data_type
+                FROM information_schema.columns
+                WHERE table_schema = ''' || migration_schema || ''' AND table_name = ''' || base_staging_table || ''' AND is_nullable = ''NO'' AND column_default IS NULL;
+        ';
+        FOR columns IN
+            SELECT table_schema, table_name, column_name, data_type
+            FROM information_schema.columns
+            WHERE table_schema = migration_schema AND table_name = base_staging_table AND is_nullable = 'NO' AND column_default IS NULL
+        LOOP
+            EXECUTE 'ALTER TABLE ' || columns.table_schema || '.' || columns.table_name || ' ALTER COLUMN ' || columns.column_name || ' DROP NOT NULL;';
+        END LOOP;
+    END;
+$function$;
+
+CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN) RETURNS VOID AS $$
+    DECLARE
+        test ALIAS FOR $1;
+    BEGIN
+        IF NOT test THEN
+            RAISE EXCEPTION 'assertion';
+        END IF;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN,TEXT) RETURNS VOID AS $$
+    DECLARE
+        test ALIAS FOR $1;
+        msg ALIAS FOR $2;
+    BEGIN
+        IF NOT test THEN
+            RAISE EXCEPTION '%', msg;
+        END IF;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN,TEXT,TEXT) RETURNS TEXT AS $$
+    DECLARE
+        test ALIAS FOR $1;
+        fail_msg ALIAS FOR $2;
+        success_msg ALIAS FOR $3;
+    BEGIN
+        IF NOT test THEN
+            RAISE EXCEPTION '%', fail_msg;
+        END IF;
+        RETURN success_msg;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
index e835074..28d4360 100644 (file)
@@ -86,7 +86,7 @@ CREATE OR REPLACE FUNCTION migration_tools.apply_circ_matrix( tablename TEXT ) R
 --   circ_lib, target_copy, usr, and *_renewal).  User profiles and
 --   circ modifiers must also be in place.
 --
---   SELECT migration_tools.apply_circ_matrix('m_pioneer.action_circulation');
+--   SELECT migration_tools.apply_circ_matrix('m_pioneer.m_action_circulation');
 --
 
 DECLARE
@@ -191,7 +191,7 @@ CREATE OR REPLACE FUNCTION migration_tools.apply_circ_matrix_to_specific_circ( t
 --   circ_lib, target_copy, usr, and *_renewal).  User profiles and
 --   circ modifiers must also be in place.
 --
---   SELECT migration_tools.apply_circ_matrix_to_specific_circ('m_nwrl.action_circulation', 18391960);
+--   SELECT migration_tools.apply_circ_matrix_to_specific_circ('m_nwrl.m_action_circulation', 18391960);
 --
 
 DECLARE
@@ -356,12 +356,12 @@ $$ LANGUAGE plpgsql;
 
 CREATE OR REPLACE FUNCTION migration_tools.create_cards( schemaname TEXT ) RETURNS VOID AS $$
 
--- USAGE: Make sure the patrons are staged in schemaname.actor_usr_legacy and have 'usrname' assigned.
+-- USAGE: Make sure the patrons are staged in schemaname.m_actor_usr_legacy and have 'usrname' assigned.
 --        Then SELECT migration_tools.create_cards('m_foo');
 
 DECLARE
-       u                    TEXT := schemaname || '.actor_usr_legacy';
-       c                    TEXT := schemaname || '.actor_card';
+       u                    TEXT := schemaname || '.m_actor_usr_legacy';
+       c                    TEXT := schemaname || '.m_actor_card';
   
 BEGIN
 
@@ -461,42 +461,42 @@ CREATE OR REPLACE FUNCTION migration_tools.simple_export_library_config(dir TEXT
 BEGIN
    EXECUTE $$COPY (SELECT * FROM actor.hours_of_operation WHERE id IN ($$ ||
            ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
-           $$) TO '$$ ||  dir || $$/actor_hours_of_operation'$$;
+           $$) TO '$$ ||  dir || $$/m_actor_hours_of_operation'$$;
    EXECUTE $$COPY (SELECT org_unit, close_start, close_end, reason FROM actor.org_unit_closed WHERE org_unit IN ($$ ||
            ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
-           $$) TO '$$ ||  dir || $$/actor_org_unit_closed'$$;
+           $$) TO '$$ ||  dir || $$/m_actor_org_unit_closed'$$;
    EXECUTE $$COPY (SELECT org_unit, name, value FROM actor.org_unit_setting WHERE org_unit IN ($$ ||
            ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
-           $$) TO '$$ ||  dir || $$/actor_org_unit_setting'$$;
+           $$) TO '$$ ||  dir || $$/m_actor_org_unit_setting'$$;
    EXECUTE $$COPY (SELECT name, owning_lib, holdable, hold_verify, opac_visible, circulate FROM asset.copy_location WHERE owning_lib IN ($$ ||
            ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
-           $$) TO '$$ ||  dir || $$/asset_copy_location'$$;
+           $$) TO '$$ ||  dir || $$/m_asset_copy_location'$$;
    EXECUTE $$COPY (SELECT grp, org_unit, penalty, threshold FROM permission.grp_penalty_threshold WHERE org_unit IN ($$ ||
            ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
-           $$) TO '$$ ||  dir || $$/permission_grp_penalty_threshold'$$;
+           $$) TO '$$ ||  dir || $$/m_permission_grp_penalty_threshold'$$;
    EXECUTE $$COPY (SELECT owning_lib, label, label_sortkey FROM asset.call_number_prefix WHERE owning_lib IN ($$ ||
            ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
-           $$) TO '$$ ||  dir || $$/asset_call_number_prefix'$$;
+           $$) TO '$$ ||  dir || $$/m_asset_call_number_prefix'$$;
    EXECUTE $$COPY (SELECT owning_lib, label, label_sortkey FROM asset.call_number_suffix WHERE owning_lib IN ($$ ||
            ARRAY_TO_STRING(orgs, ',') || $$)$$ ||
-           $$) TO '$$ ||  dir || $$/asset_call_number_suffix'$$;
-   EXECUTE $$COPY config.rule_circ_duration TO '$$ ||  dir || $$/config_rule_circ_duration'$$;
-   EXECUTE $$COPY config.rule_age_hold_protect TO '$$ ||  dir || $$/config_rule_age_hold_protect'$$;
-   EXECUTE $$COPY config.rule_max_fine TO '$$ ||  dir || $$/config_rule_max_fine'$$;
-   EXECUTE $$COPY config.rule_recurring_fine TO '$$ ||  dir || $$/config_rule_recurring_fine'$$;
-   EXECUTE $$COPY permission.grp_tree TO '$$ ||  dir || $$/permission_grp_tree'$$;
+           $$) TO '$$ ||  dir || $$/m_asset_call_number_suffix'$$;
+   EXECUTE $$COPY config.rule_circ_duration TO '$$ ||  dir || $$/m_config_rule_circ_duration'$$;
+   EXECUTE $$COPY config.rule_age_hold_protect TO '$$ ||  dir || $$/m_config_rule_age_hold_protect'$$;
+   EXECUTE $$COPY config.rule_max_fine TO '$$ ||  dir || $$/m_config_rule_max_fine'$$;
+   EXECUTE $$COPY config.rule_recurring_fine TO '$$ ||  dir || $$/m_config_rule_recurring_fine'$$;
+   EXECUTE $$COPY permission.grp_tree TO '$$ ||  dir || $$/m_permission_grp_tree'$$;
 END;
 $FUNC$ LANGUAGE PLPGSQL;
 
 CREATE OR REPLACE FUNCTION migration_tools.simple_import_library_config(dir TEXT) RETURNS VOID AS $FUNC$
 BEGIN
-   EXECUTE $$COPY actor.hours_of_operation FROM '$$ ||  dir || $$/actor_hours_of_operation'$$;
-   EXECUTE $$COPY actor.org_unit_closed (org_unit, close_start, close_end, reason) FROM '$$ ||  dir || $$/actor_org_unit_closed'$$;
-   EXECUTE $$COPY actor.org_unit_setting (org_unit, name, value) FROM '$$ ||  dir || $$/actor_org_unit_setting'$$;
-   EXECUTE $$COPY asset.copy_location (name, owning_lib, holdable, hold_verify, opac_visible, circulate) FROM '$$ ||  dir || $$/asset_copy_location'$$;
-   EXECUTE $$COPY permission.grp_penalty_threshold (grp, org_unit, penalty, threshold) FROM '$$ ||  dir || $$/permission_grp_penalty_threshold'$$;
-   EXECUTE $$COPY asset.call_number_prefix (owning_lib, label, label_sortkey) FROM '$$ ||  dir || $$/asset_call_number_prefix'$$;
-   EXECUTE $$COPY asset.call_number_suffix (owning_lib, label, label_sortkey) FROM '$$ ||  dir || $$/asset_call_number_suffix'$$;
+   EXECUTE $$COPY actor.hours_of_operation FROM '$$ ||  dir || $$/m_actor_hours_of_operation'$$;
+   EXECUTE $$COPY actor.org_unit_closed (org_unit, close_start, close_end, reason) FROM '$$ ||  dir || $$/m_actor_org_unit_closed'$$;
+   EXECUTE $$COPY actor.org_unit_setting (org_unit, name, value) FROM '$$ ||  dir || $$/m_actor_org_unit_setting'$$;
+   EXECUTE $$COPY asset.copy_location (name, owning_lib, holdable, hold_verify, opac_visible, circulate) FROM '$$ ||  dir || $$/m_asset_copy_location'$$;
+   EXECUTE $$COPY permission.grp_penalty_threshold (grp, org_unit, penalty, threshold) FROM '$$ ||  dir || $$/m_permission_grp_penalty_threshold'$$;
+   EXECUTE $$COPY asset.call_number_prefix (owning_lib, label, label_sortkey) FROM '$$ ||  dir || $$/m_asset_call_number_prefix'$$;
+   EXECUTE $$COPY asset.call_number_suffix (owning_lib, label, label_sortkey) FROM '$$ ||  dir || $$/m_asset_call_number_suffix'$$;
 
    -- import any new circ rules
    PERFORM migration_tools.simple_import_new_rows_by_value(dir, 'config', 'rule_circ_duration', 'id', 'name');
@@ -816,3 +816,1347 @@ CREATE OR REPLACE FUNCTION migration_tools.find_circ_matrix_matchpoint (INTEGER)
         )
     );
 $$ LANGUAGE SQL;
+
+-- set a new salted password
+
+CREATE OR REPLACE FUNCTION migration_tools.set_salted_passwd(INTEGER,TEXT) RETURNS BOOLEAN AS $$
+    DECLARE
+        usr_id              ALIAS FOR $1;
+        plain_passwd        ALIAS FOR $2;
+        plain_salt          TEXT;
+        md5_passwd          TEXT;
+    BEGIN
+
+        SELECT actor.create_salt('main') INTO plain_salt;
+
+        SELECT MD5(plain_passwd) INTO md5_passwd;
+        
+        PERFORM actor.set_passwd(usr_id, 'main', MD5(plain_salt || md5_passwd), plain_salt);
+
+        RETURN TRUE;
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- internal function for handle_shelf
+
+CREATE OR REPLACE FUNCTION migration_tools._handle_shelf (TEXT,TEXT,TEXT,INTEGER,BOOLEAN) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        org_shortname ALIAS FOR $3;
+        org_range ALIAS FOR $4;
+        make_assertion ALIAS FOR $5;
+        proceed BOOLEAN;
+        org INTEGER;
+        -- if x_org is on the mapping table, it'll take precedence over the passed org_shortname param
+        -- though we'll still use the passed org for the full path traversal when needed
+        x_org_found BOOLEAN;
+        x_org INTEGER;
+        org_list INTEGER[];
+        o INTEGER;
+        row_count NUMERIC;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''desired_shelf''
+        )' INTO proceed USING table_schema, table_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column desired_shelf';
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''x_org''
+        )' INTO x_org_found USING table_schema, table_name;
+
+        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
+        IF org IS NULL THEN
+            RAISE EXCEPTION 'Cannot find org by shortname';
+        END IF;
+
+        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_shelf';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_shelf INTEGER';
+
+        IF x_org_found THEN
+            RAISE INFO 'Found x_org column';
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_shelf = b.id FROM m_asset_copy_location b'
+                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
+                || ' AND b.owning_lib = x_org'
+                || ' AND NOT b.deleted';
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_shelf = b.id FROM asset.copy_location b'
+                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
+                || ' AND b.owning_lib = x_org'
+                || ' AND x_shelf IS NULL'
+                || ' AND NOT b.deleted';
+        ELSE
+            RAISE INFO 'Did not find x_org column';
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_shelf = b.id FROM m_asset_copy_location b'
+                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
+                || ' AND b.owning_lib = $1'
+                || ' AND NOT b.deleted'
+            USING org;
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_shelf = b.id FROM m_asset_copy_location b'
+                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
+                || ' AND b.owning_lib = $1'
+                || ' AND x_shelf IS NULL'
+                || ' AND NOT b.deleted'
+            USING org;
+        END IF;
+
+        FOREACH o IN ARRAY org_list LOOP
+            RAISE INFO 'Considering org %', o;
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_shelf = b.id FROM asset.copy_location b'
+                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
+                || ' AND b.owning_lib = $1 AND x_shelf IS NULL'
+                || ' AND NOT b.deleted'
+            USING o;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            RAISE INFO 'Updated % rows', row_count;
+        END LOOP;
+
+        IF make_assertion THEN
+            EXECUTE 'SELECT migration_tools.assert(
+                NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_shelf <> '''' AND x_shelf IS NULL),
+                ''Cannot find a desired location'',
+                ''Found all desired locations''
+            );';
+        END IF;
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience functions for handling copy_location maps
+CREATE OR REPLACE FUNCTION migration_tools.handle_shelf (TEXT,TEXT,TEXT,INTEGER) RETURNS VOID AS $$
+    SELECT migration_tools._handle_shelf($1,$2,$3,$4,TRUE);
+$$ LANGUAGE SQL;
+
+-- convenience functions for handling circmod maps
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_circmod (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''desired_circmod''
+        )' INTO proceed USING table_schema, table_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column desired_circmod'; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_circmod';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_circmod TEXT';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_circmod = code FROM config.circ_modifier b'
+            || ' WHERE BTRIM(UPPER(a.desired_circmod)) = BTRIM(UPPER(b.code))';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_circmod = code FROM config.circ_modifier b'
+            || ' WHERE BTRIM(UPPER(a.desired_circmod)) = BTRIM(UPPER(b.name))'
+            || ' AND x_circmod IS NULL';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_circmod = code FROM config.circ_modifier b'
+            || ' WHERE BTRIM(UPPER(a.desired_circmod)) = BTRIM(UPPER(b.description))'
+            || ' AND x_circmod IS NULL';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_circmod <> '''' AND x_circmod IS NULL),
+            ''Cannot find a desired circulation modifier'',
+            ''Found all desired circulation modifiers''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience functions for handling item status maps
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_status (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''desired_status''
+        )' INTO proceed USING table_schema, table_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column desired_status'; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_status';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_status INTEGER';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_status = id FROM config.copy_status b'
+            || ' WHERE BTRIM(UPPER(a.desired_status)) = BTRIM(UPPER(b.name))';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_status <> '''' AND x_status IS NULL),
+            ''Cannot find a desired copy status'',
+            ''Found all desired copy statuses''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience functions for handling org maps
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_org (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''desired_org''
+        )' INTO proceed USING table_schema, table_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column desired_org'; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_org';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_org INTEGER';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_org = b.id FROM actor.org_unit b'
+            || ' WHERE BTRIM(a.desired_org) = BTRIM(b.shortname)';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_org <> '''' AND x_org IS NULL),
+            ''Cannot find a desired org unit'',
+            ''Found all desired org units''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for handling desired_not_migrate
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_not_migrate (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''desired_not_migrate''
+        )' INTO proceed USING table_schema, table_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column desired_not_migrate'; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_migrate';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_migrate BOOLEAN';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_migrate = CASE'
+            || ' WHEN BTRIM(desired_not_migrate) = ''TRUE'' THEN FALSE'
+            || ' WHEN BTRIM(desired_not_migrate) = ''DNM'' THEN FALSE'
+            || ' WHEN BTRIM(desired_not_migrate) = ''Do Not Migrate'' THEN FALSE'
+            || ' WHEN BTRIM(desired_not_migrate) = ''FALSE'' THEN TRUE'
+            || ' WHEN BTRIM(desired_not_migrate) = ''Migrate'' THEN TRUE'
+            || ' WHEN BTRIM(desired_not_migrate) = '''' THEN TRUE'
+            || ' END';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE x_migrate IS NULL),
+            ''Not all desired_not_migrate values understood'',
+            ''All desired_not_migrate values understood''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for handling desired_not_migrate
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_barred_or_blocked (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''desired_barred_or_blocked''
+        )' INTO proceed USING table_schema, table_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column desired_barred_or_blocked'; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_barred';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_barred BOOLEAN';
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_blocked';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_blocked BOOLEAN';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_barred = CASE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Barred'' THEN TRUE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Blocked'' THEN FALSE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Neither'' THEN FALSE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = '''' THEN FALSE'
+            || ' END';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_blocked = CASE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Blocked'' THEN TRUE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Barred'' THEN FALSE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Neither'' THEN FALSE'
+            || ' WHEN BTRIM(desired_barred_or_blocked) = '''' THEN FALSE'
+            || ' END';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE x_barred IS NULL or x_blocked IS NULL),
+            ''Not all desired_barred_or_blocked values understood'',
+            ''All desired_barred_or_blocked values understood''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for handling desired_profile
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_profile (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = ''desired_profile''
+        )' INTO proceed USING table_schema, table_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column desired_profile'; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_profile';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_profile INTEGER';
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+            || ' SET x_profile = b.id FROM permission.grp_tree b'
+            || ' WHERE BTRIM(UPPER(a.desired_profile)) = BTRIM(UPPER(b.name))';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_profile <> '''' AND x_profile IS NULL),
+            ''Cannot find a desired profile'',
+            ''Found all desired profiles''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for handling desired actor stat cats
+
+CREATE OR REPLACE FUNCTION migration_tools.vivicate_actor_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
+        org_shortname ALIAS FOR $4;
+        proceed BOOLEAN;
+        org INTEGER;
+        org_list INTEGER[];
+        sc TEXT;
+        sce TEXT;
+    BEGIN
+
+        SELECT 'desired_sc' || field_suffix INTO sc;
+        SELECT 'desired_sce' || field_suffix INTO sce;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sc;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sc; 
+        END IF;
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sce;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sce; 
+        END IF;
+
+        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
+        IF org IS NULL THEN
+            RAISE EXCEPTION 'Cannot find org by shortname';
+        END IF;
+        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
+
+        -- caller responsible for their own truncates though we try to prevent duplicates
+        EXECUTE 'INSERT INTO m_actor_stat_cat (owner, name)
+            SELECT DISTINCT
+                 $1
+                ,BTRIM('||sc||')
+            FROM 
+                ' || quote_ident(table_name) || '
+            WHERE
+                NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM actor.stat_cat
+                    WHERE owner = ANY ($2)
+                    AND name = BTRIM('||sc||')
+                )
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM m_actor_stat_cat
+                    WHERE owner = ANY ($2)
+                    AND name = BTRIM('||sc||')
+                )
+            ORDER BY 2;'
+        USING org, org_list;
+
+        EXECUTE 'INSERT INTO m_actor_stat_cat_entry (stat_cat, owner, value)
+            SELECT DISTINCT
+                COALESCE(
+                    (SELECT id
+                        FROM actor.stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name))
+                   ,(SELECT id
+                        FROM m_actor_stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name))
+                )
+                ,$1
+                ,BTRIM('||sce||')
+            FROM 
+                ' || quote_ident(table_name) || '
+            WHERE
+                    NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
+                AND NULLIF(BTRIM('||sce||'),'''') IS NOT NULL
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM actor.stat_cat_entry
+                    WHERE stat_cat = (
+                        SELECT id
+                        FROM actor.stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name)
+                    ) AND value = BTRIM('||sce||')
+                    AND owner = ANY ($2)
+                )
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM m_actor_stat_cat_entry
+                    WHERE stat_cat = (
+                        SELECT id
+                        FROM m_actor_stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name)
+                    ) AND value = BTRIM('||sce||')
+                    AND owner = ANY ($2)
+                )
+            ORDER BY 1,3;'
+        USING org, org_list;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_actor_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
+        org_shortname ALIAS FOR $4;
+        proceed BOOLEAN;
+        org INTEGER;
+        org_list INTEGER[];
+        o INTEGER;
+        sc TEXT;
+        sce TEXT;
+    BEGIN
+        SELECT 'desired_sc' || field_suffix INTO sc;
+        SELECT 'desired_sce' || field_suffix INTO sce;
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sc;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sc; 
+        END IF;
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sce;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sce; 
+        END IF;
+
+        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
+        IF org IS NULL THEN
+            RAISE EXCEPTION 'Cannot find org by shortname';
+        END IF;
+
+        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_sc' || field_suffix;
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_sc' || field_suffix || ' INTEGER';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_sce' || field_suffix;
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_sce' || field_suffix || ' INTEGER';
+
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
+            SET
+                x_sc' || field_suffix || ' = id
+            FROM
+                (SELECT id, name, owner FROM m_actor_stat_cat
+                    UNION SELECT id, name, owner FROM actor.stat_cat) u
+            WHERE
+                    BTRIM(UPPER(u.name)) = BTRIM(UPPER(' || sc || '))
+                AND u.owner = ANY ($1);'
+        USING org_list;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
+            SET
+                x_sce' || field_suffix || ' = id
+            FROM
+                (SELECT id, stat_cat, owner, value FROM m_actor_stat_cat_entry
+                    UNION SELECT id, stat_cat, owner, value FROM actor.stat_cat_entry) u
+            WHERE
+                    u.stat_cat = x_sc' || field_suffix || '
+                AND BTRIM(UPPER(u.value)) = BTRIM(UPPER(' || sce || '))
+                AND u.owner = ANY ($1);'
+        USING org_list;
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sc' || field_suffix || ' <> '''' AND x_sc' || field_suffix || ' IS NULL),
+            ''Cannot find a desired stat cat'',
+            ''Found all desired stat cats''
+        );';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sce' || field_suffix || ' <> '''' AND x_sce' || field_suffix || ' IS NULL),
+            ''Cannot find a desired stat cat entry'',
+            ''Found all desired stat cat entries''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience functions for adding shelving locations
+DROP FUNCTION IF EXISTS migration_tools.find_shelf(INT,TEXT);
+CREATE OR REPLACE FUNCTION migration_tools.find_shelf(org_id INT, shelf_name TEXT) RETURNS INTEGER AS $$
+DECLARE
+    return_id   INT;
+    d           INT;
+    cur_id      INT;
+BEGIN
+    SELECT INTO d MAX(distance) FROM actor.org_unit_ancestors_distance(org_id);
+    WHILE d >= 0
+    LOOP
+        SELECT INTO cur_id id FROM actor.org_unit_ancestor_at_depth(org_id,d);
+        SELECT INTO return_id id FROM asset.copy_location WHERE owning_lib = cur_id AND name ILIKE shelf_name;
+        IF return_id IS NOT NULL THEN
+                RETURN return_id;
+        END IF;
+        d := d - 1;
+    END LOOP;
+
+    RETURN NULL;
+END
+$$ LANGUAGE plpgsql;
+
+-- may remove later but testing using this with new migration scripts and not loading acls until go live
+
+DROP FUNCTION IF EXISTS migration_tools.find_mig_shelf(INT,TEXT);
+CREATE OR REPLACE FUNCTION migration_tools.find_mig_shelf(org_id INT, shelf_name TEXT) RETURNS INTEGER AS $$
+DECLARE
+    return_id   INT;
+    d           INT;
+    cur_id      INT;
+BEGIN
+    SELECT INTO d MAX(distance) FROM actor.org_unit_ancestors_distance(org_id);
+    WHILE d >= 0
+    LOOP
+        SELECT INTO cur_id id FROM actor.org_unit_ancestor_at_depth(org_id,d);
+        
+        SELECT INTO return_id id FROM 
+            (SELECT * FROM asset.copy_location UNION ALL SELECT * FROM m_asset_copy_location) x
+            WHERE owning_lib = cur_id AND name ILIKE shelf_name;
+        IF return_id IS NOT NULL THEN
+                RETURN return_id;
+        END IF;
+        d := d - 1;
+    END LOOP;
+
+    RETURN NULL;
+END
+$$ LANGUAGE plpgsql;
+
+-- convenience function for linking to the item staging table
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_item_barcode (TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        foreign_column_name ALIAS FOR $3;
+        main_column_name ALIAS FOR $4;
+        btrim_desired ALIAS FOR $5;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, foreign_column_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_name, foreign_column_name; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = ''m_asset_copy_legacy''
+            and column_name = $2
+        )' INTO proceed USING table_schema, main_column_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'No %.m_asset_copy_legacy with column %', table_schema, main_column_name; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_item';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_item BIGINT';
+
+        IF btrim_desired THEN
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_item = b.id FROM m_asset_copy_legacy b'
+                || ' WHERE BTRIM(a.' || quote_ident(foreign_column_name)
+                || ') = BTRIM(b.' || quote_ident(main_column_name) || ')';
+        ELSE
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_item = b.id FROM m_asset_copy_legacy b'
+                || ' WHERE a.' || quote_ident(foreign_column_name)
+                || ' = b.' || quote_ident(main_column_name);
+        END IF;
+
+        --EXECUTE 'SELECT migration_tools.assert(
+        --    NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(foreign_column_name) || ' <> '''' AND x_item IS NULL),
+        --    ''Cannot link every barcode'',
+        --    ''Every barcode linked''
+        --);';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for linking to the user staging table
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_user_barcode (TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        foreign_column_name ALIAS FOR $3;
+        main_column_name ALIAS FOR $4;
+        btrim_desired ALIAS FOR $5;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, foreign_column_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_name, foreign_column_name; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = ''m_actor_usr_legacy''
+            and column_name = $2
+        )' INTO proceed USING table_schema, main_column_name;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'No %.m_actor_usr_legacy with column %', table_schema, main_column_name; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_user';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_user INTEGER';
+
+        IF btrim_desired THEN
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_user = b.id FROM m_actor_usr_legacy b'
+                || ' WHERE BTRIM(a.' || quote_ident(foreign_column_name)
+                || ') = BTRIM(b.' || quote_ident(main_column_name) || ')';
+        ELSE
+            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
+                || ' SET x_user = b.id FROM m_actor_usr_legacy b'
+                || ' WHERE a.' || quote_ident(foreign_column_name)
+                || ' = b.' || quote_ident(main_column_name);
+        END IF;
+
+        --EXECUTE 'SELECT migration_tools.assert(
+        --    NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(foreign_column_name) || ' <> '''' AND x_user IS NULL),
+        --    ''Cannot link every barcode'',
+        --    ''Every barcode linked''
+        --);';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for handling desired asset stat cats
+
+CREATE OR REPLACE FUNCTION migration_tools.vivicate_asset_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
+        org_shortname ALIAS FOR $4;
+        proceed BOOLEAN;
+        org INTEGER;
+        org_list INTEGER[];
+        sc TEXT;
+        sce TEXT;
+    BEGIN
+
+        SELECT 'desired_sc' || field_suffix INTO sc;
+        SELECT 'desired_sce' || field_suffix INTO sce;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sc;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sc; 
+        END IF;
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sce;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sce; 
+        END IF;
+
+        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
+        IF org IS NULL THEN
+            RAISE EXCEPTION 'Cannot find org by shortname';
+        END IF;
+        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
+
+        -- caller responsible for their own truncates though we try to prevent duplicates
+        EXECUTE 'INSERT INTO m_asset_stat_cat (owner, name)
+            SELECT DISTINCT
+                 $1
+                ,BTRIM('||sc||')
+            FROM 
+                ' || quote_ident(table_name) || '
+            WHERE
+                NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM asset.stat_cat
+                    WHERE owner = ANY ($2)
+                    AND name = BTRIM('||sc||')
+                )
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM m_asset_stat_cat
+                    WHERE owner = ANY ($2)
+                    AND name = BTRIM('||sc||')
+                )
+            ORDER BY 2;'
+        USING org, org_list;
+
+        EXECUTE 'INSERT INTO m_asset_stat_cat_entry (stat_cat, owner, value)
+            SELECT DISTINCT
+                COALESCE(
+                    (SELECT id
+                        FROM asset.stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name))
+                   ,(SELECT id
+                        FROM m_asset_stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name))
+                )
+                ,$1
+                ,BTRIM('||sce||')
+            FROM 
+                ' || quote_ident(table_name) || '
+            WHERE
+                    NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
+                AND NULLIF(BTRIM('||sce||'),'''') IS NOT NULL
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM asset.stat_cat_entry
+                    WHERE stat_cat = (
+                        SELECT id
+                        FROM asset.stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name)
+                    ) AND value = BTRIM('||sce||')
+                    AND owner = ANY ($2)
+                )
+                AND NOT EXISTS (
+                    SELECT id
+                    FROM m_asset_stat_cat_entry
+                    WHERE stat_cat = (
+                        SELECT id
+                        FROM m_asset_stat_cat
+                        WHERE owner = ANY ($2)
+                        AND BTRIM('||sc||') = BTRIM(name)
+                    ) AND value = BTRIM('||sce||')
+                    AND owner = ANY ($2)
+                )
+            ORDER BY 1,3;'
+        USING org, org_list;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_asset_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_name ALIAS FOR $2;
+        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
+        org_shortname ALIAS FOR $4;
+        proceed BOOLEAN;
+        org INTEGER;
+        org_list INTEGER[];
+        o INTEGER;
+        sc TEXT;
+        sce TEXT;
+    BEGIN
+        SELECT 'desired_sc' || field_suffix INTO sc;
+        SELECT 'desired_sce' || field_suffix INTO sce;
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sc;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sc; 
+        END IF;
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_name, sce;
+        IF NOT proceed THEN
+            RAISE EXCEPTION 'Missing column %', sce; 
+        END IF;
+
+        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
+        IF org IS NULL THEN
+            RAISE EXCEPTION 'Cannot find org by shortname';
+        END IF;
+
+        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_sc' || field_suffix;
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_sc' || field_suffix || ' INTEGER';
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' DROP COLUMN IF EXISTS x_sce' || field_suffix;
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_name)
+            || ' ADD COLUMN x_sce' || field_suffix || ' INTEGER';
+
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
+            SET
+                x_sc' || field_suffix || ' = id
+            FROM
+                (SELECT id, name, owner FROM m_asset_stat_cat
+                    UNION SELECT id, name, owner FROM asset.stat_cat) u
+            WHERE
+                    BTRIM(UPPER(u.name)) = BTRIM(UPPER(' || sc || '))
+                AND u.owner = ANY ($1);'
+        USING org_list;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
+            SET
+                x_sce' || field_suffix || ' = id
+            FROM
+                (SELECT id, stat_cat, owner, value FROM m_asset_stat_cat_entry
+                    UNION SELECT id, stat_cat, owner, value FROM asset.stat_cat_entry) u
+            WHERE
+                    u.stat_cat = x_sc' || field_suffix || '
+                AND BTRIM(UPPER(u.value)) = BTRIM(UPPER(' || sce || '))
+                AND u.owner = ANY ($1);'
+        USING org_list;
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sc' || field_suffix || ' <> '''' AND x_sc' || field_suffix || ' IS NULL),
+            ''Cannot find a desired stat cat'',
+            ''Found all desired stat cats''
+        );';
+
+        EXECUTE 'SELECT migration_tools.assert(
+            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sce' || field_suffix || ' <> '''' AND x_sce' || field_suffix || ' IS NULL),
+            ''Cannot find a desired stat cat entry'',
+            ''Found all desired stat cat entries''
+        );';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for handling item barcode collisions in m_asset_copy_legacy
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_asset_barcode_collisions(migration_schema TEXT) RETURNS VOID AS $function$
+DECLARE
+    x_barcode TEXT;
+    x_id BIGINT;
+    row_count NUMERIC;
+    internal_collision_count NUMERIC := 0;
+    incumbent_collision_count NUMERIC := 0;
+BEGIN
+    FOR x_barcode IN SELECT barcode FROM m_asset_copy_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
+    LOOP
+        FOR x_id IN SELECT id FROM m_asset_copy WHERE barcode = x_barcode
+        LOOP
+            UPDATE m_asset_copy SET barcode = migration_schema || '_internal_collision_' || id || '_' || barcode WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            internal_collision_count := internal_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% internal collisions', internal_collision_count;
+    FOR x_barcode IN SELECT a.barcode FROM asset.copy a, m_asset_copy_legacy b WHERE x_migrate AND a.deleted IS FALSE AND a.barcode = b.barcode
+    LOOP
+        FOR x_id IN SELECT id FROM m_asset_copy_legacy WHERE barcode = x_barcode
+        LOOP
+            UPDATE m_asset_copy_legacy SET barcode = migration_schema || '_incumbent_collision_' || id || '_' || barcode WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            incumbent_collision_count := incumbent_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% incumbent collisions', incumbent_collision_count;
+END
+$function$ LANGUAGE plpgsql;
+
+-- convenience function for handling patron barcode/usrname collisions in m_actor_usr_legacy
+-- this should be ran prior to populating m_actor_card
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_actor_barcode_collisions(migration_schema TEXT) RETURNS VOID AS $function$
+DECLARE
+    x_barcode TEXT;
+    x_id BIGINT;
+    row_count NUMERIC;
+    internal_collision_count NUMERIC := 0;
+    incumbent_barcode_collision_count NUMERIC := 0;
+    incumbent_usrname_collision_count NUMERIC := 0;
+BEGIN
+    FOR x_barcode IN SELECT usrname FROM m_actor_usr_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
+    LOOP
+        FOR x_id IN SELECT id FROM m_actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
+        LOOP
+            UPDATE m_actor_usr_legacy SET usrname = migration_schema || '_internal_collision_' || id || '_' || usrname WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            internal_collision_count := internal_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% internal usrname/barcode collisions', internal_collision_count;
+
+    FOR x_barcode IN
+        SELECT a.barcode FROM actor.card a, m_actor_usr_legacy b WHERE x_migrate AND a.barcode = b.usrname
+    LOOP
+        FOR x_id IN SELECT DISTINCT id FROM m_actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
+        LOOP
+            UPDATE m_actor_usr_legacy SET usrname = migration_schema || '_incumbent_barcode_collision_' || id || '_' || usrname WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            incumbent_barcode_collision_count := incumbent_barcode_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% incumbent barcode collisions', incumbent_barcode_collision_count;
+
+    FOR x_barcode IN
+        SELECT a.usrname FROM actor.usr a, m_actor_usr_legacy b WHERE x_migrate AND a.usrname = b.usrname
+    LOOP
+        FOR x_id IN SELECT DISTINCT id FROM m_actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
+        LOOP
+            UPDATE m_actor_usr_legacy SET usrname = migration_schema || '_incumbent_usrname_collision_' || id || '_' || usrname WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            incumbent_usrname_collision_count := incumbent_usrname_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% incumbent usrname collisions (post barcode collision munging)', incumbent_usrname_collision_count;
+END
+$function$ LANGUAGE plpgsql;
+
+-- alternate version: convenience function for handling item barcode collisions in m_asset_copy_legacy
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_asset_barcode_collisions2(migration_schema TEXT) RETURNS VOID AS $function$
+DECLARE
+    x_barcode TEXT;
+    x_id BIGINT;
+    row_count NUMERIC;
+    internal_collision_count NUMERIC := 0;
+    incumbent_collision_count NUMERIC := 0;
+BEGIN
+    FOR x_barcode IN SELECT barcode FROM m_asset_copy_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
+    LOOP
+        FOR x_id IN SELECT id FROM m_asset_copy WHERE barcode = x_barcode
+        LOOP
+            UPDATE m_asset_copy SET barcode = migration_schema || '_internal_collision_' || id || '_' || barcode WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            internal_collision_count := internal_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% internal collisions', internal_collision_count;
+    FOR x_barcode IN SELECT a.barcode FROM asset.copy a, m_asset_copy_legacy b WHERE x_migrate AND a.deleted IS FALSE AND a.barcode = b.barcode
+    LOOP
+        FOR x_id IN SELECT id FROM m_asset_copy_legacy WHERE barcode = x_barcode
+        LOOP
+            UPDATE m_asset_copy_legacy SET barcode = migration_schema || '_' || barcode WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            incumbent_collision_count := incumbent_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% incumbent collisions', incumbent_collision_count;
+END
+$function$ LANGUAGE plpgsql;
+
+-- alternate version: convenience function for handling patron barcode/usrname collisions in m_actor_usr_legacy
+-- this should be ran prior to populating m_actor_card
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_actor_barcode_collisions2(migration_schema TEXT) RETURNS VOID AS $function$
+DECLARE
+    x_barcode TEXT;
+    x_id BIGINT;
+    row_count NUMERIC;
+    internal_collision_count NUMERIC := 0;
+    incumbent_barcode_collision_count NUMERIC := 0;
+    incumbent_usrname_collision_count NUMERIC := 0;
+BEGIN
+    FOR x_barcode IN SELECT usrname FROM m_actor_usr_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
+    LOOP
+        FOR x_id IN SELECT id FROM m_actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
+        LOOP
+            UPDATE m_actor_usr_legacy SET usrname = migration_schema || '_internal_collision_' || id || '_' || usrname WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            internal_collision_count := internal_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% internal usrname/barcode collisions', internal_collision_count;
+
+    FOR x_barcode IN
+        SELECT a.barcode FROM actor.card a, m_actor_usr_legacy b WHERE x_migrate AND a.barcode = b.usrname
+    LOOP
+        FOR x_id IN SELECT DISTINCT id FROM m_actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
+        LOOP
+            UPDATE m_actor_usr_legacy SET usrname = migration_schema || '_' || usrname WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            incumbent_barcode_collision_count := incumbent_barcode_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% incumbent barcode collisions', incumbent_barcode_collision_count;
+
+    FOR x_barcode IN
+        SELECT a.usrname FROM actor.usr a, m_actor_usr_legacy b WHERE x_migrate AND a.usrname = b.usrname
+    LOOP
+        FOR x_id IN SELECT DISTINCT id FROM m_actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
+        LOOP
+            UPDATE m_actor_usr_legacy SET usrname = migration_schema || '_' || usrname WHERE id = x_id;
+            GET DIAGNOSTICS row_count = ROW_COUNT;
+            incumbent_usrname_collision_count := incumbent_usrname_collision_count + row_count;
+        END LOOP;
+    END LOOP;
+    RAISE INFO '% incumbent usrname collisions (post barcode collision munging)', incumbent_usrname_collision_count;
+END
+$function$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION migration_tools.is_circ_rule_safe_to_delete( test_matchpoint INTEGER ) RETURNS BOOLEAN AS $func$
+-- WARNING: Use at your own risk
+-- FIXME: not considering marc_type, marc_form, marc_bib_level, marc_vr_format, usr_age_lower_bound, usr_age_upper_bound, item_age
+DECLARE
+    item_object asset.copy%ROWTYPE;
+    user_object actor.usr%ROWTYPE;
+    test_rule_object config.circ_matrix_matchpoint%ROWTYPE;
+    result_rule_object config.circ_matrix_matchpoint%ROWTYPE;
+    safe_to_delete BOOLEAN := FALSE;
+    m action.found_circ_matrix_matchpoint;
+    n action.found_circ_matrix_matchpoint;
+    -- ( success BOOL, matchpoint config.circ_matrix_matchpoint, buildrows INT[] )
+    result_matchpoint INTEGER;
+BEGIN
+    SELECT INTO test_rule_object * FROM config.circ_matrix_matchpoint WHERE id = test_matchpoint;
+    RAISE INFO 'testing rule: %', test_rule_object;
+
+    INSERT INTO actor.usr (
+        profile,
+        usrname,
+        passwd,
+        ident_type,
+        first_given_name,
+        family_name,
+        home_ou,
+        juvenile
+    ) SELECT
+        COALESCE(test_rule_object.grp, 2),
+        'is_circ_rule_safe_to_delete_' || test_matchpoint || '_' || NOW()::text,
+        MD5(NOW()::TEXT),
+        1,
+        'Ima',
+        'Test',
+        COALESCE(test_rule_object.user_home_ou, test_rule_object.org_unit),
+        COALESCE(test_rule_object.juvenile_flag, FALSE)
+    ;
+    
+    SELECT INTO user_object * FROM actor.usr WHERE id = currval('actor.usr_id_seq');
+
+    INSERT INTO asset.call_number (
+        creator,
+        editor,
+        record,
+        owning_lib,
+        label,
+        label_class
+    ) SELECT
+        1,
+        1,
+        -1,
+        COALESCE(test_rule_object.copy_owning_lib,test_rule_object.org_unit),
+        'is_circ_rule_safe_to_delete_' || test_matchpoint || '_' || NOW()::text,
+        1
+    ;
+
+    INSERT INTO asset.copy (
+        barcode,
+        circ_lib,
+        creator,
+        call_number,
+        editor,
+        location,
+        loan_duration,
+        fine_level,
+        ref,
+        circ_modifier
+    ) SELECT
+        'is_circ_rule_safe_to_delete_' || test_matchpoint || '_' || NOW()::text,
+        COALESCE(test_rule_object.copy_circ_lib,test_rule_object.org_unit),
+        1,
+        currval('asset.call_number_id_seq'),
+        1,
+        COALESCE(test_rule_object.copy_location,1),
+        2,
+        2,
+        COALESCE(test_rule_object.ref_flag,FALSE),
+        test_rule_object.circ_modifier
+    ;
+
+    SELECT INTO item_object * FROM asset.copy WHERE id = currval('asset.copy_id_seq');
+
+    SELECT INTO m * FROM action.find_circ_matrix_matchpoint(
+        test_rule_object.org_unit,
+        item_object,
+        user_object,
+        COALESCE(test_rule_object.is_renewal,FALSE)
+    );
+    RAISE INFO '   action.find_circ_matrix_matchpoint(%,%,%,%) = (%,%,%)',
+        test_rule_object.org_unit,
+        item_object.id,
+        user_object.id,
+        COALESCE(test_rule_object.is_renewal,FALSE),
+        m.success,
+        m.matchpoint,
+        m.buildrows
+    ;
+
+    --  disable the rule being tested to see if the outcome changes
+    UPDATE config.circ_matrix_matchpoint SET active = FALSE WHERE id = (m.matchpoint).id;
+
+    SELECT INTO n * FROM action.find_circ_matrix_matchpoint(
+        test_rule_object.org_unit,
+        item_object,
+        user_object,
+        COALESCE(test_rule_object.is_renewal,FALSE)
+    );
+    RAISE INFO 'VS action.find_circ_matrix_matchpoint(%,%,%,%) = (%,%,%)',
+        test_rule_object.org_unit,
+        item_object.id,
+        user_object.id,
+        COALESCE(test_rule_object.is_renewal,FALSE),
+        n.success,
+        n.matchpoint,
+        n.buildrows
+    ;
+
+    -- FIXME: We could dig deeper and see if the referenced config.rule_*
+    -- entries are effectively equivalent, but for now, let's assume no
+    -- duplicate rules at that level
+    IF (
+            (m.matchpoint).circulate = (n.matchpoint).circulate
+        AND (m.matchpoint).duration_rule = (n.matchpoint).duration_rule
+        AND (m.matchpoint).recurring_fine_rule = (n.matchpoint).recurring_fine_rule
+        AND (m.matchpoint).max_fine_rule = (n.matchpoint).max_fine_rule
+        AND (
+                (m.matchpoint).hard_due_date = (n.matchpoint).hard_due_date
+                OR (
+                        (m.matchpoint).hard_due_date IS NULL
+                    AND (n.matchpoint).hard_due_date IS NULL
+                )
+        )
+        AND (
+                (m.matchpoint).renewals = (n.matchpoint).renewals
+                OR (
+                        (m.matchpoint).renewals IS NULL
+                    AND (n.matchpoint).renewals IS NULL
+                )
+        )
+        AND (
+                (m.matchpoint).grace_period = (n.matchpoint).grace_period
+                OR (
+                        (m.matchpoint).grace_period IS NULL
+                    AND (n.matchpoint).grace_period IS NULL
+                )
+        )
+        AND (
+                (m.matchpoint).total_copy_hold_ratio = (n.matchpoint).total_copy_hold_ratio
+                OR (
+                        (m.matchpoint).total_copy_hold_ratio IS NULL
+                    AND (n.matchpoint).total_copy_hold_ratio IS NULL
+                )
+        )
+        AND (
+                (m.matchpoint).available_copy_hold_ratio = (n.matchpoint).available_copy_hold_ratio
+                OR (
+                        (m.matchpoint).available_copy_hold_ratio IS NULL
+                    AND (n.matchpoint).available_copy_hold_ratio IS NULL
+                )
+        )
+        AND NOT EXISTS (
+            SELECT limit_set, fallthrough
+            FROM config.circ_matrix_limit_set_map
+            WHERE active and matchpoint = (m.matchpoint).id
+            EXCEPT
+            SELECT limit_set, fallthrough
+            FROM config.circ_matrix_limit_set_map
+            WHERE active and matchpoint = (n.matchpoint).id
+        )
+
+    ) THEN
+        RAISE INFO 'rule has same outcome';
+        safe_to_delete := TRUE;
+    ELSE
+        RAISE INFO 'rule has different outcome';
+        safe_to_delete := FALSE;
+    END IF;
+
+    RAISE EXCEPTION 'rollback the temporary changes';
+
+EXCEPTION WHEN OTHERS THEN
+
+    RAISE INFO 'inside exception block: %, %', SQLSTATE, SQLERRM;
+    RETURN safe_to_delete;
+
+END;
+$func$ LANGUAGE plpgsql;
+
index 41d8a01..e8c342a 100644 (file)
@@ -5,3 +5,84 @@ CREATE OR REPLACE FUNCTION migration_tools.is_blank (TEXT) RETURNS BOOLEAN AS $$
   END;
 $$ LANGUAGE PLPGSQL STRICT STABLE;
 
+DROP FUNCTION IF EXISTS migration_tools.btrim_lcolumns(TEXT,TEXT);
+CREATE OR REPLACE FUNCTION migration_tools.btrim_lcolumns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+    c_name     TEXT;
+BEGIN
+
+    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE 
+            table_name = t_name
+            AND table_schema = s_name
+            AND (data_type='text' OR data_type='character varying')
+            AND column_name like 'l_%'
+    LOOP
+       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = BTRIM(' || c_name || ')'); 
+    END LOOP;  
+
+    RETURN TRUE;
+END
+$function$;
+
+DROP FUNCTION IF EXISTS migration_tools.btrim_columns(TEXT,TEXT);
+CREATE OR REPLACE FUNCTION migration_tools.btrim_columns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+    c_name     TEXT;
+BEGIN
+
+    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE 
+            table_name = t_name
+            AND table_schema = s_name
+            AND (data_type='text' OR data_type='character varying')
+    LOOP
+       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = BTRIM(' || c_name || ')'); 
+    END LOOP;  
+
+    RETURN TRUE;
+END
+$function$;
+
+DROP FUNCTION IF EXISTS migration_tools.null_empty_lcolumns(TEXT,TEXT);
+CREATE OR REPLACE FUNCTION migration_tools.null_empty_lcolumns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+    c_name     TEXT;
+BEGIN
+
+    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE 
+            table_name = t_name
+            AND table_schema = s_name
+            AND (data_type='text' OR data_type='character varying')
+            AND column_name like 'l_%'
+    LOOP
+       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = NULL WHERE ' || c_name || ' = '''' '); 
+    END LOOP;  
+
+    RETURN TRUE;
+END
+$function$;
+
+DROP FUNCTION IF EXISTS migration_tools.null_empty_columns(TEXT,TEXT);
+CREATE OR REPLACE FUNCTION migration_tools.null_empty_columns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+    c_name     TEXT;
+BEGIN
+
+    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE
+            table_name = t_name
+            AND table_schema = s_name
+            AND (data_type='text' OR data_type='character varying')
+    LOOP
+       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = NULL WHERE ' || c_name || ' = '''' ');
+    END LOOP;
+
+    RETURN TRUE;
+END
+$function$;
index 3e8fc63..f2e7d77 100644 (file)
@@ -505,3 +505,456 @@ BEGIN
 END;
 
 $$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION migration_tools.log (TEXT,TEXT,INTEGER) RETURNS VOID AS $$
+    DECLARE
+        migration_schema ALIAS FOR $1;
+        sql ALIAS FOR $2;
+        nrows ALIAS FOR $3;
+    BEGIN
+        EXECUTE 'INSERT INTO ' || migration_schema || '.sql_log ( sql, row_count ) VALUES ( ' || quote_literal(sql) || ', ' || nrows || ' );';
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.exec (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        migration_schema ALIAS FOR $1;
+        sql ALIAS FOR $2;
+        nrows INTEGER;
+    BEGIN
+        EXECUTE 'UPDATE ' || migration_schema || '.sql_current SET sql = ' || quote_literal(sql) || ';';
+        --RAISE INFO '%', sql;
+        EXECUTE sql;
+        GET DIAGNOSTICS nrows = ROW_COUNT;
+        PERFORM migration_tools.log(migration_schema,sql,nrows);
+    EXCEPTION
+        WHEN OTHERS THEN 
+            RAISE EXCEPTION '!!!!!!!!!!! state = %, msg = %, sql = %', SQLSTATE, SQLERRM, sql;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.debug_exec (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        migration_schema ALIAS FOR $1;
+        sql ALIAS FOR $2;
+        nrows INTEGER;
+    BEGIN
+        EXECUTE 'UPDATE ' || migration_schema || '.sql_current SET sql = ' || quote_literal(sql) || ';';
+        RAISE INFO 'debug_exec sql = %', sql;
+        EXECUTE sql;
+        GET DIAGNOSTICS nrows = ROW_COUNT;
+        PERFORM migration_tools.log(migration_schema,sql,nrows);
+    EXCEPTION
+        WHEN OTHERS THEN 
+            RAISE EXCEPTION '!!!!!!!!!!! state = %, msg = %, sql = %', SQLSTATE, SQLERRM, sql;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.insert_base_into_production (TEXT) RETURNS VOID AS $$
+    DECLARE
+        migration_schema ALIAS FOR $1;
+        production_tables TEXT[];
+    BEGIN
+        --RAISE INFO 'In migration_tools.insert_into_production(%)', migration_schema;
+        SELECT migration_tools.production_tables(migration_schema) INTO STRICT production_tables;
+        FOR i IN array_lower(production_tables,1) .. array_upper(production_tables,1) LOOP
+            PERFORM migration_tools.insert_into_production(migration_schema,production_tables[i]);
+        END LOOP;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.insert_into_production (TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        migration_schema ALIAS FOR $1;
+        production_table ALIAS FOR $2;
+        base_staging_table TEXT;
+        columns RECORD;
+    BEGIN
+        base_staging_table = REPLACE( production_table, '.', '_' );
+        --RAISE INFO 'In migration_tools.insert_into_production(%,%) -> %', migration_schema, production_table, base_staging_table;
+        EXECUTE 'INSERT INTO ' || production_table || ' SELECT * FROM ' || migration_schema || '.' || base_staging_table || ';';
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- push bib sequence and return starting value for reserved range
+CREATE OR REPLACE FUNCTION migration_tools.push_bib_sequence(INTEGER) RETURNS BIGINT AS $$
+    DECLARE
+        bib_count ALIAS FOR $1;
+        output BIGINT;
+    BEGIN
+        PERFORM setval('biblio.record_entry_id_seq',(SELECT MAX(id) FROM biblio.record_entry) + bib_count + 2000);
+        FOR output IN
+            SELECT CEIL(MAX(id)/1000)*1000+1000 FROM biblio.record_entry WHERE id < (SELECT last_value FROM biblio.record_entry_id_seq)
+        LOOP
+            RETURN output;
+        END LOOP;
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for linking two tables
+-- e.g. select migration_tools.handle_link(:'migschema','asset_copy','barcode','test_foo','l_barcode','x_acp_id',false);
+CREATE OR REPLACE FUNCTION migration_tools.handle_link (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_x ALIAS FOR $6;
+        btrim_desired ALIAS FOR $7;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_b)
+            || ' DROP COLUMN IF EXISTS ' || quote_ident(column_x);
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_b)
+            || ' ADD COLUMN ' || quote_ident(column_x) || ' BIGINT';
+
+        IF btrim_desired THEN
+            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+                || ' SET ' || quote_ident(column_x) || ' = a.id FROM ' || quote_ident(table_a) || ' a'
+                || ' WHERE BTRIM(a.' || quote_ident(column_a)
+                || ') = BTRIM(b.' || quote_ident(column_b) || ')';
+        ELSE
+            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+                || ' SET ' || quote_ident(column_x) || ' = a.id FROM ' || quote_ident(table_a) || ' a'
+                || ' WHERE a.' || quote_ident(column_a)
+                || ' = b.' || quote_ident(column_b);
+        END IF;
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for linking two tables, but copying column w into column x instead of "id"
+-- e.g. select migration_tools.handle_link2(:'migschema','asset_copy','barcode','test_foo','l_barcode','id','x_acp_id',false);
+CREATE OR REPLACE FUNCTION migration_tools.handle_link2 (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_w ALIAS FOR $6;
+        column_x ALIAS FOR $7;
+        btrim_desired ALIAS FOR $8;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_b)
+            || ' DROP COLUMN IF EXISTS ' || quote_ident(column_x);
+        EXECUTE 'ALTER TABLE '
+            || quote_ident(table_b)
+            || ' ADD COLUMN ' || quote_ident(column_x) || ' TEXT';
+
+        IF btrim_desired THEN
+            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+                || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
+                || ' WHERE BTRIM(a.' || quote_ident(column_a)
+                || ') = BTRIM(b.' || quote_ident(column_b) || ')';
+        ELSE
+            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+                || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
+                || ' WHERE a.' || quote_ident(column_a)
+                || ' = b.' || quote_ident(column_b);
+        END IF;
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+-- convenience function for linking two tables, but copying column w into column x instead of "id". Unlike handle_link2, this one won't drop the target column, and it also doesn't have a final boolean argument for btrim
+-- e.g. select migration_tools.handle_link3(:'migschema','asset_copy','barcode','test_foo','l_barcode','id','x_acp_id');
+CREATE OR REPLACE FUNCTION migration_tools.handle_link3 (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_w ALIAS FOR $6;
+        column_x ALIAS FOR $7;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
+            || ' WHERE a.' || quote_ident(column_a)
+            || ' = b.' || quote_ident(column_b);
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_null_or_empty_string (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_w ALIAS FOR $6;
+        column_x ALIAS FOR $7;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
+            || ' WHERE a.' || quote_ident(column_a)
+            || ' = b.' || quote_ident(column_b)
+            || ' AND NULLIF(a.' || quote_ident(column_w) || ','''') IS NOT NULL';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_null (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_w ALIAS FOR $6;
+        column_x ALIAS FOR $7;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
+            || ' WHERE a.' || quote_ident(column_a)
+            || ' = b.' || quote_ident(column_b)
+            || ' AND a.' || quote_ident(column_w) || ' IS NOT NULL';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_true (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_w ALIAS FOR $6;
+        column_x ALIAS FOR $7;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
+            || ' WHERE a.' || quote_ident(column_a)
+            || ' = b.' || quote_ident(column_b)
+            || ' AND a.' || quote_ident(column_w) || ' IS NOT TRUE';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_false (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_w ALIAS FOR $6;
+        column_x ALIAS FOR $7;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
+            || ' WHERE a.' || quote_ident(column_a)
+            || ' = b.' || quote_ident(column_b)
+            || ' AND a.' || quote_ident(column_w) || ' IS NOT FALSE';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
+
+CREATE OR REPLACE FUNCTION migration_tools.handle_link3_concat_skip_null (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
+    DECLARE
+        table_schema ALIAS FOR $1;
+        table_a ALIAS FOR $2;
+        column_a ALIAS FOR $3;
+        table_b ALIAS FOR $4;
+        column_b ALIAS FOR $5;
+        column_w ALIAS FOR $6;
+        column_x ALIAS FOR $7;
+        proceed BOOLEAN;
+    BEGIN
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_a, column_a;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
+        END IF;
+
+        EXECUTE 'SELECT EXISTS (
+            SELECT 1
+            FROM information_schema.columns
+            WHERE table_schema = $1
+            AND table_name = $2
+            and column_name = $3
+        )' INTO proceed USING table_schema, table_b, column_b;
+        IF NOT proceed THEN
+            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
+        END IF;
+
+        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
+            || ' SET ' || quote_ident(column_x) || ' = CONCAT_WS('' ; '',b.' || quote_ident(column_x) || ',a.' || quote_ident(column_w) || ') FROM ' || quote_ident(table_a) || ' a'
+            || ' WHERE a.' || quote_ident(column_a)
+            || ' = b.' || quote_ident(column_b)
+            || ' AND NULLIF(a.' || quote_ident(column_w) || ','''') IS NOT NULL';
+
+    END;
+$$ LANGUAGE PLPGSQL STRICT VOLATILE;
index ba3eb66..cd8e32e 100755 (executable)
@@ -1,6 +1,7 @@
 #!/bin/bash
-grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_tools.+?)[ \(].*$/) { print "# $1:$2\n"; }' | sort 
+grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_tools.+?)[ \(].*$/) { print "# $1:$2\n"; }' | sort | uniq
 
+# 00-infrastructure.sql:migration_tools.assert
 # 00-infrastructure.sql:migration_tools.build
 # 00-infrastructure.sql:migration_tools.build_base_staging_tables
 # 00-infrastructure.sql:migration_tools.build_specific_base_staging_table
@@ -13,8 +14,6 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 01-marc.sql:migration_tools.get_marc_tags
 # 01-marc.sql:migration_tools.get_marc_tags_filtered
 # 01-marc.sql:migration_tools.insert_tags
-# 01-marc.sql:migration_tools.insert_tags
-# 01-marc.sql:migration_tools.make_stub_bib
 # 01-marc.sql:migration_tools.make_stub_bib
 # 01-marc.sql:migration_tools.marc_parses
 # 01-marc.sql:migration_tools.merge_marc_fields
@@ -24,11 +23,8 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 01-marc.sql:migration_tools.owner_change_sf9_substring_match
 # 01-marc.sql:migration_tools.owner_change_sf9_substring_match2
 # 01-marc.sql:migration_tools.set_008
-# 01-marc.sql:migration_tools.set_008
 # 01-marc.sql:migration_tools.set_indicator
 # 01-marc.sql:migration_tools.set_leader
-# 01-marc.sql:migration_tools.set_leader
-# 01-marc.sql:migration_tools.strip_tag
 # 01-marc.sql:migration_tools.strip_tag
 # 02-barcodes.sql:migration_tools.add_codabar_checkdigit
 # 02-barcodes.sql:migration_tools.add_code39mod43_checkdigit
@@ -37,7 +33,6 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 02-barcodes.sql:migration_tools.rebarcode
 # 03-items.sql:migration_tools.change_call_number
 # 03-items.sql:migration_tools.change_owning_lib
-# 03-items.sql:migration_tools.change_owning_lib
 # 04-names.sql:migration_tools.name_parse_out_first_middle_last_comma_suffix
 # 04-names.sql:migration_tools.name_parse_out_fuller_last_first_middle_and_random_affix
 # 04-names.sql:migration_tools.name_parse_out_fuller_last_first_middle_and_random_affix2
@@ -66,13 +61,35 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 07-eg-specific.sql:migration_tools.find_circ_matrix_matchpoint
 # 07-eg-specific.sql:migration_tools.find_hold_matrix_matchpoint
 # 07-eg-specific.sql:migration_tools.find_hold_matrix_matchpoint2
+# 07-eg-specific.sql:migration_tools.find_mig_shelf
+# 07-eg-specific.sql:migration_tools.find_shelf
 # 07-eg-specific.sql:migration_tools.get_copy_price
+# 07-eg-specific.sql:migration_tools.handle_actor_barcode_collisions
+# 07-eg-specific.sql:migration_tools.handle_actor_barcode_collisions2
+# 07-eg-specific.sql:migration_tools.handle_actor_sc_and_sce
+# 07-eg-specific.sql:migration_tools.handle_asset_barcode_collisions
+# 07-eg-specific.sql:migration_tools.handle_asset_barcode_collisions2
+# 07-eg-specific.sql:migration_tools.handle_asset_sc_and_sce
+# 07-eg-specific.sql:migration_tools.handle_barred_or_blocked
+# 07-eg-specific.sql:migration_tools.handle_circmod
+# 07-eg-specific.sql:migration_tools.handle_item_barcode
+# 07-eg-specific.sql:migration_tools.handle_not_migrate
+# 07-eg-specific.sql:migration_tools.handle_org
+# 07-eg-specific.sql:migration_tools.handle_profile
+# 07-eg-specific.sql:migration_tools._handle_shelf
+# 07-eg-specific.sql:migration_tools.handle_shelf
+# 07-eg-specific.sql:migration_tools.handle_status
+# 07-eg-specific.sql:migration_tools.handle_user_barcode
 # 07-eg-specific.sql:migration_tools.insert_metarecords_for_incumbent_database
 # 07-eg-specific.sql:migration_tools.insert_metarecords_for_pristine_database
+# 07-eg-specific.sql:migration_tools.is_circ_rule_safe_to_delete
 # 07-eg-specific.sql:migration_tools.is_staff_profile
 # 07-eg-specific.sql:migration_tools.reset_event
+# 07-eg-specific.sql:migration_tools.set_salted_passwd
 # 07-eg-specific.sql:migration_tools.simple_export_library_config
 # 07-eg-specific.sql:migration_tools.simple_import_library_config
+# 07-eg-specific.sql:migration_tools.vivicate_actor_sc_and_sce
+# 07-eg-specific.sql:migration_tools.vivicate_asset_sc_and_sce
 # 08-casting-and-validation.sql:migration_tools.attempt_cast
 # 08-casting-and-validation.sql:migration_tools.attempt_date
 # 08-casting-and-validation.sql:migration_tools.attempt_money
@@ -80,7 +97,11 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 08-casting-and-validation.sql:migration_tools.attempt_money_from_pennies
 # 08-casting-and-validation.sql:migration_tools.attempt_money_from_pennies6
 # 08-casting-and-validation.sql:migration_tools.attempt_timestamptz
+# 09-misc.sql:migration_tools.btrim_columns
+# 09-misc.sql:migration_tools.btrim_lcolumns
 # 09-misc.sql:migration_tools.is_blank
+# 09-misc.sql:migration_tools.null_empty_columns
+# 09-misc.sql:migration_tools.null_empty_lcolumns
 # 10-staging.sql:migration_tools.simple_import_new_rows_by_value
 # 10-staging.sql:migration_tools.split_rows_on_column_with_delimiter
 # 10-staging.sql:migration_tools.stage_not_applicable_asset_stat_cats
@@ -93,8 +114,6 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 21-fixed-fields.sql:migration_tools.stage_vlist
 # 21-fixed-fields.sql:migration_tools.view_staged_vlist
 # 22-anyarray.sql:migration_tools.anyarray_concat
-# 22-anyarray.sql:migration_tools.anyarray_concat
-# 22-anyarray.sql:migration_tools.anyarray_concat_uniq
 # 22-anyarray.sql:migration_tools.anyarray_concat_uniq
 # 22-anyarray.sql:migration_tools.anyarray_diff
 # 22-anyarray.sql:migration_tools.anyarray_diff_uniq
@@ -102,7 +121,6 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 22-anyarray.sql:migration_tools.anyarray_numeric_only
 # 22-anyarray.sql:migration_tools.anyarray_ranges
 # 22-anyarray.sql:migration_tools.anyarray_remove
-# 22-anyarray.sql:migration_tools.anyarray_remove
 # 22-anyarray.sql:migration_tools.anyarray_remove_null
 # 22-anyarray.sql:migration_tools.anyarray_sort
 # 22-anyarray.sql:migration_tools.anyarray_uniq
@@ -112,61 +130,25 @@ grep -i 'CREATE OR REPLACE FUNCTION' *.sql | perl -ne 'if (/^(.+?):.*(migration_
 # 99-deprecated.sql:migration_tools.base_circ_field_map
 # 99-deprecated.sql:migration_tools.base_copy_location_map
 # 99-deprecated.sql:migration_tools.base_item_dynamic_field_map
+# 99-deprecated.sql:migration_tools.debug_exec
+# 99-deprecated.sql:migration_tools.exec
+# 99-deprecated.sql:migration_tools.handle_link
+# 99-deprecated.sql:migration_tools.handle_link2
+# 99-deprecated.sql:migration_tools.handle_link3
+# 99-deprecated.sql:migration_tools.handle_link3_concat_skip_null
+# 99-deprecated.sql:migration_tools.handle_link3_skip_false
+# 99-deprecated.sql:migration_tools.handle_link3_skip_null
+# 99-deprecated.sql:migration_tools.handle_link3_skip_null_or_empty_string
+# 99-deprecated.sql:migration_tools.handle_link3_skip_true
 # 99-deprecated.sql:migration_tools.insert_856_9
 # 99-deprecated.sql:migration_tools.insert_856_9_conditional
+# 99-deprecated.sql:migration_tools.insert_base_into_production
+# 99-deprecated.sql:migration_tools.insert_into_production
 # 99-deprecated.sql:migration_tools.is_staff_profile
+# 99-deprecated.sql:migration_tools.log
 # 99-deprecated.sql:migration_tools.map_base_circ_table_dynamic
 # 99-deprecated.sql:migration_tools.map_base_item_table_dynamic
 # 99-deprecated.sql:migration_tools.map_base_item_table_locations
 # 99-deprecated.sql:migration_tools.map_base_patron_profile
+# 99-deprecated.sql:migration_tools.push_bib_sequence
 # 99-deprecated.sql:migration_tools.refresh_opac_visible_copies
-# base.sql:migration_tools.assert
-# base.sql:migration_tools.assert
-# base.sql:migration_tools.assert
-# base.sql:migration_tools.btrim_columns
-# base.sql:migration_tools.btrim_lcolumns
-# base.sql:migration_tools.build
-# base.sql:migration_tools.build_base_staging_tables
-# base.sql:migration_tools.build_specific_base_staging_table
-# base.sql:migration_tools.country_code
-# base.sql:migration_tools.create_linked_legacy_table_from
-# base.sql:migration_tools.debug_exec
-# base.sql:migration_tools.exec
-# base.sql:migration_tools.find_mig_shelf
-# base.sql:migration_tools.find_shelf
-# base.sql:migration_tools.handle_actor_barcode_collisions
-# base.sql:migration_tools.handle_actor_barcode_collisions2
-# base.sql:migration_tools.handle_actor_sc_and_sce
-# base.sql:migration_tools.handle_asset_barcode_collisions
-# base.sql:migration_tools.handle_asset_barcode_collisions2
-# base.sql:migration_tools.handle_asset_sc_and_sce
-# base.sql:migration_tools.handle_barred_or_blocked
-# base.sql:migration_tools.handle_circmod
-# base.sql:migration_tools.handle_item_barcode
-# base.sql:migration_tools.handle_link
-# base.sql:migration_tools.handle_link2
-# base.sql:migration_tools.handle_link3
-# base.sql:migration_tools.handle_link3_concat_skip_null
-# base.sql:migration_tools.handle_link3_skip_false
-# base.sql:migration_tools.handle_link3_skip_null
-# base.sql:migration_tools.handle_link3_skip_null_or_empty_string
-# base.sql:migration_tools.handle_link3_skip_true
-# base.sql:migration_tools.handle_not_migrate
-# base.sql:migration_tools.handle_org
-# base.sql:migration_tools.handle_profile
-# base.sql:migration_tools._handle_shelf
-# base.sql:migration_tools.handle_shelf
-# base.sql:migration_tools.handle_status
-# base.sql:migration_tools.handle_user_barcode
-# base.sql:migration_tools.init
-# base.sql:migration_tools.insert_base_into_production
-# base.sql:migration_tools.insert_into_production
-# base.sql:migration_tools.is_circ_rule_safe_to_delete
-# base.sql:migration_tools.log
-# base.sql:migration_tools.null_empty_columns
-# base.sql:migration_tools.null_empty_lcolumns
-# base.sql:migration_tools.production_tables
-# base.sql:migration_tools.push_bib_sequence
-# base.sql:migration_tools.set_salted_passwd
-# base.sql:migration_tools.vivicate_actor_sc_and_sce
-# base.sql:migration_tools.vivicate_asset_sc_and_sce
index a3572e6..4c49959 100644 (file)
--- Copyright 2009-2012, Equinox Software, Inc.
---
--- This program is free software; you can redistribute it and/or
--- modify it under the terms of the GNU General Public License
--- as published by the Free Software Foundation; either version 2
--- of the License, or (at your option) any later version.
---
--- This program is distributed in the hope that it will be useful,
--- but WITHOUT ANY WARRANTY; without even the implied warranty of
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--- GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License
--- along with this program; if not, write to the Free Software
--- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-
---------------------------------------------------------------------------
--- An example of how to use:
--- 
--- DROP SCHEMA foo CASCADE; CREATE SCHEMA foo; 
--- \i base.sql
--- SELECT migration_tools.init('foo');
--- SELECT migration_tools.build('foo');
--- SELECT * FROM foo.fields_requiring_mapping;
--- \d foo.actor_usr
--- create some incoming ILS specific staging tables, like CREATE foo.legacy_items ( l_barcode TEXT, .. ) INHERITS (foo.asset_copy);
--- Do some mapping, like UPDATE foo.legacy_items SET barcode = TRIM(BOTH ' ' FROM l_barcode);
--- Then, to move into production, do: select migration_tools.insert_base_into_production('foo')
-
-CREATE SCHEMA migration_tools;
-
-CREATE OR REPLACE FUNCTION migration_tools.production_tables (TEXT) RETURNS TEXT[] AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        output  RECORD;
-    BEGIN
-        FOR output IN
-            EXECUTE 'SELECT string_to_array(value,'','') AS tables FROM ' || migration_schema || '.config WHERE key = ''production_tables'';'
-        LOOP
-            RETURN output.tables;
-        END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
-
-CREATE OR REPLACE FUNCTION migration_tools.country_code (TEXT) RETURNS TEXT AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        output TEXT;
-    BEGIN
-        FOR output IN
-            EXECUTE 'SELECT value FROM ' || migration_schema || '.config WHERE key = ''country_code'';'
-        LOOP
-            RETURN output;
-        END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT STABLE;
-
-
-CREATE OR REPLACE FUNCTION migration_tools.log (TEXT,TEXT,INTEGER) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        sql ALIAS FOR $2;
-        nrows ALIAS FOR $3;
-    BEGIN
-        EXECUTE 'INSERT INTO ' || migration_schema || '.sql_log ( sql, row_count ) VALUES ( ' || quote_literal(sql) || ', ' || nrows || ' );';
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.exec (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        sql ALIAS FOR $2;
-        nrows INTEGER;
-    BEGIN
-        EXECUTE 'UPDATE ' || migration_schema || '.sql_current SET sql = ' || quote_literal(sql) || ';';
-        --RAISE INFO '%', sql;
-        EXECUTE sql;
-        GET DIAGNOSTICS nrows = ROW_COUNT;
-        PERFORM migration_tools.log(migration_schema,sql,nrows);
-    EXCEPTION
-        WHEN OTHERS THEN 
-            RAISE EXCEPTION '!!!!!!!!!!! state = %, msg = %, sql = %', SQLSTATE, SQLERRM, sql;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.debug_exec (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        sql ALIAS FOR $2;
-        nrows INTEGER;
-    BEGIN
-        EXECUTE 'UPDATE ' || migration_schema || '.sql_current SET sql = ' || quote_literal(sql) || ';';
-        RAISE INFO 'debug_exec sql = %', sql;
-        EXECUTE sql;
-        GET DIAGNOSTICS nrows = ROW_COUNT;
-        PERFORM migration_tools.log(migration_schema,sql,nrows);
-    EXCEPTION
-        WHEN OTHERS THEN 
-            RAISE EXCEPTION '!!!!!!!!!!! state = %, msg = %, sql = %', SQLSTATE, SQLERRM, sql;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.init (TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        sql TEXT;
-    BEGIN
-        EXECUTE 'DROP TABLE IF EXISTS ' || migration_schema || '.sql_current;';
-        EXECUTE 'CREATE TABLE ' || migration_schema || '.sql_current ( sql TEXT);';
-        EXECUTE 'INSERT INTO ' || migration_schema || '.sql_current ( sql ) VALUES ( '''' );';
-        BEGIN
-            SELECT 'CREATE TABLE ' || migration_schema || '.sql_log ( time TIMESTAMP NOT NULL DEFAULT NOW(), row_count INTEGER, sql TEXT );' INTO STRICT sql;
-            EXECUTE sql;
-        EXCEPTION
-            WHEN OTHERS THEN 
-                RAISE INFO '!!!!!!!!!!! state = %, msg = %, sql = %', SQLSTATE, SQLERRM, sql;
-        END;
-        PERFORM migration_tools.exec( $1, 'DROP TABLE IF EXISTS ' || migration_schema || '.config;' );
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || '.config ( key TEXT UNIQUE, value TEXT);' );
-        PERFORM migration_tools.exec( $1, 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''production_tables'', ''asset.call_number,asset.call_number_prefix,asset.call_number_suffix,asset.copy_location,asset.copy,asset.copy_alert,asset.stat_cat,asset.stat_cat_entry,asset.stat_cat_entry_copy_map,asset.copy_note,actor.usr,actor.card,actor.usr_address,actor.stat_cat,actor.stat_cat_entry,actor.stat_cat_entry_usr_map,actor.usr_note,actor.usr_standing_penalty,actor.usr_setting,action.circulation,action.hold_request,action.hold_notification,action.hold_request_note,action.hold_transit_copy,action.transit_copy,money.grocery,money.billing,money.cash_payment,money.forgive_payment,acq.provider,acq.provider_address,acq.provider_note,acq.provider_contact,acq.provider_contact_address,acq.fund,acq.fund_allocation,acq.fund_tag,acq.fund_tag_map,acq.funding_source,acq.funding_source_credit,acq.lineitem,acq.purchase_order,acq.po_item,acq.invoice,acq.invoice_item,acq.invoice_entry,acq.lineitem_detail,acq.fund_debit,acq.fund_transfer,acq.po_note,config.circ_matrix_matchpoint,config.circ_matrix_limit_set_map,config.hold_matrix_matchpoint,asset.copy_tag,asset.copy_tag_copy_map,config.copy_tag_type,serial.item,serial.item_note,serial.record_entry,biblio.record_entry'' );' );
-        PERFORM migration_tools.exec( $1, 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''country_code'', ''USA'' );' );
-        PERFORM migration_tools.exec( $1, 'DROP TABLE IF EXISTS ' || migration_schema || '.fields_requiring_mapping;' );
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || '.fields_requiring_mapping( table_schema TEXT, table_name TEXT, column_name TEXT, data_type TEXT);' );
-        PERFORM migration_tools.exec( $1, 'DROP TABLE IF EXISTS ' || migration_schema || '.base_profile_map;' );  
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || E'.base_profile_map ( 
-            id SERIAL,
-            perm_grp_id INTEGER,
-            transcribed_perm_group TEXT,
-            legacy_field1 TEXT,
-            legacy_value1 TEXT,
-            legacy_field2 TEXT,
-            legacy_value2 TEXT,
-            legacy_field3 TEXT,
-            legacy_value3 TEXT
-        );' );
-        PERFORM migration_tools.exec( $1, 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''base_profile_map'', ''base_profile_map'' );' );
-        PERFORM migration_tools.exec( $1, 'DROP TABLE IF EXISTS ' || migration_schema || '.base_item_dynamic_field_map;' );  
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || E'.base_item_dynamic_field_map ( 
-            id SERIAL,
-            evergreen_field TEXT,
-            evergreen_value TEXT,
-            evergreen_datatype TEXT,
-            legacy_field1 TEXT,
-            legacy_value1 TEXT,
-            legacy_field2 TEXT,
-            legacy_value2 TEXT,
-            legacy_field3 TEXT,
-            legacy_value3 TEXT
-        );' );
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_item_dynamic_lf1_idx ON ' || migration_schema || '.base_item_dynamic_field_map (legacy_field1,legacy_value1);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_item_dynamic_lf2_idx ON ' || migration_schema || '.base_item_dynamic_field_map (legacy_field2,legacy_value2);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_item_dynamic_lf3_idx ON ' || migration_schema || '.base_item_dynamic_field_map (legacy_field3,legacy_value3);' ); 
-        PERFORM migration_tools.exec( $1, 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''base_item_dynamic_field_map'', ''base_item_dynamic_field_map'' );' );
-        PERFORM migration_tools.exec( $1, 'DROP TABLE IF EXISTS ' || migration_schema || '.base_copy_location_map;' );  
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || E'.base_copy_location_map ( 
-            id SERIAL,
-            location INTEGER,
-            holdable BOOLEAN NOT NULL DEFAULT TRUE,
-            hold_verify BOOLEAN NOT NULL DEFAULT FALSE,
-            opac_visible BOOLEAN NOT NULL DEFAULT TRUE,
-            circulate BOOLEAN NOT NULL DEFAULT TRUE,
-            transcribed_location TEXT,
-            legacy_field1 TEXT,
-            legacy_value1 TEXT,
-            legacy_field2 TEXT,
-            legacy_value2 TEXT,
-            legacy_field3 TEXT,
-            legacy_value3 TEXT
-        );' );
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_base_copy_location_lf1_idx ON ' || migration_schema || '.base_copy_location_map (legacy_field1,legacy_value1);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_base_copy_location_lf2_idx ON ' || migration_schema || '.base_copy_location_map (legacy_field2,legacy_value2);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_base_copy_location_lf3_idx ON ' || migration_schema || '.base_copy_location_map (legacy_field3,legacy_value3);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_base_copy_location_loc_idx ON ' || migration_schema || '.base_copy_location_map (transcribed_location);' ); 
-        PERFORM migration_tools.exec( $1, 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''base_copy_location_map'', ''base_copy_location_map'' );' );
-        PERFORM migration_tools.exec( $1, 'DROP TABLE IF EXISTS ' || migration_schema || '.base_circ_field_map;' );  
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || E'.base_circ_field_map ( 
-            id SERIAL,
-            circulate BOOLEAN,
-            loan_period TEXT,
-            max_renewals TEXT,
-            max_out TEXT,
-            fine_amount TEXT,
-            fine_interval TEXT,
-            max_fine TEXT,
-            item_field1 TEXT,
-            item_value1 TEXT,
-            item_field2 TEXT,
-            item_value2 TEXT,
-            patron_field1 TEXT,
-            patron_value1 TEXT,
-            patron_field2 TEXT,
-            patron_value2 TEXT
-        );' );
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_circ_dynamic_lf1_idx ON ' || migration_schema || '.base_circ_field_map (item_field1,item_value1);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_circ_dynamic_lf2_idx ON ' || migration_schema || '.base_circ_field_map (item_field2,item_value2);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_circ_dynamic_lf3_idx ON ' || migration_schema || '.base_circ_field_map (patron_field1,patron_value1);' ); 
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_circ_dynamic_lf4_idx ON ' || migration_schema || '.base_circ_field_map (patron_field2,patron_value2);' ); 
-        PERFORM migration_tools.exec( $1, 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''base_circ_field_map'', ''base_circ_field_map'' );' );
-
-        BEGIN
-            PERFORM migration_tools.exec( $1, 'INSERT INTO ' || migration_schema || '.config (key,value) VALUES ( ''last_init'', now() );' );
-        EXCEPTION
-            WHEN OTHERS THEN PERFORM migration_tools.exec( $1, 'UPDATE ' || migration_schema || '.config SET value = now() WHERE key = ''last_init'';' );
-        END;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.build (TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        production_tables TEXT[];
-    BEGIN
-        --RAISE INFO 'In migration_tools.build(%)', migration_schema;
-        SELECT migration_tools.production_tables(migration_schema) INTO STRICT production_tables;
-        PERFORM migration_tools.build_base_staging_tables(migration_schema,production_tables);
-        PERFORM migration_tools.exec( $1, 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_barcode_key ON ' || migration_schema || '.actor_card ( barcode );' );
-        PERFORM migration_tools.exec( $1, 'CREATE UNIQUE INDEX ' || migration_schema || '_patron_usrname_key ON ' || migration_schema || '.actor_usr ( usrname );' );
-        PERFORM migration_tools.exec( $1, 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_barcode_key ON ' || migration_schema || '.asset_copy ( barcode );' );
-        PERFORM migration_tools.exec( $1, 'CREATE UNIQUE INDEX ' || migration_schema || '_copy_id_key ON ' || migration_schema || '.asset_copy ( id );' );
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_callnum_record_idx ON ' || migration_schema || '.asset_call_number ( record );' );
-        PERFORM migration_tools.exec( $1, 'CREATE INDEX ' || migration_schema || '_callnum_upper_label_id_lib_idx ON ' || migration_schema || '.asset_call_number ( UPPER(label),id,owning_lib );' );
-        PERFORM migration_tools.exec( $1, 'CREATE UNIQUE INDEX ' || migration_schema || '_callnum_label_once_per_lib ON ' || migration_schema || '.asset_call_number ( record,owning_lib,label,prefix,suffix );' );
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.build_base_staging_tables (TEXT,TEXT[]) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        production_tables ALIAS FOR $2;
-    BEGIN
-        --RAISE INFO 'In migration_tools.build_base_staging_tables(%,%)', migration_schema, production_tables;
-        FOR i IN array_lower(production_tables,1) .. array_upper(production_tables,1) LOOP
-            PERFORM migration_tools.build_specific_base_staging_table(migration_schema,production_tables[i]);
-        END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.build_specific_base_staging_table (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        production_table ALIAS FOR $2;
-        base_staging_table TEXT;
-        columns RECORD;
-    BEGIN
-        base_staging_table = REPLACE( production_table, '.', '_' );
-        --RAISE INFO 'In migration_tools.build_specific_base_staging_table(%,%) -> %', migration_schema, production_table, base_staging_table;
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || '.' || base_staging_table || ' ( LIKE ' || production_table || ' INCLUDING DEFAULTS EXCLUDING CONSTRAINTS );' );
-        PERFORM migration_tools.exec( $1, '
-            INSERT INTO ' || migration_schema || '.fields_requiring_mapping
-                SELECT table_schema, table_name, column_name, data_type
-                FROM information_schema.columns 
-                WHERE table_schema = ''' || migration_schema || ''' AND table_name = ''' || base_staging_table || ''' AND is_nullable = ''NO'' AND column_default IS NULL;
-        ' );
-        FOR columns IN 
-            SELECT table_schema, table_name, column_name, data_type
-            FROM information_schema.columns 
-            WHERE table_schema = migration_schema AND table_name = base_staging_table AND is_nullable = 'NO' AND column_default IS NULL
-        LOOP
-            PERFORM migration_tools.exec( $1, 'ALTER TABLE ' || columns.table_schema || '.' || columns.table_name || ' ALTER COLUMN ' || columns.column_name || ' DROP NOT NULL;' );
-        END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- creates other child table so you can have more than one child table in a schema from a base table 
-CREATE OR REPLACE FUNCTION build_variant_staging_table(text, text, text)
- RETURNS void
- LANGUAGE plpgsql
- STRICT
-AS $function$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        production_table ALIAS FOR $2;
-        base_staging_table ALIAS FOR $3;
-        columns RECORD;
-    BEGIN
-        --RAISE INFO 'In migration_tools.build_specific_base_staging_table(%,%) -> %', migration_schema, production_table, base_staging_table;
-        PERFORM migration_tools.exec( $1, 'CREATE TABLE ' || migration_schema || '.' || base_staging_table || ' ( LIKE ' || production_table || ' INCLUDING DEFAULTS EXCLUDING CONSTRAINTS );' );
-        PERFORM migration_tools.exec( $1, '
-            INSERT INTO ' || migration_schema || '.fields_requiring_mapping
-                SELECT table_schema, table_name, column_name, data_type
-                FROM information_schema.columns
-                WHERE table_schema = ''' || migration_schema || ''' AND table_name = ''' || base_staging_table || ''' AND is_nullable = ''NO'' AND column_default IS NULL;
-        ' );
-        FOR columns IN
-            SELECT table_schema, table_name, column_name, data_type
-            FROM information_schema.columns
-            WHERE table_schema = migration_schema AND table_name = base_staging_table AND is_nullable = 'NO' AND column_default IS NULL
-        LOOP
-            PERFORM migration_tools.exec( $1, 'ALTER TABLE ' || columns.table_schema || '.' || columns.table_name || ' ALTER COLUMN ' || columns.column_name || ' DROP NOT NULL;' );
-        END LOOP;
-    END;
-$function$
-
-CREATE OR REPLACE FUNCTION migration_tools.create_linked_legacy_table_from (TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        parent_table ALIAS FOR $2;
-        source_table ALIAS FOR $3;
-        columns RECORD;
-        create_sql TEXT;
-        insert_sql TEXT;
-        column_list TEXT := '';
-        column_count INTEGER := 0;
-    BEGIN
-        create_sql := 'CREATE TABLE ' || migration_schema || '.' || parent_table || '_legacy ( ';
-        FOR columns IN
-            SELECT table_schema, table_name, column_name, data_type
-            FROM information_schema.columns
-            WHERE table_schema = migration_schema AND table_name = source_table
-        LOOP
-            column_count := column_count + 1;
-            if column_count > 1 then
-                create_sql := create_sql || ', ';
-                column_list := column_list || ', ';
-            end if;
-            create_sql := create_sql || columns.column_name || ' ';
-            if columns.data_type = 'ARRAY' then
-                create_sql := create_sql || 'TEXT[]';
-            else
-                create_sql := create_sql || columns.data_type;
-            end if;
-            column_list := column_list || columns.column_name;
-        END LOOP;
-        create_sql := create_sql || ' ) INHERITS ( ' || migration_schema || '.' || parent_table || ' );';
-        --RAISE INFO 'create_sql = %', create_sql;
-        EXECUTE create_sql;
-        insert_sql := 'INSERT INTO ' || migration_schema || '.' || parent_table || '_legacy (' || column_list || ') SELECT ' || column_list || ' FROM ' || migration_schema || '.' || source_table || ';';
-        --RAISE INFO 'insert_sql = %', insert_sql;
-        EXECUTE insert_sql;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.insert_base_into_production (TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        production_tables TEXT[];
-    BEGIN
-        --RAISE INFO 'In migration_tools.insert_into_production(%)', migration_schema;
-        SELECT migration_tools.production_tables(migration_schema) INTO STRICT production_tables;
-        FOR i IN array_lower(production_tables,1) .. array_upper(production_tables,1) LOOP
-            PERFORM migration_tools.insert_into_production(migration_schema,production_tables[i]);
-        END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.insert_into_production (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        migration_schema ALIAS FOR $1;
-        production_table ALIAS FOR $2;
-        base_staging_table TEXT;
-        columns RECORD;
-    BEGIN
-        base_staging_table = REPLACE( production_table, '.', '_' );
-        --RAISE INFO 'In migration_tools.insert_into_production(%,%) -> %', migration_schema, production_table, base_staging_table;
-        PERFORM migration_tools.exec( $1, 'INSERT INTO ' || production_table || ' SELECT * FROM ' || migration_schema || '.' || base_staging_table || ';' );
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-
-CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN) RETURNS VOID AS $$
-    DECLARE
-        test ALIAS FOR $1;
-    BEGIN
-        IF NOT test THEN
-            RAISE EXCEPTION 'assertion';
-        END IF;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN,TEXT) RETURNS VOID AS $$
-    DECLARE
-        test ALIAS FOR $1;
-        msg ALIAS FOR $2;
-    BEGIN
-        IF NOT test THEN
-            RAISE EXCEPTION '%', msg;
-        END IF;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.assert (BOOLEAN,TEXT,TEXT) RETURNS TEXT AS $$
-    DECLARE
-        test ALIAS FOR $1;
-        fail_msg ALIAS FOR $2;
-        success_msg ALIAS FOR $3;
-    BEGIN
-        IF NOT test THEN
-            RAISE EXCEPTION '%', fail_msg;
-        END IF;
-        RETURN success_msg;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- push bib sequence and return starting value for reserved range
-CREATE OR REPLACE FUNCTION migration_tools.push_bib_sequence(INTEGER) RETURNS BIGINT AS $$
-    DECLARE
-        bib_count ALIAS FOR $1;
-        output BIGINT;
-    BEGIN
-        PERFORM setval('biblio.record_entry_id_seq',(SELECT MAX(id) FROM biblio.record_entry) + bib_count + 2000);
-        FOR output IN
-            SELECT CEIL(MAX(id)/1000)*1000+1000 FROM biblio.record_entry WHERE id < (SELECT last_value FROM biblio.record_entry_id_seq)
-        LOOP
-            RETURN output;
-        END LOOP;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- set a new salted password
-
-CREATE OR REPLACE FUNCTION migration_tools.set_salted_passwd(INTEGER,TEXT) RETURNS BOOLEAN AS $$
-    DECLARE
-        usr_id              ALIAS FOR $1;
-        plain_passwd        ALIAS FOR $2;
-        plain_salt          TEXT;
-        md5_passwd          TEXT;
-    BEGIN
-
-        SELECT actor.create_salt('main') INTO plain_salt;
-
-        SELECT MD5(plain_passwd) INTO md5_passwd;
-        
-        PERFORM actor.set_passwd(usr_id, 'main', MD5(plain_salt || md5_passwd), plain_salt);
-
-        RETURN TRUE;
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-
--- convenience functions for handling copy_location maps
-CREATE OR REPLACE FUNCTION migration_tools.handle_shelf (TEXT,TEXT,TEXT,INTEGER) RETURNS VOID AS $$
-    SELECT migration_tools._handle_shelf($1,$2,$3,$4,TRUE);
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION migration_tools._handle_shelf (TEXT,TEXT,TEXT,INTEGER,BOOLEAN) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        org_shortname ALIAS FOR $3;
-        org_range ALIAS FOR $4;
-        make_assertion ALIAS FOR $5;
-        proceed BOOLEAN;
-        org INTEGER;
-        -- if x_org is on the mapping table, it'll take precedence over the passed org_shortname param
-        -- though we'll still use the passed org for the full path traversal when needed
-        x_org_found BOOLEAN;
-        x_org INTEGER;
-        org_list INTEGER[];
-        o INTEGER;
-        row_count NUMERIC;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''desired_shelf''
-        )' INTO proceed USING table_schema, table_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column desired_shelf';
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''x_org''
-        )' INTO x_org_found USING table_schema, table_name;
-
-        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
-        IF org IS NULL THEN
-            RAISE EXCEPTION 'Cannot find org by shortname';
-        END IF;
-
-        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_shelf';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_shelf INTEGER';
-
-        IF x_org_found THEN
-            RAISE INFO 'Found x_org column';
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_shelf = b.id FROM asset_copy_location b'
-                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
-                || ' AND b.owning_lib = x_org'
-                || ' AND NOT b.deleted';
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_shelf = b.id FROM asset.copy_location b'
-                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
-                || ' AND b.owning_lib = x_org'
-                || ' AND x_shelf IS NULL'
-                || ' AND NOT b.deleted';
-        ELSE
-            RAISE INFO 'Did not find x_org column';
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_shelf = b.id FROM asset_copy_location b'
-                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
-                || ' AND b.owning_lib = $1'
-                || ' AND NOT b.deleted'
-            USING org;
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_shelf = b.id FROM asset_copy_location b'
-                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
-                || ' AND b.owning_lib = $1'
-                || ' AND x_shelf IS NULL'
-                || ' AND NOT b.deleted'
-            USING org;
-        END IF;
-
-        FOREACH o IN ARRAY org_list LOOP
-            RAISE INFO 'Considering org %', o;
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_shelf = b.id FROM asset.copy_location b'
-                || ' WHERE BTRIM(UPPER(a.desired_shelf)) = BTRIM(UPPER(b.name))'
-                || ' AND b.owning_lib = $1 AND x_shelf IS NULL'
-                || ' AND NOT b.deleted'
-            USING o;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            RAISE INFO 'Updated % rows', row_count;
-        END LOOP;
-
-        IF make_assertion THEN
-            EXECUTE 'SELECT migration_tools.assert(
-                NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_shelf <> '''' AND x_shelf IS NULL),
-                ''Cannot find a desired location'',
-                ''Found all desired locations''
-            );';
-        END IF;
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience functions for handling circmod maps
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_circmod (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''desired_circmod''
-        )' INTO proceed USING table_schema, table_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column desired_circmod'; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_circmod';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_circmod TEXT';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_circmod = code FROM config.circ_modifier b'
-            || ' WHERE BTRIM(UPPER(a.desired_circmod)) = BTRIM(UPPER(b.code))';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_circmod = code FROM config.circ_modifier b'
-            || ' WHERE BTRIM(UPPER(a.desired_circmod)) = BTRIM(UPPER(b.name))'
-            || ' AND x_circmod IS NULL';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_circmod = code FROM config.circ_modifier b'
-            || ' WHERE BTRIM(UPPER(a.desired_circmod)) = BTRIM(UPPER(b.description))'
-            || ' AND x_circmod IS NULL';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_circmod <> '''' AND x_circmod IS NULL),
-            ''Cannot find a desired circulation modifier'',
-            ''Found all desired circulation modifiers''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience functions for handling item status maps
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_status (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''desired_status''
-        )' INTO proceed USING table_schema, table_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column desired_status'; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_status';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_status INTEGER';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_status = id FROM config.copy_status b'
-            || ' WHERE BTRIM(UPPER(a.desired_status)) = BTRIM(UPPER(b.name))';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_status <> '''' AND x_status IS NULL),
-            ''Cannot find a desired copy status'',
-            ''Found all desired copy statuses''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience functions for handling org maps
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_org (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''desired_org''
-        )' INTO proceed USING table_schema, table_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column desired_org'; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_org';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_org INTEGER';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_org = b.id FROM actor.org_unit b'
-            || ' WHERE BTRIM(a.desired_org) = BTRIM(b.shortname)';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_org <> '''' AND x_org IS NULL),
-            ''Cannot find a desired org unit'',
-            ''Found all desired org units''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for handling desired_not_migrate
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_not_migrate (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''desired_not_migrate''
-        )' INTO proceed USING table_schema, table_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column desired_not_migrate'; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_migrate';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_migrate BOOLEAN';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_migrate = CASE'
-            || ' WHEN BTRIM(desired_not_migrate) = ''TRUE'' THEN FALSE'
-            || ' WHEN BTRIM(desired_not_migrate) = ''DNM'' THEN FALSE'
-            || ' WHEN BTRIM(desired_not_migrate) = ''Do Not Migrate'' THEN FALSE'
-            || ' WHEN BTRIM(desired_not_migrate) = ''FALSE'' THEN TRUE'
-            || ' WHEN BTRIM(desired_not_migrate) = ''Migrate'' THEN TRUE'
-            || ' WHEN BTRIM(desired_not_migrate) = '''' THEN TRUE'
-            || ' END';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE x_migrate IS NULL),
-            ''Not all desired_not_migrate values understood'',
-            ''All desired_not_migrate values understood''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for handling desired_not_migrate
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_barred_or_blocked (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''desired_barred_or_blocked''
-        )' INTO proceed USING table_schema, table_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column desired_barred_or_blocked'; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_barred';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_barred BOOLEAN';
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_blocked';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_blocked BOOLEAN';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_barred = CASE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Barred'' THEN TRUE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Blocked'' THEN FALSE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Neither'' THEN FALSE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = '''' THEN FALSE'
-            || ' END';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_blocked = CASE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Blocked'' THEN TRUE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Barred'' THEN FALSE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = ''Neither'' THEN FALSE'
-            || ' WHEN BTRIM(desired_barred_or_blocked) = '''' THEN FALSE'
-            || ' END';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE x_barred IS NULL or x_blocked IS NULL),
-            ''Not all desired_barred_or_blocked values understood'',
-            ''All desired_barred_or_blocked values understood''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for handling desired_profile
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_profile (TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = ''desired_profile''
-        )' INTO proceed USING table_schema, table_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column desired_profile'; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_profile';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_profile INTEGER';
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-            || ' SET x_profile = b.id FROM permission.grp_tree b'
-            || ' WHERE BTRIM(UPPER(a.desired_profile)) = BTRIM(UPPER(b.name))';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_profile <> '''' AND x_profile IS NULL),
-            ''Cannot find a desired profile'',
-            ''Found all desired profiles''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for handling desired actor stat cats
-
-CREATE OR REPLACE FUNCTION migration_tools.vivicate_actor_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
-        org_shortname ALIAS FOR $4;
-        proceed BOOLEAN;
-        org INTEGER;
-        org_list INTEGER[];
-        sc TEXT;
-        sce TEXT;
-    BEGIN
-
-        SELECT 'desired_sc' || field_suffix INTO sc;
-        SELECT 'desired_sce' || field_suffix INTO sce;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sc;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sc; 
-        END IF;
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sce;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sce; 
-        END IF;
-
-        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
-        IF org IS NULL THEN
-            RAISE EXCEPTION 'Cannot find org by shortname';
-        END IF;
-        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
-
-        -- caller responsible for their own truncates though we try to prevent duplicates
-        EXECUTE 'INSERT INTO actor_stat_cat (owner, name)
-            SELECT DISTINCT
-                 $1
-                ,BTRIM('||sc||')
-            FROM 
-                ' || quote_ident(table_name) || '
-            WHERE
-                NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM actor.stat_cat
-                    WHERE owner = ANY ($2)
-                    AND name = BTRIM('||sc||')
-                )
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM actor_stat_cat
-                    WHERE owner = ANY ($2)
-                    AND name = BTRIM('||sc||')
-                )
-            ORDER BY 2;'
-        USING org, org_list;
-
-        EXECUTE 'INSERT INTO actor_stat_cat_entry (stat_cat, owner, value)
-            SELECT DISTINCT
-                COALESCE(
-                    (SELECT id
-                        FROM actor.stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name))
-                   ,(SELECT id
-                        FROM actor_stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name))
-                )
-                ,$1
-                ,BTRIM('||sce||')
-            FROM 
-                ' || quote_ident(table_name) || '
-            WHERE
-                    NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
-                AND NULLIF(BTRIM('||sce||'),'''') IS NOT NULL
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM actor.stat_cat_entry
-                    WHERE stat_cat = (
-                        SELECT id
-                        FROM actor.stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name)
-                    ) AND value = BTRIM('||sce||')
-                    AND owner = ANY ($2)
-                )
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM actor_stat_cat_entry
-                    WHERE stat_cat = (
-                        SELECT id
-                        FROM actor_stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name)
-                    ) AND value = BTRIM('||sce||')
-                    AND owner = ANY ($2)
-                )
-            ORDER BY 1,3;'
-        USING org, org_list;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_actor_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
-        org_shortname ALIAS FOR $4;
-        proceed BOOLEAN;
-        org INTEGER;
-        org_list INTEGER[];
-        o INTEGER;
-        sc TEXT;
-        sce TEXT;
-    BEGIN
-        SELECT 'desired_sc' || field_suffix INTO sc;
-        SELECT 'desired_sce' || field_suffix INTO sce;
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sc;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sc; 
-        END IF;
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sce;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sce; 
-        END IF;
-
-        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
-        IF org IS NULL THEN
-            RAISE EXCEPTION 'Cannot find org by shortname';
-        END IF;
-
-        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_sc' || field_suffix;
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_sc' || field_suffix || ' INTEGER';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_sce' || field_suffix;
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_sce' || field_suffix || ' INTEGER';
-
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
-            SET
-                x_sc' || field_suffix || ' = id
-            FROM
-                (SELECT id, name, owner FROM actor_stat_cat
-                    UNION SELECT id, name, owner FROM actor.stat_cat) u
-            WHERE
-                    BTRIM(UPPER(u.name)) = BTRIM(UPPER(' || sc || '))
-                AND u.owner = ANY ($1);'
-        USING org_list;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
-            SET
-                x_sce' || field_suffix || ' = id
-            FROM
-                (SELECT id, stat_cat, owner, value FROM actor_stat_cat_entry
-                    UNION SELECT id, stat_cat, owner, value FROM actor.stat_cat_entry) u
-            WHERE
-                    u.stat_cat = x_sc' || field_suffix || '
-                AND BTRIM(UPPER(u.value)) = BTRIM(UPPER(' || sce || '))
-                AND u.owner = ANY ($1);'
-        USING org_list;
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sc' || field_suffix || ' <> '''' AND x_sc' || field_suffix || ' IS NULL),
-            ''Cannot find a desired stat cat'',
-            ''Found all desired stat cats''
-        );';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sce' || field_suffix || ' <> '''' AND x_sce' || field_suffix || ' IS NULL),
-            ''Cannot find a desired stat cat entry'',
-            ''Found all desired stat cat entries''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience functions for adding shelving locations
-DROP FUNCTION IF EXISTS migration_tools.find_shelf(INT,TEXT);
-CREATE OR REPLACE FUNCTION migration_tools.find_shelf(org_id INT, shelf_name TEXT) RETURNS INTEGER AS $$
-DECLARE
-    return_id   INT;
-    d           INT;
-    cur_id      INT;
-BEGIN
-    SELECT INTO d MAX(distance) FROM actor.org_unit_ancestors_distance(org_id);
-    WHILE d >= 0
-    LOOP
-        SELECT INTO cur_id id FROM actor.org_unit_ancestor_at_depth(org_id,d);
-        SELECT INTO return_id id FROM asset.copy_location WHERE owning_lib = cur_id AND name ILIKE shelf_name;
-        IF return_id IS NOT NULL THEN
-                RETURN return_id;
-        END IF;
-        d := d - 1;
-    END LOOP;
-
-    RETURN NULL;
-END
-$$ LANGUAGE plpgsql;
-
--- may remove later but testing using this with new migration scripts and not loading acls until go live
-
-DROP FUNCTION IF EXISTS migration_tools.find_mig_shelf(INT,TEXT);
-CREATE OR REPLACE FUNCTION migration_tools.find_mig_shelf(org_id INT, shelf_name TEXT) RETURNS INTEGER AS $$
-DECLARE
-    return_id   INT;
-    d           INT;
-    cur_id      INT;
-BEGIN
-    SELECT INTO d MAX(distance) FROM actor.org_unit_ancestors_distance(org_id);
-    WHILE d >= 0
-    LOOP
-        SELECT INTO cur_id id FROM actor.org_unit_ancestor_at_depth(org_id,d);
-        
-        SELECT INTO return_id id FROM 
-            (SELECT * FROM asset.copy_location UNION ALL SELECT * FROM asset_copy_location) x
-            WHERE owning_lib = cur_id AND name ILIKE shelf_name;
-        IF return_id IS NOT NULL THEN
-                RETURN return_id;
-        END IF;
-        d := d - 1;
-    END LOOP;
-
-    RETURN NULL;
-END
-$$ LANGUAGE plpgsql;
-
--- convenience function for linking to the item staging table
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_item_barcode (TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        foreign_column_name ALIAS FOR $3;
-        main_column_name ALIAS FOR $4;
-        btrim_desired ALIAS FOR $5;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, foreign_column_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_name, foreign_column_name; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = ''asset_copy_legacy''
-            and column_name = $2
-        )' INTO proceed USING table_schema, main_column_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'No %.asset_copy_legacy with column %', table_schema, main_column_name; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_item';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_item BIGINT';
-
-        IF btrim_desired THEN
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_item = b.id FROM asset_copy_legacy b'
-                || ' WHERE BTRIM(a.' || quote_ident(foreign_column_name)
-                || ') = BTRIM(b.' || quote_ident(main_column_name) || ')';
-        ELSE
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_item = b.id FROM asset_copy_legacy b'
-                || ' WHERE a.' || quote_ident(foreign_column_name)
-                || ' = b.' || quote_ident(main_column_name);
-        END IF;
-
-        --EXECUTE 'SELECT migration_tools.assert(
-        --    NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(foreign_column_name) || ' <> '''' AND x_item IS NULL),
-        --    ''Cannot link every barcode'',
-        --    ''Every barcode linked''
-        --);';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for linking to the user staging table
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_user_barcode (TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        foreign_column_name ALIAS FOR $3;
-        main_column_name ALIAS FOR $4;
-        btrim_desired ALIAS FOR $5;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, foreign_column_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_name, foreign_column_name; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = ''actor_usr_legacy''
-            and column_name = $2
-        )' INTO proceed USING table_schema, main_column_name;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'No %.actor_usr_legacy with column %', table_schema, main_column_name; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_user';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_user INTEGER';
-
-        IF btrim_desired THEN
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_user = b.id FROM actor_usr_legacy b'
-                || ' WHERE BTRIM(a.' || quote_ident(foreign_column_name)
-                || ') = BTRIM(b.' || quote_ident(main_column_name) || ')';
-        ELSE
-            EXECUTE 'UPDATE ' || quote_ident(table_name) || ' a'
-                || ' SET x_user = b.id FROM actor_usr_legacy b'
-                || ' WHERE a.' || quote_ident(foreign_column_name)
-                || ' = b.' || quote_ident(main_column_name);
-        END IF;
-
-        --EXECUTE 'SELECT migration_tools.assert(
-        --    NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE ' || quote_ident(foreign_column_name) || ' <> '''' AND x_user IS NULL),
-        --    ''Cannot link every barcode'',
-        --    ''Every barcode linked''
-        --);';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for linking two tables
--- e.g. select migration_tools.handle_link(:'migschema','asset_copy','barcode','test_foo','l_barcode','x_acp_id',false);
-CREATE OR REPLACE FUNCTION migration_tools.handle_link (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_x ALIAS FOR $6;
-        btrim_desired ALIAS FOR $7;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_b)
-            || ' DROP COLUMN IF EXISTS ' || quote_ident(column_x);
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_b)
-            || ' ADD COLUMN ' || quote_ident(column_x) || ' BIGINT';
-
-        IF btrim_desired THEN
-            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-                || ' SET ' || quote_ident(column_x) || ' = a.id FROM ' || quote_ident(table_a) || ' a'
-                || ' WHERE BTRIM(a.' || quote_ident(column_a)
-                || ') = BTRIM(b.' || quote_ident(column_b) || ')';
-        ELSE
-            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-                || ' SET ' || quote_ident(column_x) || ' = a.id FROM ' || quote_ident(table_a) || ' a'
-                || ' WHERE a.' || quote_ident(column_a)
-                || ' = b.' || quote_ident(column_b);
-        END IF;
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for linking two tables, but copying column w into column x instead of "id"
--- e.g. select migration_tools.handle_link2(:'migschema','asset_copy','barcode','test_foo','l_barcode','id','x_acp_id',false);
-CREATE OR REPLACE FUNCTION migration_tools.handle_link2 (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,BOOLEAN) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_w ALIAS FOR $6;
-        column_x ALIAS FOR $7;
-        btrim_desired ALIAS FOR $8;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_b)
-            || ' DROP COLUMN IF EXISTS ' || quote_ident(column_x);
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_b)
-            || ' ADD COLUMN ' || quote_ident(column_x) || ' TEXT';
-
-        IF btrim_desired THEN
-            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-                || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
-                || ' WHERE BTRIM(a.' || quote_ident(column_a)
-                || ') = BTRIM(b.' || quote_ident(column_b) || ')';
-        ELSE
-            EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-                || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
-                || ' WHERE a.' || quote_ident(column_a)
-                || ' = b.' || quote_ident(column_b);
-        END IF;
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for linking two tables, but copying column w into column x instead of "id". Unlike handle_link2, this one won't drop the target column, and it also doesn't have a final boolean argument for btrim
--- e.g. select migration_tools.handle_link3(:'migschema','asset_copy','barcode','test_foo','l_barcode','id','x_acp_id');
-CREATE OR REPLACE FUNCTION migration_tools.handle_link3 (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_w ALIAS FOR $6;
-        column_x ALIAS FOR $7;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
-            || ' WHERE a.' || quote_ident(column_a)
-            || ' = b.' || quote_ident(column_b);
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_null_or_empty_string (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_w ALIAS FOR $6;
-        column_x ALIAS FOR $7;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
-            || ' WHERE a.' || quote_ident(column_a)
-            || ' = b.' || quote_ident(column_b)
-            || ' AND NULLIF(a.' || quote_ident(column_w) || ','''') IS NOT NULL';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_null (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_w ALIAS FOR $6;
-        column_x ALIAS FOR $7;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
-            || ' WHERE a.' || quote_ident(column_a)
-            || ' = b.' || quote_ident(column_b)
-            || ' AND a.' || quote_ident(column_w) || ' IS NOT NULL';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_true (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_w ALIAS FOR $6;
-        column_x ALIAS FOR $7;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
-            || ' WHERE a.' || quote_ident(column_a)
-            || ' = b.' || quote_ident(column_b)
-            || ' AND a.' || quote_ident(column_w) || ' IS NOT TRUE';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_link3_skip_false (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_w ALIAS FOR $6;
-        column_x ALIAS FOR $7;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-            || ' SET ' || quote_ident(column_x) || ' = a.' || quote_ident(column_w) || ' FROM ' || quote_ident(table_a) || ' a'
-            || ' WHERE a.' || quote_ident(column_a)
-            || ' = b.' || quote_ident(column_b)
-            || ' AND a.' || quote_ident(column_w) || ' IS NOT FALSE';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_link3_concat_skip_null (TEXT,TEXT,TEXT,TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_a ALIAS FOR $2;
-        column_a ALIAS FOR $3;
-        table_b ALIAS FOR $4;
-        column_b ALIAS FOR $5;
-        column_w ALIAS FOR $6;
-        column_x ALIAS FOR $7;
-        proceed BOOLEAN;
-    BEGIN
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_a, column_a;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_a, column_a; 
-        END IF;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_b, column_b;
-        IF NOT proceed THEN
-            RAISE EXCEPTION '%.% missing column %', table_schema, table_b, column_b; 
-        END IF;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_b) || ' b'
-            || ' SET ' || quote_ident(column_x) || ' = CONCAT_WS('' ; '',b.' || quote_ident(column_x) || ',a.' || quote_ident(column_w) || ') FROM ' || quote_ident(table_a) || ' a'
-            || ' WHERE a.' || quote_ident(column_a)
-            || ' = b.' || quote_ident(column_b)
-            || ' AND NULLIF(a.' || quote_ident(column_w) || ','''') IS NOT NULL';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
--- convenience function for handling desired asset stat cats
-
-CREATE OR REPLACE FUNCTION migration_tools.vivicate_asset_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
-        org_shortname ALIAS FOR $4;
-        proceed BOOLEAN;
-        org INTEGER;
-        org_list INTEGER[];
-        sc TEXT;
-        sce TEXT;
-    BEGIN
-
-        SELECT 'desired_sc' || field_suffix INTO sc;
-        SELECT 'desired_sce' || field_suffix INTO sce;
-
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sc;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sc; 
-        END IF;
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sce;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sce; 
-        END IF;
-
-        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
-        IF org IS NULL THEN
-            RAISE EXCEPTION 'Cannot find org by shortname';
-        END IF;
-        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
-
-        -- caller responsible for their own truncates though we try to prevent duplicates
-        EXECUTE 'INSERT INTO asset_stat_cat (owner, name)
-            SELECT DISTINCT
-                 $1
-                ,BTRIM('||sc||')
-            FROM 
-                ' || quote_ident(table_name) || '
-            WHERE
-                NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM asset.stat_cat
-                    WHERE owner = ANY ($2)
-                    AND name = BTRIM('||sc||')
-                )
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM asset_stat_cat
-                    WHERE owner = ANY ($2)
-                    AND name = BTRIM('||sc||')
-                )
-            ORDER BY 2;'
-        USING org, org_list;
-
-        EXECUTE 'INSERT INTO asset_stat_cat_entry (stat_cat, owner, value)
-            SELECT DISTINCT
-                COALESCE(
-                    (SELECT id
-                        FROM asset.stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name))
-                   ,(SELECT id
-                        FROM asset_stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name))
-                )
-                ,$1
-                ,BTRIM('||sce||')
-            FROM 
-                ' || quote_ident(table_name) || '
-            WHERE
-                    NULLIF(BTRIM('||sc||'),'''') IS NOT NULL
-                AND NULLIF(BTRIM('||sce||'),'''') IS NOT NULL
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM asset.stat_cat_entry
-                    WHERE stat_cat = (
-                        SELECT id
-                        FROM asset.stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name)
-                    ) AND value = BTRIM('||sce||')
-                    AND owner = ANY ($2)
-                )
-                AND NOT EXISTS (
-                    SELECT id
-                    FROM asset_stat_cat_entry
-                    WHERE stat_cat = (
-                        SELECT id
-                        FROM asset_stat_cat
-                        WHERE owner = ANY ($2)
-                        AND BTRIM('||sc||') = BTRIM(name)
-                    ) AND value = BTRIM('||sce||')
-                    AND owner = ANY ($2)
-                )
-            ORDER BY 1,3;'
-        USING org, org_list;
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_asset_sc_and_sce (TEXT,TEXT,TEXT,TEXT) RETURNS VOID AS $$
-    DECLARE
-        table_schema ALIAS FOR $1;
-        table_name ALIAS FOR $2;
-        field_suffix ALIAS FOR $3; -- for distinguishing between desired_sce1, desired_sce2, etc.
-        org_shortname ALIAS FOR $4;
-        proceed BOOLEAN;
-        org INTEGER;
-        org_list INTEGER[];
-        o INTEGER;
-        sc TEXT;
-        sce TEXT;
-    BEGIN
-        SELECT 'desired_sc' || field_suffix INTO sc;
-        SELECT 'desired_sce' || field_suffix INTO sce;
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sc;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sc; 
-        END IF;
-        EXECUTE 'SELECT EXISTS (
-            SELECT 1
-            FROM information_schema.columns
-            WHERE table_schema = $1
-            AND table_name = $2
-            and column_name = $3
-        )' INTO proceed USING table_schema, table_name, sce;
-        IF NOT proceed THEN
-            RAISE EXCEPTION 'Missing column %', sce; 
-        END IF;
-
-        SELECT id INTO org FROM actor.org_unit WHERE shortname = org_shortname;
-        IF org IS NULL THEN
-            RAISE EXCEPTION 'Cannot find org by shortname';
-        END IF;
-
-        SELECT INTO org_list ARRAY_ACCUM(id) FROM actor.org_unit_full_path( org );
-
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_sc' || field_suffix;
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_sc' || field_suffix || ' INTEGER';
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' DROP COLUMN IF EXISTS x_sce' || field_suffix;
-        EXECUTE 'ALTER TABLE '
-            || quote_ident(table_name)
-            || ' ADD COLUMN x_sce' || field_suffix || ' INTEGER';
-
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
-            SET
-                x_sc' || field_suffix || ' = id
-            FROM
-                (SELECT id, name, owner FROM asset_stat_cat
-                    UNION SELECT id, name, owner FROM asset.stat_cat) u
-            WHERE
-                    BTRIM(UPPER(u.name)) = BTRIM(UPPER(' || sc || '))
-                AND u.owner = ANY ($1);'
-        USING org_list;
-
-        EXECUTE 'UPDATE ' || quote_ident(table_name) || '
-            SET
-                x_sce' || field_suffix || ' = id
-            FROM
-                (SELECT id, stat_cat, owner, value FROM asset_stat_cat_entry
-                    UNION SELECT id, stat_cat, owner, value FROM asset.stat_cat_entry) u
-            WHERE
-                    u.stat_cat = x_sc' || field_suffix || '
-                AND BTRIM(UPPER(u.value)) = BTRIM(UPPER(' || sce || '))
-                AND u.owner = ANY ($1);'
-        USING org_list;
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sc' || field_suffix || ' <> '''' AND x_sc' || field_suffix || ' IS NULL),
-            ''Cannot find a desired stat cat'',
-            ''Found all desired stat cats''
-        );';
-
-        EXECUTE 'SELECT migration_tools.assert(
-            NOT EXISTS (SELECT 1 FROM ' || quote_ident(table_name) || ' WHERE desired_sce' || field_suffix || ' <> '''' AND x_sce' || field_suffix || ' IS NULL),
-            ''Cannot find a desired stat cat entry'',
-            ''Found all desired stat cat entries''
-        );';
-
-    END;
-$$ LANGUAGE PLPGSQL STRICT VOLATILE;
-
-DROP FUNCTION IF EXISTS migration_tools.btrim_lcolumns(TEXT,TEXT);
-CREATE OR REPLACE FUNCTION migration_tools.btrim_lcolumns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
- LANGUAGE plpgsql
-AS $function$
-DECLARE
-    c_name     TEXT;
-BEGIN
-
-    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE 
-            table_name = t_name
-            AND table_schema = s_name
-            AND (data_type='text' OR data_type='character varying')
-            AND column_name like 'l_%'
-    LOOP
-       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = BTRIM(' || c_name || ')'); 
-    END LOOP;  
-
-    RETURN TRUE;
-END
-$function$;
-
-DROP FUNCTION IF EXISTS migration_tools.btrim_columns(TEXT,TEXT);
-CREATE OR REPLACE FUNCTION migration_tools.btrim_columns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
- LANGUAGE plpgsql
-AS $function$
-DECLARE
-    c_name     TEXT;
-BEGIN
-
-    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE 
-            table_name = t_name
-            AND table_schema = s_name
-            AND (data_type='text' OR data_type='character varying')
-    LOOP
-       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = BTRIM(' || c_name || ')'); 
-    END LOOP;  
-
-    RETURN TRUE;
-END
-$function$;
-
-DROP FUNCTION IF EXISTS migration_tools.null_empty_lcolumns(TEXT,TEXT);
-CREATE OR REPLACE FUNCTION migration_tools.null_empty_lcolumns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
- LANGUAGE plpgsql
-AS $function$
-DECLARE
-    c_name     TEXT;
-BEGIN
-
-    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE 
-            table_name = t_name
-            AND table_schema = s_name
-            AND (data_type='text' OR data_type='character varying')
-            AND column_name like 'l_%'
-    LOOP
-       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = NULL WHERE ' || c_name || ' = '''' '); 
-    END LOOP;  
-
-    RETURN TRUE;
-END
-$function$;
-
-DROP FUNCTION IF EXISTS migration_tools.null_empty_columns(TEXT,TEXT);
-CREATE OR REPLACE FUNCTION migration_tools.null_empty_columns(s_name TEXT, t_name TEXT) RETURNS BOOLEAN
- LANGUAGE plpgsql
-AS $function$
-DECLARE
-    c_name     TEXT;
-BEGIN
-
-    FOR c_name IN SELECT column_name FROM information_schema.columns WHERE
-            table_name = t_name
-            AND table_schema = s_name
-            AND (data_type='text' OR data_type='character varying')
-    LOOP
-       EXECUTE FORMAT('UPDATE ' || s_name || '.' || t_name || ' SET ' || c_name || ' = NULL WHERE ' || c_name || ' = '''' ');
-    END LOOP;
-
-    RETURN TRUE;
-END
-$function$;
-
-
--- convenience function for handling item barcode collisions in asset_copy_legacy
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_asset_barcode_collisions(migration_schema TEXT) RETURNS VOID AS $function$
-DECLARE
-    x_barcode TEXT;
-    x_id BIGINT;
-    row_count NUMERIC;
-    internal_collision_count NUMERIC := 0;
-    incumbent_collision_count NUMERIC := 0;
-BEGIN
-    FOR x_barcode IN SELECT barcode FROM asset_copy_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
-    LOOP
-        FOR x_id IN SELECT id FROM asset_copy WHERE barcode = x_barcode
-        LOOP
-            UPDATE asset_copy SET barcode = migration_schema || '_internal_collision_' || id || '_' || barcode WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            internal_collision_count := internal_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% internal collisions', internal_collision_count;
-    FOR x_barcode IN SELECT a.barcode FROM asset.copy a, asset_copy_legacy b WHERE x_migrate AND a.deleted IS FALSE AND a.barcode = b.barcode
-    LOOP
-        FOR x_id IN SELECT id FROM asset_copy_legacy WHERE barcode = x_barcode
-        LOOP
-            UPDATE asset_copy_legacy SET barcode = migration_schema || '_incumbent_collision_' || id || '_' || barcode WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            incumbent_collision_count := incumbent_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% incumbent collisions', incumbent_collision_count;
-END
-$function$ LANGUAGE plpgsql;
-
--- convenience function for handling patron barcode/usrname collisions in actor_usr_legacy
--- this should be ran prior to populating actor_card
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_actor_barcode_collisions(migration_schema TEXT) RETURNS VOID AS $function$
-DECLARE
-    x_barcode TEXT;
-    x_id BIGINT;
-    row_count NUMERIC;
-    internal_collision_count NUMERIC := 0;
-    incumbent_barcode_collision_count NUMERIC := 0;
-    incumbent_usrname_collision_count NUMERIC := 0;
-BEGIN
-    FOR x_barcode IN SELECT usrname FROM actor_usr_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
-    LOOP
-        FOR x_id IN SELECT id FROM actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
-        LOOP
-            UPDATE actor_usr_legacy SET usrname = migration_schema || '_internal_collision_' || id || '_' || usrname WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            internal_collision_count := internal_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% internal usrname/barcode collisions', internal_collision_count;
-
-    FOR x_barcode IN
-        SELECT a.barcode FROM actor.card a, actor_usr_legacy b WHERE x_migrate AND a.barcode = b.usrname
-    LOOP
-        FOR x_id IN SELECT DISTINCT id FROM actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
-        LOOP
-            UPDATE actor_usr_legacy SET usrname = migration_schema || '_incumbent_barcode_collision_' || id || '_' || usrname WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            incumbent_barcode_collision_count := incumbent_barcode_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% incumbent barcode collisions', incumbent_barcode_collision_count;
-
-    FOR x_barcode IN
-        SELECT a.usrname FROM actor.usr a, actor_usr_legacy b WHERE x_migrate AND a.usrname = b.usrname
-    LOOP
-        FOR x_id IN SELECT DISTINCT id FROM actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
-        LOOP
-            UPDATE actor_usr_legacy SET usrname = migration_schema || '_incumbent_usrname_collision_' || id || '_' || usrname WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            incumbent_usrname_collision_count := incumbent_usrname_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% incumbent usrname collisions (post barcode collision munging)', incumbent_usrname_collision_count;
-END
-$function$ LANGUAGE plpgsql;
-
--- alternate version: convenience function for handling item barcode collisions in asset_copy_legacy
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_asset_barcode_collisions2(migration_schema TEXT) RETURNS VOID AS $function$
-DECLARE
-    x_barcode TEXT;
-    x_id BIGINT;
-    row_count NUMERIC;
-    internal_collision_count NUMERIC := 0;
-    incumbent_collision_count NUMERIC := 0;
-BEGIN
-    FOR x_barcode IN SELECT barcode FROM asset_copy_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
-    LOOP
-        FOR x_id IN SELECT id FROM asset_copy WHERE barcode = x_barcode
-        LOOP
-            UPDATE asset_copy SET barcode = migration_schema || '_internal_collision_' || id || '_' || barcode WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            internal_collision_count := internal_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% internal collisions', internal_collision_count;
-    FOR x_barcode IN SELECT a.barcode FROM asset.copy a, asset_copy_legacy b WHERE x_migrate AND a.deleted IS FALSE AND a.barcode = b.barcode
-    LOOP
-        FOR x_id IN SELECT id FROM asset_copy_legacy WHERE barcode = x_barcode
-        LOOP
-            UPDATE asset_copy_legacy SET barcode = migration_schema || '_' || barcode WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            incumbent_collision_count := incumbent_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% incumbent collisions', incumbent_collision_count;
-END
-$function$ LANGUAGE plpgsql;
-
--- alternate version: convenience function for handling patron barcode/usrname collisions in actor_usr_legacy
--- this should be ran prior to populating actor_card
-
-CREATE OR REPLACE FUNCTION migration_tools.handle_actor_barcode_collisions2(migration_schema TEXT) RETURNS VOID AS $function$
-DECLARE
-    x_barcode TEXT;
-    x_id BIGINT;
-    row_count NUMERIC;
-    internal_collision_count NUMERIC := 0;
-    incumbent_barcode_collision_count NUMERIC := 0;
-    incumbent_usrname_collision_count NUMERIC := 0;
-BEGIN
-    FOR x_barcode IN SELECT usrname FROM actor_usr_legacy WHERE x_migrate GROUP BY 1 HAVING COUNT(*) > 1
-    LOOP
-        FOR x_id IN SELECT id FROM actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
-        LOOP
-            UPDATE actor_usr_legacy SET usrname = migration_schema || '_internal_collision_' || id || '_' || usrname WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            internal_collision_count := internal_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% internal usrname/barcode collisions', internal_collision_count;
-
-    FOR x_barcode IN
-        SELECT a.barcode FROM actor.card a, actor_usr_legacy b WHERE x_migrate AND a.barcode = b.usrname
-    LOOP
-        FOR x_id IN SELECT DISTINCT id FROM actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
-        LOOP
-            UPDATE actor_usr_legacy SET usrname = migration_schema || '_' || usrname WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            incumbent_barcode_collision_count := incumbent_barcode_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% incumbent barcode collisions', incumbent_barcode_collision_count;
-
-    FOR x_barcode IN
-        SELECT a.usrname FROM actor.usr a, actor_usr_legacy b WHERE x_migrate AND a.usrname = b.usrname
-    LOOP
-        FOR x_id IN SELECT DISTINCT id FROM actor_usr_legacy WHERE x_migrate AND usrname = x_barcode
-        LOOP
-            UPDATE actor_usr_legacy SET usrname = migration_schema || '_' || usrname WHERE id = x_id;
-            GET DIAGNOSTICS row_count = ROW_COUNT;
-            incumbent_usrname_collision_count := incumbent_usrname_collision_count + row_count;
-        END LOOP;
-    END LOOP;
-    RAISE INFO '% incumbent usrname collisions (post barcode collision munging)', incumbent_usrname_collision_count;
-END
-$function$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION migration_tools.is_circ_rule_safe_to_delete( test_matchpoint INTEGER ) RETURNS BOOLEAN AS $func$
--- WARNING: Use at your own risk
--- FIXME: not considering marc_type, marc_form, marc_bib_level, marc_vr_format, usr_age_lower_bound, usr_age_upper_bound, item_age
-DECLARE
-    item_object asset.copy%ROWTYPE;
-    user_object actor.usr%ROWTYPE;
-    test_rule_object config.circ_matrix_matchpoint%ROWTYPE;
-    result_rule_object config.circ_matrix_matchpoint%ROWTYPE;
-    safe_to_delete BOOLEAN := FALSE;
-    m action.found_circ_matrix_matchpoint;
-    n action.found_circ_matrix_matchpoint;
-    -- ( success BOOL, matchpoint config.circ_matrix_matchpoint, buildrows INT[] )
-    result_matchpoint INTEGER;
-BEGIN
-    SELECT INTO test_rule_object * FROM config.circ_matrix_matchpoint WHERE id = test_matchpoint;
-    RAISE INFO 'testing rule: %', test_rule_object;
-
-    INSERT INTO actor.usr (
-        profile,
-        usrname,
-        passwd,
-        ident_type,
-        first_given_name,
-        family_name,
-        home_ou,
-        juvenile
-    ) SELECT
-        COALESCE(test_rule_object.grp, 2),
-        'is_circ_rule_safe_to_delete_' || test_matchpoint || '_' || NOW()::text,
-        MD5(NOW()::TEXT),
-        1,
-        'Ima',
-        'Test',
-        COALESCE(test_rule_object.user_home_ou, test_rule_object.org_unit),
-        COALESCE(test_rule_object.juvenile_flag, FALSE)
-    ;
-    
-    SELECT INTO user_object * FROM actor.usr WHERE id = currval('actor.usr_id_seq');
-
-    INSERT INTO asset.call_number (
-        creator,
-        editor,
-        record,
-        owning_lib,
-        label,
-        label_class
-    ) SELECT
-        1,
-        1,
-        -1,
-        COALESCE(test_rule_object.copy_owning_lib,test_rule_object.org_unit),
-        'is_circ_rule_safe_to_delete_' || test_matchpoint || '_' || NOW()::text,
-        1
-    ;
-
-    INSERT INTO asset.copy (
-        barcode,
-        circ_lib,
-        creator,
-        call_number,
-        editor,
-        location,
-        loan_duration,
-        fine_level,
-        ref,
-        circ_modifier
-    ) SELECT
-        'is_circ_rule_safe_to_delete_' || test_matchpoint || '_' || NOW()::text,
-        COALESCE(test_rule_object.copy_circ_lib,test_rule_object.org_unit),
-        1,
-        currval('asset.call_number_id_seq'),
-        1,
-        COALESCE(test_rule_object.copy_location,1),
-        2,
-        2,
-        COALESCE(test_rule_object.ref_flag,FALSE),
-        test_rule_object.circ_modifier
-    ;
-
-    SELECT INTO item_object * FROM asset.copy WHERE id = currval('asset.copy_id_seq');
-
-    SELECT INTO m * FROM action.find_circ_matrix_matchpoint(
-        test_rule_object.org_unit,
-        item_object,
-        user_object,
-        COALESCE(test_rule_object.is_renewal,FALSE)
-    );
-    RAISE INFO '   action.find_circ_matrix_matchpoint(%,%,%,%) = (%,%,%)',
-        test_rule_object.org_unit,
-        item_object.id,
-        user_object.id,
-        COALESCE(test_rule_object.is_renewal,FALSE),
-        m.success,
-        m.matchpoint,
-        m.buildrows
-    ;
-
-    --  disable the rule being tested to see if the outcome changes
-    UPDATE config.circ_matrix_matchpoint SET active = FALSE WHERE id = (m.matchpoint).id;
-
-    SELECT INTO n * FROM action.find_circ_matrix_matchpoint(
-        test_rule_object.org_unit,
-        item_object,
-        user_object,
-        COALESCE(test_rule_object.is_renewal,FALSE)
-    );
-    RAISE INFO 'VS action.find_circ_matrix_matchpoint(%,%,%,%) = (%,%,%)',
-        test_rule_object.org_unit,
-        item_object.id,
-        user_object.id,
-        COALESCE(test_rule_object.is_renewal,FALSE),
-        n.success,
-        n.matchpoint,
-        n.buildrows
-    ;
-
-    -- FIXME: We could dig deeper and see if the referenced config.rule_*
-    -- entries are effectively equivalent, but for now, let's assume no
-    -- duplicate rules at that level
-    IF (
-            (m.matchpoint).circulate = (n.matchpoint).circulate
-        AND (m.matchpoint).duration_rule = (n.matchpoint).duration_rule
-        AND (m.matchpoint).recurring_fine_rule = (n.matchpoint).recurring_fine_rule
-        AND (m.matchpoint).max_fine_rule = (n.matchpoint).max_fine_rule
-        AND (
-                (m.matchpoint).hard_due_date = (n.matchpoint).hard_due_date
-                OR (
-                        (m.matchpoint).hard_due_date IS NULL
-                    AND (n.matchpoint).hard_due_date IS NULL
-                )
-        )
-        AND (
-                (m.matchpoint).renewals = (n.matchpoint).renewals
-                OR (
-                        (m.matchpoint).renewals IS NULL
-                    AND (n.matchpoint).renewals IS NULL
-                )
-        )
-        AND (
-                (m.matchpoint).grace_period = (n.matchpoint).grace_period
-                OR (
-                        (m.matchpoint).grace_period IS NULL
-                    AND (n.matchpoint).grace_period IS NULL
-                )
-        )
-        AND (
-                (m.matchpoint).total_copy_hold_ratio = (n.matchpoint).total_copy_hold_ratio
-                OR (
-                        (m.matchpoint).total_copy_hold_ratio IS NULL
-                    AND (n.matchpoint).total_copy_hold_ratio IS NULL
-                )
-        )
-        AND (
-                (m.matchpoint).available_copy_hold_ratio = (n.matchpoint).available_copy_hold_ratio
-                OR (
-                        (m.matchpoint).available_copy_hold_ratio IS NULL
-                    AND (n.matchpoint).available_copy_hold_ratio IS NULL
-                )
-        )
-        AND NOT EXISTS (
-            SELECT limit_set, fallthrough
-            FROM config.circ_matrix_limit_set_map
-            WHERE active and matchpoint = (m.matchpoint).id
-            EXCEPT
-            SELECT limit_set, fallthrough
-            FROM config.circ_matrix_limit_set_map
-            WHERE active and matchpoint = (n.matchpoint).id
-        )
-
-    ) THEN
-        RAISE INFO 'rule has same outcome';
-        safe_to_delete := TRUE;
-    ELSE
-        RAISE INFO 'rule has different outcome';
-        safe_to_delete := FALSE;
-    END IF;
-
-    RAISE EXCEPTION 'rollback the temporary changes';
-
-EXCEPTION WHEN OTHERS THEN
-
-    RAISE INFO 'inside exception block: %, %', SQLSTATE, SQLERRM;
-    RETURN safe_to_delete;
-
-END;
-$func$ LANGUAGE plpgsql;
-
+\i 00-infrastructure.sql
+\i 01-marc.sql
+\i 02-barcodes.sql
+\i 03-items.sql
+\i 04-names.sql
+\i 05-addresses.sql
+\i 06-ils-specific.sql
+\i 07-eg-specific.sql
+\i 08-casting-and-validation.sql
+\i 09-misc.sql
+\i 10-staging.sql
+\i 21-fixed-fields.sql
+\i 22-anyarray.sql
+--\i 99-deprecated.sql
diff --git a/sql/base/base_replacement.sql b/sql/base/base_replacement.sql
deleted file mode 100644 (file)
index bfdcd60..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-\i 00-infrastructure.sql
-\i 01-marc.sql
-\i 02-barcodes.sql
-\i 03-items.sql
-\i 04-names.sql
-\i 05-addresses.sql
-\i 06-ils-specific.sql
-\i 07-eg-specific.sql
-\i 08-casting-and-validation.sql
-\i 09-misc.sql
-\i 10-staging.sql
-\i 21-fixed-fields.sql
-\i 22-anyarray.sql
-\i 99-deprecated.sql
index 599a5d0..2781a07 100755 (executable)
@@ -585,7 +585,7 @@ if ($apply && -e $ARGV[0] . '.fixes') {
 ################################################################## CSV Setup
 $CSV_options{sep_char} = get_separator( path => $ARGV[0], lucky => 1 );
 if ($config && -e $config) {
-       do $config;
+       eval `cat $config`;
 }
 $csv = Text::CSV_XS->new(\%CSV_options);
 $csv->callbacks(
index 9ee8203..2d74d0a 100755 (executable)
@@ -19,7 +19,7 @@ sub init {
         $dbh = connect_db($PGDATABASE,$PGUSER,undef,$PGHOST) or die $DBI::errstr;
     } else {
         our %config;
-        do '/openils/conf/offline-config.pl';
+        eval `cat /openils/conf/offline-config.pl`;
         $dbh = DBI->connect( $config{dsn}, $config{usr}, $config{pw} ) or die $DBI::errstr;
     }
 
@@ -52,7 +52,7 @@ sub init {
                die "$csv_config does not exist\n";
        }
        if ($csv_config && -e $csv_config) {
-               do $csv_config;
+               eval `cat $csv_config`;
        }
        if (! -e $ARGV[0]) {
                die "$ARGV[0] does not exist\n";