package SQLDB;
use Common;
@ISA = qw(Common);
#公開したいサブルーチン
#@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote);
use strict;
use Jcode;
use DBI;
#use CGI;
#use File::Path;
#use File::Basename;
#use File::Find;
use Symbol qw(gensym);
use Utils;
use Deps;
use CSV;
#===============================================
# 文字コード関係変数
#===============================================
# sjis, euc, jis, noconv, utf8
my $FileSystemCharCode = Deps::FileSystemCharCode();
my $PerlCharCode = Deps::PerlCharCode();
my $MySQLCharCode = Deps::MySQLCharCode();
my $WebCharCode = Deps::WebCharCode();
my $WebCharSet = Deps::WebCharSet();
#===============================================
# スクリプト大域変数
#===============================================
my $OS = Deps::OS();
my $LF = Deps::LF();
my $DirectorySeparator = Deps::DirectorySeparator();
my $SQLitePath = "c:/sqlite3/sqlite3.exe";
$SQLitePath = "/usr/bin/sqlite3" if(!-e $SQLitePath);
#===============================================
# 静的メンバー関数
#===============================================
sub Quote
{
my($this, $str, $sqlcharcode, $sourcecharcode) = (@_);
$sqlcharcode = 'no' if($sqlcharcode eq '' or $this->{CharCodeConversion});
$sqlcharcode = lc $sqlcharcode;
$sourcecharcode = lc $sourcecharcode;
my $strcharcode = Jcode::getcode(\$str);
$sourcecharcode = $strcharcode if(!defined $sourcecharcode);
#print "str code: $strcharcode [$str]
\n";
#print "sql code: $sqlcharcode
\n";
#print "source code: $sourcecharcode
\n";
if($this->DBMName() =~ /csv/i) {
if($strcharcode eq 'ascii') {
my $dbh = $this->dbh();
$str = $dbh->quote($str);
$str =~ s/^'//;
$str =~ s/'$//;
$str =~ s/\"/\\"/g;
# $str =~ s/\"/\"\"/g; # \","" どちらのquoteでもOK。ただし、"=>'に変換される
}
else {
$str =~ s/\\/\\\\/g;
$str =~ s/\"/\\"/g;
$str =~ s/'/''/g;
if($sqlcharcode ne 'no' and $sqlcharcode ne $sourcecharcode) {
Jcode::convert(\$str, $sqlcharcode, $sourcecharcode, "z");
}
}
#my $sc = Jcode::getcode(\$str);
#print "str [$str] ($sc)
";
return $str;
}
elsif($this->DBMName() =~ /SQLite/i) {
# my $dbh = $this->dbh();
# $str = $dbh->quote($str);
# $str =~ s/^'//;
# $str =~ s/'$//;
if($sqlcharcode ne 'no' and $strcharcode ne 'ascii') {
Jcode::convert(\$str, 'jis', $sourcecharcode, "z");
}
$str =~ s/\\/\\\\/g; # \
$str =~ s/\"/\"\"/g;
Jcode::convert(\$str, $sqlcharcode) if($sqlcharcode ne 'no' and $strcharcode ne 'ascii');
return $str;
}
elsif($this->DBMName() =~ /Pg/i) {
#print "char: $sqlcharcode, $sourcecharcode\n";
$str = $this->dbh()->quote($str);
$str =~ s/^'//;
$str =~ s/'$//;
Jcode::convert(\$str, $sqlcharcode, $sourcecharcode, "z")
if($sqlcharcode ne 'no' and $sqlcharcode ne $sourcecharcode);
return $str;
}
else {
my $s;
if($this->{UseOriginalQuote}) {
Jcode::convert(\$str, $sqlcharcode, $sourcecharcode, "z") if($sqlcharcode ne 'no' and $sqlcharcode ne $sourcecharcode);
$s = $this->dbh()->quote($str);
# $s =~ s/^\'//;
# $s =~ s/\'$//;
}
else {
#print "My\n";
#exit;
$s = MySQLQuote($str, $sqlcharcode, $sourcecharcode);
}
#print "s: $s
";
return $s;
}
#Perl DBIの関数quoteを使った場合。ただし、sjisの\を含む漢字もクオートとしてしまうため、だめ
my $dbh = $this->dbh();
$sourcecharcode = Jcode::getcode(\$str);
Jcode::convert(\$str, $sqlcharcode, $sourcecharcode, "z")
if($sqlcharcode ne 'no' and $strcharcode ne 'ascii');
$str = $dbh->quote($str);
$str =~ s/^'//;
$str =~ s/'$//;
return $str;
}
sub MySQLQuote
{
my($str, $sqlcharcode, $sourcecharcode) = (@_);
my $strcharcode = Jcode::getcode(\$str);
$sourcecharcode = $strcharcode if(!defined $sourcecharcode);
$sqlcharcode = 'no' if($sqlcharcode eq '');
#print "str code: $strcharcode [$str]
\n";
#print "sql code: $sqlcharcode
\n";
#print "source code: $sourcecharcode
\n";
if($sqlcharcode ne '') {
## my $j = jcode($str);
## $str = $j->h2z->jis;
## Jcode::convert(\$str, 'jis');
$str =~ s/\\/\\\\/g; # if($strcharcode =~ /jis/i or $strcharcode =~ /euc/i);
if($sourcecharcode ne 'utf8') {
Jcode::convert(\$str, 'euc', $sourcecharcode, "z")
if($sqlcharcode ne 'no' and $sqlcharcode ne $sourcecharcode);
}
#"表"が最後に来ると、'\'でクォートされないので、スペースをつける
# $str =~ s/$/ /;
$str =~ s/"/\\"/g;
$str =~ s/'/\\'/g;
# $str =~ s/ $//;
if($sourcecharcode ne 'utf8') {
Jcode::convert(\$str, $sqlcharcode, 'euc') if($sqlcharcode ne 'no' and $sqlcharcode ne $sourcecharcode);
}
else {
## Jcode::convert(\$str, $sqlcharcode) if($sqlcharcode ne 'no' and $sqlcharcode ne $sourcecharcode);
if($strcharcode eq $sqlcharcode) {
}
elsif($sqlcharcode ne 'no' and $sqlcharcode ne $sourcecharcode) {
# 2010/3/29 Schedule3.plで文字化けするので、この変換はやめる
# Jcode::convert(\$str, $sqlcharcode, $sourcecharcode);
}
}
}
else {
$str =~ s/\\/\\\\/g;
$str =~ s/"/\\"/g;
$str =~ s/'/\\'/g;
}
## $str =~ s/\c[/\\\c[/g; # ESC
## $str =~ s/\//\\\//g; # \
## $str =~ s/\:/\\\:/g;
## $str =~ s/\(/\\\(/g;
## $str =~ s/\)/\\\)/g;
## $str =~ s/\[([^\c[])/\\\[\1/g;
## $str =~ s/\[/\\\[/g;
## $str =~ s/\]/\\\]/g;
#文字の最後が'\'だけは変
$str =~ s/\\$//;# if($str !~ /\\\\$/);
#print " [$str]
";
return $str;
}
sub GetDBDNameFromDBManagerName
{
my ($ManagerName) = @_;
if($ManagerName =~ /mysql/i) {
return 'mysql';
}
elsif($ManagerName =~ /Postgre.*SQL/i or $ManagerName =~ /Pg/i) {
return 'Pg';
}
elsif($ManagerName =~ /sqlite/i) {
return 'SQLite';
}
elsif($ManagerName =~ /csv/i) {
return 'CSV';
}
elsif($ManagerName =~ /Excel/i) {
return 'Excel';
}
elsif($ManagerName =~ /Access/i or $ManagerName =~ /mdb/i) {
return 'Access';
}
elsif($ManagerName =~ /SQL.*Server/i) {
return 'SQLServer';
}
return $ManagerName;
}
#===============================================
# 変数取得関数
#===============================================
#sub print {
# my ($this, @a) = @_;
## return $this->App()->print(@a) if($this->App());
# return $this->App()->print(@a);
## return print(@a);
#}
#sub DebugPrint {
# my ($this, @a) = @_;
# return 1 unless($this->Debug());
# return $this->print(@a);
#}
#sub Debug {
# my ($this) = @_;
# return $this->App()->Debug() if($this->App());
# return $this->{'Debug'};
#}
#sub SetDebug {
# my ($this,$f) = @_;
# return $this->App()->SetDebug($f) if($this->App());
# return $this->{'Debug'} = $f;
#}
sub SetSQLitePath { my ($this,$p)=@_; return $this->{SQLitePath} = $p; }
sub SQLitePath { return shift->{SQLitePath}; }
sub DBMName {
my ($this) = @_;
$this->{DBMName} = 'mysql' if(!defined $this->{DBMName});
return $this->{DBMName};
}
sub SetDBMName { my($this,$d)=@_; return $this->{'DBMName'} = $d; }
sub db { return shift->{'dbh'}; }
sub dbh { return shift->{'dbh'}; }
sub sth { return shift->{'sth'}; }
sub DBServer { return shift->{'DBServer'}; }
sub DBName { return shift->{'DBName'}; }
sub DBUser { return shift->{'DBUser'}; }
sub DBPassword { return shift->{'DBPassword'}; }
sub AutoIncrementColumn { return shift->{AutoIncrementColumn}; }
sub SetAutoIncrementColumn {
my ($this, $column) = @_;
return $this->{AutoIncrementColumn} = $column;
}
sub DBCharCode { return shift->{'DBCharCode'}; }
sub SetDBCharCode { my ($this,$c)=@_; return shift->{DBCharCode} = $c; }
sub SourceCharCode { return shift->{'SourceCharCode'}; }
sub SetSourceCharCode { my ($this,$c)=@_; return shift->{SourceCharCode} = $c; }
sub SetCharCodeConversion { my ($this,$f)=@_; return shift->{CharCodeConversion} = $f; }
sub SetUseOriginalQuote { my ($this,$f)=@_; return shift->{UseOriginalQuote} = $f; }
sub ErrorNum { return DBI::err; };
sub ErrorStr { return DBI::errstr; };
sub nFields {
my ($this, $sth) = @_;
$sth = $this->sth() unless($sth);
return undef unless($sth);
return $sth->{"NUM_OF_FIELDS"};
}
sub pFieldNames {
my ($this, $sth) = @_;
$sth = $this->sth() unless($sth);
return undef unless($sth);
return $sth->{"NAME"};
}
sub GetHitDataNumber
{
my ($this, $TableName, $condition) = @_;
my $nHitData = $this->IsExistData($TableName, $condition);
return $nHitData;
}
#sub GetNextHit()
#===============================================
# コンストラクタ、デストラクタ
#===============================================
sub new
{
my ($module, $DBMName, $CharCode, $DBServer, $DBUser, $DBPassword, $DBName,
$PrintDBIError, $PrintError) = @_;
my $this = {};
bless $this;
$this->Initialize();
$this->SetSQLitePath($SQLitePath);
if($DBMName =~ /csv/i) {
$this->{'DBMName'} = 'CSV';
}
elsif($DBMName =~ /Excel/i) {
$this->{'DBMName'} = 'Excel';
}
elsif($DBMName =~ /(pg|postgre)/i) {
$this->{'DBMName'} = 'Pg';
}
elsif($DBMName =~ /mysql/i) {
$this->{'DBMName'} = 'mysql';
}
elsif($DBMName =~ /sql/i) {
$this->{'DBMName'} = $DBMName;
}
elsif($DBMName =~ /Access/i) {
$this->{'DBMName'} = 'Access';
}
elsif($DBMName =~ /SQL.*Server/i) {
$this->{'DBMName'} = 'SQLServer';
}
else {
print "Warning in SQLDB::new: [$DBMName] is not implemented.\n" if($PrintError);
($module, $CharCode, $DBServer, $DBUser, $DBPassword, $DBName, $PrintDBIError, $PrintError) = @_;
$this->{'DBMName'} = 'mysql';
}
$this->{'DBCharCode'} = $CharCode if($CharCode);
if($DBName) {
$this->Open($DBServer, $DBUser, $DBPassword, $DBName,
$CharCode, $PrintDBIError, $PrintError);
}
return $this;
}
sub DESTROY
{
my $this = shift;
$this->Close();
}
#===============================================
# 一般関数
#===============================================
sub Initialize
{
my ($this) = @_;
undef $this->{'DBCharCode'};
undef $this->{'Debug'};
undef $this->{'DBServer'};
undef $this->{'DBName'};
undef $this->{'DBUser'};
undef $this->{'DBPassword'};
}
sub Open
{
my ($this, $DBServer, $DBUser, $DBPassword, $DBName, $CharCode, $PrintDBIError, $PrintError) = @_;
$PrintDBIError = 1 unless(defined $PrintDBIError);
$PrintError = 1 unless(defined $PrintError);
$this->{'DBCharCode'} = $CharCode if($CharCode);
$this->{'DBServer'} = $DBServer;
$this->{'DBName'} = $DBName;
$this->{'DBUser'} = $DBUser;
$this->{'DBPassword'} = $DBPassword;
# DBIのエラー表示属性の設定
my %Attributes = ();
if(!$PrintDBIError) {
$Attributes{"PrintError"} = 0;
$Attributes{"RaiseError"} = 0;
}
# サーバーへの接続
my $DBMName = $this->DBMName();
if($this->DBMName() =~ /SQLServer/i) {
my $server = 'local';
$server = $DBServer if($DBServer ne '' and lc $DBServer ne 'localhost');
my $dsn = "dbi:ODBC:".
"driver={SQL Server};".
"Server=($server);database=$DBName;".
"Trusted_Connection=yes;". # yesだとWindows認証
"AutoTranslate=No;";
$this->{dbh} = DBI->connect($dsn, $DBUser, $DBPassword, \%Attributes);
}
elsif($this->DBMName() =~ /Access/i) {
my $dsn;
if($DBName eq '') {
print "Error in SQLDB::Open: Null database is not implemented for [Access].\n";
return;
# $dsn = "dbi:ODBC:driver=Microsoft Access Driver (*.mdb);dbq=tfsp05.mdb";
}
else {
$dsn = "dbi:ODBC:driver=Microsoft Access Driver (*.mdb);dbq=$DBName";
}
#print "dsn=$dsn\n";
$this->{dbh} = DBI->connect($dsn, $DBUser, $DBPassword, \%Attributes);
}
elsif($this->DBMName() =~ /pg/i) {
my $dsn;
if($DBName eq '') {
$dsn = "DBI:$DBMName:";
}
elsif($DBServer eq '' or $DBServer eq 'localhost') {
$dsn = "DBI:$DBMName:dbname=$DBName"
}
else {
$dsn = "DBI:$DBMName:dbname=$DBName;host=$DBServer";
}
if($this->{DBPort}) {
$dsn = "$dsn;Port=$this->{DBPort}";
}
#print "dsn=$dsn [$DBUser][$DBPassword]\n";
$this->{dbh} = DBI->connect($dsn, $DBUser, $DBPassword);
#print "dbh:$this->{dbh}\n";
}
elsif($this->DBMName() =~ /SQLite/i) {
my $dsn = "DBI:$DBMName:dbname=$DBName";
$this->{dbh} = DBI->connect($dsn);
}
elsif($this->DBMName() =~ /CSV/i) {
$DBName =~ s/\\/\//g;
my $dsn = "DBI:$DBMName:f_dir=$DBName";
#print "dsn: $dsn
\n";
$this->{dbh} = DBI->connect($dsn) or print "connect error: $DBI::errstr\n";
# chdir($DBName);
#print "out from connect
\n";
}
elsif($this->DBMName() =~ /Excel/i) {
$DBName =~ s/\\/\//g;
my $dsn = "DBI:$DBMName:file=$DBName";
#print "dsn: $dsn\n";
$this->{dbh} = DBI->connect($dsn);
}
elsif($this->DBMName() =~ /mysql/i) {
my $dsn;
if($DBName eq '') {
$DBName = 'mysql';
}
else {
}
$dsn = "DBI:$DBMName:database=$DBName;host=$DBServer";
if($this->{DBPort}) {
$dsn = "$dsn;port=$this->{DBPort}";
}
#print "dsn:$dsn\n";
$this->{'dbh'} = DBI->connect($dsn, $DBUser, $DBPassword, \%Attributes);
}
else {
print "Warning in SQLDB::Open: [$DBMName] is not implemented.\n";
my $dsn = "DBI:$DBMName:$DBName:$DBServer";
$this->{'dbh'} = DBI->connect($dsn, $DBUser, $DBPassword, \%Attributes);
}
if(!$this->{dbh}){
if($PrintError) {
print "Error in SQLDB::Open: Unable to connect to $DBName\n";
print " DBI::err: " . DBI::errstr . "(" . DBI::err . ")\n";
}
return undef;
}
return ($this->{dbh}, undef) unless($DBName);
if($DBMName =~ /SQLite/i or $DBMName =~ /csv/i or $DBMName =~ /Pg/i) {
#print "CSV return
\n";
return ($this->{dbh}, undef);
}
return ($this->{dbh}) if($DBName eq '');
# データベースへの接続
#Utils::InitHTML();
#print "DBN[$DBName]
\n";
return ($this->{dbh}, $this->Use($DBName, $PrintError) );
}
sub Use
{
my ($this, $DBName, $PrintError) = @_;
if($this->DBMName() =~ /SQLite/i or $this->DBMName() =~ /csv/i or
$this->DBMName() =~ /Access/i or $this->DBMName() =~ /SQLServer/i) {
return undef;
}
my $command = "use $DBName;";
if($this->DBMName() =~ /Pg/i) {
# $command = "\\c $DBName;";
return undef;
}
#print "
sql: $command
\n";
#return if($command =~ /^use\s+[\.\d]+;$/);
return undef if(!$this->{dbh});
$this->{LastFunction} = "SQLDB::Use";
$this->{LastCommand} = $command;
$this->{DBsth} = $this->{dbh}->prepare("$command\n");
if(!$this->{'DBsth'}) {
if($PrintError) {
print "Error in SQLDB::Use: Unable to prepare for opening $DBName$LF";
print " DBI::err: " . DBI::errstr . "(" . DBI::err . ")\n";
}
return undef;
}
my $result = $this->{'DBsth'}->execute;
if(!$result){
if($PrintError) {
print "Error in SQLDB::Use: Unable to execute $command$LF";
print " DBI::err: " . DBI::errstr . "(" . DBI::err . ")\n";
}
return undef;
}
$this->{DBName} = $DBName;
return $this->{DBsth};
}
sub CloseSTH
{
my ($this, $sth) = @_;
if($sth) {
$sth->finish;
return;
}
$this->{'sth'}->finish if($this->{'sth'});
undef $this->{'sth'};
$this->{'DBsth'}->finish if($this->{'DBsth'});
undef $this->{'DBsth'};
}
sub CloseDBH
{
my ($this) = @_;
$this->{'dbh'}->disconnect if($this->{'dbh'});
undef $this->{'dbh'};
}
sub Close
{
my ($this) = @_;
$this->CloseSTH();
$this->CloseDBH();
$this->Initialize();
}
sub Prepare
{
my ($this, $command, $UseNonDefSTH, $PrintError) = @_;
#print "Prepare: $command\n";
#$this->DebugPrint("SQLDB::Prepare: dbh: " . $this->dbh() . "\n");
return undef if(!$this->{'dbh'});
$this->CloseSTH() unless($UseNonDefSTH);
if($this->DBMName() =~ /csv/i) {
$command =~ s/;$//;
$command =~ s/\"/\'/g;
}
$this->{LastFunction} = "SQLDB::Prepare";
$this->{LastCommand} = $command;
my $sth = $this->{'dbh'}->prepare($command);
#print "Prepare: $command\n";
#$this->DebugPrint("SQLDB::Prepare: sth: $sth\n");
unless($sth) {
if($PrintError) {
my $dbm = $this->DBMName();
print "Error in SQLDB[$dbm]: Execute: Unable to prepare $command\n";
print " DBI::err: " . DBI::errstr . "(" . DBI::err . ")\n";
}
return undef;
}
$this->{'sth'} = $sth unless($UseNonDefSTH);
#print "sth: " . $this->{'sth'} . "\n";
return $sth;
}
sub Execute
{
my ($this, $command, $UseNonDefSTH, $PrintError) = @_;
return undef if(!$this->{'dbh'});
$this->CloseSTH();
$this->{LastFunction} = "SQLDB::Execute";
$this->{LastCommand} = $command;
my $sth = $this->Prepare($command, $UseNonDefSTH, $PrintError);
if(!$sth) {
print "Error in SQLDB::Execute: Unable to prepare for [$command]\n";
return undef;
}
my $ret = $sth->execute;
unless($ret) {
if($PrintError) {
print "Error in SQLDB::Execute: Unable to execute [$command]\n";
print " DBI::err: " . DBI::errstr . "(" . DBI::err . ")\n";
}
return undef;
}
return ($this->{'sth'} = $sth, $ret);
}
our $DidInit = 0;
sub GetNextHit
{
my ($this, $sth) = @_;
return undef if(!defined $this);
#Utils::InitHTML() if $DidInit == 0;
#$DidInit = 1;
#print(" GetNextHit: ExecuteRet=$this->{ExecuteRet} LastCommand=$this->{LastCommand} LastSQL=$this->{LastSQL}
\n");
# return undef if((!defined $this->{LastSQL} or $this->{LastSQL} eq '') and (!defined $this->{LastCommand} or $this->{LastCommand} eq ''));
# return undef if($this->{ExecuteRet} eq '0E0');
# Utils::InitHTML();
$sth = $this->{sth} unless($sth);
return undef if(!$sth);
return undef if $this->rows() == 0;
#print("ExecuteRet: $this->{$this->{ExecuteRet}}
\n");
my @a = $sth->fetchrow_array;
#print(" a=", @a, "
\n");
my $nFields = $sth->{'NUM_OF_FIELDS'};
#Utils::InitHTML();
#print("
LastSQL=", $this->{LastSQL}, "
\n");
#print(" sth=", $sth, "
\n");
my $pFieldNames = $sth->{'NAME'};
#print(" sth NAME end\n");
if(!$pFieldNames) {
# Utils::InitHTML();
# print("In SQLDB::GetNextHit()
\n");
# print("LastFunction: $this->{LastFunction}
\n");
# print("LastCommand : $this->{LastCommand}
\n");
}
my %ret;
for(my $i = 0 ; $i < $nFields ; $i++) {
my $name = $pFieldNames->[$i];
if($this->DBMName() =~ /csv/i) {
$a[$i] =~ s/''/'/g;
$a[$i] =~ s/\\\\/\\/g;
}
$ret{$name} = $a[$i];
# print("$name:$a[$i]
\n");
}
return %ret;
}
sub nHit { my ($this,$sth)=@_; return $this->nHits($sth); }
sub nHits
{
my ($this, $sth) = @_;
return $this->{nHit};
}
sub rows
{
my ($this, $sth) = @_;
$sth = $this->{'sth'} unless($sth);
return undef unless($sth);
return $sth->rows;
}
sub fetchrow_array
{
my ($this, $sth) = @_;
$sth = $this->{'sth'} unless($sth);
return $sth->fetchrow_array;
}
sub DeleteDatabase
{
my ($this, $DBName) = @_;
my $sql = "drop database $DBName;";
#$this->DebugPrint("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 0, 1);
return undef unless($sth);
$sth->finish;
return 1;
}
sub DeleteTable
{
my ($this, $DBName, $TableName, $IsPrint, $PrintError) = @_;
$IsPrint = 1 if(!defined $IsPrint);
$PrintError = 1 if(!defined $PrintError);
if($this->DBMName() !~ /SQLite/i or $this->DBMName() !~ /Pg/i) {
my $ret = $this->Use($DBName, 1);
# my $sql = "use $DBName;";
# my ($sth, $ret) = $this->Execute($sql, 0, 1);
# return undef unless($sth);
# $sth->finish;
}
my $sql = "drop table $TableName;";
#$this->DebugPrint("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 0, $PrintError);
return undef unless($sth);
$sth->finish;
return 1;
}
sub GetDatabases
{
my ($this) = @_;
my @DBs;
if($this->{DBMName} =~ /Pg/i) {
open(FILE, "psql -U postgres -l |");
while(1) {
my $in = ;
last if(!defined $in);
last if($in =~ /^-----/);
}
my $c = 0;
while(1) {
my $in = ;
last if(!defined $in);
last if($in =~ /^\s*\(/);
my ($db, $owner, $encode) = ($in =~ /^\s*(\S+)\s*\|\s*(\S+)\s*\|\s*(\S+)\s*$/);
#print "in: $in\n";
$DBs[$c++] = "$db;$owner;$encode";
}
return @DBs;;
}
elsif($this->{DBMName} =~ /SQLite/i) {
return ($this->{DBName});
}
elsif($this->{DBMName} =~ /csv/i) {
return ($this->{DBName});
}
my $sql = "show databases;";
#$this->DebugPrint("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 0, 1);
unless($sth) {
#print("Query for 'show databases' failed.
\n");
return ();
}
my $nDB = $this->rows();
$this->DebugPrint("nDatabases: $nDB\n");
for(my $i = 0 ; $i < $nDB ; $i++) {
my %hit = $this->GetNextHit();
foreach my $key (keys %hit) {
my $val = $hit{$key};
next unless(defined $val);
$this->DebugPrint(" $key: $val\n");
push(@DBs, $val);
}
}
$sth->finish;
return @DBs;
}
sub CreateDatabase
{
my ($this, $dbname) = @_;
#print "DBM: ", $this->DBMName(), " DB: $dbname\n";
return Deps::CreateDirecotry($dbname) if($this->DBMName() =~ /^csv$/i);
if($this->{DBMName} =~ /SQLite/i) {
return 1;
}
my $sql = "create database $dbname;";
my $ret;
$this->CloseSTH();
return $this->Execute($sql, 0, 1);
}
sub DescribeTable
{
my ($this, $tablename) = @_;
#print "DBM: ", $this->DBMName(), " DB: $dbname\n";
if($this->{DBMName} !~ /mysql/i) {
return 1;
}
my $sql = "DESC $tablename;";
my $ret;
$this->CloseSTH();
my $ret = $this->Execute($sql, 0, 1);
my $nHit = $this->rows();
#print "ret=$ret
\n";
#print "nHit=$nHit
\n";
my @lines;
for(my $i = 0 ; $i < $nHit ; $i++) {
my %Hit = $this->GetNextHit();
$lines[$i] = \%Hit;
}
my @Keys = keys %{$lines[0]} if($lines[0]);
return ($nHit, \@Keys, @lines);
}
sub IsExistDatabase
{
my ($this, $dbname) = @_;
return -d $dbname if($this->DBMName() =~ /^csv$/i);
if($this->{DBMName} =~ /SQLite/i) {
return -e $dbname;
}
if($this->{DBMName} =~ /Pg/i) {
my $DB = new SQLDB($this->{DBMName});
my ($dbh, $sth) = $DB->Open($this->{DBServer}, $this->{DBUser}, $this->{DBPassword}, $this->{DBName});
$DB->Close();
return $dbh;
}
$dbname = lc $dbname;
my @DBs = $this->GetDatabases();
return -1 if(@DBs == 0);
for(my $i = 0 ; $i < @DBs ; $i++) {
return 1 if($dbname eq lc $DBs[$i]);
}
return 0;
}
sub GetTables
{
my ($this, $DBName, $PrintError) = @_;
$PrintError = 1 if(!defined $PrintError);
$DBName = $this->{DBName} if(!defined $DBName);
my ($sth, $ret);
if($this->DBMName() =~ /csv/i) {
my $fmask = Utils::MakePath($DBName, "*.csv", "/", 0);
my @files = glob($fmask);
my @a;
for(my $i = 0 ; $i < @files ; $i++) {
$a[$i] = Deps::ExtractFileName($files[$i]);
}
return @a;
}
elsif($this->DBMName() =~ /Pg/i) {
my @tables = $this->dbh()->tables('', 'public', '', '');
for(my $i = 0 ; $i < @tables ; $i++) {
$tables[$i] =~ s/^public\.//;
}
return @tables;
}
elsif($this->DBMName() =~ /SQLite/i) {
my $path = (defined $this->{SQLitePath})? $this->{SQLitePath} : 'sqlite3';
my $ret = `$path $DBName .tables`;
my @tables = Utils::Split("\\s+", $ret);
return @tables;
}
else {
#Utils::InitHTML();
#print "DBN[$DBName]
\n";
my $ret = $this->Use($DBName, $PrintError);
# my $sql = "use $DBName;";
# ($sth, $ret) = $this->Execute($sql, 1, 1);
# $sth->finish if($sth);
my $sql = "show tables;";
($sth, $ret) = $this->Execute($sql, 1, 1);
return undef unless($sth);
}
my @Tables;
my $nTables = $this->rows();
$this->DebugPrint("nTables: $nTables\n");
for(my $i = 0 ; $i < $nTables ; $i++) {
my %hit = $this->GetNextHit($sth);
foreach my $key (keys %hit) {
my $val = $hit{$key};
$val = "NULL" unless(defined $val);
$this->DebugPrint(" $key: $val\n");
push(@Tables, $val);
}
}
$sth->finish;
return @Tables;
}
sub IsExistTable
{
my ($this, $DBName, $TableName) = @_;
$DBName = $this->{DBName} if(!defined $DBName);
if($this->DBMName() =~ /csv/i) {
return -e "$DBName/$TableName";
}
$TableName = lc $TableName;
my @TBLs = $this->GetTables($DBName);
for(my $i = 0 ; $i < @TBLs ; $i++) {
return 1 if(lc $TBLs[$i] eq $TableName);
}
return 0;
}
sub GetDrivers
{
my ($this) = @_;
return $this->GetDBManagers();
}
sub GetDBManagers
{
my ($this) = @_;
return DBI->available_drivers();
#print "drivers: ", scalar @drivers, "\n";
#for(my $i = 0 ; $i < @drivers ; $i++) {
# print "$i: $drivers[$i]\n";
#}
}
sub GetFieldTypes
{
my ($this, $DBName, $TableName, $FieldName, $PrintError) = @_;
$PrintError = 1 if(!defined $PrintError);
if($this->DBMName() !~ /SQLite/i) {
$this->Use($DBName, $PrintError);
}
my $sql = "select * from $TableName;";
#$this->DebugPrint("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 1, 1);
return undef unless($sth);
my $pFieldNames = $this->pFieldNames($sth);
my $pFieldTypes = $this->sth()->{TYPE};
$pFieldTypes = [] if(!defined $pFieldTypes);
my @FieldTypes = @$pFieldTypes;
my $nFieldTypes = @FieldTypes;
$this->DebugPrint(" nFieldsType: $nFieldTypes\n");
for(my $k = 0 ; $k < $nFieldTypes ; $k++) {
my $name = $pFieldNames->[$k];
my $type = $pFieldTypes->[$k];
$type = -4 if(!defined $type);
my $str = $this->GetStringType($type);
#$this->print(" $k: $name: $str [$type]\n");
$FieldTypes[$k] = $str;
}
$sth->finish;
return @FieldTypes;
}
sub GetStringType
{
my ($this, $type) = @_;
my $str;
if($type == -1) {
$str = 'text';
}
elsif($type == -4) {
$str = 'text';
}
elsif($type == 4) {
$str = 'int';
}
elsif($type == 12) {
$str = 'varchar(255)';
}
else {
$str = 'unrecognized';
}
return $str;
if($type == DBI->SQL_CHAR) {
return 'SQL_CHAR';
}
elsif($type == DBI->SQL_NUMERIC) {
return 'SQL_NUMERIC';
}
elsif($type == DBI->SQL_DECIMAL) {
return 'SQL_DECIMAL';
}
elsif($type == DBI->SQL_INTEGER) {
return 'SQL_INTEGER';
}
elsif($type == DBI->SQL_SMALLINT) {
return 'SQL_SMALLINT';
}
elsif($type == DBI->SQL_FLOAT) {
return 'SQL_FLOAT';
}
elsif($type == DBI->SQL_DOUBLE) {
return 'SQL_DOUBLE';
}
elsif($type == DBI->SQL_VARCHAR) {
return 'SQL_VARCHAR';
}
return 'unrecognized';
}
sub ExtractDBHash
{
my ($this, $DBName, $TableName, $pParams) = @_;
my @Fields = $this->GetFields($DBName, $TableName);
my %DBHash;
for(my $i = 0 ; $i < @Fields ; $i++) {
my $key = $Fields[$i];
$DBHash{$key} = $pParams->{$key} if(defined $pParams->{$key});
#print "key: $key
\n";
}
return \%DBHash;
}
sub GetFields
{
my ($this, $DBName, $TableName, $PrintError) = @_;
$PrintError = 1 if(!defined $PrintError);
if($this->DBMName() !~ /SQLite/i) {
$this->Use($DBName, $PrintError) if(defined $DBName);
# my $sql = "use $DBName;";
# my ($sth, $ret) = $this->Execute($sql, 1, 1);
# $sth->finish if($sth);
}
my $sql = "select * from $TableName;";
#$this->DebugPrint("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 1, 1);
return undef unless($sth);
my @Fields;
my $nFields = $this->nFields($sth);
$this->DebugPrint(" nFields: $nFields\n");
my $pFieldNames = $this->pFieldNames($sth);
for(my $k = 0 ; $k < $nFields ; $k++) {
my $name = $pFieldNames->[$k];
$this->DebugPrint(" $k: $name\n");
push(@Fields, $name);
}
$sth->finish;
return @Fields;
}
sub BuildDBHash
{
my ($this, $pLabels, $pHash, $DBCharCode, $AddBlankData, $SourceCharCode) = @_;
$DBCharCode = $this->{DBCharCode} if(!defined $DBCharCode);
$DBCharCode = lc $DBCharCode;
$SourceCharCode = $this->SourceCharCode() if($SourceCharCode eq '');
$DBCharCode = 'no' if($this->{CharCodeConversion});
my %d;
my $n = @$pLabels;
for(my $j = 0 ; $j < $n ; $j++) {
my $label;
if($this->{DBMName} =~ /Pg/i) {
$label = lc $pLabels->[$j];
}
else {
$label = $pLabels->[$j];
}
my $s = $pHash->{$label};
next if(!$AddBlankData and lc $label ne 'sn' and $s eq '');
$s = '' if(!defined $s);
Jcode::convert(\$s, $DBCharCode) if(defined $DBCharCode and $DBCharCode ne 'no' and $DBCharCode ne $SourceCharCode);
if(lc $label eq 'sn') {
if($s eq '') {
$s = $this->{CurrentSN} + 1;
}
if($s > $this->{CurrentSN}) {
$this->{CurrentSN} = $s
}
}
$d{$label} = $s;
}
return %d;
}
sub BuildHash
{
my ($this, $pLabels, $pData, $DBCharCode, $AddBlankData) = @_;
$DBCharCode = $this->{DBCharCode} if(!defined $DBCharCode);
$DBCharCode = lc $DBCharCode;
my $SourceCharCode = $this->SourceCharCode();
$DBCharCode = 'no' if($this->{CharCodeConversion});
my %d;
my $n = @$pLabels;
for(my $j = 0 ; $j < $n ; $j++) {
my $s = $pData->[$j];
my $label;
if($this->{DBMName} =~ /Pg/i) {
$label = lc $pLabels->[$j];
}
else {
$label = $pLabels->[$j];
}
next if(!$AddBlankData and lc $label ne 'sn' and $s eq '');
$s =~ s/\\\\/\\/g;
Jcode::convert(\$s, $DBCharCode) if(defined $DBCharCode and $DBCharCode ne 'no' and $DBCharCode ne $SourceCharCode);
if(lc $label eq 'sn') {
if($s eq '') {
$s = $this->{CurrentSN} + 1;
}
if($s > $this->{CurrentSN}) {
$this->{CurrentSN} = $s
}
}
$d{$pLabels->[$j]} = $s;
}
return %d;
}
sub GuessDatabaseDefinition
{
my ($this, $filename, $nGuessLines, $IgnoreBlank, $DBCharCode, $SourceCharCode, $IsPrint) = @_;
$nGuessLines = 100 if(!defined $nGuessLines);
$IgnoreBlank = 1 if(!defined $IgnoreBlank);
$IsPrint = 1 if(!defined $IsPrint);
$SourceCharCode = $this->SourceCharCode() if(!defined $SourceCharCode);
$DBCharCode = '' if($this->{CharCodeConversion});
$this->{CurrentSN} = 0;
my %type = (
'I' => 'int',
'F' => 'double precision',
'S' => 'text'
);
if($this->DBMName() =~ /csv/i) {
$type{F} = 'num';
}
my @DataBaseDefinition =
(
{"Field", "sn", "Type", "int", "Key", "primary"},
);
my $in = new CSV();
$in->Open($filename, "r");
if(!$in) {
print "Error in SQLDB::GuessDatabaseDefinition: Can not read [$filename].\n";
return undef;
}
my @labels = $in->ReadNextLine();
my @Type;
for(my $i = 0 ; $i < @labels ; $i++) {
$Type[$i] = 'I';
}
for(my $i = 0 ; $i < $nGuessLines ; $i++) {
my @data = $in->ReadNextLine();
last if(!defined $data[0]);
for(my $j = 0 ; $j < @labels ; $j++) {
my $s = $data[$j];
# next if($s eq '' or $Type[$j] eq 'S');
next if($Type[$j] eq 'S');
next if($IgnoreBlank and $s eq '');
if($Type[$j] eq 'I' and $s =~ /^[+\-]?\d+$/) {
$Type[$j] = 'I';
}
elsif(($Type[$j] eq 'I' or $Type[$j] eq 'F') and $s ne '' and
$s =~ /^[+\-]?\d*(\.\d*)?([EeDd][+\-]?\d+)?$/) {
$Type[$j] = 'F';
}
else {
$Type[$j] = 'S';
}
}
}
for(my $i = 0 ; $i < @labels ; $i++) {
print "$i: $labels[$i]: $Type[$i]\n" if($IsPrint);
next if($labels[$i] eq 'sn');
if($DBCharCode) {
my $s = $labels[$i];
#print "s=$s => ";
Jcode::convert(\$s, $DBCharCode, $SourceCharCode) if($DBCharCode ne 'no' and $DBCharCode ne '');
$s =~ s/[\.,]/_/g;
$s =~ s/[\r\n]/ /g;
$labels[$i] = $s;
#print "$s [$DBCharCode/$SourceCharCode]\n";
#$this->{c}++;
#exit if($this->{c} > 10);
}
my %a = (
"Field" => $labels[$i],
"Type" => $type{$Type[$i]},
"Null" => 'Yes'
);
my $n = @DataBaseDefinition;
$DataBaseDefinition[$n] = \%a;
$n++;
}
$in->Close();
return @DataBaseDefinition;
}
sub GetTableDefinition
{
my ($this, $DBName, $TableName) = @_;
my $sql = "desc $DBName.$TableName;";
my ($sth, $ret) = $this->Execute($sql, 1, 1);
return (-1) if(!$sth or !$ret);
my @pDefs;
for(my $i = 0 ; $i < $this->rows() ; $i++) {
my @a = $this->GetNextHit();
my %b;
for(my $j = 0 ; $j < @a ; $j += 2) {
$b{$a[$j]} = $a[$j+1];
}
$pDefs[$i] = \%b;
}
$sth->finish if($sth);
return @pDefs;
}
sub CreateTable
{
my ($this, $TableName, $pDefsHash) = @_;
my @pDefs = @$pDefsHash;
my $nDefs = @pDefs;
my @CSVTableDef;
# my @CSVColumnNames;
my $sql = "create table $TableName (";
my $PrimKey = '';
for(my $l = 0 ; $l < $nDefs ; $l++) {
my $pA = $pDefs[$l];
$sql .= ", " if($l > 0);
$pA->{Type} =~ s/\(\d+\)// if($pA->{Type} =~ /int/i);
#print "Def[$pA->{Type}]: $pA->{Default}\n";
if($this->DBMName() =~ /csv/i) {
# push(@CSVColumnNames, $pA->{Field});
my $type = $pA->{Type};
if($pA->{Type} =~ /int/i) {
push(@CSVTableDef, Text::CSV_XS::IV());
$type = 'integer';
}
elsif($pA->{Type} =~ /num/i) {
push(@CSVTableDef, Text::CSV_XS::NV());
}
else {
push(@CSVTableDef, Text::CSV_XS::PV());
}
$sql .= " $pA->{Field} $type";
next;
}
#print "Extra: $pA->{Extra} / DBM: ", $this->DBMName(), " / Key: $pA->{Key}\n";
if($pA->{Extra} =~ /auto.?increment/i and $this->DBMName() =~ /SQLite/i and $pA->{Key} =~ /^pri$/i) {
$sql .= " $pA->{Field} integer primary key autoincrement";
$PrimKey = '';
}
elsif($this->DBMName() =~ /Pg/i and $pA->{Key} =~ /^pri/i) {
$sql .= " $pA->{Field} integer primary key";
$PrimKey = '';
}
else {
$sql .= "$pA->{Field} $pA->{Type}";
if($pA->{Key} =~ /^pri/i) {
$PrimKey = $pA->{Field};
}
}
#print("sql: $sql\n");
if($pA->{Null} !~ /^yes$/i) {
$sql .= " not null";
}
#print "sql [Def: $pA->{Default}]: $sql => ";
if(defined $pA->{Default}) {
$sql .= " default $pA->{Default}";
}
#print "$sql\n";
if(lc $pA->{Extra} eq 'auto_increment') {
if($this->DBMName =~ /SQLite/i) {
# $sql .= " primary key autoincrement";
}
else {
$sql .= " auto_increment";
}
}
}
if($PrimKey ne '' and $this->DBMName() !~ /csv/i and $this->DBMName() !~ /Pg/i) {
$sql .= " , PRIMARY KEY ($PrimKey)";
}
# $sql .= ");";
$sql .= ")";
#print("sql: $sql\n");
if($this->DBMName() =~ /csv/i) {
#print "Def: ", @CSVTableDef, "\n";
#print "Col: ", @CSVColumnNames, "\n";
$this->dbh()->{csv_tables}->{$TableName}->{types} = \@CSVTableDef;
# $this->dbh()->{csv_tables}->{$TableName}->{col_names} = \@CSVColumnNames;
}
#print "sql: $sql => ";
#Jcode::convert(\$sql, $this->DBCharCode(), "sjis");
#print "$sql\n";
#exit;
my ($sth, $ret) = $this->Execute($sql, 1, 1);
unless($sth) {
$this->print("Error in CreateTable: $sql\n");
return 0;
}
return ($sth, $ret);
}
sub IsExistData
{
my ($this, $TableName, $condition) = @_;
return -1 if(!defined $TableName);
$condition = '' if(!defined $condition);
my $sql = "select * from $TableName";
if($condition ne '') {
$condition = "where $condition" unless($condition =~ /^\s*where/i);
$sql = "$sql $condition";
}
$sql = "$sql;";
my ($sth, $ret) = $this->Execute($sql, 1, 1);
unless($sth) {
$this->print("Error: selelct in MakeSQLUpdateCommand: "
."$sql
\n");
return 0;
}
my $nHit = $this->rows();
# my $nHit = $this->nHit();
$sth->finish;
return $nHit;
}
sub JoinSearch
{
my ($this, $TableName1, $TableName2, $JoinCondition, $condition, $fields) = @_;
$this->{nHit} = 0;
$fields = '*' if(!defined $fields or $fields eq '');
my ($sql0, $sql);
$sql0 = "select COUNT(*) from $TableName1 join $TableName2 on $JoinCondition;";
$sql = "select $fields from $TableName1 join $TableName2 on $JoinCondition;";
if($condition) {
if($condition !~ /^\s*where\s/i) {
if($condition =~ /^\s*order\s/i) {
}
else {
$condition = "where $condition";
}
}
my $condition0 = $condition;
$condition0 =~ s/\sorder\s+by\s.*$//;
$sql0 = "select COUNT(*) from $TableName1 join $TableName2 on $JoinCondition $condition0;";
$sql = "select $fields from $TableName1 join $TableName2 on $JoinCondition $condition;";
}
#$this->DebugPrint("SQLDB: sql: $sql\n\n");
# if($this->DBMName =~ /SQLite/i) {
return undef if(!$this->Execute($sql0, 1, 1));
my %Hit = $this->GetNextHit();
my @k = keys %Hit;
$this->{nHit} = $Hit{$k[0]};
#print "nHit(COUNT): $k[0] = $Hit{$k[0]}
\n";
# }
$this->{LastSQL} = $sql;
#print "SQLDB::Search: Table: $TableName
\n";
#print "SQLDB::Search: sql: $sql
\n";
return $this->Execute($sql, 1, 1);
}
sub Search
{
my ($this, $TableName, $condition, $fields) = @_;
#$this->DebugPrint("Search in: fields=[$fields] \n");
#print "SQLDB::Search: condition: $condition
\n";
$this->{nHit} = 0;
$fields = '*' if(!defined $fields or $fields eq '');
my ($sql0, $sql);
# if($TableName eq '' or $this->{DBMName} =~ /csv/i) {
if($TableName eq '') {
$sql0 = "select COUNT(*);";
$sql = "select $fields;";
}
else {
$sql0 = "select COUNT(*) from $TableName;";
$sql = "select $fields from $TableName;";
}
if($condition) {
if($condition !~ /^\s*where\s/i) {
if($condition =~ /^\s*order\s/i) {
}
else {
$condition = "where $condition";
}
}
my $condition0 = $condition;
$condition0 =~ s/\sorder\s+by\s.*$//;
# if($TableName eq '' or $this->{DBMName} =~ /csv/i) {
if($TableName eq '') {
$sql0 = "select COUNT(*) $condition0;";
$sql = "select $fields $condition;";
}
else {
$sql0 = "select COUNT(*) from $TableName $condition0;";
$sql = "select $fields from $TableName $condition;";
}
}
#$this->DebugPrint("SQLDB: sql: $sql\n\n");
# if($this->DBMName =~ /SQLite/i) {
return undef if(!$this->Execute($sql0, 1, 1));
my %Hit = $this->GetNextHit();
my @k = keys %Hit;
$this->{nHit} = $Hit{$k[0]};
#print "nHit(COUNT): $k[0] = $Hit{$k[0]}
\n";
# }
$this->{LastSQL} = $sql;
#print "SQLDB::Search: Table: $TableName
\n";
#print "SQLDB::Search: sql: $sql
\n";
my $ret = $this->Execute($sql, 1, 1);
$this->{ExecuteRet} = $ret;
#Utils::InitHTML();
#print " Execute ret: $ret
\n";
return $ret;
}
sub InsertData
{
my ($this, $TableName, @a) = @_;
my $CharCode = $this->{DBCharCode};
if($this->DBMName() =~ /csv/i and $this->AutoIncrementColumn() ne '') {
my $c = $this->AutoIncrementColumn();
$this->Search($TableName, "order by $c desc", "");
my $sn = 1;
my %Hit = $this->GetNextHit();
$sn = $Hit{sn}+1 if(defined $Hit{sn});
@a = (
@a,
$c, $sn
);
}
my $sql = $this->MakeUpdateCommand($TableName, $CharCode, "insert", '', @a);
#print "sql: $sql
\n";
my ($sth, $ret) = $this->Execute($sql, 1, 1);
return undef unless($sth);
$sth->finish;
return 1;
}
sub UpdateData
{
my ($this, $TableName, $condition, @a) = @_;
my $CharCode = $this->{'DBCharCode'};
my $sql = $this->MakeUpdateCommand($TableName, $CharCode, "update", $condition, @a);
#$this->DebugPrint("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 1, 1);
return undef unless($sth);
$sth->finish;
return 1;
}
sub DeleteData
{
my ($this, $TableName, $condition) = @_;
my $CharCode = $this->{'DBCharCode'};
my $sql = "delete from $TableName where $condition;\n";
#$this->DebugPrint("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 1, 1);
return undef unless($sth);
$sth->finish;
return 1;
}
sub UpdateDataByAutoJudge
{
my ($this, $TableName, $condition, @a) = @_;
my $CharCode = $this->{'DBCharCode'};
my $sql = $this->MakeUpdateCommand($TableName, $CharCode, "auto", $condition, @a);
#$this->print("SQLDB: sql: $sql\n");
my ($sth, $ret) = $this->Execute($sql, 1, 1);
return undef unless($sth);
$sth->finish;
return 1;
}
#'auto', 'insert', 'update'
#$DB->MakeUpdateCommand('paper_tbl', 'sjis', 'auto', 'where EMail = \'$EMail\',
# 'Title', $Title,
# 'Name', $Name
# );
sub MakeUpdateCommand
{
my $this = shift;
my ($DBTableName, $charcode, $action, $condition, @a) = (@_);
$charcode = $this->DBCharCode() if($charcode eq '');
$charcode = '';
my $narg = @_;
my $quote = '"';
if($this->DBMName() =~ /csv/i or $this->DBMName() =~ /Pg/i) {
$quote = '\'';
}
elsif($this->DBMName() =~ /mysql/i and $this->{UseOriginalQuote}) {
$quote = '';
}
# my @Fields = $this->GetFields($this->{DBName}, $DBTableName);
#$this->DebugPrint("SQLDB: charcode : $charcode\n");
#$this->DebugPrint("SQLDB: action : $action\n");
#$this->DebugPrint("SQLDB: condition: $condition\n");
#$this->print("SQLDB: narg: $narg\n");
my $sql;
#$print "***action: $action\n";
if($action =~ /^auto$/i) {
if($condition eq '') {
$this->print("Error in MakeSQLUpdateCommand: "
."Condition should be specified for \'auto\'
\n");
return "";
}
else {
#print "***condition: $condition
\n";
# my $nHit = $this->IsExistData($DBTableName, $condition);
$this->Search($DBTableName, $condition, "");
my $nHit = $this->nHit();
if($nHit <= 0) {
$action = 'insert';
}
else {
$action = 'update';
}
}
}
#print "***Action: $action ($condition)\n";
if($action =~ /^insert$/i) {
my $sql0 = "insert into $DBTableName(";
#$this->print("SQLDB: sql: $sql
\n");
$sql = '';
#$this->DebugPrint("SQLDB: sql: $sql\n");
for(my $i = 4 ; $i < $narg ; $i += 2) {
#print "m i=$i\n";
next if(!defined $_[$i+1]);
my $key;
if($this->{DBMName} =~ /Pg/i) {
$key = $_[$i];
# $key = lc $_[$i];
}
else {
$key = $_[$i];
}
if($sql eq '') {
$sql = $key;
}
else {
$sql .= ",$key";
}
# if($i < $narg-2) {
# $sql = "$key,";
# }
# else {
# $sql .= "$key) ";
# }
#$this->DebugPrint("SQLDB: sql[$i]: $sql\n");
}
$sql .= ") ";
$sql .= "values(";
my $sql2 = '';
#$this->DebugPrint("SQLDB: sql: $sql\n");
for(my $i = 4 ; $i < $narg ; $i += 2) {
#print "m i=$i\n";
#$this->print("SQLDB3: sql: $sql [$charcode]
\n");
#print("i=$i: key=$_[$i]
\n");
next if(!defined $_[$i+1]);
# $_[$i+1] = '' if(!defined $_[$i+1]);
# my $s = SQLDB::MySQLQuote($_[$i+1], $charcode, $this->SourceCharCode());
#print "s=$_[$i+1]\n";
#print "m i=$i\n";
my $s = $this->Quote($_[$i+1], $charcode, $this->SourceCharCode());
# my $s = ($charcode ne '')? $this->Quote($_[$i+1], $charcode, $this->SourceCharCode()) : $_[$i+1];
#$s =~ s/\"/\'/mg;
#print " => $s
\n";
if($sql2 eq '') {
$sql2 = "$quote$s$quote";
}
else {
$sql2 .= ",$quote$s$quote";
}
# if($i < $narg-2) {
# $sql .= "$quote$s$quote,";
# }
# else {
# $sql .= "$quote$s$quote);";
# }
#$this->DebugPrint("SQLDB: sql[$i]: $sql\n");
}
$sql = $sql0 . $sql . $sql2 . ");";
#$this->print("SQLDB2: sql: $sql\n");
}
elsif($action =~ /^update$/i) {
$sql = "update $DBTableName set ";
#$this->DebugPrint("SQLDB: c: $sql\n");
for(my $i = 4 ; $i < $narg ; $i += 2) {
#print("i=$i: key=$_[$i]
\n");
next if(!defined $_[$i+1]);
my $key = $_[$i];
# my $s = SQLDB::MySQLQuote($_[$i+1], $charcode, $this->SourceCharCode());
my $s = $this->Quote($_[$i+1], $charcode, $this->SourceCharCode());
# my $s = ($charcode ne '')? $this->Quote($_[$i+1], $charcode, $this->SourceCharCode()) : $_[$i+1];
#$s =~ s/\"/\'/mg;
if($i < $narg-2) {
$sql .= "$key=$quote$s$quote,";
}
else {
$sql .= "$key=$quote$s$quote ";
}
#$this->DebugPrint("SQLDB: c: $sql\n");
}
$condition = "where $condition" if($condition !~ /^\s*where\s/i);
$sql =~ s/,\s*$/ /;
$sql .= "$condition;";
}
else {
print "Error: Invalid action: $action
\n";
return "";
}
#$this->DebugPrint("SQLDB: c: $sql\n");
#print("SQLDB: c: $sql\n");
return $sql;
}
sub SaveToCSV
{
my ($this, $TableName, $condition, $fields, $path, $charcode, $pDeleteKeys) = @_;
$charcode = 'no' if($charcode eq '' and $this->{CharCodeConversion});
my $out = new CSV();
return 0 if(!$out->Open($path, "w", 0));
$this->Search($TableName, $condition, $fields);
my $nFields = $this->nFields();
#print "nFields: $nFields
\n";
my $pFieldNames = $this->pFieldNames();
$out->WriteLabelLine(@$pFieldNames);
my $nHit = $this->nHit();
for(my $i = 0 ; $i < $nHit ; $i++) {
my %Hit = $this->GetNextHit();
if($pDeleteKeys) {
for(my $i = 0 ; $i < @$pDeleteKeys ; $i++) {
delete $Hit{$pDeleteKeys->[$i]};
}
}
my @data;
my $line = join('', %Hit);#@data);
my $sourcecharcode = Jcode::getcode($line);
for(my $j = 0 ; $j < $nFields ; $j++) {
my $field = $pFieldNames->[$j];
$data[$j] = $Hit{$field};
if($charcode ne 'no' and $sourcecharcode ne 'ascii' and $sourcecharcode ne $charcode) {
Jcode::convert(\$data[$j], $charcode);
# Jcode::convert(\$data[$j], $charcode, $sourcecharcode);
#print "c: $sourcecharcode => $charcode
\n";
}
}
$out->WriteDataLine(\@data);
}
return 1;
}
#================================================================================
# Utility関数
#================================================================================
sub MakeCSVFile
{
my ($this, $OutFilePath, $CSVFileCharCode, $DBTableName, $sql, %args) = @_;
my $IsPrint = (defined $args{IsPrint})? $args{IsPrint} : 0;
my $pLabel = $args{pLabel};
my $DBName = (defined $args{DBName})? $args{DBName} : $this->{DBName};
my $pDBFields = (defined $args{pDBFields})? $args{pDBFields} : sort $this->GetFields($DBName, $DBTableName, 0);
# my $pDBFields = $args{pDBFields};
my $pFirstDBList = (defined $args{pFirstDBList})? $args{pFirstDBList} : [qw(sn EMail Name JName)];
my $pLastDBList = (defined $args{pLastDBList})? $args{pLastDBList} : [qw(IPAddress LastUpdateTime LastLogonTime)];
my $out = new CSV;
if(!$out->Open($OutFilePath, "w", 0)) {
return 0;
}
my @DBFields = ($pDBFields)? @$pDBFields : ();
my @keys;
$this->Search($DBTableName, $sql, "");
my $nHit = $this->nHit();
for(my $i = 0 ; $i < $nHit ; $i++) {
my %Hit = $this->GetNextHit();
if(@DBFields == 0) {
@DBFields = sort keys %Hit;
@DBFields = (@$pFirstDBList, Utils::DeleteItemFromList(\@DBFields, $pFirstDBList)) if($pFirstDBList);
@DBFields = (Utils::DeleteItemFromList(\@DBFields, $pLastDBList), @$pLastDBList) if($pLastDBList);
@keys = @DBFields;
if($pLabel) {
for(my $i = 0 ; $i < @keys ; $i++) {
if($pLabel->{$keys[$i]}) {
$keys[$i] = $pLabel->{$keys[$i]};
Jcode::convert(\$keys[$i], $CSVFileCharCode) if(defined $CSVFileCharCode and $CSVFileCharCode ne 'ascii');
}
}
}
$out->WriteDataLine(\@keys);
}
my @a;
for(my $i = 0 ; $i < @DBFields ; $i++) {
my $key = $DBFields[$i];
my $val = $Hit{$key};
Jcode::convert(\$val, $CSVFileCharCode) if(defined $CSVFileCharCode and $CSVFileCharCode ne 'ascii');
$a[$i] = $val;
}
$out->WriteDataLine(\@a);
}
$out->Close();
return $nHit;
}
#================================================================================
# コマンドラインインターフェース
#================================================================================
sub RestoreDBFromFile
{
my ($this, $DBServer, $DBUser, $DBPassword, $File, $ShowMessage) = @_;
$DBServer = $this->{'DBServer'} unless($DBServer);
$DBUser = $this->{'DBUser'} unless($DBUser);
$DBPassword = $this->{'DBPassword'} unless($DBPassword);
my $HidePass = '***';
$HidePass = $DBPassword if($ShowMessage >= 2);
my $command = "mysql -h $DBServer -u $DBUser --password=$HidePass < $File";
print " $command\n" if($ShowMessage);
$command = "mysql -h $DBServer -u $DBUser --password=$DBPassword < $File";
system($command);
}
# $ShowMessage: 0: メッセージ無し 1: パスワードを隠してメッセージを表示
# 2: パスワードとともにメッセージを表示
sub MakeBackupFile
{
my ($this, $DBServer, $DBName, $DBUser, $DBPassword, $File, $ShowMessage) = @_;
$DBServer = $this->{'DBServer'} unless($DBServer);
$DBName = $this->{'DBName'} unless($DBName);
$DBUser = $this->{'DBUser'} unless($DBUser);
$DBPassword = $this->{'DBPassword'} unless($DBPassword);
my $HidePass = '***';
$HidePass = $DBPassword if($ShowMessage >= 2);
my $command = "mysqldump --opt --databases $DBName "
."-h $DBServer -u $DBUser --password=$HidePass > $File";
if($DBName eq 'all') {
$command = "mysqldump --opt --all-databases "
."-h $DBServer -u $DBUser --password=$HidePass > $File";
}
print " $command\n" if($ShowMessage);
$command = "mysqldump --opt --all-databases "
."-h $DBServer -u $DBUser --password=$DBPassword > $File";
if($DBName eq 'all') {
$command = "mysqldump --opt --all-databases "
."-h $DBServer -u $DBUser --password=$DBPassword > $File";
}
system($command);
}
1;