/*
 * Copyright (C) 2004-2005  exedio GmbH (www.exedio.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package com.exedio.cope;

import java.sql.SQLException;

import com.mysql.jdbc.Driver;

/**
 * This MySQL driver requires the InnoDB engine.
 * It makes no sense supporting older engines,
 * since cope heavily depends on foreign key constraints.
 * @author Ralf Wiebicke
 */
public final class MysqlDatabase extends Database

// TODO
//	implements DatabaseTimestampCapable
// would require type "timestamp(14,3) null default null"
// but (14,3) is not yet supported
// "null default null" is needed to allow null and
// make null the default value
// This works with 4.1.6 and higher only

{
	static
	{
		try
		{
			Class.forName(Driver.class.getName());
		}
		catch(ClassNotFoundException e)
		{
			throw new NestingRuntimeException(e);
		}
	}

	protected MysqlDatabase(final Properties properties)
	{
		super(properties);
	}

	String getIntegerType(final int precision)
	{
		// TODO: use precision to select between TINYINT, SMALLINT, INTEGER, BIGINT, NUMBER
		return (precision <= 10) ? "integer" : "bigint";
	}

	String getDoubleType(final int precision)
	{
		return "double";
	}

	String getStringType(final int maxLength)
	{
		// TODO:
		// 255 is needed for unique columns only,
		// non-unique can have more,
		// and for longer unique columns you may specify a shorter key length
		
		// IMPLEMENTATION NOTE: "binary" is needed to make string comparisions case sensitive
		return "varchar("+(maxLength!=Integer.MAX_VALUE ? maxLength : 255)+") binary";
	}
	
	protected String protectName(final String name)
	{
		return '`' + name + '`';
	}

	protected boolean supportsForeignKeyConstraints()
	{
		return false;
	}

	protected String extractUniqueConstraintName(final SQLException e)
	{
		// TODO: MySQL does not deliver constraint name in exception
		//System.out.println("-u-"+e.getClass()+" "+e.getCause()+" "+e.getErrorCode()+" "+e.getLocalizedMessage()+" "+e.getSQLState()+" "+e.getNextException());
		if(e.getErrorCode()==1062 &&
				e.getMessage().startsWith("Duplicate entry "))
			return ANY_CONSTRAINT;
		else
			return null;
	}

	protected String extractIntegrityConstraintName(final SQLException e)
	{
		// TODO: MySQL does not deliver constraint name in exception
		//System.out.println("-i-"+e.getClass()+" "+e.getCause()+" "+e.getErrorCode()+" "+e.getLocalizedMessage()+" "+e.getSQLState()+" "+e.getNextException());
		if(e.getErrorCode()==1217 && 
				e.getMessage().startsWith("Cannot delete or update a parent row: a foreign key constraint fails"))
			return ANY_CONSTRAINT;
		else
			return null;
	}

	Statement getRenameColumnStatement(final String tableName, final String oldColumnName, final String newColumnName, final String columnType)
	{
		final Statement bf = createStatement();
		bf.append("alter table ").
			append(tableName).
			append(" change ").
			append(oldColumnName).
			append(' ').
			append(newColumnName).
			append(' ').
			append(columnType);
		return bf;
	}

	// TODO is same as hsqldb
	Statement getCreateColumnStatement(final String tableName, final String columnName, final String columnType)
	{
		final Statement bf = createStatement();
		bf.append("alter table ").
			append(tableName).
			append(" add column ").
			append(columnName).
			append(' ').
			append(columnType);
		return bf;
	}

	Statement getModifyColumnStatement(final String tableName, final String columnName, final String newColumnType)
	{
		throw new RuntimeException("not implemented");
	}

}

@@ -2415,39 +2415,43 @@
 n false;%0A%09%7D%0A%0A%09pr
-otected
+ivate final
  String extractU
@@ -2453,13 +2453,8 @@
 ract
-Uniqu
 eCon
@@ -2477,32 +2477,74 @@
 l SQLException e
+, final int vendorCode, final String start
 )%0A%09%7B%0A%09%09// TODO: 
@@ -2742,32 +2742,33 @@
 xtException());%0A
+%0A
 %09%09if(e.getErrorC
@@ -2778,12 +2778,18 @@
 ()==
-1062
+vendorCode
  &&%0A
@@ -2822,26 +2822,13 @@
 ith(
-%22Duplicate entry %22
+start
 ))%0A%09
@@ -2908,17 +2908,14 @@
 ract
-Integrity
+Unique
 Cons
@@ -2956,41 +2956,24 @@
 %7B%0A%09%09
-// TODO: MySQL does not deliver c
+return extracteC
 onst
@@ -2981,244 +2981,162 @@
 aint
- name in exception%0A%09%09//System.out.println(%22-i-%22+e.getClass()+%22 %22+e.getCause()+%22 %22+e.getErrorCode()+%22 %22+e.getLocalizedMessage()+%22 %22+e.getSQLState()+%22 %22+e.getNextException());%0A%09%09if(e.getErrorCode()==1217 && %0A%09%09%09%09e.getMessage().startsWith(
+Name(e, 1062, %22Duplicate entry %22);%0A%09%7D%0A%0A%09protected String extractIntegrityConstraintName(final SQLException e)%0A%09%7B%0A%09%09return extracteConstraintName(e, 1217, 
 %22Can
@@ -3206,57 +3206,8 @@
 ls%22)
-)%0A%09%09%09return ANY_CONSTRAINT;%0A%09%09else%0A%09%09%09return null
 ;%0A%09%7D

introduce extracteConstraintName