| 1 | unit UPDClient;
|
|---|
| 2 |
|
|---|
| 3 | interface
|
|---|
| 4 |
|
|---|
| 5 | uses
|
|---|
| 6 | Classes, SysUtils, Generics.Collections, Generics;
|
|---|
| 7 |
|
|---|
| 8 | const
|
|---|
| 9 | SystemVersionObject = 'SystemVersion';
|
|---|
| 10 |
|
|---|
| 11 | type
|
|---|
| 12 | EClientNotSet = class(Exception);
|
|---|
| 13 |
|
|---|
| 14 | TPDClient = class;
|
|---|
| 15 | TPDType = class;
|
|---|
| 16 |
|
|---|
| 17 | TOrderDirection = (odNone, odAscending, odDescending);
|
|---|
| 18 |
|
|---|
| 19 | { TObjectProxy }
|
|---|
| 20 |
|
|---|
| 21 | TObjectProxy = class
|
|---|
| 22 | Id: Integer;
|
|---|
| 23 | Properties: TDictionaryStringString;
|
|---|
| 24 | Client: TPDClient;
|
|---|
| 25 | ObjectName: string;
|
|---|
| 26 | Path: string;
|
|---|
| 27 | procedure Load;
|
|---|
| 28 | procedure Save;
|
|---|
| 29 | procedure Delete;
|
|---|
| 30 | constructor Create;
|
|---|
| 31 | destructor Destroy; override;
|
|---|
| 32 | procedure Assign(Source: TObjectProxy);
|
|---|
| 33 | end;
|
|---|
| 34 |
|
|---|
| 35 | { TObjectProxies }
|
|---|
| 36 |
|
|---|
| 37 | TObjectProxies = class(TObjectList<TObjectProxy>)
|
|---|
| 38 | function AddProxy: TObjectProxy;
|
|---|
| 39 | end;
|
|---|
| 40 |
|
|---|
| 41 | TOperation = (opUndefined, opDefined, opEqual, opNotEqual,
|
|---|
| 42 | opLess, opMore, opLessOrEqual, opMoreOrEqual);
|
|---|
| 43 |
|
|---|
| 44 | TCondition = class
|
|---|
| 45 | Column: string;
|
|---|
| 46 | Operation: TOperation;
|
|---|
| 47 | Value: string;
|
|---|
| 48 | end;
|
|---|
| 49 |
|
|---|
| 50 | { TListProxy }
|
|---|
| 51 |
|
|---|
| 52 | TListProxy = class
|
|---|
| 53 | Client: TPDClient;
|
|---|
| 54 | OrderColumn: string;
|
|---|
| 55 | OrderDirection: TOrderDirection;
|
|---|
| 56 | OrderUse: Boolean;
|
|---|
| 57 | PageItemFirst: Integer;
|
|---|
| 58 | PageItemCount: Integer;
|
|---|
| 59 | PageUse: Boolean;
|
|---|
| 60 | ColumnsFilter: TListString;
|
|---|
| 61 | ColummsFilterUse: Boolean;
|
|---|
| 62 | Condition: string;
|
|---|
| 63 | ObjectName: string;
|
|---|
| 64 | Path: string;
|
|---|
| 65 | Objects: TObjectList<TObjectProxy>;
|
|---|
| 66 | procedure Clear;
|
|---|
| 67 | constructor Create;
|
|---|
| 68 | destructor Destroy; override;
|
|---|
| 69 | procedure Load; virtual;
|
|---|
| 70 | procedure Save; virtual;
|
|---|
| 71 | end;
|
|---|
| 72 |
|
|---|
| 73 | TPDTypeProperty = class
|
|---|
| 74 | Name: string;
|
|---|
| 75 | DbType: TPDType;
|
|---|
| 76 | Unique: Boolean;
|
|---|
| 77 | Index: Boolean;
|
|---|
| 78 | end;
|
|---|
| 79 |
|
|---|
| 80 | { TPDTypeProperties }
|
|---|
| 81 |
|
|---|
| 82 | TPDTypeProperties = class(TObjectList<TPDTypeProperty>)
|
|---|
| 83 | Client: TPDClient;
|
|---|
| 84 | function AddSimple(Name: string; TypeName: string; Unique: Boolean = False;
|
|---|
| 85 | Index: Boolean = False): TPDTypeProperty;
|
|---|
| 86 | end;
|
|---|
| 87 |
|
|---|
| 88 | { TPDType }
|
|---|
| 89 |
|
|---|
| 90 | TPDType = class
|
|---|
| 91 | private
|
|---|
| 92 | FClient: TPDClient;
|
|---|
| 93 | procedure SetClient(AValue: TPDClient);
|
|---|
| 94 | public
|
|---|
| 95 | Name: string;
|
|---|
| 96 | DbType: string;
|
|---|
| 97 | Properties: TPDTypeProperties;
|
|---|
| 98 | function IsDefined: Boolean;
|
|---|
| 99 | procedure Define;
|
|---|
| 100 | procedure Undefine;
|
|---|
| 101 | constructor Create;
|
|---|
| 102 | destructor Destroy; override;
|
|---|
| 103 | property Client: TPDClient read FClient write SetClient;
|
|---|
| 104 | end;
|
|---|
| 105 |
|
|---|
| 106 | { TPDTypes }
|
|---|
| 107 |
|
|---|
| 108 | TPDTypes = class(TObjectList<TPDType>)
|
|---|
| 109 | Client: TPDClient;
|
|---|
| 110 | function AddType(Name: string; DbType: string = ''): TPDType;
|
|---|
| 111 | function SearchByName(Name: string): TPDType;
|
|---|
| 112 | end;
|
|---|
| 113 |
|
|---|
| 114 | { TPDClient }
|
|---|
| 115 |
|
|---|
| 116 | TPDClient = class(TComponent)
|
|---|
| 117 | private
|
|---|
| 118 | FSchema: string;
|
|---|
| 119 | procedure SetConnected(AValue: Boolean);
|
|---|
| 120 | protected
|
|---|
| 121 | procedure InitSystemTypes; virtual;
|
|---|
| 122 | procedure Init; virtual;
|
|---|
| 123 | function GetConnected: Boolean; virtual;
|
|---|
| 124 | function GetConnectionString: string; virtual;
|
|---|
| 125 | procedure SetConnectionString(AValue: string); virtual;
|
|---|
| 126 | public
|
|---|
| 127 | Types: TPDTypes;
|
|---|
| 128 | Version: string;
|
|---|
| 129 | BackendName: string;
|
|---|
| 130 | procedure ObjectLoad(AObject: TObjectProxy); virtual; abstract;
|
|---|
| 131 | procedure ObjectSave(AObject: TObjectProxy); virtual; abstract;
|
|---|
| 132 | procedure ObjectDelete(AObject: TObjectProxy); virtual; abstract;
|
|---|
| 133 | procedure ListLoad(AList: TListProxy); virtual; abstract;
|
|---|
| 134 | procedure ListSave(AList: TListProxy); virtual; abstract;
|
|---|
| 135 | function TypeIsDefined(AType: TPDType): Boolean; virtual; abstract;
|
|---|
| 136 | procedure TypeDefine(AType: TPDType); virtual; abstract;
|
|---|
| 137 | procedure TypeUndefine(AType: TPDType); virtual; abstract;
|
|---|
| 138 | procedure CheckTypes;
|
|---|
| 139 | constructor Create(AOwner: TComponent); override;
|
|---|
| 140 | destructor Destroy; override;
|
|---|
| 141 | procedure Connect; virtual;
|
|---|
| 142 | procedure Disconnect; virtual;
|
|---|
| 143 | procedure Install; virtual;
|
|---|
| 144 | procedure Uninstall; virtual;
|
|---|
| 145 | procedure Update; virtual;
|
|---|
| 146 | published
|
|---|
| 147 | property Schema: string read FSchema write FSchema;
|
|---|
| 148 | property Connected: Boolean read GetConnected write SetConnected;
|
|---|
| 149 | property ConnectionString: string read GetConnectionString
|
|---|
| 150 | write SetConnectionString;
|
|---|
| 151 | end;
|
|---|
| 152 |
|
|---|
| 153 | TPDClientClass = class of TPDClient;
|
|---|
| 154 |
|
|---|
| 155 | resourcestring
|
|---|
| 156 | SClientNotSet = 'Client not set';
|
|---|
| 157 | SNotSupported = 'Not supported';
|
|---|
| 158 | SVersionMismatch = 'Version mismatch, client: %0:s, server: %1:s. Please upgrade database.';
|
|---|
| 159 | SCantLoadObjectWithoutId = 'Can''t load object without id';
|
|---|
| 160 |
|
|---|
| 161 |
|
|---|
| 162 | implementation
|
|---|
| 163 |
|
|---|
| 164 | { TObjectProxies }
|
|---|
| 165 |
|
|---|
| 166 | function TObjectProxies.AddProxy: TObjectProxy;
|
|---|
| 167 | begin
|
|---|
| 168 | Result := TObjectProxy.Create;
|
|---|
| 169 | Add(Result);
|
|---|
| 170 | end;
|
|---|
| 171 |
|
|---|
| 172 | { TPDTypeProperties }
|
|---|
| 173 |
|
|---|
| 174 | function TPDTypeProperties.AddSimple(Name: string; TypeName: string;
|
|---|
| 175 | Unique: Boolean = False; Index: Boolean = False): TPDTypeProperty;
|
|---|
| 176 | begin
|
|---|
| 177 | Result := TPDTypeProperty.Create;
|
|---|
| 178 | Result.Name := Name;
|
|---|
| 179 | Result.DbType := Client.Types.SearchByName(TypeName);
|
|---|
| 180 | Result.Unique := Unique;
|
|---|
| 181 | Result.Index := Index;
|
|---|
| 182 | Add(Result);
|
|---|
| 183 | end;
|
|---|
| 184 |
|
|---|
| 185 | { TPDTypes }
|
|---|
| 186 |
|
|---|
| 187 | function TPDTypes.AddType(Name: string; DbType: string = ''): TPDType;
|
|---|
| 188 | begin
|
|---|
| 189 | Result := TPDType.Create;
|
|---|
| 190 | Result.Client := Client;
|
|---|
| 191 | Result.Name := Name;
|
|---|
| 192 | Result.DbType := DbType;
|
|---|
| 193 | Add(Result);
|
|---|
| 194 | end;
|
|---|
| 195 |
|
|---|
| 196 | function TPDTypes.SearchByName(Name: string): TPDType;
|
|---|
| 197 | var
|
|---|
| 198 | I: Integer;
|
|---|
| 199 | begin
|
|---|
| 200 | I := 0;
|
|---|
| 201 | while (I < Count) and (TPDType(Items[I]).Name <> Name) do Inc(I);
|
|---|
| 202 | if I < Count then Result := TPDType(Items[I])
|
|---|
| 203 | else Result := nil;
|
|---|
| 204 | end;
|
|---|
| 205 |
|
|---|
| 206 | procedure TPDType.SetClient(AValue: TPDClient);
|
|---|
| 207 | begin
|
|---|
| 208 | if FClient = AValue then Exit;
|
|---|
| 209 | FClient := AValue;
|
|---|
| 210 | Properties.Client := AValue;
|
|---|
| 211 | end;
|
|---|
| 212 |
|
|---|
| 213 | function TPDType.IsDefined: Boolean;
|
|---|
| 214 | begin
|
|---|
| 215 | if Assigned(Client) then Result := Client.TypeIsDefined(Self)
|
|---|
| 216 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 217 | end;
|
|---|
| 218 |
|
|---|
| 219 | procedure TPDType.Define;
|
|---|
| 220 | begin
|
|---|
| 221 | if Assigned(Client) then Client.TypeDefine(Self)
|
|---|
| 222 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 223 | end;
|
|---|
| 224 |
|
|---|
| 225 | procedure TPDType.Undefine;
|
|---|
| 226 | begin
|
|---|
| 227 | if Assigned(Client) then Client.TypeUndefine(Self)
|
|---|
| 228 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 229 | end;
|
|---|
| 230 |
|
|---|
| 231 | constructor TPDType.Create;
|
|---|
| 232 | begin
|
|---|
| 233 | Properties := TPDTypeProperties.Create;
|
|---|
| 234 | end;
|
|---|
| 235 |
|
|---|
| 236 | destructor TPDType.Destroy;
|
|---|
| 237 | begin
|
|---|
| 238 | FreeAndNil(Properties);
|
|---|
| 239 | inherited;
|
|---|
| 240 | end;
|
|---|
| 241 |
|
|---|
| 242 | { TObjectProxy }
|
|---|
| 243 |
|
|---|
| 244 | procedure TObjectProxy.Load;
|
|---|
| 245 | begin
|
|---|
| 246 | if Assigned(Client) then Client.ObjectLoad(Self)
|
|---|
| 247 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 248 | end;
|
|---|
| 249 |
|
|---|
| 250 | procedure TObjectProxy.Save;
|
|---|
| 251 | begin
|
|---|
| 252 | if Assigned(Client) then Client.ObjectSave(Self)
|
|---|
| 253 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 254 | end;
|
|---|
| 255 |
|
|---|
| 256 | procedure TObjectProxy.Delete;
|
|---|
| 257 | begin
|
|---|
| 258 | if Assigned(Client) then Client.ObjectDelete(Self)
|
|---|
| 259 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 260 | end;
|
|---|
| 261 |
|
|---|
| 262 | constructor TObjectProxy.Create;
|
|---|
| 263 | begin
|
|---|
| 264 | Properties := TDictionaryStringString.Create;
|
|---|
| 265 | end;
|
|---|
| 266 |
|
|---|
| 267 | destructor TObjectProxy.Destroy;
|
|---|
| 268 | begin
|
|---|
| 269 | FreeAndNil(Properties);
|
|---|
| 270 | inherited;
|
|---|
| 271 | end;
|
|---|
| 272 |
|
|---|
| 273 | procedure TObjectProxy.Assign(Source: TObjectProxy);
|
|---|
| 274 | begin
|
|---|
| 275 | Path := Source.Path;
|
|---|
| 276 | Client := Source.Client;
|
|---|
| 277 | ObjectName := Source.ObjectName;
|
|---|
| 278 | Id := Source.Id;
|
|---|
| 279 | Properties.Assign(Source.Properties);
|
|---|
| 280 | end;
|
|---|
| 281 |
|
|---|
| 282 | { TListProxy }
|
|---|
| 283 |
|
|---|
| 284 | procedure TListProxy.Clear;
|
|---|
| 285 | begin
|
|---|
| 286 | PageUse := False;
|
|---|
| 287 | ColummsFilterUse := False;
|
|---|
| 288 | OrderUse := False;
|
|---|
| 289 | Objects.Free;
|
|---|
| 290 | end;
|
|---|
| 291 |
|
|---|
| 292 | constructor TListProxy.Create;
|
|---|
| 293 | begin
|
|---|
| 294 | ColumnsFilter := TListString.Create;
|
|---|
| 295 | Objects := TObjectList<TObjectProxy>.Create;
|
|---|
| 296 | end;
|
|---|
| 297 |
|
|---|
| 298 | destructor TListProxy.Destroy;
|
|---|
| 299 | begin
|
|---|
| 300 | FreeAndNil(Objects);
|
|---|
| 301 | FreeAndNil(ColumnsFilter);
|
|---|
| 302 | inherited;
|
|---|
| 303 | end;
|
|---|
| 304 |
|
|---|
| 305 | procedure TListProxy.Load;
|
|---|
| 306 | begin
|
|---|
| 307 | if Assigned(Client) then Client.ListLoad(Self)
|
|---|
| 308 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 309 | end;
|
|---|
| 310 |
|
|---|
| 311 | procedure TListProxy.Save;
|
|---|
| 312 | begin
|
|---|
| 313 | if Assigned(Client) then Client.ListSave(Self)
|
|---|
| 314 | else raise EClientNotSet.Create(SClientNotSet);
|
|---|
| 315 | end;
|
|---|
| 316 |
|
|---|
| 317 | { TPDClient }
|
|---|
| 318 |
|
|---|
| 319 | function TPDClient.GetConnectionString: string;
|
|---|
| 320 | begin
|
|---|
| 321 | Result := '';
|
|---|
| 322 | end;
|
|---|
| 323 |
|
|---|
| 324 | procedure TPDClient.SetConnectionString(AValue: string);
|
|---|
| 325 | begin
|
|---|
| 326 | end;
|
|---|
| 327 |
|
|---|
| 328 | procedure TPDClient.SetConnected(AValue: Boolean);
|
|---|
| 329 | begin
|
|---|
| 330 | if AValue then Connect else Disconnect;
|
|---|
| 331 | end;
|
|---|
| 332 |
|
|---|
| 333 | procedure TPDClient.InitSystemTypes;
|
|---|
| 334 | begin
|
|---|
| 335 | end;
|
|---|
| 336 |
|
|---|
| 337 | procedure TPDClient.Init;
|
|---|
| 338 | var
|
|---|
| 339 | NewProxy: TListProxy;
|
|---|
| 340 | NewType: TPDType;
|
|---|
| 341 | NewObject: TObjectProxy;
|
|---|
| 342 | DbVersion: string;
|
|---|
| 343 | begin
|
|---|
| 344 | NewProxy := TListProxy.Create;
|
|---|
| 345 | NewProxy.Client := Self;
|
|---|
| 346 | NewProxy.Path := 'information_schema';
|
|---|
| 347 | NewProxy.ObjectName := 'TABLES';
|
|---|
| 348 | NewProxy.Condition := '(TABLE_SCHEMA = "' + Schema +
|
|---|
| 349 | '") AND (TABLE_NAME = "' + SystemVersionObject + '")';
|
|---|
| 350 | NewProxy.Load;
|
|---|
| 351 | if NewProxy.Objects.Count > 0 then begin
|
|---|
| 352 | NewObject := TObjectProxy.Create;
|
|---|
| 353 | NewObject.Client := Self;
|
|---|
| 354 | NewObject.Path := Schema;
|
|---|
| 355 | NewObject.ObjectName := SystemVersionObject;
|
|---|
| 356 | NewObject.Id := 1;
|
|---|
| 357 | NewObject.Load;
|
|---|
| 358 |
|
|---|
| 359 | DbVersion := NewObject.Properties.Items['Version'];
|
|---|
| 360 | if Version <> DbVersion then
|
|---|
| 361 | raise Exception.Create(Format(SVersionMismatch, [Version, DbVersion]));
|
|---|
| 362 | end else begin
|
|---|
| 363 | NewType := TPDType.Create;
|
|---|
| 364 | NewType.Client := Self;
|
|---|
| 365 | NewType.Name := SystemVersionObject;
|
|---|
| 366 | NewType.Properties.AddSimple('Version', 'String');
|
|---|
| 367 | NewType.Properties.AddSimple('Time', 'DateTime');
|
|---|
| 368 | NewType.Define;
|
|---|
| 369 |
|
|---|
| 370 | NewObject := TObjectProxy.Create;
|
|---|
| 371 | NewObject.Client := Self;
|
|---|
| 372 | NewObject.Path := Schema;
|
|---|
| 373 | NewObject.ObjectName := SystemVersionObject;
|
|---|
| 374 | NewObject.Properties.Add('Version', Version);
|
|---|
| 375 | NewObject.Properties.Add('Time', 'NOW()');
|
|---|
| 376 | NewObject.Save;
|
|---|
| 377 |
|
|---|
| 378 | Install;
|
|---|
| 379 | end;
|
|---|
| 380 | end;
|
|---|
| 381 |
|
|---|
| 382 | function TPDClient.GetConnected: Boolean;
|
|---|
| 383 | begin
|
|---|
| 384 | Result := False;
|
|---|
| 385 | end;
|
|---|
| 386 |
|
|---|
| 387 | procedure TPDClient.CheckTypes;
|
|---|
| 388 | var
|
|---|
| 389 | StructureVersion: string;
|
|---|
| 390 | Data: TDictionaryStringString;
|
|---|
| 391 | ObjectId: Integer;
|
|---|
| 392 | Tables: TListString;
|
|---|
| 393 | I: Integer;
|
|---|
| 394 | NewProxy: TListProxy;
|
|---|
| 395 | begin
|
|---|
| 396 | try
|
|---|
| 397 | Tables := TListString.Create;
|
|---|
| 398 | Data := TDictionaryStringString.Create;
|
|---|
| 399 |
|
|---|
| 400 | NewProxy := TListProxy.Create;
|
|---|
| 401 | NewProxy.Client := Self;
|
|---|
| 402 | NewProxy.Path := 'information_schema';
|
|---|
| 403 | NewProxy.ObjectName := 'TABLES';
|
|---|
| 404 | NewProxy.Condition := 'TABLE_SCHEMA = "' + Schema + '"';
|
|---|
| 405 | NewProxy.Load;
|
|---|
| 406 | //Database.Query(DbRows, 'SHOW TABLES');
|
|---|
| 407 | Tables.Count := NewProxy.Objects.Count;
|
|---|
| 408 | for I := 0 to NewProxy.Objects.Count - 1 do
|
|---|
| 409 | Tables[I] := TObjectProxy(NewProxy.Objects[I]).Properties.Items['TABLE_NAME'];
|
|---|
| 410 |
|
|---|
| 411 | for I := 0 to Types.Count - 1 do
|
|---|
| 412 | with TPDType(Types[I]) do begin
|
|---|
| 413 | if (DbType = '') and (Tables.IndexOf(Name) = -1) then begin
|
|---|
| 414 | Define;
|
|---|
| 415 | end;
|
|---|
| 416 | end;
|
|---|
| 417 | finally
|
|---|
| 418 | NewProxy.Free;
|
|---|
| 419 | Data.Free;
|
|---|
| 420 | Tables.Free;
|
|---|
| 421 | end;
|
|---|
| 422 | end;
|
|---|
| 423 |
|
|---|
| 424 | constructor TPDClient.Create(AOwner: TComponent);
|
|---|
| 425 | begin
|
|---|
| 426 | inherited;
|
|---|
| 427 | Types := TPDTypes.Create;
|
|---|
| 428 | Types.Client := Self;
|
|---|
| 429 | InitSystemTypes;
|
|---|
| 430 | end;
|
|---|
| 431 |
|
|---|
| 432 | destructor TPDClient.Destroy;
|
|---|
| 433 | begin
|
|---|
| 434 | FreeAndNil(Types);
|
|---|
| 435 | inherited;
|
|---|
| 436 | end;
|
|---|
| 437 |
|
|---|
| 438 | procedure TPDClient.Connect;
|
|---|
| 439 | begin
|
|---|
| 440 | end;
|
|---|
| 441 |
|
|---|
| 442 | procedure TPDClient.Disconnect;
|
|---|
| 443 | begin
|
|---|
| 444 | end;
|
|---|
| 445 |
|
|---|
| 446 | procedure TPDClient.Install;
|
|---|
| 447 | begin
|
|---|
| 448 | end;
|
|---|
| 449 |
|
|---|
| 450 | procedure TPDClient.Uninstall;
|
|---|
| 451 | begin
|
|---|
| 452 | //Types.Uninstall;
|
|---|
| 453 | end;
|
|---|
| 454 |
|
|---|
| 455 | procedure TPDClient.Update;
|
|---|
| 456 | begin
|
|---|
| 457 | end;
|
|---|
| 458 |
|
|---|
| 459 | end.
|
|---|
| 460 |
|
|---|