001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to you under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package gudusoft.gsqlparser.ext.catalog.impl;
018
019import gudusoft.gsqlparser.ext.catalog.Catalog;
020import gudusoft.gsqlparser.ext.catalog.Column;
021import gudusoft.gsqlparser.ext.catalog.Schema;
022import gudusoft.gsqlparser.ext.catalog.Table;
023
024import java.util.ArrayList;
025import java.util.LinkedHashMap;
026import java.util.List;
027import java.util.Map;
028
029import static java.util.Objects.requireNonNull;
030
031/**
032 * Simple, mutable implementation of {@link Catalog}.
033 *
034 * <p>This implementation uses LinkedHashMap to maintain insertion order.
035 */
036public class SimpleCatalog implements Catalog {
037  private final String name;
038  private final Map<String, SimpleSchema> schemas;
039  private String defaultSchemaName;
040
041  public SimpleCatalog(String name) {
042    this.name = requireNonNull(name, "name");
043    this.schemas = new LinkedHashMap<>();
044  }
045
046  @Override public String getName() {
047    return name;
048  }
049
050  @Override public List<Schema> getSchemas() {
051    return new ArrayList<>(schemas.values());
052  }
053
054  @Override public Schema getSchema(String schemaName) {
055    return schemas.get(schemaName);
056  }
057
058  @Override public List<String> getSchemaNames() {
059    return new ArrayList<>(schemas.keySet());
060  }
061
062  @Override public Table getTable(String schemaName, String tableName) {
063    Schema schema = getSchema(schemaName);
064    return schema == null ? null : schema.getTable(tableName);
065  }
066
067  @Override public String getDefaultSchemaName() {
068    return defaultSchemaName;
069  }
070
071  /**
072   * Adds a schema to this catalog.
073   *
074   * @param schema Schema to add
075   * @return This catalog (for chaining)
076   */
077  public SimpleCatalog addSchema(SimpleSchema schema) {
078    schemas.put(schema.getName(), schema);
079    return this;
080  }
081
082  /**
083   * Creates and adds a new schema to this catalog.
084   *
085   * @param schemaName Schema name
086   * @return The newly created schema
087   */
088  public SimpleSchema createSchema(String schemaName) {
089    SimpleSchema schema = new SimpleSchema(schemaName, this);
090    addSchema(schema);
091    return schema;
092  }
093
094  /**
095   * Sets the default schema name.
096   *
097   * @param defaultSchemaName Default schema name
098   * @return This catalog (for chaining)
099   */
100  public SimpleCatalog setDefaultSchemaName(String defaultSchemaName) {
101    this.defaultSchemaName = defaultSchemaName;
102    return this;
103  }
104
105  /**
106   * Simple, mutable implementation of {@link Schema}.
107   */
108  public static class SimpleSchema implements Schema {
109    private final String name;
110    private final SimpleCatalog catalog;
111    private final Map<String, SimpleTable> tables;
112
113    public SimpleSchema(String name, SimpleCatalog catalog) {
114      this.name = requireNonNull(name, "name");
115      this.catalog = requireNonNull(catalog, "catalog");
116      this.tables = new LinkedHashMap<>();
117    }
118
119    @Override public String getName() {
120      return name;
121    }
122
123    @Override public Catalog getCatalog() {
124      return catalog;
125    }
126
127    @Override public List<Table> getTables() {
128      return new ArrayList<>(tables.values());
129    }
130
131    @Override public Table getTable(String tableName) {
132      return tables.get(tableName);
133    }
134
135    @Override public List<String> getTableNames() {
136      return new ArrayList<>(tables.keySet());
137    }
138
139    /**
140     * Adds a table to this schema.
141     *
142     * @param table Table to add
143     * @return This schema (for chaining)
144     */
145    public SimpleSchema addTable(SimpleTable table) {
146      tables.put(table.getName(), table);
147      return this;
148    }
149
150    /**
151     * Creates and adds a new table to this schema.
152     *
153     * @param tableName Table name
154     * @param tableType Table type (e.g., "TABLE", "VIEW")
155     * @return The newly created table
156     */
157    public SimpleTable createTable(String tableName, String tableType) {
158      SimpleTable table = new SimpleTable(tableName, tableType, this);
159      addTable(table);
160      return table;
161    }
162
163    /**
164     * Creates and adds a new table to this schema with type "TABLE".
165     *
166     * @param tableName Table name
167     * @return The newly created table
168     */
169    public SimpleTable createTable(String tableName) {
170      return createTable(tableName, "TABLE");
171    }
172  }
173
174  /**
175   * Simple, mutable implementation of {@link Table}.
176   */
177  public static class SimpleTable implements Table {
178    private final String name;
179    private final String tableType;
180    private final SimpleSchema schema;
181    private final Map<String, SimpleColumn> columns;
182    private final List<String> primaryKeys;
183    private String comment;
184
185    public SimpleTable(String name, String tableType, SimpleSchema schema) {
186      this.name = requireNonNull(name, "name");
187      this.tableType = requireNonNull(tableType, "tableType");
188      this.schema = requireNonNull(schema, "schema");
189      this.columns = new LinkedHashMap<>();
190      this.primaryKeys = new ArrayList<>();
191    }
192
193    @Override public String getName() {
194      return name;
195    }
196
197    @Override public String getTableType() {
198      return tableType;
199    }
200
201    @Override public Schema getSchema() {
202      return schema;
203    }
204
205    @Override public List<Column> getColumns() {
206      return new ArrayList<>(columns.values());
207    }
208
209    @Override public Column getColumn(String columnName) {
210      return columns.get(columnName);
211    }
212
213    @Override public String getComment() {
214      return comment;
215    }
216
217    @Override public List<String> getPrimaryKeys() {
218      return new ArrayList<>(primaryKeys);
219    }
220
221    /**
222     * Adds a column to this table.
223     *
224     * @param column Column to add
225     * @return This table (for chaining)
226     */
227    public SimpleTable addColumn(SimpleColumn column) {
228      columns.put(column.getName(), column);
229      return this;
230    }
231
232    /**
233     * Creates and adds a new column to this table.
234     *
235     * @param columnName Column name
236     * @param typeName SQL type name
237     * @param nullable Whether the column is nullable
238     * @return The newly created column
239     */
240    public SimpleColumn createColumn(String columnName, String typeName, boolean nullable) {
241      int ordinal = columns.size() + 1;
242      SimpleColumn column = new SimpleColumn(columnName, typeName, ordinal, nullable);
243      addColumn(column);
244      return column;
245    }
246
247    /**
248     * Sets the comment for this table.
249     *
250     * @param comment Table comment
251     * @return This table (for chaining)
252     */
253    public SimpleTable setComment(String comment) {
254      this.comment = comment;
255      return this;
256    }
257
258    /**
259     * Sets the primary key columns.
260     *
261     * @param primaryKeys Primary key column names
262     * @return This table (for chaining)
263     */
264    public SimpleTable setPrimaryKeys(List<String> primaryKeys) {
265      this.primaryKeys.clear();
266      this.primaryKeys.addAll(primaryKeys);
267      return this;
268    }
269
270    /**
271     * Adds a primary key column.
272     *
273     * @param columnName Primary key column name
274     * @return This table (for chaining)
275     */
276    public SimpleTable addPrimaryKey(String columnName) {
277      this.primaryKeys.add(columnName);
278      return this;
279    }
280  }
281
282  /**
283   * Simple, mutable implementation of {@link Column}.
284   */
285  public static class SimpleColumn implements Column {
286    private final String name;
287    private final String typeName;
288    private final int ordinalPosition;
289    private final boolean nullable;
290    private Integer size;
291    private Integer decimalDigits;
292    private String defaultValue;
293    private String comment;
294
295    public SimpleColumn(String name, String typeName, int ordinalPosition, boolean nullable) {
296      this.name = requireNonNull(name, "name");
297      this.typeName = requireNonNull(typeName, "typeName");
298      this.ordinalPosition = ordinalPosition;
299      this.nullable = nullable;
300    }
301
302    @Override public String getName() {
303      return name;
304    }
305
306    @Override public String getTypeName() {
307      return typeName;
308    }
309
310    @Override public int getOrdinalPosition() {
311      return ordinalPosition;
312    }
313
314    @Override public boolean isNullable() {
315      return nullable;
316    }
317
318    @Override public Integer getSize() {
319      return size;
320    }
321
322    @Override public Integer getDecimalDigits() {
323      return decimalDigits;
324    }
325
326    @Override public String getDefaultValue() {
327      return defaultValue;
328    }
329
330    @Override public String getComment() {
331      return comment;
332    }
333
334    /**
335     * Sets the size of the column.
336     *
337     * @param size Column size
338     * @return This column (for chaining)
339     */
340    public SimpleColumn setSize(Integer size) {
341      this.size = size;
342      return this;
343    }
344
345    /**
346     * Sets the decimal digits of the column.
347     *
348     * @param decimalDigits Decimal digits
349     * @return This column (for chaining)
350     */
351    public SimpleColumn setDecimalDigits(Integer decimalDigits) {
352      this.decimalDigits = decimalDigits;
353      return this;
354    }
355
356    /**
357     * Sets the default value of the column.
358     *
359     * @param defaultValue Default value
360     * @return This column (for chaining)
361     */
362    public SimpleColumn setDefaultValue(String defaultValue) {
363      this.defaultValue = defaultValue;
364      return this;
365    }
366
367    /**
368     * Sets the comment for the column.
369     *
370     * @param comment Column comment
371     * @return This column (for chaining)
372     */
373    public SimpleColumn setComment(String comment) {
374      this.comment = comment;
375      return this;
376    }
377  }
378}