ANTLR How to get specific error message when using 2 alternatives in a start rule - antlr3

I am trying to parse a file that can contain either a table creation script or index creation script.
Below is the grammar. When I run scripts rule with some junk input create xyz table
I get an error as line 1:0 no viable alternative at input 'create'
However when I run table_script or index_script i get specific error message as line 1:8 missing 'table' at 'xxxtab'
Is it possible to get the same error message even when I run scripts as missing table or index...?
grammar DBScript;
options { output=AST; }
tokens {
CREATE;
TABLE;
INDEX;
}
scripts
:
index_script | table_script
;
index_script
: create index index_name;
table_script
: create table table_name ;
create
: 'create';
table
: 'table';
index
: 'index';
table_name
:
IDENT;
index_name
:
IDENT;
fragment LETTER : ('a'..'z' | 'A'..'Z') ;
fragment DIGIT : '0'..'9';
INTEGER : DIGIT+ ;
IDENT : LETTER (LETTER | DIGIT)*;
WS : (' ' | '\t' | '\n' | '\r' | '\f')+ {$channel = HIDDEN;};

I believe that starting in ANTLR 3.5 the error message is might be more specific. However, there is no perfect way to report errors for all types of errors. The best tip I can give is telling you that ANTLR is best at reporting (and recovering from) errors appearing in LL(1) decisions, which you can write by left-factoring rules with longer lookahead requirements.
For the example above, you can left factor the reference to create as follows. Notice that neither index_script nor table_script directly reference create after the left-factoring.
scripts : create_script;
create_script : create (index_script | table_script);
index_script : index index_name;
table_script : table table_name;

Related

CognosTM1 Error: Syntax Error on or before Value

I am trying to insert a Numeric value( mesure ) to database from Tm1 cube.
The variable 'Value' type in tm1 is a Numeric, and the 'Value' type in Database is decimal.
I tried to do a check if the variable contains string values , so I put them in a sperated file. And if they are Numeric I insert them in the database.
But it seems that there is an error in my sql query which states :
Syntax Error on or before Value
I dont know why it gives me an error even I checked o it and verified if it is Numeric.
Here is a snippet of my code :
zType = DTYPE( 'Sales', Sales );
IF(zType #= 'N');
SQL_INSERT_N2 = 'INSERT INTO DB VALUES ( '''| dim1|''' , '''| dim2|''', '''|Value|''') ' ; #error in this line
ELSE;
zValue =NumberToString( Value ) ;
zText = dim1 | ';' | dim2 | ';' | Value | ;
ASCIIOUTPUT( zFile, zText );
ENDIF;
The problem was that I was declaring a numeric value as a string value by adding '''|Value|'''.
So it should be something like this :
SQL= 'INSERT INTO DB VALUES ( '''| dim1|''' , '''| dim2|''', '|NumberToString(Value)|') ' ;

Oracle text phrase error (DRG-50920). Query parsing and SYN function

I just started working with Oracle Text, already red the docs but I really struggle to find a solution.
Currently using with progressive relaxation but I keep getting the following error:
ORA-29902: error in executing ODCIIndexStart() routine
ORA-20000: Oracle Text error:
DRG-50920: part of phrase not itself a phrase or equivalence
29902. 00000 - "error in executing ODCIIndexStart() routine"
*Cause: The execution of ODCIIndexStart routine caused an error.
*Action: Examine the error messages produced by the indextype code and
take appropriate action.
I have two questions:
How to escape the query in the tag? Maybe {} ? Without escaping it won't work when I type something like COCA COLA 0,5L.
On the other hand, when the query is enclosed in the escape chars ({ }) and I try with "EL K" it thorws the same exception. "EL" is part of a thesaurus.
Code
Table and index creation:
CREATE TABLE "DAVID"."INVENTAR_DEV" (
"ID" VARCHAR2(16 BYTE)
NOT NULL ENABLE,
"NAME" VARCHAR2(255 BYTE)
NOT NULL ENABLE
);
CREATE INDEX "DAVID"."INV_DEV_NAME_IDX" ON
"DAVID"."INVENTAR_DEV" (
"NAME"
)
INDEXTYPE IS "CTXSYS"."CONTEXT" PARAMETERS ( 'DATASTORE CTXSYS.DEFAULT_DATASTORE FILTER CTXSYS.NULL_FILTER LEXER INVENTAR_DEV_LEXER WORDLIST INV_DEV_WORDLIST STOPLIST CTXSYS.EMPTY_STOPLIST'
);
The SELECT which I'm using:
SELECT /*+ FIRST_ROWS(150) */
XMLELEMENT("object",
XMLForest(i.id "id",
i.name "name"
).getStringVal()
FROM david.inv_dev i
WHERE contains(i.name,
'<query>
<textquery grammar="context"> {EL KOS}
<progression>
<seq><rewrite>transform((TOKENS, "FUZZY(SYN({", "}, inv_thes), 70, 10, weight)", " "))</rewrite></seq>
<seq><rewrite>transform((TOKENS, "FUZZY(SYN({", "}, inv_thes), 70, 10, weight)", " AND "))</rewrite></seq>
</progression>
</textquery>
<score datatype="FLOAT" algorithm="DEFAULT"/>
<order>
<orderkey> Score DESC </orderkey>
</order>
</query>', 1) > 0;
Also created my own WORDLIST and LEXER:
BEGIN
ctx_ddl.create_preference('INVENTAR_DEV_LEXER','BASIC_LEXER');
ctx_ddl.set_attribute('INVENTAR_DEV_LEXER', 'numgroup',',');
ctx_ddl.set_attribute('INVENTAR_DEV_LEXER', 'numjoin','.');
ctx_ddl.set_attribute('INVENTAR_DEV_LEXER', 'skipjoins','.-_%:;/,()?!*+');
ctx_ddl.create_preference('INV_DEV_WORDLIST', 'BASIC_WORDLIST');
ctx_ddl.set_attribute('INV_DEV_WORDLIST','FUZZY_MATCH','GENERIC');
ctx_ddl.set_attribute('INV_DEV_WORDLIST','FUZZY_SCORE','70');
ctx_ddl.set_attribute('INV_DEV_WORDLIST','FUZZY_NUMRESULTS','10');
ctx_ddl.set_attribute('INV_DEV_WORDLIST','SUBSTRING_INDEX','FALSE');
ctx_ddl.set_attribute('INV_DEV_WORDLIST','STEMMER','NULL');
ctx_ddl.set_attribute('INV_DEV_WORDLIST','PREFIX_INDEX','TRUE');
ctx_ddl.set_attribute('INV_DEV_WORDLIST','PREFIX_MIN_LENGTH',3);
ctx_ddl.set_attribute('INV_DEV_WORDLIST','PREFIX_MAX_LENGTH',7);
Ctx_thes.create_thesaurus('inv_thes', FALSE); -- NAMEE, CASE-SENSITIVE
CTX_THES.CREATE_RELATION('inv_thes','el','SYN','elektro');
END;
Update
I realized that SYN({something}, thes) doesn't work when there are multiple words devided by spaces.
So there must be an operator between those words.
The query works with the SYN if I remove the following line from the textquery:
<seq><rewrite>transform((TOKENS, "FUZZY(SYN({", "}, inv_thes), 70, 10, weight)", " "))</rewrite></seq>
But I'm still not sure what could be the reason.
My solution to the problem was to use a custom workaround function instead of SYN and a custom query parsing function.
The workaround function for SYN:
FUNCTION f_synonyms(p_word IN VARCHAR2)
RETURN VARCHAR2
AS
CURSOR c_synonyms (p_word IN VARCHAR2)
IS
SELECT REPLACE(CTX_THES.SYN(p_word, g_thesaurus_name), '|','=')
FROM SYS.dual;
v_retVal VARCHAR(255);
BEGIN
OPEN c_synonyms(p_word);
FETCH c_synonyms INTO v_retVal;
CLOSE c_synonyms;
RETURN v_retVal;
END;

PL-SQL: why does a dynamic statement using bind-variable input not work?

I am trying to create and execute a dynamic SQL statement (using Oracle PL/SQL) and when things didn't work I condensed it to the below two code snippets:
My understanding was that the following two statements would be equivalent (table_name, row_name and row_value are all VARCHAR2 strings):
query_statement VARCHAR2(1000);
-- variant a:
query_statement := 'select * from ' || table_name || ' where ' || row_name || ' = ' || row_value;
dbms_output.put_line('query="' || query_statement || '"');
execute immediate (query_statement);
-- variant b:
query_statement := 'select * from :table where :row = :value';
dbms_output.put_line('query="' || query_statement || '"');
execute immediate (query_statement) using table_name, row_name, row_value;
But not so! The first variant works fine, the second always fails with an error:
** An error was encountered: -903 ORA-00903: invalid table name
From a readability point of view I would prefer variant b but I don't get, why that second variant fails and why the table_name is flagged as wrong. After all that very same name obviously works in variant a. The emitted queries also looks identical to me - of course modulo the fact that the second string still contains placeholders only while the first string contains already concrete values.
Could some kind soul shed some light on this? Why is variant b not working? What am I missing?
As mentioned by #William, usage of bind variable as Tablename is prohibited. On similar lines, you cannot use bind variables as Column Names and Order By clause as well.
Although this is not documented anywhere but its important to note that replacing these ordinal notation affects the execution plan.
You can't use a bind variable as a table_reference. As documented in the link, the table_reference must be static part of the statement.
select * from :table -- ILLEGAL
Contrary to that the usage in the WHERE clause is allowed
where :row = :value -- LEGAL, but questionable
but it doesn't do what you expect. The whereclause returns TRUE, if both bind variables passed are same.
I.e. it is equivalent to
where 'name' = 'xxxx'
and not to
where name = 'xxxx'

Getting error "Error parsing insert statement for table ROOT.LOAD_SQL" while using ltrim in sql loader

I trying to load the datas from data file to the database table load_sql using sql loader. I have data like below in the data file.
empid,ename
1,Raja,**Kanchi
2,Poo,**Kanchi
3,Bhasker,**Kanchi
4,Siva,**Kanchi
I have to load to load it in the load_sql table like below format:
1,Raja,Kanchi
2,Poo,Kanchi
3,Bhasker,Kanchi
4,Siva,Kanchi
I have written a control file with help of char manipulation function for inserting records in third column but im getting error:
options(skip = 1,Errors = 100, direct = True)
load data
infile 'D:\SQLLDR\control.ctl'
truncate into table load_sql
when city = 'Kanchi'
fields terminated by ','
optionally enclosed by '"'
(
empid,
ename,
X filler,
city "ltrim(:city,*)"
)
I'm getting the error like
'SQL*Loader-951: Error calling once/load initialization
ORA-02373: Error parsing insert statement for table ROOT.LOAD_SQL.
ORA-00936: missing expression'
You have some syntax errors in your control file. Try this:
options(skip = 1,Errors = 100, direct = True)
load data
infile 'D:\SQLLDR\control.ctl' <-- This doesn't look like a data file name?
truncate into table load_sql
when (city = '**Kanchi')
fields terminated by ','
optionally enclosed by '"'
(
empid,
ename,
city "ltrim(:city, '*')"
)
ltrim(:city,*)
^
|
this is invalid
Should have been
ltrim(:city, '*')
or, possibly,
replace(:city, '*', '')

How to use trim function in codeigniter active record

I wrote the below in format of codeigniter
$this->db->select("TRIM(BOTH ',' FROM column_name )");
$this->db->get(table_name)->result_array();
But when I printed the query using $this->db->last_query(), I found a space after comma(,) like this
SELECT TRIM(BOTH ', ' FROM column_name ) FROM table_name. How to remove that space so that my query will run.
You can set in the validation message like :
$this->form_validation->set_rules('input_field', 'Input Field', 'trim|required|valid_email|xss_clean');

Resources