base.stringtokenizer split a String by word

Started by ORGA-SOFT B., May 22, 2018, 03:17:24 PM

Previous topic - Next topic

ORGA-SOFT B.

Hello community,

we try to split a STRING by the word "AND". Because we wan't to split the String returned by a construct statement.

So if we try this with the following code:

LET strtok = base.stringtokenizer.CREATE(buf.toString(), "AND")

The String is splitted by "A", "N", and "D" so can you tell us what is the correct Syntax to split by a whole word.


Thanks
ORGA-SOFT Backnang

Sebastien F.

Hello,

The StringTokenizer accepts a list of single-char separators, as described in

http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassStringTokenizer_create.html

Parsing SQL is not that easy:

You can have the AND characters in a string literal:

  colname = 'ANDERSON'

Can you please explain why you need to parse the SQL produced by CONSTRUCT?

Seb

ORGA-SOFT B.

Hello Sebastien,

thanks for your answer. Perhabs we are looking in the wrong direction.
We have several input fields and we try to modify the construnct so when a user put in a value in a field we are looking forward to make a matches search and not  =

for example user put Jo in the field we want to search like 'Jo*' not only 'Jo' any ideas?

Thanks.

Sebastien F.

I see no easy way to do that.

Adding a * at the end of the entered value depends on the field type:

You don't want to do add it for numeric or date/time fields.

Maybe use some generic function in all AFTER FIELD of the char/varchar fields, to add the * at the end of the input buffer if not there, so the end user sees it.

Code (genero) Select
    CONSTRUCT BY NAME sql ON id, name
        AFTER FIELD name
           CALL add_star()
    END CONSTRUCT

...

FUNCTION add_star()
    DEFINE v STRING
    LET v = fgl_dialog_getBuffer()
    IF v NOT LIKE "%*" THEN
       CALL fgl_dialog_setBuffer( v || "*" )
    END IF
END FUNCTION


But what if the end user wants to distinguish "Jo" from "John" and "Johan"?

So first I would teach end users how to use the CONSTRUCT syntax
http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_Construct_004.html

If they are not happy with CONSTRUCT, implement an option to have another query dialog like:

https://github.com/FourjsGenero/fgl_query_dialog

?

Seb

Reuben B.

For the original question, the base.StringBuffer.getIndexOf documentation has an example parsing a string by a word http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassStringBuffer_getIndexOf.html.  The getIndexOf and subString methods available in both String and StringBuffer would allow you to attempt to do what you are attempting to do. 

getIndexOf(" AND ",pos) would be better than getIndexOf("AND",pos), but you have to be aware that even " AND " could be part of the entered value, as in "SMITH AND JONES", or part of the generated value "A..B" becomes "fieldname between 'A' and 'B'".  Parsing SQL can be a slippery slope ...

I suspect you want to make the problem easier.  That is append the "*" during the CONSTRUCT as Seb suggested using the set and get field buffer methods.
http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_BuiltInFunctions_FGL_DIALOG_SETBUFFER.html
http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_BuiltInFunctions_FGL_DIALOG_GETBUFFER.html

What I will also throw into the mix is to use multi-dialog.   So for the field you are appending '*" to, that is in an INPUT, and you generate and append a string to the end of the where clause generated by the CONSTRUCT. 

Code (genero) Select
DIALOG
   INPUT BY NAME id
   END INPUT
   CONSTRUCT where_part BY NAME ON ...
   END CONSTRUCT
END DIALOG
LET where_part = where_part, SFMT(" AND id MATCHES '*%1*'", id)


Or you have multi-dialog with a CONSTRUCT for each individual field.

Code (genero) Select
DIALOG
   CONSTRUCT BY NAME field1_sql ON field1
   END CONSTRUCT
   CONSTRUCT BY NAME field2_sql ON field2
   END CONSTRUCT
   ... etc...
END DIALOG


then it is a case of manipulating the individual field SQL before concatenating back together.  This approach is good for adding UPPER() etc for case insensitive, or for doing OR instead of AND.

Reuben   
Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero

ORGA-SOFT B.

Hello Reuben and Sebastien,

you have good ideas ;-).
We figured out a solution with the fgl_dialog_get and fgl_dialog_setbuffer.

Tanks for your good and fast support!

Perhabs we meet in munich next week.

Best regards
Martin Stigmond

Nuno G.

MAIN
   DEFINE l_toBreak, l_delim STRING
   DEFINE l_tk base.stringTokenizer

   LET l_toBreak =
      "token 1 AND",
      "token 2 AND",
      "token 3 AND",
      "token 4 AND"

   LET l_delim = "AND"

   LET l_tk = base.stringTokenizer.createExt(l_toBreak, l_delim, "", FALSE)
   WHILE l_tk.hasMoreTokens()
      DISPLAY l_tk.nextToken()
   END WHILE

END MAIN


HIH

Sebastien F.

Hello Nuno,

The delimiter parameter for the StringTokenizer create methods is not a word, it defines a set of single characters.

Passing "AND" means the delimiter can be "A", "N" or "D".

Try to replace:

Code (genero) Select
   LET l_delim = "AND"

by:

Code (genero) Select
   LET l_delim = "DNA"

See:

http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassStringTokenizer_createExt.html

"The method can take a unique or multiple delimiters into account. A delimiter is always one character long."

Seb