Collection : query plante 4D!

Bonjour à tous,

Pourquoi ce malheureux morceaux de code plante lamentablement 4D v17.4 ??

C_ENTIER LONG($var1;$var2)
C_COLLECTION($col;$foundCol)


$var1:=0
$var2:=0


$col:=Créer collection
$col.push(Créer objet("name";->$var1;"value";-1))
$col.push(Créer objet("name";->$var2;"value";-1))


  // retrouver la valeur d'un attribut dans la collection

$foundCol:=$col.query("name = :1";->$var1)

Jean-Michel,
It crashes because you are passing a pointer as the query argument value.

4D manages the pointer reference when you create the object. It does not save the pointer as a pointer value, however. So you can’t search an object for a pointer to a particular field or variable.

At the same time you haven’t told 4D exactly what to do with the pointer so it just waits and tries to be helpful. For example, if you wrote the code like this:

$var1:=0
$var2:=0

$col:=New collection
$col.push(OB Copy(New object("name";->$var1;"value";-1);True))
$col.push(New object("name";->$var2;"value";-1))

$foundCol:=$col.query("name = :1";$var1)

$foundCol will have 1 hit. In your example the result will be empty if you remove -> from the query argument.

If you want to search for pointers as pointers you need to use classic 4D and a pointer array. Pointers are really a mainstay of classic 4D. Their support in objects and ORDA is really a compatibility thing. Using the modern code you don’t need pointers.

Thanks for your reply.

If it’s not possible to use 4D pointer with collection why 4D permite it?
It’s very strange approch…

In your code is it necessary to use ‘OB Copy’? push doesn’t make a object copy?

$col.push(OB Copy(New object("name";->$var1;"value";-1);True))

And why the 4D documentation say 4D pointer it’s possible?
https://doc.4d.com/4Dv17/4D/17.4/Data-Types.300-4883016.en.html

Under 4D v18 an error is displaying (au moins c’est clair;-)

Bonjour Jean-Michel,
tu peux parfaitement utiliser un pointeur comme valeur d’une propriété, 4D le gère très bien (sur un champ, sur une table, etc). Mais comme nom de propriété, ça me laisse perplexe et je ne suis guère étonné que ça plante : quel est le but ?

Bonjour Arnaud,

Mais c’est bien le cas dans la structure de mon objet

attribut : “name”
value : ->$var1

d’ailleurs au passage la doc précise que ce n’est pas possible sur un pointeur de champ…
https://doc.4d.com/4Dv17/4D/17.4/Data-Types.300-4883016.en.html

Oups, j’avais encore lu en diagonale, désolé.

Selon cette page que tu as mise en lien :
« Les variables ou expressions de type Pointeur sont des références à d’autres variables (y compris des tableaux et des éléments de tableaux), à des tables ou à des champs. Il n’existe pas de champs de type Pointeur. »
On te dit bien que pointer un champ est parfaitement licite, par contre comme il n’y a pas de champ de type pointeur, il est illicite de chercher un pointeur dans un champ, ce que fait cette ligne :

$foundCol:=$col.query("name = :1";->$var1)

La propriété name est un champ, pas un pointeur, or tu demandes à 4D d’y chercher un pointeur. Il comprendrait si tu faisais ça, autrement dit chercher la valeur pointée par $var1 :

$foundCol:=$col.query("name = :1";$var1->)

Jean-Michel,

In your code is it necessary to use ‘OB Copy’? push doesn’t make a object copy?

I used the OB Copy just to illustrate how you can tell 4D to resolve the pointers to the value. It was just an example. In the code you provided there’s no reason to use pointers at all.

.push does not make a copy. It pushes a reference to the object itself.

Arnaud answers your question about how pointers work. In your original example you are defining name as the value pointed to in $var1. Which is 0.

Really, there’s no reason to get involved with pointers at all unless you are working with some legacy code and need to connect with old variables or have some very particular task. Keep it simple. Just because 4D has the option to do something does not mean it’s a good thing to do.

Thanks for your reply.

So be carefully with 4D sometimes you can do something but it can crash ?!?
claps your hand for 1st rule in programmation : don’t trust user input and keep in mind you must check before do anything with data…

Vraiment déconcertant !!

Why I can’t use pointer if I want ?
The good question is : why 4D let’s me do that and finally crash !!!

Ce qui fait crasher 4D ne devrait pas être permis That’s All !!

D’ailleurs, ce plantage a été corrigé en 4D v18 et dans ce cas 4D affiche une erreur mais au moins ne plante pas…

Ça va sans doute me motiver à passer à v18 :wink:

Je suis un peu d’accord avec vous, un crashing bug ne devrait pas être laissé autorisé. Même si ce code n’a pas d’intérêt dans votre cas.

Il y a d’autres crashing bugs qui ont été (enfin) corrigés en v18. Notamment le fait de trier sur des images (qui (le tri) ne fonctionne toujours pas) mais au moins ne fait plus planter 4D…

Si vous utilisez des plugins (style 4D Write Pro), je vous encourage à passer rapidement en v18.

Jean-Michel,

why 4D let’s me do that and finally crash !!!

Hmm - for the same reason you can cut your finger with a sharp knife? 4D is a tool, and a good tool. But it’s up to you to know how to use it.

2 Likes

Ne devrait pas, c’est vite dit. Tu réagis comme ça quand c’est outlook, mail, safari ou excel qui plante sèchement, ou affiche une roue multicolore sans fin ? :rofl:

Ça ne me choque pas que 4D puisse crasher, ça dépend sur quoi… J’ai eu un crash (serveur, en plus, un beau et vachement reproductible) il y a qq mois, je l’ai signalé, il a été pris très au sérieux et corrigé dans une version ultérieure. 4d n’est pas insensible aux crash, mais ils ne peuvent imaginer toute les perversités que nous sommes capables d’inventer.

Jean-Michel,

Je suis en V18 et ça plante.
Donc pas d’urgence à migrer pour cette raison !

Les objets permettant certainement de réaliser la fonction que tu souhaites sans pointeur ;
J’avoue ne pas comprendre ce que tu cherches à faire ; on peut t’aider mais il faudrait que tu nous donnes un exemple moins abstrait…

In the documentation of collection.query()
i missed some more examples and explanations.
Ok, “…refer to the dataClass.query()…”
helps to get more infos,
but some features of “dataClass.query()”
not compatible to “collection.query()”
https://doc.4d.com/4Dv18R3/4D/18-R3/collectionquery.305-4900878.en.html

This “dataClass.query()” features
i can not get to work it with “collection.query()”:

ds.Students.query("true")
ds.Students.query("eval(checkName($1.exclude))";$settings)
ds.Students.query("eval(length(This.lastname) >=30)")
ds.Students.query(":1";$formula)
ds.Students.query($formula)

For example this one feature works fine with “collection.query()”:

C_COLLECTION($colA;$colB;$colResult)
$colA:=New collection("a";"b";"c")
$colB:=New collection
$colB.push(New object("value";"d"))
$colB.push(New object("value";"e"))
$colB.push(New object("value";"f"))
$colB.push(New object("value";"a"))
$colResult:=$colB.query("value IN :1";$colA)

To detect two 4D-Pointers point to same 4D-Variable
can easy done in classic 4D code:

Bool($ptrA=$ptrB) // It is true when point to same Var

When in “collection.query()”
“eval” or “formula” (maybe in future) made possible
than you can compare pointers with it.

Otherwise, you can use “collection.filter()” to compare two 4D-Var-Pointers in col-obj-item:
Project method “colFiMatchPtr”:

// PM: "colFiMatchPtr"
C_OBJECT($1)
C_TEXT($2)
C_POINTER($3)
If (Value type($1.value)=Is object)
  If (Value type(OB Get($1.value;$2))=Is pointer)
    $1.result:=Bool($3=OB Get($1.value;$2))
  End if 
End if

// …use example of project method “colFiMatchPtr”

$colResult:=$colB.filter("colFiMatchPtr";"name";$ptr)


Here another example with col.filter()
Project method “colFiMatchRgx”:

// PM: "colFiMatchRgx"
C_OBJECT($1)
C_TEXT($2)
C_TEXT($3)
If (Error#0)
  Error:=0
End if 
If (OK#0)
  OK:=0
End if 
If (Value type($1.value)=Is object)
  If (Value type(OB Get($1.value;$2))=Is text)
    $1.result:=Match regex($3;OB Get($1.value;$2))
  End if 
End if 
Case of 
  : ((Error#0) | (OK#0))
    $1.stop:=True
    ALERT("Error in RegExpression, filtering must canceled")
  : (getUserPressCancelOrQuit)
    $1.stop:=True
    ALERT("Stop signal detected, filtering is canceled")
End case
// ...use example of project method "colFiMatchRgx"
C_TEXT($filterItemName;$filterString)
$filterItemName:="value"
$filterString:=Form.filterString  // user-input regex and chooseType contain/equal/beginWith/endWith
Case of 
  : (($ptrChooseFilterType->)=1)  // contains the regexPattern
    If ($filterString#"[\\d\\D]*@[\\d\\D]*")
      $filterString:="[\\d\\D]*"+$filterString+"[\\d\\D]*"
    End if 
  : (($ptrChooseFilterType->)=2)  // equal with regexPattern
  : (($ptrChooseFilterType->)=3)  // beginWith with regexPattern
    If ($filterString#"@[\\d\\D]*")
      $filterString:=$filterString+"[\\d\\D]*"
    End if 
  : (($ptrChooseFilterType->)=4)  // endWith with regexPattern
    If ($filterString#"[\\d\\D]*@")
      $filterString:="[\\d\\D]*"+$filterString
    End if 
End case
OK:=0
Error:=0
$currErrMethode:=Method called on error
ON ERR CALL("errMatchRgx")
$colResult:=$colB.filter("colFiMatchRgx";$filterItemName;$filterString)
ON ERR CALL($currErrMethode)
1 Like

You can test “$col.filter(“colFiMatchPtr”;“varPtr”;$ptr)” with this code snipped

C_COLLECTION($col;$colResult)
C_POINTER($ptr)
C_LONGINT($var1;$var2;$var3)

$var1:=3  // $var1 has same value as $var3, but two diff vars!
$var2:=2
$var3:=3

$col:=New collection
$ptr:=->$var1
$col.push(New object("id";$col.length;"varPtr";$ptr))  // id begin with 0
$ptr:=->$var2
$col.push(New object("id";$col.length;"varPtr";$ptr))
$ptr:=->$var3
$col.push(New object("id";$col.length;"varPtr";$ptr))
$col.push(New object("id";$col.length;"varPtr";Null))
$col.push(New object("id";$col.length))

$ptr:=->$var3  // ...points to $var3
$colResult:=$col.filter("colFiMatchPtr";"varPtr";$ptr)  // -> [{id:2,varPtr:->$var3}]
  // ($colResult.length=1) because only one colElement.varPtr points to $var3
1 Like

Ben je suppose qu’ils ont toute une panoplie de tests de non régression et même sans doute des tests unitaires.

Dans le cas de la méthode query qui crash sur un pointeur, je suis désolé, mais ça devrait être pris en charge par ce genre de gardes fous… et d’ailleurs 4D lui-même me donne raison puisque ça ne plante plus en v18…

Good luck with 4D !!

Thanks for your help!

Filter is definitively a good way to retrieve a pointer into a collection.

My conclusion :
So 4D can use pointer into a collection and more, it’s possible to filter it and get it.