What is the difference between the field lookup and the function lookup? - delphi

Is there any difference in performance or another difference or are both the same thing (as per the lookup fields in the TADOquery and TCustomADODataSet)?
I have read the Help files, but I didn't found anything explaining on this.

The Lookup() function is a virtual function of TDataSet.
Being a virtual function means that the implementation can change from class to class.
Because of this, the documentation has different comments that varies from each TDataSet descendant.
Let's take a closer look:
TDataSet's Lookup():
Implements a virtual method to retrieve field values from a record
that matches specified search values.
See more here
Note this remark at the end of the document:
Descendant classes that are not unidirectional override this method so
that it locates the record where the fields identified by the
comma-delimited string KeyFields have the values specified by the
Variant or Variant array KeyValues. In classes that implement Lookup,
it returns a Variant or Variant array that contains the value or
values of the fields specified by the comma-delimited string
ResultFields on the specified record.
TCustomADODataSet's Lookup():
Here, the remark above is happening in pratice. Note, in this implementation there is no call to inherited.
The Documentation says:
Retrieves field values from a row that matches specified search
values.
Details here
Now, you can only understand the difference by digging into the source code. At the end, you will note that there is no difference at all. You will realise that the lookup fields will just call Lookup() function:
1. A lookup field is like a calculated field.
Is affected by the AutoCalcFields property (See here)
The same function the fires OnCalcFields event is responsible for
calling CalcLookupValue
UniDirectional DataSet also do not have Lookup Fields. (See
here)
2. The Lookup Field calls the Lookup() Function
On this, there is no documentation, you will have to see for yourself:
procedure TField.CalcLookupValue;
The Lookup() arguments is filled with the TField properties: FLookupDataSet.Lookup(FLookupKeyFields,
FDataSet.FieldValues[FKeyFields], FLookupResultField);
The Lookup() function consumes all related properties from the lookup field, as you can see above:
FKeyFields = TField.KeyFields
FLookupDataSet = TField.LookupDataSet
FLookupKeyFields = TField.LookupKeyFields
FLookupResultField = TField.LookupResultField

Related

Move to specific record in TFDQuery with primary key

Question
I am wondering if there is any way I can move to a specific record in a DataSet (FDQuery) by knowing only the Primary Key of the table.
What I know
I know I can move to the next/prior record by using FDQuery.Next; FDQuery.Prior; or move to a specific record number using FDQuery.RecNo := 2.
In my case, I just know the Primary Key (id) of the item and I want to move to this specific record that has the same id as mine.
To make it clear I can achieve this by iterating through the records, however, I would like to know if the is a way to move directly to the record, without needing to iterate through all the records.
with FDQuery do
begin
First;
while not Eof do
begin
if FieldByName(C_ID).AsInteger = IDAsPrimaryKey then
// Found!
Break;
Next;
end;
end;
The simplest way to do this is to use the Locate boolean function, as in
if FDQuery.Locate(C_ID, IDAsPrimaryKey, []) then
// do whatever
See e.g. http://docwiki.embarcadero.com/RADStudio/Rio/en/Using_Locate for more info.
Note that Locate will accept a ;-separated list of field names as the first argument. In that case, the second argument needs to be a variant array of field values, which you can construct at run-time using the VarArrayOf function.
Btw, Locate is defined in the TDataSet class, but it is up to the authors of a given descendant library like FireDAC whether and how it is implemented in specific component classes.
You could also use the GoToKey or FindKey methods - see http://docwiki.embarcadero.com/RADStudio/Rio/en/Executing_a_Search_with_Goto_Methods. You may find one or other of these to be quicker than Locate, especially if your dataset already has a client-side index on the primary key but Locate is generally more convenient and concise, because the others are more long-winded to use.

How to match nodes only by value? (not defining specific property)

I want to search nodes by value only, which can be in any of node properties. I know that this is an expensive operation, but nodes will be cut off by some relationship conditions.
I want something like this:
MATCH (n: {*:"Search value"})
RETURN n
Where * imply "any property".
Is there a way to do this?
interesting tidbits can be found in this abstract regarding this topic and why it might not be implemented
https://docs.google.com/document/d/1FPfGkgzhcRXVkleBLBsA92U94Mx4yafu3nO-Xf-NzsE/edit#heading=h.pyvdg2rbofq
Semantics of dynamic key expressions
Using a dynamic key expression like <mapExpr>[<keyExpr>] requires that <mapExpr> evaluates to a map or an entity, and that <keyExpr> evaluates to a string. If this is not the case, a type error is produced either at compile time or at runtime.
If this is given, evaluating <mapExpr>[<keyExpr>] first evaluates keyExpr to a string value (the key), and then evaluates <mapExpr> to a map-like value (the map). Finally the result of <mapExpr>[<keyExpr>] is computed by performing a lookup of the key in the map. If the key is found, the associated value becomes the result. If the key is not found, <mapExpr>[<keyExpr>] evaluates to NULL.
Thus the result of evaluating <mapExpr>[<keyExpr>] can be any value (including NULL
Caveats
Dynamic property lookup might entice users to encode information in property key names. This is bad practice as it interferes with planning, leads to unnatural data models, and might lead to exhausting the available property key id space. This is addressed by issuing a warning when a query uses a dynamic property lookup with a dynamic property key name.
To my knowledge, no. Seems to me that what you really are trying to do would be better achieved by creating a search index over the graph using something like elasticsearch or solr. This would give you the ability to search over all properties. Your choice of analyzer whilst indexing would give you the option of exact or partial value matches.

How to implement a TDataSet-bound combobox with not-in-list values

I need to implement a combobox, which is bound to a TpFIBDataSet (descendant of TDataSet). I've done this several times before. It's not a big thing if it contains only predefined values.
This time, I'd like to have a combobox that accepts custom values entered by the user, also giving the ability to the user to select some predefined value. Newly entered values shall be inserted into some table of the database just before the record the combobox's field belongs to is posted.
The main problem seems to me, that predefined values are internally represented as integer IDs (the combobox I use is TwwDBComboBox from Roy Woll's InfoPower package, as it implements maplist functionality) because the field is a foreign key, while custom values may be nearly everything (only restricted by a mask).
How can I distinguish between an integer ID and integer user-input, for example?
See the set properties of the combobox:
AComboBox.Style := csDropDown;
AComboBox.MapList := True;
I don't request a solution as take this piece of code and be happy. I'm rather looking for some advice by others who might have or had a similar problem.
How can I distinguish between an integer ID and integer user-input, for example?
You go back to the database. Either query directly select count(*) from table where id = ComboBoxId.
Or use the Locate method of the dataset.
Or keep a cache handy in a MyList: TList<Integer> and do a MyList.BinarySearch to see if the item is already in the DB.
Obviously the cache will only work if the DB is single-user, because otherwise you will not be able to keep it up-to-date.
If it is not in the DB, you run the insert query.
After it's inserted you run the default combobox behavior, because now the values is sure to be in the DB.

What is a "tag" in Lua 4.0?

I was reading the Lua 4.0 manual and I came across this "tag" thing but I have no idea what it is referring to.
http://www.lua.org/manual/4.0/manual.html#3
That's the section where it mentions it but I still have no idea what the manual is talking about.
TL;DR: Tags are the precursor to modern-day meta-tables. Where now the event-handler-pairs are stored directly in the meta-table using normal table-manipulation, as it is a normal table, then we used those tags, normal though unique numbers, and special data-structures, which restricted the events we could set, and had a different interface.
One of the disadvantages of tags was they could not be garbage-collected as they were normal numbers, and thus their associated data could not either.
Quoting the important parts of section 3 "types and tags":
Besides a type, all values also have a tag.
Each of the types nil, number, and string has a different tag. All values of each of these types have the same pre-defined tag. As explained above, values of type function can have two different tags, depending on whether they are Lua functions or C functions. Finally, values of type userdata and table can have variable tags, assigned by the programmer (see Section 4.8). The tag function returns the tag of a given value. User tags are created with the function newtag. The settag function is used to change the tag of a table (see Section 6.1). The tag of userdata values can only be set from C (see Section 5.7). Tags are mainly used to select tag methods when some events occur. Tag methods are the main mechanism for extending the semantics of Lua (see Section 4.8).
So, think of tags as unique ids.
Every value has a tag, depending on its type:
All values of the types nil, number, string, function (C-flavor), function (Lua flavor) have a type-specific tag set on the C side.
All values of the types table and userdata have tags too, but those are set by the programmer for each value indepent from any other.
tag returns the tag, settag sets it for table and userdata, newtag creates a new one.
And looking at section 4.8 "tag methods", we understand that those unique ids are just used for comfortably associating all values of the same Lua type (or for tables and userdatas of the same semantic user-type) with special behavior:
Lua provides a powerful mechanism to extend its semantics, called tag methods. A tag method is a programmer-defined function that is called at specific key points during the execution of a Lua program, allowing the programmer to change the standard Lua behavior at these points. Each of these points is called an event.
The tag method called for any specific event is selected according to the tag of the values involved in the event (see Section 3). The function settagmethod changes the tag method associated with a given pair (tag, event). Its first parameter is the tag, the second parameter is the event name (a string; see below), and the third parameter is the new method (a function), or nil to restore the default behavior for the pair. The settagmethod function returns the previous tag method for that pair. A companion function gettagmethod receives a tag and an event name and returns the current method associated with the pair.
Which just boils down to settagmethod and gettagmethod being used to manage a mapping from tag+event to handler, and the runtime using that as an extension point.
As LHF mentions below, there's a wealth of additional detail and history in The evolution of Lua, for example how the tag-methods evolved from the previous extension-mechanism of "fallbacks", which did not support different behavior for separate groups of values, instead being global.

SSRS - Pass Null to Multi-Value Parameter

I'm in a tough pickle here, using SSRS and trying to feed a NULL value, with others, from a multi-valued parameter into the stored procedure used for the dataset.
The values the user selects in the multi-value parameter of the report, are fed to a single input parameter in the stored procedure. For example, the multi-value drop down called #Color can feed 'Red','White', and 'Blue' to the stored procedure's '#ColorList' parameter. The stored procedure uses the parameter for SQL statement building functions and gives the result set. I want to add the NULL value to the multi-value parameter in addition to the values, as some records do not have a Color value.
Unfortunately, I don't have permissions to the modify the stored procedure so I can't use the ISNULL(Value,'') work-around or change anything with the 'IN' syntax. The stored procedure is being executed in the report as follows:
EXEC StoredProc
#Name = #Name
#ColorList = #Color
#Color is passed using a JOIN expression
=JOIN(Parameters!Color.Value,",")
Any suggestions?
It sounds like you undertand your situation well: You cannot pass the value of NULL as a parameter, because NULL simply is not a value and has no value. You could pass the string "NULL" as the parameter #color, but you'd probably be better off creating a colorfully-named (shall we say, distinctive?) distinctive variable, such as noColor just to keep things clear.

Resources