I was chasing this problem
(http://tracker.firebirdsql.org/browse/DNET-327) and was about to post
to the list to try to find a solution when I found this
http://blog.cincura.net/232192-ado-net-provider-2-6-0-for-firebird-released/
and in one of the comments (DEC 20, 2010) Jiri said:
"I was testing it with Mono 2.8.1 and 2.8.0 on Slackware, but maybe Mac
version is missing some charsets. Simply comment out the line in
FirebirdSql.Data.Common.Charset."
That tipped me off to an easy workaround so I started putting the #if
(!MONO) around Charsets until I stopped getting the error. This solved
my problem (for now, until I put my code on a different platform or
version of my platform), but don't see this as a good solution for the
Firebird provider project. In all I had to eliminate 15 character sets
from that type initializer to get it to work, and it took the better
part of a day to track down the root cause and do that elimination process.
So I'm posting to try to get an understanding of how this part of the
code could work better, and contribute an enhancement. I'm not all that
familiar with how the different OS, runtime and DB platforms deal with
character sets, so I may be guilty of wishful thinking...so my question
was: Is there a way to detect the character sets supported by the
platform? We could then merge that with the character sets supported by
Firebird and this provider and prevent this problem from reoccurring.
I tried a very straightforward approach using Encoding.GetEncodings and
trying to search that list to eliminate unsupported encodings before
problems were encountered, but that didn't work because accessing the
EncodingInfo data (as returned from that method) throws an exception if
the CodePage isn't supported, apparently because it is trying to
initialize it's internal encoding when accessed*. So I mangled it to
the less elegant version that I've attached. I've tested it here and it
solves my problem without conditional compilation or commenting out
unsupported encodings. Look for "InitializeSupportedCharsets". The old
version is present, but commented out.
*This doesn't happen on MS.NET. My environments are:
danno@puma:~/dev/firebird$ mono --version
Mono JIT compiler version 2.6.7 (Debian 2.6.7-5ubuntu1~dhx1)
Copyright (C) 2002-2010 Novell, Inc and Contributors. www.mono-project.com
TLS: __thread
GC: Included Boehm (with typed GC and Parallel Mark)
SIGSEGV: altstack
Notifications: epoll
Architecture: amd64
Disabled: none
Firebird.NET Provider 2.6.0 (compiled on Ubuntu Desktop 10.04.2) testing
on Ubuntu Server 10.04.2 (Lucid Lynx)
...and...
Windows.NET 2.0, Firebird.NET Provider 2.5.1 from download running on
Windows XP (development and unit test with VS.NET 2005).
Also, one side note: when compiling 2.6.0 without the ENTITY_FRAMEWORK
directive, I got errors on Entity.SSDLToFB.cs (added sometime after
2.5.2). Adding #if (NET_35 && ENTITY_FRAMEWORK) condition solved that
problem. Is that missing conditional an oversight, or should I not need
that conditional and is there something else wrong with my setup?
Cheers,
Danny
--
Danny Gorton II
Co-founder
Absolute Power and Control, LLC
www.absolutepowerandcontrol.com
/*
* Firebird ADO.NET Data provider for .NET and Mono
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.firebirdsql.org/index.php?op=doc&id=idpl
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* Copyright (c) 2002, 2007 Carlos Guzman Alvarez
* All Rights Reserved.
*
* Contributors:
* Jiri Cincura (j...@cincura.net)
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace FirebirdSql.Data.Common
{
internal sealed class Charset
{
#region · Static Fields ·
private readonly static List<Charset> supportedCharsets =
Charset.InitializeSupportedCharsets();
#endregion
#region · Static Properties ·
public static Charset DefaultCharset
{
get { return Charset.supportedCharsets[0]; }
}
#endregion
#region · Static Methods ·
public static Charset GetCharset(int charsetId)
{
foreach (Charset charset in supportedCharsets)
{
if (charset.Identifier == charsetId)
return charset;
}
return null;
}
public static Charset GetCharset(string charsetName)
{
foreach (Charset charset in supportedCharsets)
{
if (GlobalizationHelper.CultureAwareCompare(charset.Name,
charsetName))
return charset;
}
return null;
}
private static List<Charset> InitializeSupportedCharsets()
{
EncodingInfo[] systemEncodings =
Encoding.GetEncodings();
List<Charset> charsets = new List<Charset>();
//these won't be in the system encodings and are
handled differently.
// NONE
charsets.Add(new Charset(0, "NONE", 1, "NONE"));
// OCTETS
charsets.Add(new Charset(1, "OCTETS", 1, "OCTETS"));
// American Standard Code for Information Interchange
addCharset(charsets, systemEncodings, 2, "ASCII", 1, "ascii");
// Eight-bit Unicode Transformation Format
addCharset(charsets, systemEncodings, 3, "UNICODE_FSS", 3, "UTF-8");
// UTF8
addCharset(charsets, systemEncodings, 4, "UTF8", 4, "UTF-8");
// Shift-JIS, Japanese
addCharset(charsets, systemEncodings, 5, "SJIS_0208", 2,
"shift_jis");
// JIS X 0201, 0208, 0212, EUC encoding, Japanese
addCharset(charsets, systemEncodings, 6, "EUCJ_0208", 2, "euc-jp");
// Windows Japanese
addCharset(charsets, systemEncodings, 7, "ISO2022-JP", 2,
"iso-2022-jp");
// MS-DOS United States, Australia, New Zealand, South Africa
addCharset(charsets, systemEncodings, 10, "DOS437", 1, "IBM437");
// MS-DOS Latin-1
addCharset(charsets, systemEncodings, 11, "DOS850", 1, "ibm850");
// MS-DOS Nordic
addCharset(charsets, systemEncodings, 12, "DOS865", 1, "IBM865");
// MS-DOS Portuguese
addCharset(charsets, systemEncodings, 13, "DOS860", 1, "IBM860");
// MS-DOS Canadian French
addCharset(charsets, systemEncodings, 14, "DOS863", 1, "IBM863");
// ISO 8859-1, Latin alphabet No. 1
addCharset(charsets, systemEncodings, 21, "ISO8859_1", 1,
"iso-8859-1");
// ISO 8859-2, Latin alphabet No. 2
addCharset(charsets, systemEncodings, 22, "ISO8859_2", 1,
"iso-8859-2");
// Windows Korean
addCharset(charsets, systemEncodings, 44, "KSC_5601", 2,
"ks_c_5601-1987");
// MS-DOS Icelandic
addCharset(charsets, systemEncodings, 47, "DOS861", 1, "ibm861");
// Windows Eastern European
addCharset(charsets, systemEncodings, 51, "WIN1250", 1,
"windows-1250");
// Windows Cyrillic
addCharset(charsets, systemEncodings, 52, "WIN1251", 1,
"windows-1251");
// Windows Latin-1
addCharset(charsets, systemEncodings, 53, "WIN1252", 1,
"windows-1252");
// Windows Greek
addCharset(charsets, systemEncodings, 54, "WIN1253", 1,
"windows-1253");
// Windows Turkish
addCharset(charsets, systemEncodings, 55, "WIN1254", 1,
"windows-1254");
// Big5, Traditional Chinese
addCharset(charsets, systemEncodings, 56, "BIG_5", 2, "big5");
// GB2312, EUC encoding, Simplified Chinese
addCharset(charsets, systemEncodings, 57, "GB_2312", 2, "gb2312");
// Windows Hebrew
addCharset(charsets, systemEncodings, 58, "WIN1255", 1,
"windows-1255");
// Windows Arabic
addCharset(charsets, systemEncodings, 59, "WIN1256", 1,
"windows-1256");
// Windows Baltic
addCharset(charsets, systemEncodings, 60, "WIN1257", 1,
"windows-1257");
// UTF-16
addCharset(charsets, systemEncodings, 61, "UTF16", 4, "utf-16");
// UTF-32
addCharset(charsets, systemEncodings, 62, "UTF32", 4, "utf-32");
// Russian KOI8R
addCharset(charsets, systemEncodings, 63, "KOI8R", 2,
"koi8-r");
// Ukrainian KOI8U
addCharset(charsets, systemEncodings, 64, "KOI8U", 2, "koi8-u");
return charsets;
}
#region Old InitializeSupportedCharsets culled by dgorton
/*
private static List<Charset> InitializeSupportedCharsets()
{
List<Charset> charsets = new List<Charset>();
// NONE
charsets.Add(new Charset(0, "NONE", 1, "NONE"));
// OCTETS
charsets.Add(new Charset(1, "OCTETS", 1, "OCTETS"));
// American Standard Code for Information Interchange
charsets.Add(new Charset(2, "ASCII", 1, "ascii"));
// Eight-bit Unicode Transformation Format
charsets.Add(new Charset(3, "UNICODE_FSS", 3, "UTF-8"));
// UTF8
charsets.Add(new Charset(4, "UTF8", 4, "UTF-8"));
// Shift-JIS, Japanese
charsets.Add(new Charset(5, "SJIS_0208", 2, "shift_jis"));
// JIS X 0201, 0208, 0212, EUC encoding, Japanese
charsets.Add(new Charset(6, "EUCJ_0208", 2, "euc-jp"));
// Windows Japanese
charsets.Add(new Charset(7, "ISO2022-JP", 2, "iso-2022-jp"));
#endif
// MS-DOS United States, Australia, New Zealand, South Africa
charsets.Add(new Charset(10, "DOS437", 1, "IBM437"));
// MS-DOS Latin-1
charsets.Add(new Charset(11, "DOS850", 1, "ibm850"));
// MS-DOS Nordic
charsets.Add(new Charset(12, "DOS865", 1, "IBM865"));
// MS-DOS Portuguese
charsets.Add(new Charset(13, "DOS860", 1, "IBM860"));
// MS-DOS Canadian French
charsets.Add(new Charset(14, "DOS863", 1, "IBM863"));
// ISO 8859-1, Latin alphabet No. 1
charsets.Add(new Charset(21, "ISO8859_1", 1, "iso-8859-1"));
// ISO 8859-2, Latin alphabet No. 2
charsets.Add(new Charset(22, "ISO8859_2", 1, "iso-8859-2"));
#if (!MONO)
// Windows Korean
charsets.Add(new Charset(44, "KSC_5601", 2, "ks_c_5601-1987"));
#endif
// MS-DOS Icelandic
charsets.Add(new Charset(47, "DOS861", 1, "ibm861"));
// Windows Eastern European
charsets.Add(new Charset(51, "WIN1250", 1, "windows-1250"));
#if (!MONO)
// Windows Cyrillic
charsets.Add(new Charset(52, "WIN1251", 1, "windows-1251"));
#endif
// Windows Latin-1
charsets.Add(new Charset(53, "WIN1252", 1, "windows-1252"));
// Windows Greek
charsets.Add(new Charset(54, "WIN1253", 1, "windows-1253"));
#if (!MONO)
// Windows Turkish
charsets.Add(new Charset(55, "WIN1254", 1, "windows-1254"));
// Big5, Traditional Chinese
charsets.Add(new Charset(56, "BIG_5", 2, "big5"));
// GB2312, EUC encoding, Simplified Chinese
charsets.Add(new Charset(57, "GB_2312", 2, "gb2312"));
// Windows Hebrew
charsets.Add(new Charset(58, "WIN1255", 1, "windows-1255"));
// Windows Arabic
charsets.Add(new Charset(59, "WIN1256", 1, "windows-1256"));
// Windows Baltic
charsets.Add(new Charset(60, "WIN1257", 1, "windows-1257"));
// UTF-16
// Charset.Add(new Charset(61, "UTF16", 4, "utf-16"));
// UTF-32
// Charset.Add(new Charset(62, "UTF32", 4, "utf-32"));
// Russian KOI8R
charsets.Add(new Charset(63, "KOI8R", 2, "koi8-r"));
// Ukrainian KOI8U
charsets.Add(new Charset(64, "KOI8U", 2, "koi8-u"));
#endif
return charsets;
}
*/
#endregion Old InitializeSupportedCharsets culled by dgorton
private static void addCharset(List<Charset> list,
EncodingInfo[] systemEncodings,
int id,
string name,
int bytesPerCharacter,
string systemName)
{
foreach(EncodingInfo ei in systemEncodings)
{
try
{
if (ei.Name.Equals(systemName,
StringComparison.OrdinalIgnoreCase))
{
list.Add(new Charset(id, name,
bytesPerCharacter, systemName));
}
}
catch
{
/*I hate doing this, but eat
it, and possibly log it out.
However, note that the
exception is thrown upon accessing ei.Name
(CodePage xx not supported),
so it must be trying to access the
encoding for internal
reasons, which doesn't happen on MS.NET.
One way to clean this up
might be to access the encodings by their
codepage rather than by name.
I'm not sure what the Charset.ID
property means to Firebird,
but it doesn't seem to correlate to
codepage as I understand it,
so this is about as far as I can go
without some collaborative
input.
*/
}
}
}
#endregion
#region · Fields ·
private int id;
private int bytesPerCharacter;
private string name;
private string systemName;
private Encoding encoding;
private object syncObject;
#endregion
#region · Properties ·
public int Identifier
{
get { return this.id; }
}
public string Name
{
get { return this.name; }
}
public int BytesPerCharacter
{
get { return this.bytesPerCharacter; }
}
public bool IsOctetsCharset
{
get { return (this.id == Charset.GetCharset("OCTETS").Identifier); }
}
#endregion
#region · Constructors ·
public Charset(int id, string name, int bytesPerCharacter,
string systemName)
{
this.id = id;
this.name = name;
this.bytesPerCharacter = bytesPerCharacter;
this.systemName = systemName;
this.syncObject = new object();
#if (!NET_CF)
this.GetEncoding();
#endif
}
#endregion
#region · Methods ·
public byte[] GetBytes(string s)
{
#if (NET_CF)
return this.GetEncoding().GetBytes(s);
#else
return this.encoding.GetBytes(s);
#endif
}
public int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
#if (NET_CF)
return this.GetEncoding().GetBytes(s, charIndex,
charCount, bytes, byteIndex);
#else
return this.encoding.GetBytes(s, charIndex, charCount, bytes,
byteIndex);
#endif
}
public string GetString(byte[] buffer)
{
return this.GetString(buffer, 0, buffer.Length);
}
public string GetString(byte[] buffer, int index, int count)
{
#if (NET_CF)
return this.GetEncoding().GetString(buffer, index,
count);
#else
return this.encoding.GetString(buffer, index, count);
#endif
}
#endregion
#region · Private Methods ·
private Encoding GetEncoding()
{
lock (this.syncObject)
{
if (this.encoding == null)
{
switch (this.systemName)
{
case "NONE":
this.encoding = Encoding.Default;
break;
case "OCTETS":
this.encoding = new BinaryEncoding();
break;
default:
this.encoding =
Encoding.GetEncoding(this.systemName);
break;
}
}
}
return this.encoding;
}
#endregion
}
}
------------------------------------------------------------------------------
Enable your software for Intel(R) Active Management Technology to meet the
growing manageability and security demands of your customers. Businesses
are taking advantage of Intel(R) vPro (TM) technology - will your software
be a part of the solution? Download the Intel(R) Manageability Checker
today! http://p.sf.net/sfu/intel-dev2devmar
_______________________________________________
Firebird-net-provider mailing list
Firebird-net-provider@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/firebird-net-provider