Guest User

Untitled

a guest
Apr 21st, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.22 KB | None | 0 0
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use utf8;
  5. use DBD::Oracle;
  6. use Text::ASCIITable;
  7. use Term::ReadLine;
  8.  
  9. my $dbh;
  10. BEGIN {
  11. my $dsn = 'dbi:Oracle:'.(shift || 'default dsn'),
  12. my $user = (shift || 'default user');
  13. my $pass = (shift || 'default pass');
  14.  
  15. $dbh = DBI->connect(
  16. $dsn, $user, $pass,
  17. {
  18. AutoCommit => 0,
  19. RaiseError => 0,
  20. PrintError => 1,
  21. },
  22. ) or die $DBI::errstr;
  23. }
  24. END { $dbh->disconnect() if $dbh }
  25.  
  26. my $history;
  27. my $term;
  28. BEGIN {
  29. $history = "$ENV{HOME}/.oraclient_history";
  30. $term = new Term::ReadLine 'OraClient' or die "can't load term";
  31. $term->StifleHistory(500);
  32. $term->Features->{readHistory} and
  33. $term->ReadHistory($history) and
  34. print "loaded $history\n";
  35. }
  36. END {
  37. print "\n";
  38. $term and
  39. $term->Features->{writeHistory} and
  40. $term->WriteHistory($history) and
  41. print "saved $history\n";
  42. }
  43.  
  44.  
  45. my $interactive = -t STDIN;
  46. my @bold = $interactive ? ("\e[1m","\e[m") : ('','');
  47. sub getline() { $interactive ? $term->readline('sql>') : <STDIN> }
  48.  
  49. my $attribs = $term->Attribs;
  50. $attribs->{completion_word} = [qw(
  51. delete from group order having insert join merge
  52. prepare select truncate union update where rownum
  53. )];
  54. $attribs->{completion_append_character} = '';
  55. $attribs->{completion_entry_function} =
  56. $attribs->{list_completion_function};
  57.  
  58. my $database_object_match = [];
  59. sub database_object_generator($$@)
  60. {
  61. my ($text, $state, $sql, @bind) = @_;
  62. unless($state) {
  63. $database_object_match = $dbh->selectcol_arrayref($sql, undef, @bind);
  64. }
  65. while(defined($_ = pop @$database_object_match)) {
  66. return lc $_ if /^$text/i
  67. }
  68. return undef;
  69. }
  70.  
  71. # TODO collect table aliases and map them
  72. sub column_generator($$)
  73. {
  74. my ($text, $state) = @_;
  75. database_object_generator($text, $state, qq{
  76. SELECT table_name || '.' || column_name
  77. FROM all_tab_columns
  78. WHERE table_name = ? AND column_name LIKE ?
  79. ORDER BY table_name
  80. }, uc($1), uc($2).'%') if $text =~ /^(\w+)\.(\w*)/
  81. }
  82. sub table_generator($$)
  83. {
  84. my ($text, $state) = @_;
  85. database_object_generator($text, $state, qq{
  86. SELECT table_name
  87. FROM all_tables
  88. WHERE table_name LIKE ?
  89. ORDER BY table_name
  90. }, uc($text).'%')
  91. }
  92.  
  93. $attribs->{attempted_completion_function} = sub {
  94. my ($text, $line, $start, $end) = @_;
  95. my @match = ();
  96. my @try = ();
  97. push @try, \&table_generator if $text =~ /^tb/;
  98. push @try, \&column_generator if $text =~ /^\w+\.\w*/;
  99. push @try, $attribs->{list_completion_function};
  100. push @try, \&table_generator unless grep {$_ eq \&table_generator} @try;
  101. while(@try && !(@match = $term->completion_matches($text, pop @try))) { ;}
  102. @match
  103. };
  104.  
  105. my $sth;
  106. while ( defined (my $input = getline) ) {
  107. for my $cmd (split /;/, $input) {
  108. next unless $cmd =~ /\S/;
  109. print "$cmd\n";
  110. $sth = $dbh->prepare($cmd) and
  111. do {
  112. $sth->execute() and
  113. @{$sth->{NAME}} and
  114. do {
  115. my $table = Text::ASCIITable->new({
  116. allowANSI => 1,
  117. undef_as => "$bold[0]NULL$bold[1]",
  118. });
  119. my @col =
  120. map {"$bold[0]$_$bold[1]"}
  121. @{$sth->{NAME_uc}};
  122. $table->setCols(@col);
  123. my $i = 0;
  124. for my $row (@{$sth->fetchall_arrayref}) {
  125. $table->addRow(@$row);
  126. if(++$i % 20 == 0) {
  127. $table->addRowLine();
  128. $table->addRow(@col);
  129. $table->addRowLine();
  130. }
  131. }
  132. print $table;
  133. } or
  134. print $sth->rows, " row(s)\n\n";
  135. }
  136. }
  137. }
  138.  
  139. __END__
Add Comment
Please, Sign In to add comment