From 9cd91942a7cdc6f1a7aa3eae70d96192f8fc5022 Mon Sep 17 00:00:00 2001
From: Gerhard Gonter <ggonter@gmail.com>
Date: Wed, 15 Jun 2016 19:06:19 +0200
Subject: [PATCH] add schema inspection code (which is not really realted to
 redmine)

---
 lib/Redmine/DB/MySQL.pm | 101 +++++++++++++++++++++++++++++++++++++---
 t_sync.pl               |   2 +-
 2 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/lib/Redmine/DB/MySQL.pm b/lib/Redmine/DB/MySQL.pm
index ca7c367..e750243 100644
--- a/lib/Redmine/DB/MySQL.pm
+++ b/lib/Redmine/DB/MySQL.pm
@@ -22,10 +22,13 @@ sub connect
   my $dbh= $self->{'_dbh'};
   return $dbh if (defined ($dbh));
 
-  my $db_con= join (':', 'dbi', map { $self->{$_} } qw(adapter database host));
-  print "db_con=[$db_con]\n";
+  my $adapter= $self->{adapter};
+  $adapter= 'mysql' if ($adapter eq 'mysql2');
+
+  my $db_con= join (':', 'dbi', $adapter, map { $self->{$_} } qw(database host));
+  # print "db_con=[$db_con]\n";
   $dbh= DBI->connect($db_con, map { $self->{$_} } qw(username password));
-  print "dbh=[$dbh]\n";
+  # print "dbh=[$dbh]\n";
   $self->{'_dbh'}= $dbh;
 }
 
@@ -40,7 +43,7 @@ sub table
   $t;
 }
 
-=head2 $con->get_all_x ($table_name, $query_ref)
+=head2 $con->get_all_x ($table_name, $query_ref, $field_ref)
 
 Query_ref is an array reference where the first parameter gives the WHERE clause (without the string "WHERE").
 The query should not contain untrustable values, these should be indicated by placeholders (an "?" for each
@@ -57,6 +60,7 @@ sub get_all_x
   my $self= shift;
   my $table= shift;
   my $where= shift;
+  my $field_ref= shift || '*';
 
   my $dbh= $self->connect();
   return undef unless (defined ($dbh));
@@ -64,7 +68,7 @@ sub get_all_x
   # my $project= new Redmine::DB::Project (%par);
   # print "project: ", Dumper ($project);
 
-  my $ss= "SELECT * FROM $table";
+  my $ss= "SELECT $field_ref FROM $table";
 
   my @v= ();
   if (defined ($where))
@@ -88,16 +92,101 @@ sub get_all_x
   my $t= $self->table($table);
   my $tt= {};
 
+  my $pri= (exists ($self->{PRI}->{$table})) ? $self->{PRI}->{$table} : 'id';
   while (defined (my $x= $sth->fetchrow_hashref()))
   {
     print "x: ", Dumper ($x) if ($show_fetched);
-    my $i= $x->{'id'};
+    my $i= $x->{$pri};
     $t->{$i}= $tt->{$i}= $x;
   }
 
   $tt;
 }
 
+sub tables
+{
+  my $self= shift;
+
+  my $dbh= $self->connect();
+  return undef unless (defined ($dbh));
+
+  my $ss= "SHOW TABLES";
+
+  if ($show_query)
+  {
+    print "ss=[$ss]\n";
+  }
+
+  my $sth= $dbh->prepare($ss) or print $dbh->errstr;
+  # print "sth=[$sth]\n";
+  $sth->execute();
+
+  my $table_filter= $self->{table_filter};
+
+  my $table_names= $self->{table_names}= {};
+  while (defined (my $table_name= $sth->fetchrow_array()))
+  {
+    next if (defined ($table_filter) && &$table_filter($table_name) == 0);
+    $table_names->{$table_name}= undef;
+  }
+
+  $table_names;
+}
+
+sub desc_all
+{
+  my $self= shift;
+
+  my $table_names= $self->tables();
+
+  foreach my $table_name (sort keys %$table_names)
+  {
+    $self->desc($table_name);
+  }
+}
+
+sub desc
+{
+  my $self= shift;
+  my $table= shift;
+
+  my $dbh= $self->connect();
+  return undef unless (defined ($dbh));
+
+  my $ss= "DESC `$table`";
+
+  if ($show_query)
+  {
+    print "ss=[$ss]\n";
+  }
+
+  my $sth= $dbh->prepare($ss) or print $dbh->errstr;
+  # print "sth=[$sth]\n";
+  $sth->execute();
+
+  # get table definition
+  my $td= $self->{table_names}->{$table};
+  my $td= $self->{table_names}->{$table}= {} unless (defined ($td));
+  my $tt= $td->{'columns'}= [];
+
+  # my @desc_columns= qw(Field Type Null Key Default Extra);
+
+  while (defined (my @x= $sth->fetchrow_array()))
+  {
+    last unless (@x);
+    # print "x: ", Dumper (\@x); # if ($show_fetched);
+    push (@$tt, \@x);
+
+    if ($x[3] eq 'PRI')
+    {
+      $self->{PRI}->{$table}= $x[0];
+    }
+  }
+
+  $td;
+}
+
+# BEGIN Redmine specific part
 sub fetch_custom
 {
   my $db= shift;
diff --git a/t_sync.pl b/t_sync.pl
index cd244c7..d9213c7 100755
--- a/t_sync.pl
+++ b/t_sync.pl
@@ -300,7 +300,7 @@ sub read_configs
   # $ss->{'_cfg'}=
   my $c= $x->{$db};
 
-  $c->{'adapter'}= 'mysql' if ($c->{'adapter'} eq 'mysql2');
+  # $c->{'adapter'}= 'mysql' if ($c->{'adapter'} eq 'mysql2');
   my $m= new Redmine::DB::MySQL (%$c);
 
   $ss->{'m'}= $m;
-- 
GitLab