Wednesday 24 March 2010

Customising NHibernate to work with Visual FoxPro

So far I have added a new class to create a dialect for VFP9 and altered some of the Nhibernate code to allow for generation of basic VFP tables.. Problems you might face include locking since NHibernate uses a SELECT ... FOR UPDATE to lock rows. Since I am using optimistic locking throughout I shall have to design the system without using LockMode.Upgrade. The VFP9Dialect class is below, if you have any improvements let me know!

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Text.RegularExpressions;
using NHibernate.Dialect.Function;
using NHibernate.Dialect.Schema;
using NHibernate.Engine;
using NHibernate.Mapping;
using NHibernate.SqlCommand;
using NHibernate.Type;
using NHibernate.Util;
using Environment=NHibernate.Cfg.Environment;

namespace NHibernate.Dialect
{
///
/// An SQL dialect compatible with Microsoft Visual Foxpro 9.
///

///
/// The VFP9Dialect defaults the following configuration properties:
///
///
/// Property
/// Default Value
///

///
/// use_outer_join
///
///

///
/// connection.driver_class
///
///

///
/// prepare_sql
///
///

///

///

public class VFP9Dialect : Dialect
{
///
public VFP9Dialect()
{
// standard sql92 functions (can be overridden by subclasses)
RegisterFunction("substring", new SQLFunctionTemplate(NHibernateUtil.String, "substr(?1, ?2, ?3)"));
RegisterFunction("length", new StandardSQLFunction("len", NHibernateUtil.Int32));

// the syntax of current_timestamp is extracted from H3.2 tests
// - test\hql\ASTParserLoadingTest.java
// - test\org\hibernate\test\hql\HQLTest.java
RegisterFunction("current_timestamp", new NoArgSQLFunction("datetime()", NHibernateUtil.DateTime, true));
RegisterFunction("sysdate", new NoArgSQLFunction("date()", NHibernateUtil.DateTime, false));

//map second/minute/hour/day/month/year to ANSI extract(), override on subclasses
RegisterFunction("second", new SQLFunctionTemplate(NHibernateUtil.Int32, "sec(?1)"));
RegisterFunction("minute", new SQLFunctionTemplate(NHibernateUtil.Int32, "minute(?1)"));
RegisterFunction("hour", new SQLFunctionTemplate(NHibernateUtil.Int32, "hour(?1)"));
RegisterFunction("day", new SQLFunctionTemplate(NHibernateUtil.Int32, "day(?1)"));
RegisterFunction("month", new SQLFunctionTemplate(NHibernateUtil.Int32, "month(?1)"));
RegisterFunction("year", new SQLFunctionTemplate(NHibernateUtil.Int32, "year(?1)"));

RegisterColumnType(DbType.AnsiStringFixedLength, "C(254)");
RegisterColumnType(DbType.AnsiStringFixedLength, 254, "C($l)");
RegisterColumnType(DbType.AnsiString, "V(254)");
RegisterColumnType(DbType.AnsiString, 254, "V($l)");
RegisterColumnType(DbType.AnsiString, 2147483647, "M");
RegisterColumnType(DbType.Binary, "Q(254)");
RegisterColumnType(DbType.Binary, 254, "Q($l)");
RegisterColumnType(DbType.Binary, 2147483647, "W");
RegisterColumnType(DbType.Boolean, "L");
RegisterColumnType(DbType.Byte, "I");
RegisterColumnType(DbType.Currency, "Y");
RegisterColumnType(DbType.Date, "D");
RegisterColumnType(DbType.DateTime, "T");
RegisterColumnType(DbType.Decimal, "N(19,5)");
RegisterColumnType(DbType.Decimal, 19, "N($p, $s)");
RegisterColumnType(DbType.Double, "B"); //synonym for FLOAT(53)
RegisterColumnType(DbType.Guid, "C(40)");
RegisterColumnType(DbType.Int16, "I");
RegisterColumnType(DbType.Int32, "I");
RegisterColumnType(DbType.Int64, "I");
RegisterColumnType(DbType.Single, "B"); //synonym for FLOAT(24)
RegisterColumnType(DbType.StringFixedLength, "C(254)");
RegisterColumnType(DbType.StringFixedLength, 254, "C($l)");
RegisterColumnType(DbType.String, "V(254)");
RegisterColumnType(DbType.String, 254, "V($l)");
RegisterColumnType(DbType.String, 1073741823, "M");
RegisterColumnType(DbType.Time, "T");
}

public static Random random = new Random();

public override char OpenQuote
{
get { return ' '; }
}

///
/// The closing quote for a quoted identifier.
///

public override char CloseQuote
{
get { return ' '; }
}

public override string ForUpdateString
{
get { return string.Empty; }
}

public override bool QualifyIndexName
{
get { return false ; }
}

public override string QuoteForColumnName(string columnName)
{
return columnName;
}
public override bool SupportsOuterJoinForUpdate
{
get { return false; }
}

public override bool SupportsUniqueConstraintInCreateAlterTable
{
get { return false; }
}

///
/// Does this dialect support the UNIQUE column syntax?
///

public override bool SupportsUnique
{
get { return false ; }
}

public override bool SupportsColumnCheck
{
get { return false; }
}

/// Does this dialect support table-level check constraints?
/// True if table-level CHECK constraints are supported; false otherwise.
public override bool SupportsTableCheck
{
get { return false; }
}

public override bool DropConstraints
{
get { return false; }
}

public override bool SupportsCascadeDelete
{
get { return false; }
}

public override bool SupportsNotNullUnique
{
get { return false; }
}

public override bool SupportsLimit
{
get { return false; }
}
public override string PrimaryKeyOpenParen
{
get { return ""; }
}
public override string PrimaryKeyCloseParen
{
get {
return " TAG PK" + random.Next(10000000, 99999999).ToString();
}
}

public override string GetAddForeignKeyConstraintString(string constraintName, string[] foreignKey,
string referencedTable, string[] primaryKey, bool referencesPrimaryKey)
{
var res = new StringBuilder(200);

res.Append(" add foreign key ")
.Append(StringHelper.Join(StringHelper.CommaSpace, foreignKey))
.Append(" TAG FK")
.Append(random.Next(10000000, 99999999).ToString())
.Append(" references ")
.Append(referencedTable);

if (!referencesPrimaryKey)
{
res.Append(" TAG ")
.Append(StringHelper.Join(StringHelper.CommaSpace, primaryKey));
}

return res.ToString();
}

public override string GetAddPrimaryKeyConstraintString(string constraintName)
{
return " add primary key ";
}
public override string DropForeignKeyString
{
get { return " drop Foreign Key Tag "; }
}

}
}

Friday 4 December 2009

Making Amavis work with Office 2007 documents

Want to unblock Office 2007 documents from the ban list in Amavis, e.g. because they contain WMF thumbnails! Add the following to amavis conf files in banned_filename_re section

[ qr'^application/vnd.openxmlformats-officedocument.spreadsheetml.sheet$'i => 0 ],
[ qr'^application/vnd.openxmlformats-officedocument.wordprocessingml.document$'i => 0 ],
[ qr'^application/vnd.openxmlformats-officedocument.presentationml.presentation$'i => 0 ],