Неправильная кодировка прочитанного значения из sqlite базы
#38078271
Ссылка:
Ссылка на сообщение:
Ссылка с названием темы:
|
|
|
Есть sqlite база данных - описатель, содержащая список таблиц, список доменов, список полей, список ограничений (первичных и внешних ключей), список индексов. Я подключаюсь из Delphi XE3 c помощью встроенного компонента к этой базе. Есть отдельный модуль, в котором описанны классы TTableSpec, TFieldSpec, TConstraintSpec, TConstraintDetSpeс. Эти классы соответствуют записям вышеупомяноутой sqlite базы. В классах типа ТTableSpec есть такие поля типа FFields : TComponent, которое делается владельцем объектов типа TFieldSpec, также выгруженных из базы. После создания объектов путем чтения базы-описателя я обнаружил, что значения некоторых свойств объектов (например, TFieldSpec) находятся не в той кодировке(строка Edit2.Text:=TFieldSpec(TConstraintDetailSpec(TConstraintSpec(TTableSpec(DBSchema.Tables.FindComponent(InputTableName)).Constraints.Components[i]).DetailList).FieldSpec).FieldName; в нижеприведенной функции проверки на то, что является поле первичным ключом данной таблицы).
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
function TfmSettings.IsPrimaryKey(InputTableName : string; InputFieldName: string):Boolean;
var
i : integer;
flag: boolean;
begin
flag:=False;
for i:=0 to TTableSpec(DBSchema.Tables.FindComponent(InputTableName)).Constraints.ComponentCount-1 do
begin
if ((TConstraintSpec(TTableSpec(DBSchema.Tables.FindComponent(InputTableName)).Constraints.Components[i]).ConstraintType='PRIMARY') and (TTableSpec(DBSchema.Tables.FindComponent(InputTableName)).Fields.FindComponent(InputFieldName).Name=TConstraintDetailSpec(TConstraintSpec(TTableSpec(DBSchema.Tables.FindComponent(InputTableName)).Constraints.Components[i]).DetailList).FieldName)) then
flag:=True;
Edit1.Text:=TConstraintSpec(TTableSpec(DBSchema.Tables.FindComponent(InputTableName)).Constraints.Components[i]).Name;
Edit2.Text:=TFieldSpec(TConstraintDetailSpec(TConstraintSpec(TTableSpec(DBSchema.Tables.FindComponent(InputTableName)).Constraints.Components[i]).DetailList).FieldSpec).FieldName;
Edit3.Text:=InputFieldName;
end;
Result:=flag;
end;
Привожу также код процедур, создающих объекты, связанных с неправильной кодировкой:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126.
procedure CreationListOfFields(SQLConn: TSQLConnection; DBSchema : TDBSchemaSpec);
var
NameField : TField;
PositionField : TField;
DescriptionField : TField;
CanInputField : TField;
CanEditField : TField;
ShowInGridField : TField;
ShowInDetailsField : TField;
IsMeanField : TField;
AutocalculatedField : TField;
RequiredField : TField;
Name1 : TField;
Name2 : TField;
begin
SQLConn.Execute('select f.id, f.position, f.name, f.description, f.can_input, '
+' f.can_edit, f.show_in_grid, f.show_in_details, f.is_mean, f.autocalculated, f.required, t.name, d.name '
+' from fields f left join tables t on f.table_id=t.id '
+' left join domains d on f.domain_id=d.id order by t.name, d.name ', nil, results);
if not results.IsEmpty then
begin
results.First;
Name1:=results.FieldByName('name_1');
Name2:=results.FieldByName('name_2');
lastTable:=Name1.AsString;
TableSpec:=TTableSpec(DBSchema.Tables.FindComponent(lastTable));
lastDomain:=Name2.AsString;
DomainSpec:=TDomainSpec(DBSchema.Domains.FindComponent(lastDomain));
NameField:=results.FieldByName('name');
PositionField:=results.FieldByName('position');
DescriptionField:=results.FieldByName('description');
CanInputField:=results.FieldByName('can_input');
CanEditField:=results.FieldByName('can_edit');
ShowInGridField:=results.FieldByName('show_in_grid');
ShowInDetailsField:=results.FieldByName('show_in_details');
IsMeanField:=results.FieldByName('is_mean');
AutocalculatedField:=results.FieldByName('autocalculated');
RequiredField:=results.FieldByName('required');
while not results.Eof do
begin
if (Name1.AsString<>lastTable) then
begin
lastTable:=Name1.AsString;
TableSpec:=TTableSpec(DBSchema.Tables.FindComponent(lastTable));
end;
if (Name2.AsString<>lastDomain) then
begin
lastDomain:=Name2.AsString;
DomainSpec:=TDomainSpec(DBSchema.Domains.FindComponent(lastDomain));
end;
FieldSpec:=TFieldSpec.Create(TableSpec.Fields);
FieldSpec.Setup( DomainSpec, PositionField.AsInteger,
NameField.AsString, DescriptionField.AsString,
FieldToBoolean(CanInputField),FieldToBoolean(CanEditField),
FieldToBoolean(ShowInGridField), FieldToBoolean(ShowInDetailsField),
FieldToBoolean(IsMeanField),FieldToBoolean(AutocalculatedField),
FieldToBoolean(RequiredField));
TComponent(FieldSpec).Name:=NameField.AsString;
TableSpec.Fields.InsertComponent(FieldSpec);
results.Next;
end;
end;
end;
procedure CreationListOfConstrAndConstrDet(SQLConn : TSQLConnection; DBSchema : TDBSchemaSpec);
var
IDField : TField;
NameField : TField;
ConstrTypeField : TField;
ReferenceField : TField;
UniqueKeyIdField : TField;
HasValueEditField : TField;
CascadingDeleteField: TField;
ExpressionField : TField;
NameField1 : TField;
Name1 : TField;
begin
SQLConn.Execute('select c.id, c.name, constraint_type, reference, unique_key_id, has_value_edit, '
+ 'cascading_delete, expression, t.name from constraints c left join tables t on c.table_id=t.id order'
+' by t.name ', nil, results);
if not results.IsEmpty then
begin
results.First;
IDField:=results.FieldByName('ID');
NameField:=results.FieldByName('name');
ConstrTypeField:=results.FieldByName('constraint_type');
ReferenceField:=results.FieldByName('reference');
UniqueKeyIdField:=results.FieldByName('unique_key_id');
HasValueEditField:=results.FieldByName('has_value_edit');
CascadingDeleteField:=results.FieldByName('cascading_delete');
ExpressionField:=results.FieldByName('expression');
Name1:=results.FieldByName('name_1');
lastTable:=Name1.AsString;
TableSpec:=TTableSpec(DBSchema.Tables.FindComponent(lastTable));
while not results.Eof do
begin
if (Name1.AsString<>lastTable) then
begin
lastTable:=Name1.AsString;
TableSpec:=TTableSpec(DBSchema.Tables.FindComponent(lastTable));
end;
ConstraintSpec:=TConstraintSpec.Create(TableSpec.Constraints);
ConstraintSpec.Setup(IDField.AsInteger,NameField.AsString, ConstrTypeField.AsString,
ReferenceField.AsString, ConvertToInt(UniqueKeyIdField.AsString), FieldToBoolean(HasValueEditField),
FieldToBoolean(CascadingDeleteField), ExpressionField.AsString);
TComponent(ConstraintSpec).Name:=results.FieldByName('name').AsString;
TableSpec.Constraints.InsertComponent(ConstraintSpec);
SQLConn.Execute('select cd.id, f.name from constraint_details cd left join'
+' fields f on f.id=cd.field_id where cd.constraint_id = '+inttostr(ConstraintSpec.ID), nil, results1);
if not results1.IsEmpty then
begin
results1.First;
NameField1:=results1.FieldByName('name');
while not results1.Eof do
begin
FieldSpec:=TFieldSpec(TableSpec.Fields.FindComponent(NameField1.AsString));
ConstDetSpec:=TConstraintDetailSpec.Create(ConstraintSpec.DetailList);
ConstDetSpec.Setup(NameField1.AsString, FieldSpec);
ConstraintSpec.DetailList.InsertComponent(ConstDetSpec);
results1.Next;
end;
end;
results.Next;
end;
end;
end;
P.S. SQL-запросы выполняются в sqlite нормально. Выдает нужные строки в нужной кодировке (по крайней мере визуально результат содержит читабельные английские и русские символы). Привожу также код классов:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327.
unit DatabaseClasses;
interface
uses Classes;
type
TDataTypeId = (DataTypeId_String, DataTypeId_SmallInt, DataTypeId_Integer, DataTypeId_Word,
DataTypeId_Boolean, DataTypeId_Float, DataTypeId_Currency,
DataTypeId_BCD, DataTypeId_FmtBCD, DataTypeId_Date,
DataTypeId_Time, DataTypeId_DateTime, DataTypeId_TimeStamp,
DataTypeId_Bytes, DataTypeId_VarBytes, DataTypeId_Blob,
DataTypeId_Memo, DataTypeId_Graphic, DataTypeId_fmtMemo,
DataTypeId_FixedChar, DataTypeId_WideChar, DataTypeId_LargeInt,
DataTypeId_Array, DataTypeId_FixedWideChar, DataTypeId_WideMemo);
TAlignSpec = (AlignSpec_Left, AlignSpec_Right, AlignSpec_Center);
TFieldSpec=class;
TConstraintDetailSpec = class;
TIndexDetailSpec = class;
TDBSchemaSpec=class(Tcomponent)
private
FDomains: TComponent;
FTables : TComponent;
public
procedure Setup();
destructor Destroy; override;
property Domains: TComponent read FDomains;
property Tables : TComponent read FTables;
end;
TDomainSpec = class(TComponent)
private
FName: string;
FDescription: String;
FDataTypeId: TDataTypeId;
FLength: Cardinal;
FCharLength: Cardinal;
FPrecision: Cardinal;
FScale: Cardinal;
FWidth: Word;
FAlign: TAlignSpec;
FShowNull: Boolean;
FShowLeadNulls: Boolean;
FThousandsSeparator: Boolean;
public
procedure Setup(FName: string; FDescription: String; FDataTypeId: TDataTypeId;
FLength: Cardinal;FCharLength: Cardinal;FPrecision: Cardinal;FScale: Cardinal;
FWidth: Word;FAlign: TAlignSpec;FShowNull: Boolean;FShowLeadNulls: Boolean;
FThousandsSeparator: Boolean);
destructor Destroy; override;
property Name: String read FName;
property Description: String read FDescription;
property DataTypeId: TDataTypeId read FDataTypeId;
property Length: Cardinal read FLength;
property CharLength: Cardinal read FCharLength;
property Precision: Cardinal read FPrecision;
property Scale: Cardinal read FScale;
property Width: Word read FWidth;
property Align: TAlignSpec read FAlign;
property ShowNull: Boolean read FShowNull;
property ShowLeadNulls: Boolean read FShowLeadNulls;
property ThousandsSeparator: Boolean read FThousandsSeparator;
end;
TTableSpec= class(TComponent)
private
FFields : TComponent;
FIndices: TComponent;
FConstraints : TComponent;
FName : string;
FDescription: string;
FCanAdd: boolean;
FCanEdit: boolean;
FCanDelete: boolean;
public
procedure Setup(FName : string; FDescription:string;
FCanAdd: boolean; FCanEdit: boolean; FCanDelete: boolean);
destructor Destroy; override;
property Description : string read FDescription;
property Name : string read FName;
property CanAdd: boolean read FCanAdd;
property CanEdit: boolean read FCanEdit;
property CanDelete: boolean read FCanDelete;
property Fields : TComponent read FFields;
property Indices: TComponent read FIndices;
property Constraints : TComponent read FConstraints;
end;
TFieldSpec = class(TComponent)
private
FDomainSpec: TDomainSpec;
FPosition: integer;
FFieldName: string;
FDescription: string;
FCanInput: boolean;
FCanEdit: boolean;
FShowInGrid: boolean;
FShowInDetails: boolean;
FIsMean: boolean;
FAutoCalculated: boolean;
FRequired: boolean;
public
procedure Setup(FDomainSpec: TDomainSpec; FPosition: integer; FFieldName: string; FDescription: string; FCanInput: boolean; FCanEdit: boolean;
FShowInGrid: boolean; FShowInDetails: boolean; FIsMean: boolean;FAutoCalculated: boolean;
FRequired: boolean);
destructor Destroy; override;
property DomainSpec: TDomainSpec read FDomainSpec;
property Position: integer read FPosition;
property FieldName: string read FFieldName;
property Description: string read FDescription;
property CanInput: boolean read FCanInput;
property CanEdit: boolean read FCanEdit;
property ShowInGrid: boolean read FShowInGrid;
property ShowInDetails: boolean read FShowInDetails;
property IsMean: boolean read FIsMean;
property AutoCalculated: boolean read FAutoCalculated;
property Required: boolean read FRequired;
end;
TConstraintSpec = class(TComponent)
private
FID: integer;
FDetails: TComponent;
FName: string;
FConstraintType: string;
FReference: string;
FUniqueKeyId: integer;
FHasValueEdit: boolean;
FCascadingDelete: boolean;
FExpression: string;
public
procedure Setup(FID: integer; FName: string;
FConstraintType: string; FReference: string; FUniqueKeyId: integer;
FHasValueEdit: boolean; FCascadingDelete: boolean; FExpression: string);
destructor Destroy; override;
property ID: integer read FID;
property Name: string read FName;
property ConstraintType: string read FConstraintType;
property Reference: string read FReference;
property UniqueKeyId: integer read FUniqueKeyId;
property HasValueEdit: boolean read FHasValueEdit;
property CascadingDelete: boolean read FCascadingDelete;
property Expression: string read FExpression;
property DetailList: TComponent read FDetails;
end;
TConstraintDetailSpec = class(TComponent)
private
FFieldName: string;
FFieldSpec: TFieldSpec;
public
procedure Setup(FFieldName: string; FFieldSpec: TFieldSpec);
destructor Destroy; override;
property FieldName: string read FFieldName;
property FieldSpec: TFieldSpec read FFieldSpec;
end;
TIndexSpec = class(TComponent)
private
FDetails: TComponent;
FID : integer;
FName: string;
FUniqueness: boolean;
public
procedure Setup(FID: integer; FName: string; FUniqueness: boolean );
destructor Destroy; override;
property ID : integer read FID;
property DetailList:TComponent read FDetails;
property Name: string read FName;
property Uniqueness: boolean read FUniqueness;
end;
TIndexDetailSpec = class(TComponent)
private
FPosition: integer;
FFieldSpec: TFieldSpec;
FExpression: string;
FDescend: boolean;
public
procedure Setup(FPosition: integer; FFieldSpec: TFieldSpec;
FExpression: string; FDescend: boolean );
destructor Destroy; override;
property FieldSpec: TFieldSpec read FFieldSpec;
property Position: integer read FPosition;
property Expression: string read FExpression;
property Descend: boolean read FDescend;
end;
implementation
procedure TDBSchemaSpec.Setup;
begin
FDomains := TComponent.Create(self);
FTables := TComponent.Create(self);
end;
destructor TDBSchemaSpec.Destroy;
begin
FDomains.Free;
FTables.Free;
inherited Destroy;
end;
procedure TDomainSpec.Setup;
begin
self.FName:=FName;
self.FDescription:=FDescription;
self.FDataTypeId:=FDataTypeId;
self.FLength:=FLength;
self.FCharLength:=FCharLength;
self.FPrecision:=FPrecision;
self.FScale:=FScale;
self.FWidth:=FWidth;
self.FAlign:=FAlign;
self.FShowNull:=FShowNull;
self.FShowLeadNulls:=FShowLeadNulls;
self.FThousandsSeparator:=FThousandsSeparator;
end;
destructor TDomainSpec.Destroy;
begin
inherited Destroy;
end;
procedure TTableSpec.Setup;
begin
FFields := TComponent.Create(Self);
FConstraints := TComponent.Create(Self);
FIndices := TComponent.Create(Self);
Self.FName:=FName;
self.FDescription:=FDescription;
self.FCanAdd:=FCanAdd;
self.FCanEdit:=FCanEdit;
self.FCanDelete:=FCanDelete;
end;
destructor TTableSpec.Destroy;
begin
FFields.Free;
FConstraints.Free;
FIndices.Free;
inherited Destroy;
end;
procedure TFieldSpec.Setup;
begin
self.FDomainSpec:=FDomainSpec;
self.FPosition:=Fposition;
self.FFieldName:=FFieldName;
self.FDescription:=FDescription;
self.FCanInput:=FCanInput;
self.FCanEdit:=FCanEdit;
self.FShowInGrid:=FShowInGrid;
self.FShowInDetails:=FShowInDetails;
self.FIsMean:=FIsMean;
self.FAutoCalculated:=FAutoCalculated;
self.FRequired:=FRequired;
end;
destructor TFieldSpec.Destroy;
begin
inherited Destroy;
end;
procedure TConstraintSpec.Setup;
begin
FDetails := TComponent.Create(self);
self.FID:=FID;
self.FName:=FName;
self.FConstraintType:=FConstraintType;
self.FReference:=FReference;
self.FUniqueKeyId:=FUniqueKeyId;
self.FHasValueEdit:=FhasValueEdit;
self.FCascadingDelete:=FCascadingDelete;
self.FExpression:=FExpression;
end;
destructor TConstraintSpec.Destroy;
begin
FDetails.Free;
inherited Destroy;
end;
procedure TConstraintDetailSpec.Setup;
begin
self.FFieldName:=FFieldName;
self.FFieldSpec:=FFieldSpec;
end;
destructor TConstraintDetailSpec.Destroy;
begin
inherited Destroy;
end;
procedure TIndexSpec.Setup;
begin
FDetails := TComponent.Create(self);
self.FID:=FID;
self.FName:=FName;
self.FUniqueness:=FUniqueness;
end;
destructor TIndexSpec.Destroy;
begin
FDetails.Free;
inherited Destroy;
end;
procedure TIndexDetailSpec.setup;
begin
self.FPosition:=FPosition;
self.FFieldSpec:=FFieldSpec;
self.FExpression:=FExpression;
self.FDescend:=FDescend;
end;
destructor TIndexDetailSpec.Destroy;
begin
inherited Destroy;
end;
end.
|
|