Use reserved keyword as alias in doctrine query builder - doctrine-orm

$em->createQueryBuilder()
->select("MIN(m.price) AS min")
->addSelect('MAX(m.price) AS max')
->from('AppBundle:Sites', 'm');`
How can I escape min to make this work? I tried to change min Alias to something like _min instead but there should be a better way.
I tried both single quotes and backticks but neither worked.

You won't be able to use min or max as an alias since it is simply not available with the current grammar of the DQL. You can find this info in the section of the documentation that is defining the grammar of DQL. There you will find out the following:
In Select Expressions:
SimpleSelectExpression ::= (...) [["AS"] AliasResultVariable]
In Identifiers:
/* Alias ResultVariable declaration (the "total" of "COUNT(*) AS total") */
AliasResultVariable = identifier
And eventually, in Terminals:
identifier (name, email, …) must match [a-z_][a-z0-9_]*
As you can see, there is nothing in there to help you escape your keyword in anyway. Thus, as it is, when stumbling upon min, the Lexer will identify it as the MIN function (see this section of the code) and not as an identifier, hence the error.
Long story short, you will have to either rely on a native query or use an alias name that is not one of the reserved keywords listed here.
Note: Doctrine allows you to implement your own quoting strategy as discussed in this post but the issue is unrelated. Here, the problem with your alias is that it is matched as a function by the DQL parser which is unexpected at this position.

Using Mysql, you could escape it using the backtick `min`
Using Postgres, you could escape it using the doublequote "min"
You can use another word like minimum as an alias to avoid being database dependant

Related

What is a "path_expression" in BigQuery

BigQuery describes a path_expression in the Syntax page as follows:
A path expression describes how to navigate to an object in a graph of objects and generally follows this structure...
Examples:
foo.bar
foo.bar/25
foo/bar:25
foo/bar/25-31
/foo/bar
/25/foo/bar
What are some actual examples of a Path Expression with a valid table, for example in a CTE? My thinking was that a path expression would be something that explicitly qualifies a field or struct sub-field, such as:
myTable.myField.mySubfield
But from the above syntax, which allows for:
/:-
I'm not exactly sure what it is or how it would be used. Could someone show a real-world example of how a path expression would be used?
Path expressions describe where to search for (or store) data. Consider this example from the docs:
#legacySQL
SELECT
weight_pounds, state, year, gestation_weeks
FROM
[bigquery-public-data:samples.natality]
ORDER BY
weight_pounds DESC
LIMIT
10;
In this example, the portion [bigquery-public-data:samples.natality] is the path_expression.
It is saying to look at the natality table in the samples database in the bigquery-public-data project.
But from the above syntax, which allows for: /:-
This would actually not be allowed, as a path_expression.
This example would be parsed as:
/:-
{first_part}/{subsequent_part}:{subsequent_part}
{{ unquoted_identifier | quoted_identifier }} /
{{ unquoted_identifier | quoted_identifier | number }} :
{{ unquoted_identifier | quoted_identifier | number }}
An unquoted_identifier must at least begin with a letter or an underscore. A quoted_identifier can contain any character, but cannot be empty. The empty string therefore cannot be considered an unquoted_identifier, quoted_identifier, or number, so this expression is invalid (and is invalid in 3 positions).
A possible minimal path_expression could be something like:
a:b.c
meaning look in the c table in the b database in the a project.
I can be wrong, but I think you are confusing Path Expression (as it is defined in referenced documentation) with something like (for example) JSONPath.
In my mind, the the former is just terminology that introduced in order to have consistent reference within the documentation, while later (obviously) is query language for JSON, similar to XPath for XML, etc.
So, if you would asked for something like JSONPath use - I bet you would get tones of usage examples, but asking about Path Expression use has not much chances to gather answers even having hefty bounty as it is ONLY used in that documentation.

Is quote REQUIRED in calcite sql parser?

From the config there is a few options, of \", [ etc.
However is it possible for calcite to parse identifiers without quotes? like
select * from a.b?
Now I must write
select * from \"a\".\"b\"
and it's kind of annoying.
Quotes are never required but you may need to change how Calcite handles the casing of identifiers depending on your application. By default, unquoted identifiers are converted to uppercase and quoted identifiers are left unchanged. So if you have lowercase identifiers, they need to be quoted by default.
To change this behaviour, you need to modify the config you pass to SqlParser so that the case of unquoted identifiers is also unchanged.
SqlParser.Config = SqlParser.configBuilder().setUnquotedCasing(Casing.Unchanged);
SqlParser parser = SqlParser.create(/* what you're parsing here */, config);

wxStyledTextCtrl how to style keywords

Having some trouble getting wxStyledTextCtrl to colourise my word listings.
x->m_ctlEdit->SetKeyWords(0,"true false");
x->SetWordChars(wxT("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMONPQRSTUVWXYZ._") );
x->StyleSetForeground(wxSTC_HPHP_WORD, wxColour(0x67,0xa6,0xff));
true and false receive no colouring this way, I've used the StyleSetForeground on many of the other definitions and it all works fine, just having trouble with the word lists.
As a second question, How do I seperate colours for different word listings? I'm aware I can set different keywords list with the number identifier, but how do I apply the styles per keyword list since the function doesn't take in an identifier?
Note:
Using the HTML/PHP lexer that comes as a default option with wxStyledTextCtrl
For the wxSTC_LEX_HTML html lexer or the wxSTC_LEX_PHPSCRIPT php lexer, you need to specify key word set 4. So for example:
x->m_ctlEdit->SetKeyWords(4,"true false");
If you're using the html lexer, you can learn this by calling x->m_ctlEdit->DescribeKeyWordSets(); which will return the following list:
HTML elements and attributes
JavaScript keywords
VBScript keywords
Python keywords
PHP keywords
SGML and DTD keywords
In this case, the 0-based index of the PHP keywords is 4, so this would be the number to pass in to the SetKeyWords method.
However this way of checking this fails when using the PHP lexer since calling DescribeKeyWordSets will only return "PHP keywords". So you would think you should call SetKeyWords with 0, but in fact you still need to use 4 because the php script lexer is the same as the html lexer. That just seems to be an oddity of Scintilla.
On an unrelated note, I think the call to SetWordChars is unnecessary. According to the documentation, that is for searching by words and not for keywords.
As a second question, How do I seperate colours for different word listings?
That depends on the lexer. For example, the C lexer offers the following keyword sets
Primary keywords and identifiers
Secondary keywords and identifiers
Documentation comment keywords
Global classes and typedefs
Preprocessor definitions
which correspond to the lexer states wxSTC_C_WORD, wxSTC_C_WORD2,wxSTC_C_COMMENTDOCKEYWORD, etc.
Unfortunately, as described above the html lexer only offers 1 keyword set for PHP.

regular expression or replace function in where clause of a mysql query

I write a mysql query
select * from table where name like '%salil%'
which works fine but it will no return records with name 'sal-il', 'sa#lil'.
So i want a query something like below
select * from table whereremove_special_character_from(name)like '%salil%'
remove_special_character_from(name) is a mysql method or a regular expression which remove all the special characters from name before like executed.
No, mysql doesn't support regexp based replace.
I'd suggest to use normalized versions of the search terms, stored in the separate fields.
So, at insert time you strip all non-alpha characters from the data and store it in the data_norm field for the future searches.
Since I know no way to do this, I'd use a "calculated column" for this, i.e. a column which depends on the value of name but without the special characters. This way, the cost for the transformation is paid only once and you can even create an index on the new column.
See this answer how to do this.
I agree with Aaron and Col. Shrapnel that you should use an extra column on the table e.g. search_name to store a normalised version of the name.
I noticed that this question was originally tagged ruby-on-rails. If this is part of a Rails application then you can use a before_save callback to set the value of this field.
In MYSQL 5.1 you can use REGEXP to do regular expression matching like this
SELECT * FROM foo WHERE bar REGEXP "baz"
see http://dev.mysql.com/doc/refman/5.1/en/regexp.html
However, take note that it will be slow and you should do what others posters suggested and store the clean value in a separate field.

Modify PL/SQL statement strings in C++

This is my use case: Input is a string representing an Oracle PL/SQL statement of arbitray complexity. We may assume it's a single statement (not a script).
Now, several bits of this input string have to be rewritten.
E.g. table names need to be prefixed, aggregate functions in the selection list that don't use a column alias should be assigned a default one:
SELECT SUM(ABS(x.value)),
TO_CHAR(y.ID,'111,111'),
y.some_col
FROM
tableX x,
(SELECT DISTINCT ID
FROM tableZ z
WHERE ID > 10) y
WHERE
...
becomes
SELECT SUM(ABS(x.value)) COL1,
TO_CHAR(y.ID,'111,111') COL2,
y.some_col
FROM
pref.tableX x,
(SELECT DISTINCT ID, some_col
FROM pref.tableZ z
WHERE ID > 10) y
WHERE
...
(Disclaimer: just to illustrate the issue, statement does not make sense)
Since aggregate functions might be nested and subSELECTs are a b_tch, I dare not use regular expressions. Well, actually I did and achieved 80% of success, but I do need the remaining 20%.
The right approach, I presume, is to use grammars and parsers.
I fiddled around with c++ ANTLR2 (although I do not know much about grammars and parsing with the help of such). I do not see an easy way to get the SQL bits:
list<string> *ssel = theAST.getSubSelectList(); // fantasy land
Could anybody maybe provide some pointers on how "parsing professionals" would pursue this issue?
EDIT: I am using Oracle 9i.
Maybe you can use this, it changes an select statement into an xml block:
declare
cl clob;
begin
dbms_lob.createtemporary (
cl,
true
);
sys.utl_xml.parsequery (
user,
'select e.deptno from emp e where deptno = 10',
cl
);
dbms_output.put_line (cl);
dbms_lob.freetemporary (cl);
end;
/
<QUERY>
<SELECT>
<SELECT_LIST>
<SELECT_LIST_ITEM>
<COLUMN_REF>
<SCHEMA>MICHAEL</SCHEMA>
<TABLE>EMP</TABLE>
<TABLE_ALIAS>E</TABLE_ALIAS>
<COLUMN_ALIAS>DEPTNO</COLUMN_ALIAS>
<COLUMN>DEPTNO</COLUMN>
</COLUMN_REF>
....
....
....
</QUERY>
See here: http://forums.oracle.com/forums/thread.jspa?messageID=3693276&#3693276
Now you 'only' need to parse this xml block.
Edit1:
Sadly I don't fully understand the needs of the OP but I hope this can help (It is another way of asking the 'names' of the columns of for example query select count(*),max(dummy) from dual):
set serveroutput on
DECLARE
c NUMBER;
d NUMBER;
col_cnt PLS_INTEGER;
f BOOLEAN;
rec_tab dbms_sql.desc_tab;
col_num NUMBER;
PROCEDURE print_rec(rec in dbms_sql.desc_rec) IS
BEGIN
dbms_output.new_line;
dbms_output.put_line('col_type = ' || rec.col_type);
dbms_output.put_line('col_maxlen = ' || rec.col_max_len);
dbms_output.put_line('col_name = ' || rec.col_name);
dbms_output.put_line('col_name_len = ' || rec.col_name_len);
dbms_output.put_line('col_schema_name= ' || rec.col_schema_name);
dbms_output.put_line('col_schema_name_len= ' || rec.col_schema_name_len);
dbms_output.put_line('col_precision = ' || rec.col_precision);
dbms_output.put_line('col_scale = ' || rec.col_scale);
dbms_output.put('col_null_ok = ');
IF (rec.col_null_ok) THEN
dbms_output.put_line('True');
ELSE
dbms_output.put_line('False');
END IF;
END;
BEGIN
c := dbms_sql.open_cursor;
dbms_sql.parse(c,'select count(*),max(dummy) from dual ',dbms_sql.NATIVE);
dbms_sql.describe_columns(c, col_cnt, rec_tab);
for i in rec_tab.first..rec_tab.last loop
print_rec(rec_tab(i));
end loop;
dbms_sql.close_cursor(c);
END;
/
(See here for more info: http://www.psoug.org/reference/dbms_sql.html)
The OP also want to be able to change the schema name of the table in a query. I think the easiest say to achieve that is to query the table names from user_tables and search in sql statement for those table names and prefix them or to do a 'alter session set current_schema = ....'.
If the source of the SQL statement strings are other coders, you could simply insist that the parts that need changing are simply marked by special escape conventions, e.g., write $TABLE instead of the table name, or $TABLEPREFIX where one is needed. Then finding the places that need patching can be accomplished with a substring search and replacement.
If you really have arbitrary SQL strings and cannot get them nicely marked, you need to somehow parse the SQL string as you have observed. The XML solution certainly is one possible way.
Another way is to use a program transformation system. Such a tool can parse a string for a language instance, build ASTs, carry out analysis and transformation on ASTs, and then spit a revised string.
The DMS Software Reengineering Toolkit is such a system. It has PLSQL front end parser. And it can use pattern-directed transformations to accomplish the rewrites you appear to need. For your example involving select items:
domain PLSQL.
rule use_explicit_column(e: expression):select_item -> select_item
"\e" -> "\e \column\(\e\)".
To read the rule, you need to understand that the stuff inside quote marks represents abstract trees in some computer langauge which we want to manipulate. What the "domain PLSQL" phrase says is, "use the PLSQL parser" to process the quoted string content, which is how it knows. (DMS has lots of langauge parsers to choose from). The terms
"expression" and "select_item" are grammatical constructs from the language of interest, e.g., PLSQL in this case. See the railroad diagrams in your PLSQL reference manual.
The backslash represents escape/meta information rather than target langauge syntax.
What the rule says is, transform those parsed elements which are select_items
that are composed solely of an expression \e, by converting it into a select_item consisting of the same expression \e and the corresponding column ( \column(\e) ) presumably based on position in the select item list for the specific table. You'd have to implement a column function that can determine the corresponding name from the position of the select item. In this example, I've chosen to define the column function to accept the expression of interest as argument; the expression is actually passed as the matched tree, and thus the column function can determine where it is in the select_items list by walking up the abstract syntax tree.
This rule handles just the select items. You'd add more rules to handle the other various cases of interest to you.
What the transformation system does for you is:
parse the language fragment of interest
build an AST
let you pattern match for places of interest (by doing AST pattern matching)
but using the surface syntax of the target langauge
replace matched patterns by other patterns
compute aritrary replacements (as ASTs)
regenerate source text from the modified ASTs.
While writing the rules isn't always trivial, it is what is necessary if your problem
is stated as posed.
The XML suggested solution is another way to build such ASTs. It doesn't have the nice pattern matching properties although you may be able to get a lot out of XSLT. What I don't know is if the XML has the parse tree in complete detail; the DMS parser does provide this by design as it is needed if you want to do arbitrary analysis and transformation.