# Hej, Emacs, give us -*- perl -*- mode here!
#
#   $Id: mysql.dbtest,v 1.1 2003/03/18 02:53:28 rlippan Exp $
#
# database specific definitions for a 'mysql' database

my $have_transactions;

#   This function generates a mapping of ANSI type names to
#   database specific type names; it is called by TableDefinition().
#
sub AnsiTypeToDb ($;$) {
    my ($type, $size) = @_;
    my ($ret);

    if ((lc $type) eq 'blob') {
	if ($size >= 1 << 16) {
	    $ret = 'MEDIUMBLOB';
	} else {
	    $ret = 'BLOB';
	}
    } elsif ((lc $type) eq 'int'  ||  (lc $type) eq 'integer') {
	$ret = $type;
    } elsif ((lc $type) eq 'char') {
	$ret = "CHAR($size)";
    } else {
	warn "Unknown type $type\n";
	$ret = $type;
    }
    $ret;
}


#
#   This function generates a table definition based on an
#   input list. The input list consists of references, each
#   reference referring to a single column. The column
#   reference consists of column name, type, size and a bitmask of
#   certain flags, namely
#
#       $COL_NULLABLE - true, if this column may contain NULL's
#       $COL_KEY - true, if this column is part of the table's
#           primary key
#
#   Hopefully there's no big need for you to modify this function,
#   if your database conforms to ANSI specifications.
#

sub TableDefinition ($@) {
    my($tablename, @cols) = @_;
    my($def);

    #
    #   Should be acceptable for most ANSI conformant databases;
    #
    #   msql 1 uses a non-ANSI definition of the primary key: A
    #   column definition has the attribute "PRIMARY KEY". On
    #   the other hand, msql 2 uses the ANSI fashion ...
    #
    my($col, @keys, @colDefs, $keyDef);

    #
    #   Count number of keys
    #
    @keys = ();
    foreach $col (@cols) {
	if ($$col[2] & $::COL_KEY) {
	    push(@keys, $$col[0]);
	}
    }

    foreach $col (@cols) {
	my $colDef = $$col[0] . " " . AnsiTypeToDb($$col[1], $$col[2]);
	if (!($$col[3] & $::COL_NULLABLE)) {
	    $colDef .= " NOT NULL";
	}
	push(@colDefs, $colDef);
    }
    if (@keys) {
	$keyDef = ", PRIMARY KEY (" . join(", ", @keys) . ")";
    } else {
	$keyDef = "";
    }
    my $suffix = "";
    if ($have_transactions) {
      $suffix = " TYPE=$have_transactions";
    }
    $def = sprintf("CREATE TABLE %s (%s%s)%s", $tablename,
		   join(", ", @colDefs), $keyDef, $suffix);
}


#
#   This function generates a list of tables associated to a
#   given DSN.
#
sub ListTables(@) {
    my($dbh) = shift;
    my(@tables);

    @tables = $dbh->func('_ListTables');
    if ($dbh->errstr) {
	die "Cannot create table list: " . $dbh->errstr;
    }
    @tables;
}


#
#   This function is called by DBD::pNET; given a hostname and a
#   dsn without hostname, return a dsn for connecting to dsn at
#   host.
sub HostDsn ($$) {
    my($hostname, $dsn) = @_;
    "$dsn:$hostname";
}


#
#   Return a string for checking, whether a given column is NULL.
#
sub IsNull($) {
    my($var) = @_;

    "$var IS NULL";
}


#
#   Return TRUE, if database supports transactions
#
sub HaveTransactions () {
    my $dbh = shift;
    return 1 unless $dbh;
    if (!defined($have_transactions)) {
	$have_transactions = "";
	my $sth = $dbh->prepare("SHOW VARIABLES");
	$sth->execute();
	while (my $row = $sth->fetchrow_hashref()) {
	    if ($row->{'Variable_name'} eq 'have_bdb'  &&
		$row->{'Value'} eq 'YES') {
		$have_transactions = "bdb";
		last;
	    }
	    if ($row->{'Variable_name'} eq 'have_innobase'  &&
		$row->{'Value'} eq 'YES') {
		$have_transactions = "innobase";
		last;
	    }
	    if ($row->{'Variable_name'} eq 'have_gemini'  &&
		$row->{'Value'} eq 'YES') {
		$have_transactions = "gemini";
		last;
	    }
	}
    }
    return $have_transactions;
}


1;
