001package gudusoft.gsqlparser.dlineage.dataflow.model;
002
003import java.util.Arrays;
004import java.util.HashSet;
005import java.util.Set;
006
007import gudusoft.gsqlparser.EDbVendor;
008import gudusoft.gsqlparser.dlineage.dataflow.listener.DataFlowHandleListener;
009
010public class Option implements Cloneable {
011
012    private EDbVendor vendor;
013    private EDbVendor powerQueryInnerVendor;
014    private DataFlowHandleListener handleListener;
015    private boolean simpleOutput;
016    private boolean textFormat = false;
017    private boolean showJoin = false;
018    private boolean ignoreRecordSet = false;
019    private boolean ignoreTemporaryTable = false;
020    private boolean ignoreTopSelect = false;
021    private boolean ignoreUnusedSynonym = true;
022    private boolean showCallRelation = false;
023    private boolean simpleShowFunction = false;
024    private boolean simpleShowSynonym = false;
025    private boolean simpleShowUdfFunctionOnly = false;
026    private boolean simpleShowCursor = false;
027    private boolean simpleShowVariable = false;
028    private boolean simpleShowTopSelectResultSet = false;
029    private boolean linkOrphanColumnToFirstTable = false;
030    private boolean ignoreCoordinate = false;
031    private boolean transform = false;
032    private boolean transformCoordinate = false;
033    private boolean showImplicitSchema = false;
034    private boolean showCountTableColumn = true;
035    private boolean showConstantTable = false;
036    private boolean showCaseWhenAsDirect = true;
037    private String filePathDatabase;
038    private String filePathSchema;
039    private long startId = 0;
040    private boolean output = true;
041    private boolean traceSQL = false;
042    private boolean traceProcedure = false;
043    private int parallel = Runtime.getRuntime().availableProcessors() / 2;
044    private String defaultServer;
045    private String defaultDatabase;
046    private String defaultSchema;
047    private boolean showERDiagram = false;
048    private Set<ResultSetType> targetResultSetTypes = new HashSet<ResultSetType>(); 
049    private Set<String> filterRelationTypes = new HashSet<String>();
050    private Set<String> simpleShowRelationTypes = new HashSet<String>();
051    private boolean sqlflowIgnoreFunction = false;
052
053    private Set<String> excludedProcedureNames = new HashSet<String>();
054
055    /**
056     * Wildcard patterns to exclude procedures from analysis.
057     * <p>
058     * Supports the following wildcard characters:
059     * <ul>
060     *   <li><code>*</code> - Matches any sequence of characters (e.g., <code>SCHEMA1.*</code> matches all procedures in SCHEMA1)</li>
061     *   <li><code>?</code> - Matches any single character (e.g., <code>SCHEMA?.PROC?</code> matches SCHEMA1.PROC1, SCHEMA2.PROC2, etc.)</li>
062     *   <li><code>.</code> - Reserved as schema/procedure name separator (e.g., <code>SCHEMA.PROC</code> matches a two-segment qualified name)</li>
063     * </ul>
064     * <p>
065     * Examples:
066     * <ul>
067     *   <li><code>"SCHEMA1.*"</code> - Excludes all procedures in SCHEMA1</li>
068     *   <li><code>"*.SP_*"</code> - Excludes all procedures starting with SP_ in any schema</li>
069     *   <li><code>"*_TEST"</code> - Excludes all procedures ending with _TEST in any schema</li>
070     *   <li><code>"SCHEMA?.PROC?"</code> - Excludes procedures like SCHEMA1.PROC1, SCHEMA2.PROC2, etc.</li>
071     *   <li><code>"DB.SCHEMA.PROC"</code> - Excludes a specific three-segment procedure</li>
072     * </ul>
073     * <p>
074     * Note: Pattern matching is case-insensitive. Quoted identifiers (double quotes, square brackets, backticks, single quotes)
075     * will be automatically stripped before matching.
076     */
077    private Set<String> excludedProcedurePatterns = new HashSet<String>();
078    private boolean showCandidateTable = true;
079    private boolean ignoreInsertIntoValues = true;
080    private boolean normalizeOutput = false;
081    /*
082     * Whether to trace all table positions. Default is false.
083     */
084    private boolean traceTablePosition = false;
085
086    private boolean enablePipelinedStitching = true;
087    private int maxPipelinedExpansionDepth = 8;
088    private int maxStitchedSourcesPerColumn = 64;
089
090    private AnalyzeMode analyzeMode;
091
092    public EDbVendor getVendor() {
093        return vendor;
094    }
095
096    public void setVendor(EDbVendor vendor) {
097        this.vendor = vendor;
098    }
099
100    /**
101     * Explicit SQL dialect for the inner SQL embedded in Power Query
102     * {@code Value.NativeQuery()} calls and for navigation-chain synthetic
103     * SELECTs. When set, this takes precedence over the connector-based
104     * inference performed by {@code TPowerQueryAnalyzer}; when {@code null}
105     * (default), inference is used.
106     */
107    public EDbVendor getPowerQueryInnerVendor() {
108        return powerQueryInnerVendor;
109    }
110
111    public void setPowerQueryInnerVendor(EDbVendor powerQueryInnerVendor) {
112        this.powerQueryInnerVendor = powerQueryInnerVendor;
113    }
114
115    public DataFlowHandleListener getHandleListener() {
116        return handleListener;
117    }
118
119    public void setHandleListener(DataFlowHandleListener handleListener) {
120        this.handleListener = handleListener;
121    }
122
123    public boolean isSimpleOutput() {
124        return simpleOutput;
125    }
126
127    public void setSimpleOutput(boolean simpleOutput) {
128        this.simpleOutput = simpleOutput;
129    }
130
131    public boolean isTextFormat() {
132        return textFormat;
133    }
134
135    public void setTextFormat(boolean textFormat) {
136        this.textFormat = textFormat;
137    }
138
139    public boolean isShowJoin() {
140        return showJoin;
141    }
142
143    public void setShowJoin(boolean showJoin) {
144        this.showJoin = showJoin;
145    }
146
147    /**
148     * When true, every UNRESOLVED / PARSE_ERROR dynamic-SQL site is also mirrored into an
149     * {@link ErrorInfo} (type {@link ErrorInfo#DYNAMIC_SQL_UNRESOLVED}) so legacy callers reading
150     * {@code getErrorMessages()} can see them. Default false, so existing callers are unaffected;
151     * the structured list is always available via {@code DataFlowAnalyzer.getDynamicSqlSites()}.
152     */
153    private boolean reportDynamicSqlSitesAsErrors = false;
154
155    public boolean isReportDynamicSqlSitesAsErrors() {
156        return reportDynamicSqlSitesAsErrors;
157    }
158
159    public void setReportDynamicSqlSitesAsErrors(boolean reportDynamicSqlSitesAsErrors) {
160        this.reportDynamicSqlSitesAsErrors = reportDynamicSqlSitesAsErrors;
161    }
162
163    public boolean isIgnoreRecordSet() {
164        return ignoreRecordSet;
165    }
166
167    public void setIgnoreRecordSet(boolean ignoreRecordSet) {
168        this.ignoreRecordSet = ignoreRecordSet;
169    }
170
171    public boolean isLinkOrphanColumnToFirstTable() {
172        return linkOrphanColumnToFirstTable;
173    }
174
175    public void setLinkOrphanColumnToFirstTable(boolean linkOrphanColumnToFirstTable) {
176        this.linkOrphanColumnToFirstTable = linkOrphanColumnToFirstTable;
177    }
178
179    public boolean isIgnoreCoordinate() {
180        return ignoreCoordinate;
181    }
182
183    public void setIgnoreCoordinate(boolean ignoreCoordinate) {
184        this.ignoreCoordinate = ignoreCoordinate;
185    }
186
187    public boolean isTransform() {
188        return transform;
189    }
190
191    public void setTransform(boolean transform) {
192        this.transform = transform;
193    }
194
195    public boolean isTransformCoordinate() {
196        return transformCoordinate;
197    }
198
199    public void setTransformCoordinate(boolean transformCoordinate) {
200        this.transformCoordinate = transformCoordinate;
201    }
202
203    public boolean isSimpleShowFunction() {
204        return simpleShowFunction;
205    }
206
207    public void setSimpleShowFunction(boolean simpleShowFunction) {
208        this.simpleShowFunction = simpleShowFunction;
209    }
210
211    public boolean isSimpleShowSynonym() {
212        return simpleShowSynonym;
213    }
214
215    public void setSimpleShowSynonym(boolean simpleShowSynonym) {
216        this.simpleShowSynonym = simpleShowSynonym;
217    }
218
219    public boolean isSimpleShowTopSelectResultSet() {
220        return simpleShowTopSelectResultSet;
221    }
222
223    public void setSimpleShowTopSelectResultSet(boolean simpleShowTopSelectResultSet) {
224        this.simpleShowTopSelectResultSet = simpleShowTopSelectResultSet;
225    }
226
227    public boolean isShowImplicitSchema() {
228        return showImplicitSchema;
229    }
230
231    public void setShowImplicitSchema(boolean showImplicitSchema) {
232        this.showImplicitSchema = showImplicitSchema;
233    }
234
235    public boolean isShowCountTableColumn() {
236        return showCountTableColumn;
237    }
238
239    public void setShowCountTableColumn(boolean showCountTableColumn) {
240        this.showCountTableColumn = showCountTableColumn;
241    }
242
243    public boolean isShowConstantTable() {
244        return showConstantTable;
245    }
246
247    public void setShowConstantTable(boolean showConstantTable) {
248        this.showConstantTable = showConstantTable;
249    }
250
251    public long getStartId() {
252        return startId;
253    }
254
255    public void setStartId(long startId) {
256        this.startId = startId;
257    }
258
259    public boolean isOutput() {
260        return output;
261    }
262
263    public void setOutput(boolean output) {
264        this.output = output;
265    }
266
267    public int getParallel() {
268        return parallel;
269    }
270
271    public void setParallel(int parallel) {
272        this.parallel = parallel;
273    }
274
275    public boolean isTraceSQL() {
276        return traceSQL;
277    }
278
279    public void setTraceSQL(boolean traceSQL) {
280        this.traceSQL = traceSQL;
281    }
282
283    public boolean isIgnoreTopSelect() {
284                return ignoreTopSelect;
285        }
286
287        public void setIgnoreTopSelect(boolean ignoreTopSelect) {
288                this.ignoreTopSelect = ignoreTopSelect;
289        }
290        
291        public void setShowCallRelation(boolean showCallRelation) {
292                this.showCallRelation = showCallRelation;
293        }
294        
295        public boolean isShowCallRelation() {
296                return showCallRelation;
297        }
298
299        public String getFilePathDatabase() {
300                return filePathDatabase;
301        }
302
303        public void setFilePathDatabase(String filePathDatabase) {
304                this.filePathDatabase = filePathDatabase;
305        }
306
307        public String getFilePathSchema() {
308                return filePathSchema;
309        }
310
311        public void setFilePathSchema(String filePathSchema) {
312                this.filePathSchema = filePathSchema;
313        }
314
315        public String getDefaultServer() {
316                return defaultServer;
317        }
318
319        public void setDefaultServer(String defaultServer) {
320                this.defaultServer = defaultServer;
321        }
322
323        public String getDefaultDatabase() {
324                return defaultDatabase;
325        }
326
327        public void setDefaultDatabase(String defaultDatabase) {
328                this.defaultDatabase = defaultDatabase;
329        }
330
331        public String getDefaultSchema() {
332                return defaultSchema;
333        }
334
335        public void setDefaultSchema(String defaultSchema) {
336                this.defaultSchema = defaultSchema;
337        }
338
339    public boolean isShowERDiagram() {
340        return showERDiagram;
341    }
342
343    public void setShowERDiagram(boolean showERDiagram) {
344        this.showERDiagram = showERDiagram;
345    }
346
347    public boolean isIgnoreTemporaryTable() {
348        return ignoreTemporaryTable;
349    }
350
351    public void setIgnoreTemporaryTable(boolean ignoreTemporaryTable) {
352        this.ignoreTemporaryTable = ignoreTemporaryTable;
353    }
354    
355    public void showResultSetTypes(ResultSetType... types) {
356        if(types!=null) {
357                targetResultSetTypes.addAll(Arrays.asList(types));
358        }
359    }
360    
361        public void showResultSetTypes(String... types) {
362                if (types != null) {
363                        for (String type : types) {
364                                ResultSetType resultSetType = ResultSetType.of(type);
365                                if (resultSetType != null) {
366                                        targetResultSetTypes.add(resultSetType);
367                                }
368                        }
369                }
370        }
371    
372    public boolean containsResultSetType(ResultSetType type) {
373        return targetResultSetTypes.contains(type);
374    }
375
376    @Override
377    public Object clone() throws CloneNotSupportedException {
378        return super.clone();
379    }
380    
381        public void filterRelationTypes(String... types) {
382                if (types != null) {
383                        for (String type : types) {
384                                RelationshipType relationshipType = RelationshipType.of(type);
385                                if (relationshipType != null) {
386                                        filterRelationTypes.add(relationshipType.name());
387                                }
388                        }
389                }
390        }
391
392        public Set<String> getFilterRelationTypes() {
393                return filterRelationTypes;
394        }
395
396    public boolean isSimpleShowCursor() {
397        return simpleShowCursor;
398    }
399
400    public void setSimpleShowCursor(boolean simpleShowCursor) {
401        this.simpleShowCursor = simpleShowCursor;
402    }
403
404    public boolean isSimpleShowVariable() {
405        return simpleShowVariable;
406    }
407
408    public void setSimpleShowVariable(boolean simpleShowVariable) {
409        this.simpleShowVariable = simpleShowVariable;
410    }
411
412    public boolean isSimpleShowUdfFunctionOnly() {
413        return simpleShowUdfFunctionOnly;
414    }
415
416    public void setSimpleShowUdfFunctionOnly(boolean simpleShowUdfFunctionOnly) {
417        this.simpleShowUdfFunctionOnly = simpleShowUdfFunctionOnly;
418    }
419
420        public boolean isTraceProcedure() {
421                return traceProcedure;
422        }
423
424        public void setTraceProcedure(boolean traceProcedure) {
425                this.traceProcedure = traceProcedure;
426        }
427
428    public boolean isSqlflowIgnoreFunction() {
429        return sqlflowIgnoreFunction;
430    }
431
432    public void setSqlflowIgnoreFunction(boolean sqlflowIgnoreFunction) {
433        this.sqlflowIgnoreFunction = sqlflowIgnoreFunction;
434    }
435
436    public boolean isShowCaseWhenAsDirect() {
437        return showCaseWhenAsDirect;
438    }
439
440    public void setShowCaseWhenAsDirect(boolean showCaseWhenAsDirect) {
441        this.showCaseWhenAsDirect = showCaseWhenAsDirect;
442    }
443
444        public boolean isIgnoreUnusedSynonym() {
445                return ignoreUnusedSynonym;
446        }
447
448        public void setIgnoreUnusedSynonym(boolean ignoreUnusedSynonym) {
449                this.ignoreUnusedSynonym = ignoreUnusedSynonym;
450        }
451
452        public boolean isShowCandidateTable() {
453                return showCandidateTable;
454        }
455
456        public void setShowCandidateTable(boolean showCandidateTable) {
457                this.showCandidateTable = showCandidateTable;
458        }
459
460        public Set<String> getSimpleShowRelationTypes() {
461                return simpleShowRelationTypes;
462        }
463
464        public void setSimpleShowRelationTypes(String... types) {
465                if (types != null) {
466                        for (String type : types) {
467                                RelationshipType relationshipType = RelationshipType.of(type);
468                                if (relationshipType != null) {
469                                        simpleShowRelationTypes.add(relationshipType.name());
470                                }
471                        }
472                }
473        }
474        
475        public void setSimpleShowRelationTypes(RelationshipType... types) {
476                if (types != null) {
477                        for (RelationshipType relationshipType : types) {
478                                simpleShowRelationTypes.add(relationshipType.name());
479                        }
480                }
481        }
482
483        public AnalyzeMode getAnalyzeMode() {
484                return analyzeMode;
485        }
486
487        public void setAnalyzeMode(AnalyzeMode analyzeMode) {
488                this.analyzeMode = analyzeMode;
489        }
490
491        public boolean isIgnoreInsertIntoValues() {
492                return ignoreInsertIntoValues;
493        }
494
495        public void setIgnoreInsertIntoValues(boolean ignoreInsertIntoValues) {
496                this.ignoreInsertIntoValues = ignoreInsertIntoValues;
497        }
498
499    public boolean isNormalizeOutput() {
500        return normalizeOutput;
501    }
502
503    public void setNormalizeOutput(boolean normalizeOutput) {
504        this.normalizeOutput = normalizeOutput;
505    }
506
507        public boolean isTraceTablePosition() {
508                return traceTablePosition;
509        }
510
511        public void setTraceTablePosition(boolean traceTablePosition) {
512                this.traceTablePosition = traceTablePosition;
513        }
514
515        public boolean isEnablePipelinedStitching() {
516                return enablePipelinedStitching;
517        }
518
519        public void setEnablePipelinedStitching(boolean enablePipelinedStitching) {
520                this.enablePipelinedStitching = enablePipelinedStitching;
521        }
522
523        public int getMaxPipelinedExpansionDepth() {
524                return maxPipelinedExpansionDepth;
525        }
526
527        public void setMaxPipelinedExpansionDepth(int maxPipelinedExpansionDepth) {
528                this.maxPipelinedExpansionDepth = maxPipelinedExpansionDepth;
529        }
530
531        public int getMaxStitchedSourcesPerColumn() {
532        return maxStitchedSourcesPerColumn;
533    }
534
535    public void setMaxStitchedSourcesPerColumn(int maxStitchedSourcesPerColumn) {
536        this.maxStitchedSourcesPerColumn = maxStitchedSourcesPerColumn;
537    }
538
539    public Set<String> getExcludedProcedureNames() {
540        return excludedProcedureNames;
541    }
542
543    public void setExcludedProcedureNames(Set<String> excludedProcedureNames) {
544        this.excludedProcedureNames = excludedProcedureNames;
545    }
546
547    public void addExcludedProcedureName(String name) {
548        if (name != null && !name.isEmpty()) {
549            this.excludedProcedureNames.add(name);
550        }
551    }
552
553    public void addExcludedProcedureNames(String... names) {
554        if (names != null) {
555            for (String name : names) {
556                addExcludedProcedureName(name);
557            }
558        }
559    }
560
561    /**
562     * @see #excludedProcedurePatterns
563     */
564    public Set<String> getExcludedProcedurePatterns() {
565        return excludedProcedurePatterns;
566    }
567
568    /**
569     * @see #excludedProcedurePatterns
570     */
571    public void setExcludedProcedurePatterns(Set<String> excludedProcedurePatterns) {
572        this.excludedProcedurePatterns = excludedProcedurePatterns;
573    }
574
575    /**
576     * Adds a wildcard pattern to exclude procedures from analysis.
577     * @param pattern A wildcard pattern (e.g., "SCHEMA1.*", "*.SP_*", "*_TEST")
578     * @see #excludedProcedurePatterns
579     */
580    public void addExcludedProcedurePattern(String pattern) {
581        if (pattern != null && !pattern.isEmpty()) {
582            this.excludedProcedurePatterns.add(pattern);
583        }
584    }
585
586    /**
587     * Adds multiple wildcard patterns to exclude procedures from analysis.
588     * @param patterns Variable number of wildcard patterns
589     * @see #excludedProcedurePatterns
590     */
591    public void addExcludedProcedurePatterns(String... patterns) {
592        if (patterns != null) {
593            for (String pattern : patterns) {
594                addExcludedProcedurePattern(pattern);
595            }
596        }
597    }
598
599}