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