How to compare two logical expressions from SQL where condition? [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I want two compare two SQL where clauses to check if the conditions are similar.
In the below example the SQL queries have same logical conditions in the where clause. What operation shall tell me that both where clause conditions are logically same?
Is there a REGEX for this? Any other approach?
String Q3 = "select t1.ID as ID,t1.FIELD8 as I_RECHARGE_TYPE,t1.FIELD28 as I_RECHARGE_AMOUNT,t1.FIELD1 as I_ACTIVATION_DATE,t1.FIELD2 as I_MSISDN from INSTANT_CDR_0 as t1 where t1.FIELD2 = ? and ((((t1.FIELD8 IS NOT NULL AND t1.FIELD28 > 0) OR DATE_FORMAT(t1.FIELD1,'%Y-%m-%d') > '2016-05-21')) or ((DATE_FORMAT(t1.FIELD1,'%Y-%m-%d') < '2015-12-03' OR ( t1.FIELD28 > 0 AND t1.FIELD28 < 101))))";
String Q4 = "select t1.ID as ID,t1.FIELD1 as I_ACTIVATION_DATE,t1.FIELD8 as I_RECHARGE_TYPE,t1.FIELD28 as I_RECHARGE_AMOUNT,t1.FIELD2 as I_MSISDN from INSTANT_CDR_0 as t1 where t1.FIELD2 = ? and (((DATE_FORMAT(t1.FIELD1,'%Y-%m-%d') > '2016-05-21' OR ( t1.FIELD8 IS NOT NULL AND t1.FIELD28 > 0))) or (((t1.FIELD28 > 0 AND t1.FIELD28 < 101) OR DATE_FORMAT(t1.FIELD1,'%Y-%m-%d') < '2015-12-03')))";
How to compare ((a=2) and (b=3)) with ((b=3) and(a=2)) and figure out they're the same?

A simpler case would be if all the fields you had were booleans. So all the logical expressions would also be boolean expressions.
What you'd then have would be the problem of trying to find out if two boolean expressions are equivalent - that is, for every possible input they provide the same answer.
One approach to doing this might be this: Let A be the first expression and B the second expression and A and B the logical and of the two. For the two expressions to be equivalent A and B applied to all possible inputs must be true. Which means not (A and B) must be false for all inputs. Thus, the last problem becomes a Boolean satisfiability problem. This problem asks whether, for a boolean expression, there exists at least one assignment of inputs which makes it true. If there is, then you can say that the two expressions are not equivalent using our construction, otherwise you say they are equivalent.
The good news is that there's loads of tools for attacking the problem, called SAT-solvers, which are used in a ton of industrial applications (circuit design, for example).
The bad news is that the problem is NP-complete. So it's a really hard one. If the setup of the problem does not lend itself to the usual heuristics employed by SAT-solvers, you're gonna have to wait a while to get your results (perhaps till the heat death of the Universe?).
The worse news is that SAT solvers are focused on boolean problems, while you have SQL data types, which are more general problems. Developing the tooling for solving that is on you, unfortunately.
All this on top of, as others have mentioned, needing to parse the expression.
Depending on how exact you want the result to be, you can do this trick: run the two queries. If they provide the same result, say the expressions are equivalent. If not, say they aren't. What you have here is a situation where you can have false positives, but no false negatives. So, if you say two expressions aren't equivalent, then that's a fact, you can't deny that, because otherwise they'd have provided the same answer. But if you say they are equivalent, there's some chance they're actually not, and you got lucky with your data. If people add more data in the future in the tables, the two won't be equivalent. There's a bit of math here involved, and I won't sketch it in this answer, but, if one makes some assumptions about the input table/tables and one also has enough rows in the tables, the probability of a false positive, that is, of you saying two expressions are equivalent, when in fact they aren't, drops pretty low - exponentially so. So if you have something like 1000 rows to test these things on, you can be pretty sure that a match is good.
You could also do algebraic manipulations on the expressions, trying to bring one to the form of the other. There's a whole set of them one can apply, from boolean expressions (DeMorgan rules, associativity, Karnaugh Maps, etc.), which perhaps might help in finding an exact solution, especially if the where clauses are simple, but that would seem more fragile to me.
Hope this helps. Make sure to order the results of the queries, so you don't discard real matches.

Simple/simplified approach that may not be good enough (initially I didn't see your comment about checking logically). As others pointed out, without relaxations, this problem is NP-Complete...
Use something like JSQLParser to get a structured representation and then traverse the object model and try to compare between the conditions. I would try to make a function that compare two expression and check for equality. This function could be called recursively in case of expressions with deep nesting/parenthesizing.
Try to use regex to split the where clause into conditions and then compare. Here you'd have to be careful with OR/AND and parenthesis... ideally, you'll want to end up with some hierarchical structure that preserve meaning of parenthesizing.
I tend to believe that the first approach would be easier as you won't have to break your neck with breaking/grouping of the conditions based on parenthesis etc.

Related

Is there any way to write parsing logic using json?

I have a map in java Map<String,Object> dataMap whose content looks like this -
{country=Australia, animal=Elephant, age=18}
Now while parsing the map the use of various conditional statements may be made like-
if(dataMap.get("country").contains("stra")
OR
if(dataMap.get("animal") || 100 ==0)
OR
Some other operation inside if
I want to create a config file that contains all the rules on how the data inside the Map should look like. In simple words, I want to define the conditions that value corresponding to keys country, animal, and age should follow, what operations should be performed on them, all in the config file, so that the if elses and extra code can be removed. The config file will be used for parsing the map.
Can someone tell me how such a config file can be written, and how can it be used inside Java?
Sample examples and code references will be of help.
I am thinking of creating a json file for this purpose
Example -
Boolean b = true;
List<String> conditions = new ArrayList<>();
if(dataMap.get("animal").toString().contains("pha")){
conditions.add("condition1 satisifed");
if(((Integer.parseInt(dataMap.get("age").toString()) || 100) ==0)){
conditions.add("condition2 satisifed");
if(dataMap.get("country").equals("Australia")){
conditions.add("condition3 satisifed");
}
else{
b=false;
}
}
else{
b=false;
}
}
else{
b=false;
}
Now suppose I want to define the conditions in a config file for each map value like the operation ( equals, OR, contains) and the test values, instead of using if else's. Then the config file can be used for parsing the java map
Just to manage expectations: Doing this in JSON is a horrible, horrible idea.
To give you some idea of what you're trying to make:
Grammars like this are best visualized as a tree structure. The 'nodes' in this tree are:
'atomics' (100 is an atom, so is "animal", so is dataMap).
'operations' (+ is an operation, so is or / ||).
potentially, 'actions', though you can encode those as operations.
Java works like this, so do almost all programming languages, and so does a relatively simple 'mathematical expression engine', such as something that can evaluate e.g. the string "(1 + 2) * 3 + 5 * 10" into 59.
In java, dataMap.get("animal") || 100 ==0 is parsed into this tree:
OR operation
/ \
INVOKE get[1] equality
/ \ / \
dataMap "animal" INT(100) INT(0)
where [1] is stored as INVOKEVIRTUAL java.util.Map :: get(Object) with as 'receiver' an IDENT node, which is an atomic, with value dataMap, and an args list node which contains 1 element, the string literal atomic "animal", to be very precise.
Once you see this tree you see how the notion of precedence works - your engine will need to be capable of representing both (1 + 2) * 3 as well as 1 + (2 * 3), so doing this without trees is not really possible unless you delve into bizarre syntaxis, where the lexical ordering matching processing ordering (if you want that, look at how reverse polish notation calculators work, or something like fortran - stack based language design. I don't think you'll like what you find there).
You're already making language design decisions here. Apparently, you think the language should adopt a 'truthy'/'falsy' concept, where dataMap.get("animal") which presumably returns an animal object, is to be considered as 'true' (as you're using it in a boolean operation) if, presumably, it isn't null or whatnot.
So, you're designing an entire programming language here. Why handicap yourself by enforcing that it is written in, of all things, JSON, which is epically unsuitable for the job? Go whole hog and write an entire language. It'll take 2 to 3 years, of course. Doing it in json isn't going to knock off more than a week off of that total, and make something that is so incredibly annoying to write, nobody would ever do it, buying you nothing.
The language will also naturally trend towards turing completeness. Once a language is turing complete, it becomes mathematically impossible to answer such questions as: "Is this code ever going to actually finish running or will it loop forever?" (see 'halting problem'), you have no idea how much memory or CPU power it takes, and other issues that then result in security needs. These are solvable problems (sandboxing, for example), but it's all very complicated.
The JVM is, what, 2000 personyears worth of experience and effort?
If you got 2000 years to write all this, by all means. The point is: There is no 'simple' way here. It's a woefully incomplete thing that never feels like you can actually do what you'd want to do (which is express arbitrary ideas in a manner that feels natural enough, can be parsed by your system, and when you read back still makes sense), or it's as complex as any language would be.
Why not just ... use a language? Let folks write not JSON but write full blown java, or js, or python, or ruby, or lua, or anything else that already exists, is open source, seems well designed?

Is an "If statement" the exact same as a "Switch statement" in Java?

Performance aside, I'm wondering if there are certain situations where only an If statement can be used and not a Switch statement and vice versa?
As in, are they completely interchangeable? Could I swap an entire section of code From Switch statements to If statements and vice versa if I so desired or would that break specific programs?
Not that I would want to but just theoretically and out of curiosity as I am new to Coding and have been wondering this.
I couldn't really find the answer I was looking for so I apologize if this is a duplicate.
They are fundamentally different in what they can do - if statements can check any logic you can distil down to a boolean value in some way, while switch statements compare exact values for each case - see the docs for details.
An if-then-else statement can test expressions based on ranges of values or conditions, whereas a switch statement tests expressions based only on a single integer, enumerated value, or String object.
This means if you want to do more complex logic than 'does this value equal this number, enum or string' for each case, you need if statements (or some other way of managing flow) rather than a switch.
A simple example is checking if a number is over 10 but under 9000.
if (value > 10 && value < 9000) {
...
}
Converting this to a switch statement would mean doing something insane like have a case for every possible value over 10 but under 9000)

Why should I learn "switch case" when "if else" already exists [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Advantage of switch over if-else statement
Why Switch/Case and not If/Else If?
I am currently learning "switch case" in school and am wondering what's the point of learning it when "if else" already exists. "if else" is basically another way of doing "switch case".
Please correct me if i am wrong.
It kinda nostalgic to heard it. Both of them actually 'looked' the same. But is a little bit different when the codes executed.
Firstly, 'switch-case' is about comparing value-only. But 'if-else' could process a boolean expression (which would support much more complex clauses)
If you use general 'if-else' when you have found what you are actually searching for, the process will still run until it has finished processing the last if (but actually it could use jump-technique to have similar mechanism like 'switch-case'.)
It won't happen if you use 'switch-case' because once the value you're searching for has been found, it will break and won't continue to the next case. Also, 'switch-case' is faster-to-process than if else because it only compares defined values (not expression). And 'switch-case' also has a good formatting structure (it's simple, compact, readable and clean).
The more tools you have the better. Flat out the best statement of why you should know both... however a more detailed example -
A switch statement works on a single type of variable of the construct:
variable == value
So for example in C if you were trying to compare something to a few different strings in order to make a decision, you can't do that with a switch. In this case you need to know about the if/else constructs.
However if you have a large number of sequential checks:
var == 1 or
var == 2 or
var == 3 etc
The compiler may take your switch statement and convert it to a jump table, which would end up being faster than a large number of comparisons that an if/else list would be.
You should learn the switch construct because it is a useful tool provided by the C language.
It is not the same as if-else blocks.
In the comments section of your question, there are links to existing StackOverflow answers explaining what the differences are.
Each construct has its strengths and weaknesses, and over time you will learn when it is appropriate to choose one over the other.
You should learn both. While it is technically possible to implement any if / else sequence with a switch and vice versa, it would be extremely bad practice to do this ... in most cases.
So you need to learn the two constructs, understand their strengths and weaknesses, and learn to use your judgement as to when it is appropriate to use each one.
And the mere fact that C and C++ and Java (and C# and Pascal and many other languages) all support switch statements should tell you something about its usefulness ...
Difference between switch-case and if-else constructs:
Switch-case switches on values only, it does not evaluates boolean expressions.
Switch-case offers execution of next cases below it automatically if you don't use break after your case block. This feature is sometimes useful for writing complex code, like "Telephone Dial Plan"
Switch-case are more elegant compared to if-else when the number of comparisons are huge, like in displaying "Menu", etc.

String.equals() argument ordering

I recently received a downvote for using the following in a recent answer:
String word = ...;
if ("s".equals(word) || "y".equals(word)
The downvote was given due to using a "yoda condition". I asked for further explanation but none was provided. I prefer this style to avoid a possible NullPointerException.
Is this a poor coding style? If so, why?
Bill Pugh asked this question at Devoxx 2011. The vast majority of people went for the form "xyz".equals(str). I am with Bill, now preferring str.equals("xyz").
It's fundamental to the Java tradition that we find errors as early as reasonably possible. NPEs are exceptionally common. We want to route these nulls out as soon as possible.
If you're expecting the reference to maybe null, then I don't particularly object to the backwards notation. It's nice to be explicit and easier to understand that there may be a null with a separate null check, but the reverse order should be well understood and sufficiently differentiate the code from the normal case where null is forbidden.
Working in security, some of the bugs null-tolerance accommodates are vulnerabilities.
Yoda conditions (i.e. putting a constant before a variable in a comparison) can be considered bad practice as it makes the line of code less comprehensible. In this specific case however I would state that using a Yoda condition makes the code more comprehensible as you don't have to put a extra null check in front of it.
Visit the following link to understand what is meant by Yoda Conditions|Notation
Its not a "poor coding style" its diferent way of coding.
Yoda can be usefull to track typos in some languages, i believe the -1 was not deserved to be honest but that is my personal opinion.
But Yoda can be bad as explained in this lengthy but very interesting article.
End of the day, there are supporters in favor and against this kinda of notation.
Well, it depends. If in your program "word" should never be null, word.equals("s") may actually be better. If for some obscure reason "word" will become null, you will get NullPointerException.
Think about it. If you get exception, you know something went wrong, and you can faster find mistake and fix it. If program will continue to work silently, and produce wrong results, it will be much harder to detect the problem. Actually, you may not notice there is the problem at all.
It all depends.
There are several reasons not to do it like that, however in the end it depends on you (or the team working on your product) if you think this is bad coding style. Arguments against it are:
Strings are rarely null (and you shouldn't make APIs where they are because people don't expect it)
It feels weird to put the value you are comparing to first
Code style uniformity is important, because this way is the exception, you should only do it, if everyone in your team does it.
As said I don't think these arguments are very strong, nor is the reason to do it like you. So it is mostly important to just agree on one way as your coding style and stick to that.
TL;DR; This definitely is poor coding style NOT :D
well, the yoda conditions are useful in languages where non-boolean can evaluate to a boolean value, e.g.
int test = 0;
if ( test ){ /* do something */
but this is not allowed in Java so you don't run into problems such as forgetting '=', e.g.
if ( test = 2 ){ /* do something */
instead of test == 2
the compiler will not let you do this. So the yoda condition may seem unnatural to someone who has not had to care about this (because he/she didn't use any other language but Java).
This definitely is NOT poor coding style it is just not very common to see Java code using it
yoda condition is where oup put the literal in front of the variable.
word.equals("s") is read as "word equals s"
"s".equals(word) a human reads as "s equals word"
Our brains read the first example much better and the code is clearer.
the only reason imho to use yoda conditions is to prevent assignment
as in "if (42 = i)" instead of "if(42 == i)"
You can write
if (word != null && (word.equals("s") || word.equals("y")))
instead of
if ("s".equals(word) || "y".equals(word))
In this case, first one will never cause any NullpointerException, but in my point of view in this case the 2nd one is better, though it is in Yoda Condition
There is a special case pf Yoda conditional I've not seen defended, or attacked, in any of the answers, so I'll add it for reference. This is the style of:
if(0 < x && x <= max) {
A Yoda conditional because the constant (0) is before the variable (x). The argument against Yoda conditionals is that is hinders readability. Contrast that example with the functionally equivalent
if(x <= max && x > 0) {
Do you really think that, non-Yoda variant, is more readable? I don't.
For readability when using ordering relational operators (<, <=, >, >=), I prefer the style of these heuristics:
Use consistent ordering relations: > is consistent with >=, but not with < or <=; < is consistent with <=.
Prefer < and <= to > and >=, as the default is ascending order.
Place conditions that impose a lower bound on the variable before conditions that impose an upper bound, if using < and <=. Do the opposite if using > and >=.
This very often produces a Yoda conditional for the lower bound.
One might argue that you should (unit-)test your code enough to be confident that nulls don't go where they're not supposed to. This should obviate the need for yoda conditions.

Effective way to handle singular/plural word based on some collection size [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
There are many instances in my work projects where I need to display the size of some collection in a sentence. For example, if the collection's size is 5, it will say "5 users". If it is size of 1 or 0, it will say "1 user" or "0 user". Right now, I'm doing it with if-else statements to determine whether to print the "s" or not, which is tedious.
I'm wondering if there's an open source JSP custom tag library that allows me to accomplish this. I know I can write one myself... basically, it will have 2 parameters like this: <lib:display word="user" collection="userList" />. Depending on the collection size, it will determine whether to append an "s" or not. But then, this implementation is not going to be too robust because I also need to handle "ies" and some words don't use any of those. So, instead of creating a half-baked tool, I'm hoping there's a more robust library I could utilize right away. I'm not too worried about prefixing the word with is/are in this case.
I use Java, by the way.
Thanks much.
Take a look at inflector, a java project which lets you do Noun.pluralOf("user"), or Noun.pluralOf("user", userList.size()), and which handles a bunch of variations and unusual cases (person->people, loaf->loaves, etc.), as well as letting you define custom mapping rules when necessary.
Hmm, I don't quite see why you need a library for this. I would think the function to do it is trivial:
public String singlePlural(int count, String singular, String plural)
{
return count==1 ? singular : plural;
}
Calls would look like:
singlePlural(count, "user", "users");
singlePlural(count, "baby", "babies");
singlePlural(count, "person", "people");
singlePlural(count, "cherub", "cherubim");
... etc ...
Maybe this library does a whole bunch of other things that make it useful. I suppose you could say that it supplies a dictionary of what all the plural forms are, but in any given program you don't care about the plurals of all the words in the language, just the ones you are using in this program. I guess if the word that could be singular or plural is not known at compile time, if it's something entered by the user, then I'd want a third party dictionary rather than trying to build one myself.
Edit
Suddenly it occurs to me that what you were looking for was a function for making plurals generically, embodying a set of rules like "normally just add 's', but if the word ends in 'y' change the 'y' to 'ies', if it ends in 's' change it to 'ses', ..." etc. I think in English that would be impossible for any practical purpose: there are too many special cases, like "person/people" and "child/children" etc. I think the best you could do would be to have a generic "add an 's'" rule, maybe a few other common cases, and then a long list of exceptions. Perhaps in other languages one could come up with a fairly simple rule.
So as I say, if the word is not known at compile time but comes from some user input, then yes, a third-party dictionary is highly desirable.
This gets complicated in languages other than English, that inflector aims to support in the future.
I am familiar with Czech where user = uživatel and:
1 uživatel
2 uživatelé
3 uživatelé
4 uživatelé
5 uživatelů
...
You can see why programs written with hardcoded singular+plural would get un-i18n-able.
Edit:
Java11 allows you to use the following:
ChoiceFormat fmt = new ChoiceFormat("1#uživatel | 1.0< uživatelé | 4< uživatelů");
System.out.println(fmt.format(1));
System.out.println(fmt.format(4));
System.out.println(fmt.format(5));
ChoiceFormat documentation
This functionality is built into Ruby on Rails. I don't know exactly where, but it should be easy enough to find in the source code, and then you could simply crib the code.
EDIT: Found you some code:
inflector.rb (very helpful comments!)
inflections.rb (extensive word list)
If I remember correctly, it's mainly a matter of appending an "s" to most words, though I believe there is a list (probably hash, err dictionary) of some common exceptions. Notable is the conversion from "person" to "people" :)
You would of course be in for a world of pain if you decided you want to internationalize this to other languages than English. Welcome to the world of highly irregular grammars, and good luck!

Categories

Resources