[Feature Request] Renaming columns
Opened this issue · 6 comments
I want to use TablesToBeExportedDic with a query that contains an alias, e.i. something like this "select ID
as 'ID_ALIAS` from table;", and the script should result "insert into table (ID_ALIAS, ..."
I am currently post-processing the script, but I think it's a good feature. Is there an existing workaround for this issue? If the feature solves a valid user case, I don't mind working on its implementation.
I have tried a quick modification to produce the result as you described. Here is the sample project:
This project uses a modified MySqlBackup.NET.
The following are the changes:
File: /MySqlBackup/MySqlBackup.cs
In this method:
private string Export_GetInsertStatementHeader(RowsDataExportMode rowsExportMode, string tableName, MySqlDataReader rdr)
replace the following line:
if (_database.Tables[tableName].Columns[_colname].IsGeneratedColumn)
continue;
with:
if (_database.Tables[tableName].Columns.Contains(_colname))
{
if (_database.Tables[tableName].Columns[_colname].IsGeneratedColumn)
continue;
}
In this method:
private string Export_GetValueString(MySqlDataReader rdr, MySqlTable table)
replace the following line
if (table.Columns[columnName].IsGeneratedColumn)
continue;
with:
if (table.Columns.Contains(columnName))
{
if (table.Columns[columnName].IsGeneratedColumn)
continue;
}
in this method:
private string Export_GetValueString(MySqlDataReader rdr, MySqlTable table)
replace the following line:
var col = table.Columns[columnName];
with:
MySqlColumn col = null;
if (table.Columns.Contains(columnName))
{
col = table.Columns[columnName];
}
There is one issue, if you replace the column name by an alias name, then the CREATE TABLE
sql statement will no longer valid.
for example:
This original table structure:
CREATE TABLE if not exists `people` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`tel` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
);
will no longer fit the generate INSERT
with alias column name. The following INSERT
will fail, since there is no column name person_name
.
INSERT INTO `people`(`id`,`person_name`,`tel`) VALUES
(1,'Sam','1111'),
(2,'Foo','2222'),
(3,'Bar','3333');
But I assume that the destination database that you are going to import to, will have the column name person_name
existed.
In this method:
private string Export_GetValueString(MySqlDataReader rdr, MySqlTable table)
The MySqlColumn
MySqlColumn col = null;
if (table.Columns.Contains(columnName))
{
col = table.Columns[columnName];
}
will be passed into another method:
QueryExpress.ConvertToSqlFormat(ob, true, true, col, ExportInfo.BlobExportMode)
The col
supplies the info for handling non-standard DateTime
value. For example in MySql, there are date, time, null date, null time, and different time fraction... which is not compatible with C# DateTime data type.
These non-compatible Date or Time values will be converted into MySqlDateTime
, here, the MySqlColumn
value will be needed
else if (ob is MySqlDateTime mdt)
{
if (mdt.IsValidDateTime)
{
DateTime dtime = mdt.GetDateTime();
if (wrapStringWithSingleQuote)
sb.AppendFormat("'");
if (col.MySqlDataType == "datetime")
sb.AppendFormat(dtime.ToString("yyyy-MM-dd HH:mm:ss", _dateFormatInfo));
else if (col.MySqlDataType == "date")
sb.AppendFormat(dtime.ToString("yyyy-MM-dd", _dateFormatInfo));
else if (col.MySqlDataType == "time")
sb.AppendFormat("{0}:{1}:{2}", mdt.Hour, mdt.Minute, mdt.Second);
else
sb.AppendFormat(dtime.ToString("yyyy-MM-dd HH:mm:ss", _dateFormatInfo));
if (col.TimeFractionLength > 0)
{
sb.Append(".");
sb.Append(((MySqlDateTime)ob).Microsecond.ToString().PadLeft(col.TimeFractionLength, '0'));
}
if (wrapStringWithSingleQuote)
sb.AppendFormat("'");
}
else
{
if (wrapStringWithSingleQuote)
sb.AppendFormat("'");
if (col.MySqlDataType == "datetime")
sb.AppendFormat("0000-00-00 00:00:00");
else if (col.MySqlDataType == "date")
sb.AppendFormat("0000-00-00");
else if (col.MySqlDataType == "time")
sb.AppendFormat("00:00:00");
else
sb.AppendFormat("0000-00-00 00:00:00");
if (col.TimeFractionLength > 0)
{
sb.Append(".".PadRight(col.TimeFractionLength, '0'));
}
if (wrapStringWithSingleQuote)
sb.AppendFormat("'");
}
}
but since you are using alias column name, the MySqlBackup.NET library unable to guess the alias column name belongs to which column in MySQL table.
In this case (in the occurance of if you do have these incompatible datetime values issues), another error (exception) will occur, where the MySqlColumn
is null.
However, there is another workaround to avoid this, which is by appending a connection string option:
convertzerodatetime=true;
example:
server=localhost;user=root;pwd=1234;database=test1;convertzerodatetime=true;
or using the ConnectionStringBuilder:
MySqlConnectionStringBuilder consb = new MySqlConnectionStringBuilder()
{
Server = "localhost",
UserID = "root",
Password = "1234",
Database = "test1",
ConvertZeroDateTime = true
};
using (MySqlConnection conn = new MySqlConnection(consb.ToString()))
{
}
By specifying ConvertZeroDateTime=true
, all non-standardized Date or Time value in MySQL will all be converted into DateTime.MinValue
in C#.
This will by pass the need to refer to MySqlColumn
to get further info about the date time behaviour.
But I assume that the destination database that you are going to import to, will have the column name
person_name
existed.
That's indeed the case.
This will by pass the need to refer to
MySqlColumn
to get further info about the date time behaviour.
Imo it should be handled by the library.
Will those changes come with a release?
Imo it should be handled by the library.
It requires user input to match the person_name
to the original name
.
It can be something like
mb.ExportInfo.MatchAliasColumns(table_name, ori_column_name, alias_column_name);
I can add it into the next release. The next release date is unscheduled at the moment. You may use the modified version of MySqlBackup.NET attached in previous reply (above).
Alright, thank you. Feel free to close the issue at your discretion.