@@ -38,14 +38,11 @@ TdRelationCache = class(TdObject)
3838 { TdRelationQueryBuilder - Query builder for relations }
3939 TdRelationQueryBuilder = class (TdObject)
4040 public
41- class function BuildOneToOneQuery (const ATargetTable, AForeignKey: string;
42- const ALocalValue: Variant): string;
43- class function BuildOneToManyQuery (const ATargetTable, AForeignKey: string;
44- const ALocalValue: Variant): string;
45- class function BuildManyToOneQuery (const ATargetTable, ALocalKey: string;
46- const AForeignValue: Variant): string;
47- class function BuildManyToManyQuery (const ATargetTable, AMappingTable,
48- AForeignKey, ALocalKey: string; const ALocalValue: Variant): string;
41+ class function BuildOneToOneQuery (const aTargetTable, aForeignKey: string; const aLocalValue: Variant): string;
42+ class function BuildOneToManyQuery (const aTargetTable, aForeignKey: string; const aLocalValue: Variant): string;
43+ class function BuildManyToOneQuery (const aTargetTable, aLocalKey: string; const aForeignValue: Variant): string;
44+ class function BuildManyToManyQuery (const aTargetTable, aMappingTable, aForeignKey, aLocalKey: string;
45+ const aLocalValue: Variant): string;
4946 end ;
5047
5148 { TdRelationFactory - Factory for creating related objects }
@@ -58,9 +55,9 @@ TdRelationFactory = class(TdObject)
5855 { TdRelationValidator - Relation validator }
5956 TdRelationValidator = class (TdObject)
6057 public
61- class function ValidateRelation (ARelation : TdRelationInfo): Boolean;
62- class function ValidateEntity (AEntity : TObject): Boolean;
63- class function GetValidationErrors (ARelation : TdRelationInfo): TStringList;
58+ class function ValidateRelation (aRelation : TdRelationInfo): Boolean;
59+ class function ValidateEntity (aEntity : TObject): Boolean;
60+ class function GetValidationErrors (aRelation : TdRelationInfo): TStringList;
6461 end ;
6562
6663 { TdAdvancedRelationalEntity - Extended version of the base class }
@@ -78,7 +75,7 @@ TdAdvancedRelationalEntity = class(TdRelationalEntity)
7875
7976 // Extended relation management methods
8077 procedure ClearRelationCache (const ARelationName: string = ' ' );
81- procedure PreloadRelation (const ARelationName: string);
78+ procedure PreloadRelation (const { %H- } ARelationName: string);
8279 procedure SetAutoLoad (AValue: Boolean);
8380
8481 // Checking relation status
@@ -91,7 +88,16 @@ TdAdvancedRelationalEntity = class(TdRelationalEntity)
9188implementation
9289
9390uses
94- Variants, TypInfo;
91+ Variants, TypInfo
92+ ;
93+
94+ function VariantToSQLValueWithOperator (aValue: Variant): String;
95+ begin
96+ if VarIsNull(aValue) then
97+ Result:=' IS NULL'
98+ else
99+ Result:=' = ' +QuotedStr(VarToStr(aValue));
100+ end ;
95101
96102{ TdRelationCache }
97103
@@ -112,33 +118,36 @@ destructor TdRelationCache.Destroy;
112118
113119procedure TdRelationCache.Store (const AKey: string; AValue: TObject);
114120var
115- Index : Integer;
121+ aIndex : Integer;
116122begin
117- Index := FCache.IndexOf(AKey);
118- if Index >= 0 then
119- FCache.Objects[Index] := AValue
123+ aIndex := FCache.IndexOf(AKey);
124+ if aIndex >= 0 then
125+ begin
126+ FCache.Objects[aIndex].Free; // vs mem leak? FCache owns its items
127+ FCache.Objects[aIndex] := AValue;
128+ end
120129 else
121130 FCache.AddObject(AKey, AValue);
122131end ;
123132
124133function TdRelationCache.Retrieve (const AKey: string): TObject;
125134var
126- Index : Integer;
135+ aIndex : Integer;
127136begin
128- Index := FCache.IndexOf(AKey);
129- if Index >= 0 then
130- Result := FCache.Objects[Index ]
137+ aIndex := FCache.IndexOf(AKey);
138+ if aIndex >= 0 then
139+ Result := FCache.Objects[aIndex ]
131140 else
132141 Result := nil ;
133142end ;
134143
135144procedure TdRelationCache.Remove (const AKey: string);
136145var
137- Index : Integer;
146+ aIndex : Integer;
138147begin
139- Index := FCache.IndexOf(AKey);
140- if Index >= 0 then
141- FCache.Delete(Index );
148+ aIndex := FCache.IndexOf(AKey);
149+ if aIndex >= 0 then
150+ FCache.Delete(aIndex );
142151end ;
143152
144153procedure TdRelationCache.Clear ;
@@ -153,44 +162,50 @@ function TdRelationCache.HasKey(const AKey: string): Boolean;
153162
154163{ TdRelationQueryBuilder }
155164
156- class function TdRelationQueryBuilder.BuildOneToOneQuery (const ATargetTable,
157- AForeignKey: string; const ALocalValue: Variant): string;
165+ class function TdRelationQueryBuilder.BuildOneToOneQuery (const aTargetTable, aForeignKey: string;
166+ const aLocalValue: Variant): string;
167+ var
168+ aValue: String;
158169begin
159- Result := Format( ' SELECT * FROM %s WHERE %s = %s ' ,
160- [ATargetTable, AForeignKey, QuotedStr(VarToStr(ALocalValue)) ]);
170+ aValue:=VariantToSQLValueWithOperator(aLocalValue);
171+ Result:=Format( ' SELECT * FROM %s WHERE %s %s ' , [aTargetTable, aForeignKey, aValue ]);
161172end ;
162173
163- class function TdRelationQueryBuilder.BuildOneToManyQuery (const ATargetTable,
164- AForeignKey: string; const ALocalValue: Variant): string;
174+ class function TdRelationQueryBuilder.BuildOneToManyQuery (const aTargetTable, aForeignKey: string;
175+ const aLocalValue: Variant): string;
176+ var
177+ aValue: String;
165178begin
166- Result := Format( ' SELECT * FROM %s WHERE %s = %s ORDER BY id ' ,
167- [ATargetTable, AForeignKey, QuotedStr(VarToStr(ALocalValue)) ]);
179+ aValue:=VariantToSQLValueWithOperator(aLocalValue);
180+ Result:=Format( ' SELECT * FROM %s WHERE %s %s ORDER BY id ' , [aTargetTable, aForeignKey, aValue ]);
168181end ;
169182
170- class function TdRelationQueryBuilder.BuildManyToOneQuery (const ATargetTable,
171- ALocalKey: string; const AForeignValue: Variant): string;
183+ class function TdRelationQueryBuilder.BuildManyToOneQuery (const aTargetTable, aLocalKey: string;
184+ const aForeignValue: Variant): string;
185+ var
186+ aValue: String;
172187begin
173- Result := Format( ' SELECT * FROM %s WHERE %s = %s ' ,
174- [ATargetTable, ALocalKey, QuotedStr(VarToStr(AForeignValue)) ]);
188+ aValue:=VariantToSQLValueWithOperator(aForeignValue);
189+ Result:=Format( ' SELECT * FROM %s WHERE %s %s ' , [aTargetTable, aLocalKey, aValue ]);
175190end ;
176191
177- class function TdRelationQueryBuilder.BuildManyToManyQuery (const ATargetTable,
178- AMappingTable, AForeignKey, ALocalKey: string; const ALocalValue: Variant): string;
192+ class function TdRelationQueryBuilder.BuildManyToManyQuery (const aTargetTable, aMappingTable, aForeignKey,
193+ aLocalKey: string; const aLocalValue: Variant): string;
194+ var
195+ aValue: String;
179196begin
180- Result := Format(
181- ' SELECT t.* FROM %s t ' +
182- ' INNER JOIN %s m ON t.%s = m.%s_target ' +
183- ' WHERE m.%s_local = %s ' +
184- ' ORDER BY t.id' ,
185- [ATargetTable, AMappingTable, ALocalKey, AForeignKey,
186- ALocalKey, QuotedStr(VarToStr(ALocalValue))]);
197+ aValue:=VariantToSQLValueWithOperator(aLocalValue);
198+ Result:=Format(
199+ ' SELECT t.* FROM %s t INNER JOIN %s m ON t.%s = m.%s_target WHERE m.%s_local %s ORDER BY t.id' ,
200+ [aTargetTable, aMappingTable, aLocalKey, aForeignKey, aLocalKey, aValue]
201+ );
187202end ;
188203
189204{ TdRelationFactory }
190205
191206class function TdRelationFactory.CreateEntity (AClass: TClass): TObject;
192207begin
193- Result := AClass.Create;
208+ Result:= AClass.Create;
194209end ;
195210
196211class function TdRelationFactory.CreateEntityList : TObjectList;
@@ -200,7 +215,7 @@ class function TdRelationFactory.CreateEntityList: TObjectList;
200215
201216{ TdRelationValidator }
202217
203- class function TdRelationValidator.ValidateRelation (ARelation : TdRelationInfo): Boolean;
218+ class function TdRelationValidator.ValidateRelation (aRelation : TdRelationInfo): Boolean;
204219begin
205220 Result := True;
206221
@@ -219,25 +234,25 @@ class function TdRelationValidator.ValidateRelation(ARelation: TdRelationInfo):
219234 Result := False;
220235end ;
221236
222- class function TdRelationValidator.ValidateEntity (AEntity : TObject): Boolean;
237+ class function TdRelationValidator.ValidateEntity (aEntity : TObject): Boolean;
223238begin
224- Result := (AEntity <> nil ) and Supports(AEntity , IdRelationalEntity);
239+ Result := (aEntity <> nil ) and Supports(aEntity , IdRelationalEntity);
225240end ;
226241
227- class function TdRelationValidator.GetValidationErrors (ARelation : TdRelationInfo): TStringList;
242+ class function TdRelationValidator.GetValidationErrors (aRelation : TdRelationInfo): TStringList;
228243begin
229244 Result := TStringList.Create;
230245
231- if ARelation .PropertyName = ' ' then
246+ if aRelation .PropertyName = ' ' then
232247 Result.Add(' Property name is required' );
233248
234- if ARelation .ForeignKey = ' ' then
249+ if aRelation .ForeignKey = ' ' then
235250 Result.Add(' Foreign key is required' );
236251
237- if ARelation .TargetClass = nil then
252+ if aRelation .TargetClass = nil then
238253 Result.Add(' Target class is required' );
239254
240- if (ARelation .RelationType = rtManyToMany) and (ARelation .MappingTable = ' ' ) then
255+ if (aRelation .RelationType = rtManyToMany) and (aRelation .MappingTable = ' ' ) then
241256 Result.Add(' Mapping table is required for Many-to-Many relations' );
242257end ;
243258
0 commit comments