Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend: SQL LIKE command added #312

Merged
merged 1 commit into from
Jun 10, 2017
Merged

Conversation

sepalani
Copy link
Collaborator

@sepalani sepalani commented Jul 21, 2016

After a long time thinking concerning how to add the LIKE command in the ast/parser backend, I explored various possibilities:

Let's begin with the main issue, the ast.parse function need a string that contains valid Python code. Obviously LIKE isn't a keyword in this langage and is the real problem. I saw two possibilities:

  1. Convert it into something like LIKE(A, B)
  2. Use an infix operator like A | LIKE | B

Convert it with regular expressions:
It might not be a good solution if there is a variable substitution that contains weird characters in a string such as parenthesis or spaces, the regex will be noneffective with string literals and others weird syntaxes like: (1)LIKE"1"

Replacing with a python function:
I tried to do so but each time I had to find a workaround wherever I put the conversion. I need A LIKE B to be a function, for example sql_like(A, B). If I replace it at the end of the process (i.e. when the string has been generated), I obviously need a regular expression to catch its operands and the case insensitiveness. Otherwise I need to mess around with the output/variables lists to change the 1st operand index in the translate_expression function and probably add the token ",", otherwise the translation can fail if get_token is called with "," as token. Plus, I also have to extend the white-list in the validate_ast function to support function calls.

Possible workaround:
Unfortunately, there is no way to add operators in python language. However, there is a hackish way to add an infix operator and we'll be able to replace LIKE with |LIKE|, this way we only need to replace the LIKE command. Easier to add because I don't have to mess with its operands. However, I needed to add another optional parameter in the validate_ast function because binary operators' constraints shouldn't be applied against it.

In sum, I tested it with Fortune Street and it works and solved the issue #277.

Ready to be reviewed and merged.

@AdmiralCurtiss
Copy link
Collaborator

I think I'm gonna test this a bit before merging it, but it looks reasonable at first glance.

@polaris-
Copy link
Collaborator

polaris- commented Aug 7, 2016

I checked it out and it seems reasonable at first glance for me as well. Definitely needs some testing. Do any other games besides Fortune Street use it? I think it's a pretty rare command so not entirely urgent, but I'd like to get this merged eventually.

@sepalani
Copy link
Collaborator Author

sepalani commented Aug 7, 2016

I assume others games use it.

According to gslist.txt from Luigi Auriemma work:

in fact the Gamespy master server supports SQL queries to filter the servers list for example to avoid empty or full servers, or to receive only italian servers and many other things. It's all server-side so that saves also the network bandwidth.

The valid operators you can use are:
<>, !=, >=, !<, <=, !>, =, <, >, (, ), +, -, *, /, %,
AND, NOT, OR, LIKE, NOT LIKE, IS NULL, IS NOT NULL

While the main items are:
hostaddr, hostport, gamever, country, hostname,
mapname, gametype, gamemode, numplayers, maxplayers

But is possible to specify any item used in a specific game like password or dedicated for example, they are the same parameters that you see when query the servers of a game

Is also possible to use the wildcard character % The delimiter for the text strings is the character '

Some usage examples:

  • for non-empty servers: -f "(numplayers > 0)"
  • for empty servers only: -f "(numplayers = 0)"
  • for finding the IP of the server with the name Jackass:
    -f "(hostname LIKE 'Jackass')"
  • for all the servers with a name containing the text ass:
    -f "(hostname LIKE '%ass%')"
  • for italian servers: -f "(country = 'IT')"
  • for servers on port 10 -f "(hostport = 10)"
  • for dedicated servers -f "(dedicated = 1)"
    -f "(dedicated LIKE 'True')"
  • for passworded servers -f "(password = 1)"
    -f "(password LIKE 'True')"
  • for servers using the version 1.1 of the game:
    -f "(gamever = '1.1')"
    or
    -f "(gamever LIKE '1.1')"

...all your fantasy, the filters are so useful and huges that you can do everything you want with them. However remember that the filters refers to the informations obtained by the Gamespy master server from the last query made by it to the game servers (usually a query for each heartbeat) so is possible that you are filtering old informations because heartbeats have a timeout of 5 minutes. Remember ever to delimit your filter with the char ", like in the above examples.

Some reference links:
http://www.gamespyarcade.com/support/filter.shtml
http://www.gamespyarcade.com/support/help/filter.shtml
http://www.gamespyarcade.com/helpers/workshop/filters/

Then the peer.h file from OpenSpy Core states:

//      The filter argument is a SQL WHERE-clause-style boolean statement used 
//      to further restrict the list of prospective game hosts that will be 
//      returned to the peerListingGamesCallback, such as:
//
//      "gametype='ctf'" or
//      "numplayers > 1 and numplayers < 8" or
//      "hostname like '%[gsf]%'" or
//      "(country = 'DE' or country = 'FR') and maxplayers >= 8".
//
//      The filter can be arbitrarily complex and supports standard SQL conditions 
//      and Boolean operations. 
//
//      The following fields can be filtered: hostport, gamever, location, hostname, 
//      mapname, gametype, gamemode, numplayers, maxplayers, groupid. 

@polaris-
Copy link
Collaborator

I'm just going to merge this. I'm going to try rewriting a bit of the server to work better over the next few months when I have some free time, so if any bugs pop up then we'll cover it then I guess.

@polaris- polaris- merged commit da177bd into barronwaffles:master Jun 10, 2017
@sepalani sepalani deleted the sql_like branch June 10, 2017 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants