I had build a ParseTree with antlr4 for analyse SQL, but how can I recover a ParseTree object to it source?
Such as I analyse the SQL to tree:
select a from (select 1 from tab);
I extract the sub query and want to convert it to sql like this:
select 1 from tab
I know write a function to retrieve the tree can recover the tree to source, but I want to know whether ANTLR4 has the function now?
Thanks!
Related
I am new to ANTLR, and I am digging into it for a project. My work would require me to generate a parse tree from a source code file, convert the parse tree into a string that holds all the information about the parse tree in a somewhat "human-readable" form. Parts of this string (representing the parse tree) will then be modified, and the modified string will have to be converted to a changed source code.
I have found out that the .toStringTree(tree) method can be used in ANTLR to print out the tree in LISP format. Is there a better way to represent the parse tree as a string that holds all information?
Can the string-parse-tree be reverted back to the original source code (in the same language) using ANTLR? If no, are there any tools for this?
Can the string-parse-tree be reverted back to the original source code (in the same language) using ANTLR?
That string does not contain the token types, just the matched text. In other words: you cannot create a parse tree from the output of the ToStringTree. Besides, many ANTLR grammars have lexer rules that skip certain input (white spaces and line breaks, for example), so converting a parse tree back to the original input source is not always possible.
If no, are there any tools for this?
Without a doubt, I suggest you do a search on GitHub. But when you have the parse tree, it is trivial to create a custom tree structure and convert that to JSON.
Usecase that I am trying to solve is:
Find all page references of all components under /apps.
i.e. First find all pages where a component is being used, and
then do this for all components under /apps.
By using the report builder tool for Adobe AEM: https://adobe-consulting-services.github.io/acs-aem-commons/features/report-builder/configuring.html
Query I am trying:
SELECT * FROM [nt:base] AS s
WHERE [sling:resourceType] IN (SELECT path FROM [cq:Component] AS s WHERE [componentGroup] IS NOT NULL AND ISDESCENDANTNODE([/apps]))
AND ISDESCENDANTNODE([/content])
Background:
I only need to sanitize the resultset from inner query.
Without sanitization, it would spit path of the form /apps/acs-commons/components/utilities/report-builder/columns/text
while sling:resourceType from outer query can only accept acs-commons/components/utilities/report-builder/columns/text.
So I need to strip out /apps/ from the inner query resultset path.
Here is the error message:
Caused by: java.text.ParseException: Query: SELECT * FROM [nt:base] AS s
WHERE [sling:resourceType] IN (SELECT(*)CAST(path, AS STRING) FROM [cq:Component] AS s WHERE [componentGroup] IS NOT NULL AND ISDESCENDANTNODE([/apps]))
AND ISDESCENDANTNODE([/content]); expected: static operand
I don't think you can manipulate result set using jcr sql2 syntax, stored procs are usually used to manipulate result sets akin to PL/SQL and I did not find any reference to this in jcr docs. In fact, to my knowledge jcr does not even support aggregate functions like MAX(), COUNT(), etc
Hacky way to do this -> you would probably have to execute the inner query first to retrieve all the components in /apps, modify the result set manually(stripping out /apps) and feed it to the outer query.
SELECT * FROM [nt:unstructured] AS comp
WHERE ISDESCENDANTNODE(comp, "/content/prj")
AND [sling:resourceType] IN ("prj/components/content/accordion","prj/components/content/breadcrumb")
To fasten the process, you can use text editors like notepad++ which helps you with block selection (ctrl + alt + shift and then left click mouse button and drag to select) to remove /apps, add start/end double quotes, comma and replace newline char to get it all in one line and construct the overall query.
Would be interested to know what others think and if this can be accomplished with just jcr sql2syntax.
I'd like to be able to auto generate client code in several languages given a cqlsh "INSERT" statement
So for instance if I have a "INSERT" statement like:
INSERT INTO MY_TABLE(C1,C2) VALUES (?,?);
I would be able to generate typesafe clients in several languages to "SELECT" against this exact query
Is this possible?
Real type safety will be possible only if you combine it with the table definition, etc. But there are no such tools exists right now...
For almost all languages the code structure be quite similar (pseudo-code):
// somewhere at beginning, only once
prepStatement = session.prepare(query)
// later in the code
boundStatement = prepStatement.bind(parameters)
session.execute(boundStatement)
I am fairly new to U-SQL and trying to run a U-SQL script in Azure Data Lake Analytics to process a parquet file using the Parquet extractor functionality. I am getting the below error and I don't find a way to get around it.
Error - Change the identifier to use at least one lower case letter. If that is not possible, then escape that identifier (for example: '[ACTIVITY]'), or embed it in a CSHARP() block (e.g CSHARP(ACTIVITY)).
Unfortunately all the different fields generated in the Parquet file are capitalized and I don't want to to escape these identifiers. I have tried if I could wrap the identifier with CSHARP block and it fails as well (E_CSC_USER_RESERVEDKEYWORDASIDENTIFIER: Reserved keyword CSHARP is used as an identifier.) Is there anyway I could extract the parquet file? Thanks for your help!
Code Snippet:
SET ##FeaturePreviews = "EnableParquetUdos:on";
#var1 =
EXTRACT ACTIVITY string,
AUTHOR_NAME string,
AFFLIATION string
FROM "adl://xxx.azuredatalakestore.net/Abstracts/FY2018_028"
USING Extractors.Parquet();
#var2 =
SELECT *
FROM #var1
ORDER BY ACTIVITY ASC
FETCH 5 ROWS;
OUTPUT #var2
TO "adl://xxx.azuredatalakestore.net/Results/AbstractsResults.csv"
USING Outputters.Csv();
Based on your description you try to say
EXTRACT ALLCAPSNAME int FROM "/data.parquet" USING Extractors.Parquet();
In U-SQL, we reserve all caps identifiers so we can add new keywords in the future without invalidating old scripts.
To work around, you just have to quote the name (escape it) like in any other SQL dialect:
EXTRACT [ALLCAPSNAME] int FROM "/data.parquet" USING Extractors.Parquet();
Note that this is not changing the name of the field. It is just the syntactic way to address the field.
Also note, that in most SQL communities, it is considered a best practice to always quote identifiers to avoid reserved keyword clashes.
If all fields in the Parquet file are all caps, you will have to quote them all... In a future update you will be able to say EXTRACT * FROM … for Parquet (and Orc) files, but you still will need to quote the columns when you refer to them explicitly.
I have an SSIS package that obtains a list of new GUIDs from a SQL table. I then shred the GUIDs into a string variable so that I have them separated out by comma. An example of how they appear in the variable is:
'5f661168-aed2-4659-86ba-fd864ca341bc','f5ba6d28-7283-4bed-9f11-e8f6bef225c5'
The problem is in the data flow task. I use the variable as a parameter in a SQL query to get my source data and I cannot get my results. When the WHERE clause looks like:
WHERE [GUID] IN (?)
I get an invalid character error so I found out the implicit conversion doesn't work with the GUIDs like I thought they would. I could resolve this by putting {} around the GUID if this were a single GUID but there are a potential 4 or 5 different GUIDs this will need to retrieve at runtime.
Figuring I could get around it with this:
WHERE CAST([GUID] AS VARCHAR(50)) IN (?)
But this simply produces no results and there should be two in my current test.
I figure there must be a way to accomplish this... What am I missing?
You can't, at least not using the mechanics you have provided.
You cannot concatenate values and make that work with a parameter.
I'm open to being proven wrong on this point but I'll be damned if I can make it work.
How can I make it work?
The trick is to just go old school and make your query via string building/concatenation.
In my package, I defined two variables, filter and query. filter will be the concatenation you are already performing.
query will be an expression (right click, properties: set EvaluateAsExpression to True, Expression would be something like "SELECT * FROM dbo.RefData R WHERE R.refkey IN (" + #[User::filter] + ")"
In your data flow, then change your source to SQL Command from variable. No mapping required there.
Basic look and feel would be like
OLE Source query