📄 fastdbfields.cs
字号:
break;
case CLI.FieldType.cli_real4:
*(Single*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer() = Convert.ToSingle(Value);
break;
case CLI.FieldType.cli_datetime:
case CLI.FieldType.cli_real8:
*(double*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer() = Convert.ToDouble(Value);
break;
case CLI.FieldType.cli_asciiz:
case CLI.FieldType.cli_pasciiz:
//byte[] bytes = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, Encoding.Unicode.GetBytes(Value.ToString()));
//cli_ex_buffer_resize(buffer, buffer.type, bytes.Length, true);
//buffer.data = Marshal.AllocCoTaskMem( bytes.Length );
//Marshal.
//Marshal.Copy(bytes, 0, buffer.data, bytes.Length);
//fixed(char* p = &bytes[0])
//{
string s = Value.ToString();
IntPtr str = Marshal.StringToHGlobalAnsi(s);
try {
CopyBufferData((CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type, s.Length, str);
}
finally {
Marshal.FreeCoTaskMem(str);
}
break;
default:
throw new CliError("Unsupported type: "+Enum.GetName(typeof(CLI.FieldType), (CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type));
}
}
// Implement IDisposable.
// This method is not virtual. A derived class should not be able to override this method.
public void Dispose() {
Dispose(true);
// Take yourself off the Finalization queue
// to prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected unsafe virtual void Dispose(bool disposing) {
// Check to see if Dispose has already been called.
if(!this.disposed) {
// If disposing equals true, dispose managed resources.
if(disposing) { // Dispose managed resources here.
Marshal.FreeCoTaskMem(((CLI.UnmanagedBuffer*)buffer.ToPointer())->data);
((CLI.UnmanagedBuffer*)buffer.ToPointer())->data = (IntPtr)0;
Marshal.FreeCoTaskMem(buffer);
}
// Release unmanaged resources.
//CLI.cli_ex_buffer_free(buffer);
disposed = true;
}
}
#region IEnumerable Members
public IEnumerator GetEnumerator() {
// TODO: Add FastDbBuffer.GetEnumerator implementation
return null;
}
#endregion
}
//-------------------------------------------------------------------------
/// <summary>
/// FastDbField implements a class that automatically manages the memory
/// associated with a field belonging to a database cursor.
/// </summary>
public class FastDbField: FastDbBuffer {
public string RefTable;
public string InvRefField;
/// <summary>
/// Field's constructor.
/// </summary>
/// <param name="name">Field name</param>
/// <param name="field_type">Field type</param>
/// <param name="idx_flags">Index types (hash/T-tree)</param>
/// <param name="ref_table">Reference table name for inverse reference fields</param>
/// <param name="inv_ref_field">Inverse reference field name</param>
public FastDbField(string name, CLI.FieldType field_type, CLI.FieldFlags idx_flags,
string ref_table, string inv_ref_field) :
base(name, field_type, idx_flags) {
this.RefTable = ref_table;
this.InvRefField = inv_ref_field;
}
/// <summary>
/// Copy field's content to the current field
/// </summary>
/// <param name="field">Source field to copy from</param>
public override void Assign(FastDbBuffer field) {
Debug.Assert(field is FastDbField, "Cannot assign " + field.GetType().Name + " type!");
base.Assign(field);
this.RefTable = ((FastDbField)field).RefTable;
this.InvRefField = ((FastDbField)field).InvRefField;
}
/// <summary>
/// Is true if the field is of array type.
/// </summary>
public bool IsArray { get { return CLI.IsArrayType(Type); } }
/// <summary>
/// Returns the number of array elements for array type fields
/// </summary>
public unsafe int ArraySize {
get {
if (CLI.IsArrayType(this.Type)) {
return Size / CLI.SizeOfCliType[(int)this.Type - (int)CLI.FieldType.cli_array_of_oid];
} else
return 0;
}
set {
Debug.Assert(CLI.IsArrayType(this.Type), "Cannot set array size on non-array fields: "+Enum.GetName(typeof(CLI.FieldType), Type));
int n = CLI.SizeOfCliType[(int)this.Type - (int)CLI.FieldType.cli_array_of_oid] * value;
if (Size != n)
SetBufferTypeAndSize((CLI.UnmanagedBuffer*)buffer.ToPointer(), this.Type, n, true);
}
}
public bool ArrayAsBoolean(int idx) { return (bool)getArrayValue(typeof(bool), idx);}
public Int16 ArrayAsInt16(int idx) { return (Int16)getArrayValue(typeof(Int16), idx);}
public uint ArrayAsOID(int idx) { return (uint)getArrayValue(typeof(uint), idx);}
public Int64 ArrayAsInt64(int idx) { return (Int64)getArrayValue(typeof(Int64), idx);}
public double ArrayAsDouble(int idx) { return (double)getArrayValue(typeof(double), idx);}
public string ArrayAsString(int idx) { return (string)getArrayValue(typeof(string), idx);}
protected unsafe Object getArrayValue(Type t, int idx) {
switch((CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type) {
case CLI.FieldType.cli_array_of_bool:
case CLI.FieldType.cli_array_of_int1: return Convert.ChangeType(*((sbyte*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(sbyte)*idx), t);
case CLI.FieldType.cli_array_of_int2: return Convert.ChangeType(*((short*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(short)*idx), t);
case CLI.FieldType.cli_array_of_oid: return Convert.ChangeType(*((uint*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(uint)*idx), t);
case CLI.FieldType.cli_array_of_int4: return Convert.ChangeType(*((int*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(int)*idx), t);
case CLI.FieldType.cli_array_of_int8: return Convert.ChangeType(*((Int64*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(Int64)*idx), t);
case CLI.FieldType.cli_array_of_real4: return Convert.ChangeType(*((Single*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(Single)*idx), t);
case CLI.FieldType.cli_array_of_real8: return Convert.ChangeType(*((double*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(double)*idx), t);
default: throw new CliError("Unsupported type!");
}
}
/// <summary>
/// This method adds functionality to the base class that allows to get
/// the content of an array field as string.
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
protected override unsafe Object getValue(Type t) {
switch((CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type) {
case CLI.FieldType.cli_array_of_int1:
case CLI.FieldType.cli_array_of_int2:
case CLI.FieldType.cli_array_of_int4:
case CLI.FieldType.cli_array_of_int8:
case CLI.FieldType.cli_array_of_oid:
case CLI.FieldType.cli_array_of_real4:
case CLI.FieldType.cli_array_of_real8:
if (t != typeof(string)) throw new CliError("getValue: Unsupported conversion type! "+Enum.GetName(typeof(CLI.FieldType), ((CLI.UnmanagedBuffer*)buffer.ToPointer())->type));
StringBuilder s = new StringBuilder("{");
for(int i=0; i < ArraySize; i++) {
s.Append(ArrayAsString(i));
s.Append( (i == ArraySize-1) ? "" : "," );
}
s.Append("}");
return s.ToString();
default:
return base.getValue(t);
}
}
/// <summary>
/// Set a value of an array element. <seealso cref="CLI.FieldType"/>
/// </summary>
/// <param name="idx">Element index</param>
/// <param name="Value">Element's new value</param>
public unsafe void SetArrayValue(int idx, Object Value) {
Debug.Assert(idx >= 0 && idx < ArraySize, "Array index " + idx + " out of bounds!");
switch((CLI.FieldType)((CLI.UnmanagedBuffer*)buffer.ToPointer())->type) {
case CLI.FieldType.cli_array_of_oid:
*((uint*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(uint)*idx) = Convert.ToUInt32(Value);
break;
case CLI.FieldType.cli_array_of_int4:
*((int*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(int)*idx) = Convert.ToInt32(Value);
break;
case CLI.FieldType.cli_array_of_bool:
case CLI.FieldType.cli_int1:
*((sbyte*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(sbyte)*idx) = Convert.ToSByte(Value);
break;
case CLI.FieldType.cli_array_of_int2:
*((Int16*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(Int16)*idx) = Convert.ToInt16(Value);
break;
case CLI.FieldType.cli_array_of_int8:
*((Int64*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(Int64)*idx) = Convert.ToInt64(Value);
break;
case CLI.FieldType.cli_array_of_real4:
*((Single*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(Single)*idx) = Convert.ToSingle(Value);
break;
case CLI.FieldType.cli_array_of_real8:
*((double*)((CLI.UnmanagedBuffer*)buffer.ToPointer())->data.ToPointer()+sizeof(double)*idx) = Convert.ToDouble(Value);
break;
default:
throw new CliError("Unsupported type!");
}
}
internal unsafe override void Bind(int StatementID) {
int res;
base.Bind(StatementID);
if (bound_to_statement == StatementID)
return;
else
bound_to_statement = StatementID;
//IntPtr pname = Marshal.StringToHGlobalAnsi(Name);
try {
if (CLI.IsArrayType(Type) || Type == CLI.FieldType.cli_asciiz || Type == CLI.FieldType.cli_pasciiz)
res = CLI.cli_array_column_ex(StatementID, name,
(Type == CLI.FieldType.cli_pasciiz) ? (int)CLI.FieldType.cli_asciiz : (int)Type,
((CLI.UnmanagedBuffer*)buffer.ToPointer())->data,
doSetColumn, doGetColumn, (CLI.UnmanagedBuffer*)buffer.ToPointer());
else
res = CLI.cli_column(StatementID, name, (int)Type, ref ((CLI.UnmanagedBuffer*)buffer.ToPointer())->size, ((CLI.UnmanagedBuffer*)buffer.ToPointer())->data);
CLI.CliCheck(res);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -