001/*
002MIT License
003
004Copyright (c) 2020 FBSQL Team
005
006Permission is hereby granted, free of charge, to any person obtaining a copy
007of this software and associated documentation files (the "Software"), to deal
008in the Software without restriction, including without limitation the rights
009to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010copies of the Software, and to permit persons to whom the Software is
011furnished to do so, subject to the following conditions:
012
013The above copyright notice and this permission notice shall be included in all
014copies or substantial portions of the Software.
015
016THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022SOFTWARE.
023
024Home:   https://fbsql.github.io
025E-Mail: fbsql.team@gmail.com
026*/
027
028package org.fbsql.antlr4.parser;
029
030import java.util.Collection;
031import java.util.HashSet;
032import java.util.UUID;
033
034import org.antlr.v4.runtime.CharStreams;
035import org.antlr.v4.runtime.CommonTokenStream;
036import org.antlr.v4.runtime.Lexer;
037import org.antlr.v4.runtime.misc.Interval;
038import org.antlr.v4.runtime.tree.ParseTree;
039import org.antlr.v4.runtime.tree.ParseTreeWalker;
040import org.fbsql.antlr4.generated.FbsqlBaseListener;
041import org.fbsql.antlr4.generated.FbsqlLexer;
042import org.fbsql.antlr4.generated.FbsqlParser;
043import org.fbsql.antlr4.generated.FbsqlParser.Compression_levelContext;
044import org.fbsql.antlr4.generated.FbsqlParser.Declare_statement_stmtContext;
045import org.fbsql.antlr4.generated.FbsqlParser.Native_sqlContext;
046import org.fbsql.antlr4.generated.FbsqlParser.Role_nameContext;
047import org.fbsql.antlr4.generated.FbsqlParser.Statement_aliasContext;
048import org.fbsql.antlr4.generated.FbsqlParser.Trigger_after_procedure_nameContext;
049import org.fbsql.antlr4.generated.FbsqlParser.Trigger_before_procedure_nameContext;
050import org.fbsql.servlet.CompressionLevel;
051import org.fbsql.servlet.DbServlet;
052
053public class ParseStmtDeclareStatement {
054        /**
055         * EXPOSE statement transfer object
056         * Expose particular SQL statement to frontend (can be used only in «init.sql» script)
057         */
058        public class StmtDeclareStatement {
059                public String             statement;
060                public boolean            prefetch;
061                public Collection<String> roles;
062                public String             trigger_before_procedure_name;
063                public String             trigger_after_procedure_name;
064                public String             alias;
065
066                /**
067                 * Results compression mode (0 - no compression, 1 - compression with best speed strategy, 9 - compression with best compression strategy (default))
068                 */
069                public int compressionLevel;
070
071                @Override
072                public String toString() {
073                        return "StmtExpose [statement=" + statement + ", prefetch=" + prefetch + ", roles=" + roles + ", trigger_before_procedure_name=" + trigger_before_procedure_name + ", trigger_after_procedure_name=" + trigger_after_procedure_name + ", alias=" + alias + ", compressionLevel=" + compressionLevel + "]";
074                }
075        }
076
077        /**
078         * StmtExpose transfer object
079         */
080        private StmtDeclareStatement st;
081
082        public ParseStmtDeclareStatement() {
083                st       = new StmtDeclareStatement();
084                st.roles = new HashSet<>();
085        }
086
087        /**
088         * EXPOSE Statement parser
089         *
090         * E.g.: EXPOSE PREFETCH ( SELECT * FROM MYTABLE ) ROLES (aamin, manager) AS myselect
091         *
092         * @param sql
093         * @return
094         */
095        public StmtDeclareStatement parse(String sql) {
096                Lexer       lexer  = new FbsqlLexer(CharStreams.fromString(sql));
097                FbsqlParser parser = new FbsqlParser(new CommonTokenStream(lexer));
098                ParseTree   tree   = parser.declare_statement_stmt();
099
100                ParseTreeWalker.DEFAULT.walk(new FbsqlBaseListener() {
101
102                        @Override
103                        public void enterStatement_alias(Statement_aliasContext ctx) {
104                                int len = ctx.getChildCount();
105                                if (len == 1)
106                                        st.alias = ctx.getChild(0).getText();
107                                if (len == 2)
108                                        st.alias = ctx.getChild(1).getText();
109                        }
110
111                        @Override
112                        public void enterDeclare_statement_stmt(Declare_statement_stmtContext ctx) {
113                                st.prefetch = ctx.STATIC() != null && ctx.STATIC().size() != 0;
114                        }
115
116                        @Override
117                        public void enterCompression_level(Compression_levelContext ctx) {
118                                if (ctx.BEST() != null && ctx.COMPRESSION() != null)
119                                        st.compressionLevel = CompressionLevel.BEST_COMPRESSION;
120                                else if (ctx.BEST() != null && ctx.SPEED() != null)
121                                        st.compressionLevel = CompressionLevel.BEST_SPEED;
122                                else
123                                        st.compressionLevel = CompressionLevel.NO_COMPRESSION;
124                        }
125
126                        @Override
127                        public void enterNative_sql(Native_sqlContext ctx) {
128                                int      startIndex = ctx.start.getStartIndex();
129                                int      stopIndex  = ctx.stop.getStopIndex();
130                                Interval interval   = new Interval(startIndex, stopIndex);
131                                st.statement = ctx.start.getInputStream().getText(interval);
132                        }
133
134                        @Override
135                        public void enterRole_name(Role_nameContext ctx) {
136                                st.roles.add(ctx.getText());
137                        }
138
139                        @Override
140                        public void enterTrigger_before_procedure_name(Trigger_before_procedure_nameContext ctx) {
141                                st.trigger_before_procedure_name = ctx.getText();
142                        }
143
144                        @Override
145                        public void enterTrigger_after_procedure_name(Trigger_after_procedure_nameContext ctx) {
146                                st.trigger_after_procedure_name = ctx.getText();
147                        }
148                }, tree);
149
150                if (st.alias == null)
151                        st.alias = ParseStmtConnectTo.NONEXPOSABLE_NAME_PREFIX + UUID.randomUUID().toString();
152
153                if (DbServlet.DEBUG)
154                        System.out.println(st);
155
156                return st;
157        }
158}
159
160/*
161Please contact FBSQL Team by E-Mail fbsql.team@gmail.com
162or visit https://fbsql.github.io if you need additional
163information or have any questions.
164*/
165
166/* EOF */