-
Content Count
3504 -
Joined
-
Last visited
-
Days Won
115
Everything posted by Lars Fosdal
-
Did you try it with a ESCAPE '_' clause?
-
I still think it is the underscore that plays a trick on you? Ref. https://www.sqlitetutorial.net/sqlite-like/ - section "SQLite LIKE with ESCAPE clause"
-
Could there be some sort of escape handling kicking in? Is it necessary to pre-process the text you send as parameter to ensure it is correctly handled by SQLite?
-
@limelect You probably should read the SQLite docs in detail. Perhaps there are clues to debugging memory consumption there? Is it a configuration thing?
-
Leaks come in many forms. It might not be in the Delphi code. https://www.sqlite.org/malloc.html
-
Can it be a leak in the application? I.e. you use a DB resource, but never release it after use?
-
FireDac is not a database, but Delphi's DB Driver framework. There is no practical size limit in FireDac itself. The limits would be the limits of the underlying database. What is your actual underlying database? A good allround DB is designed to be on disk and to be manipulated on disk and use memory mostly for indexes and caching. Using a billon row DB that fills terabytes of diskspace, does not necessarily imply a performance problem. There are free DBs you can use - even commercially: Postgresql, MariaDB (Open source MySQL), Firebird, etc. Ideally, you would want to limit what you keep in memory, and instead pull in stuff on demand - but that means a redesign of your application. However, if you need/want to load and keep everything in memory, switching from 32-bit to 64-bit will offer a much larger memory space (but then you have to face the sorry state of the 64-bit debugger).
-
[Suggestion] Add a new "Created Date" column to "To Do List"
Lars Fosdal replied to Edwin Yip's topic in GExperts
I'd use the blame view in git to get those dates. The problem with adding an explicit date in the todo comments, is that the comment text may change, but the date is not updated. -
@David Heffernan - I write about my own preferences, based on my own code, the libraries I use, and the experiences I've had. I am not trying to recommend a "one right way" to write code, since there are so many considerations depending on the context. Which part of "I prefer" do you consider to be a generally invalid point?
-
Look further back in the thread for constructor overloading. It seems like I didn't understand your "not quite the same thing" comment. Care to elaborate?
-
True. But if I need multiple constructors with different arguments to set up a class before use - is that class overly complicated and should it be broken down into a hierarchy?
-
@David Heffernan - I rarely make classes that have so few fields that they are passed in the constructor. Most of my instance data are retrieved from database tables, and each class knows what fields to retrieve (or store). The generic container instantiates the class, the instances fill themselves from the db query. I also have polymorphic classes where each element requires different initializations, which firstly are done by default initializations in the class create, and then secondarily from attributes before the declaration of the class instance reference field. I use this mechanism to build grids in code - and not in design mode. Again, the inits and attributes are the defaults. Overrides are then applied from stored settings.
-
I prefer my constructors without arguments. More abstract / generics friendly. Ref. an earlier comment - I am not so fond of the (ab)use of overload either. It is great for dealing with type translation methods - but multiple overloaded constructors could be very confusing before LSP and inline documentation actually became helpful again. As for number of arguments to a method - as many as it takes, but more than five is pretty rare.
-
... appear to be nice at first glance, but they tend to be confusing. I'd recommend unique names for each constructor instead.
-
TArray = a rack.
-
Continuous Integration with Delphi and Continua CI
Lars Fosdal replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
I love Continua CI and FinalBuilder. Massive time-savers! -
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
Perhaps check that the types used in the declaration of the API doesn't inappropriately change size on the Delphi side depending on if we compile for 32-bit vs 64-bit? -
We went from ADO to FireDAC and significantly improved the performance. However - we do NOT use db aware components and inserts and updates are done through stored procedures. We systematically use FetchOptions.Mode := fmAll; FetchOptions.Unidirectional := Unidirectional; For stored procs, we add FetchOptions.Items := FetchOptions.Items - [fiMeta]; We also avoid MARS concurrency by ensuring that every query gets a connection of its own.
-
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
It is a very old legacy Windows function, though... -
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
Working as admin by default would be considered a massive no-no by my company. -
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
Confirmed. It worked running elevated with the MAX_PREFERRED_LENGTH and returned some 16k+ users. -
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
The 64-bit simply refuses to run, unless I run it elevated. Then I get /--- Started --- hres = 0 dwRead = 35 dwTotal = 712 hres = 3608717696 EAccessViolation: Access violation at address 00007FFBCE7CB0EC in module 'SAMCLI.DLL'. Read of address 00000000D718A9A8 Press Enter: Perhaps there are further access rights that come into play? -
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
Check out unit web.win.AdsTypes: Here is some code I wrote to find out if a user had an AD membership. unit ActiveDSUtil; /// Written by Lars Fosdal, 16 DEC 2014 /// Note that calling AD functions is slow. interface uses Classes, SysUtils, ActiveX, ActiveDS_tlb, web.win.adstypes; type TADGroupList = array of String; TAnonParamFunc<TA,TR> = reference to function (const v:TA):TR; /// <summary> Enumerates the group memberships of an AD user </summary> function EnumADUserGroupMemberships(const aDomain, aUser: String; EnumHandler: TAnonParamFunc<IAdsGroup, Boolean>):Boolean; /// <summary> Returns a list of all AD groups for an AD user </summary> function GetADUserGroupMemberships(const aDomain, aUser: String):TStringList; /// <summary> Checks if an AD user is member of one or more specific groups</summary> function UserHasADGroupMembership(const aDomain, aUser: String; const GroupList: TAdGroupList): Boolean; implementation function EnumADUserGroupMemberships(const aDomain, aUser: String; EnumHandler: TAnonParamFunc<IADsGroup, Boolean>):Boolean; var hr: HREsult; User: IADsUser; Enum: IEnumVariant; varGroup: OleVariant; EnumHelper: LongWord; begin Result := False; CoInitialize(nil); try hr := ADsGetObject('WinNT://'+aDomain+'/'+aUser+',user',IID_IADsUser3 , User); if not Failed(hr) then begin try Enum := User.Groups._NewEnum as IEnumVariant; while Assigned(Enum) and (Enum.Next(1, varGroup, EnumHelper) = S_OK) do begin try if EnumHandler(IDispatch(varGroup) as IADsGroup) then EXIT(True); finally VariantClear(varGroup); end; end; finally User := nil; end; end; finally CoUninitialize; end; end; function GetADUserGroupMemberships(const aDomain, aUser: String):TStringList; var List: TStringList; begin List := TStringList.Create; List.BeginUpdate; try EnumADUserGroupMemberships(aDomain, aUser, function(const Group: IAdsGroup):Boolean begin Result := False; List.Add(Group.Name + ' ' + Group.Class_); end); finally List.Sort; List.Insert(0, aDomain +'\'+ aUser); List.EndUpdate; Result := List; end; end; function UserHasADGroupMembership(const aDomain, aUser: String; const GroupList: TAdGroupList): Boolean; begin Result := EnumADUserGroupMemberships(aDomain, aUser, function(const Group: IAdsGroup):Boolean var GroupName: String; begin Result := False; for GroupName in GroupList do begin Result := CompareText(GroupName, Group.Name) = 0; if Result then Break; // Return true for first match end; end); end; end. -
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
@Davide Angeli - BTW- Why don't you use the AD APIs instead? -
NetGroupGetUsers strange errors on Win64 on buffered reads
Lars Fosdal replied to Davide Angeli's topic in Windows API
Windows 10, 64-bit Compile to 32-bit target - runs as expected Compile to 64-bit target - unable to create process