001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.EDbObjectType;
004import gudusoft.gsqlparser.ETableEffectType;
005import gudusoft.gsqlparser.ETableSource;
006import gudusoft.gsqlparser.TBaseType;
007
008import java.util.HashMap;
009
010/*
011* Date: 2010-2-4
012* Time: 16:59:33
013*/
014public class TTableList extends TParseTreeNodeList <TTable>{
015
016    private int indexModCount = -1;
017    private HashMap<String, Integer> nameIndex;
018
019    public TTableList()
020    {
021    }
022
023    public void addTable(TTable table)
024    {
025        addElement(table);
026    }
027
028    /**
029     * add a table reference to table list, if there is already a corresponding table in table list
030     * just add this reference to that table, otherwise, create a new table instance, then add this reference.
031     * @param tableref
032     */
033    public void addTableByTableRefernce(TTableReference tableref)
034    {
035        //addElement(table);
036     boolean  isAdded = false;
037     for(int i=0; i<size();i++){
038         if (getTable(i).isTableRefBelongToThisTable(tableref)){
039            getTable(i).tablerefs.addTableReference(tableref);
040             isAdded = true;
041             break;
042         }
043     }
044    if (!isAdded){
045     addTable(new TTable(tableref.objectname));
046    }
047    }
048
049
050    public TTable getTable(int position)
051    {
052        if (position < size())
053        {
054            return (TTable)elementAt(position);
055        }else{
056        return null;
057        }
058    }
059
060    void addParseTreeNode(Object arg1){
061        addTable((TTable)arg1);
062    }
063
064    private void ensureIndex() {
065        if (nameIndex != null && indexModCount == modCount) return;
066        nameIndex = new HashMap<>(size() * 2 + 4);
067        for (int i = 0; i < size(); i++) {
068            TTable t = getTable(i);
069            String tStr = t.toString();
070            if (tStr != null) {
071                nameIndex.putIfAbsent(tStr.toLowerCase(), i);
072            }
073            if (t.getAliasClause() != null) {
074                String alias = t.getAliasClause().toString();
075                if (alias != null) {
076                    nameIndex.putIfAbsent(alias.toLowerCase(), i);
077                }
078            }
079        }
080        indexModCount = modCount;
081    }
082
083    /**
084     *
085     * @param crf column reference
086     * @return return position of table this column reference belongs to, 0 means first table. &lt; 0 means not found
087     * if no qualifier before column name, always return -2,
088     * if return -1,this column name must be found in uplevel tables
089     */
090    public int checkColumnReferenceInTables(TObjectName crf){
091        int retval = -1;
092        if (crf.getObjectToken() == null) return -2;
093
094        String crfObjectStr = crf.getObjectToken().toString();
095        String crfUnquoted = TBaseType.getTextWithoutQuoted(crfObjectStr);
096        TTable lcTable = null;
097        for(int i=0; i<size();i++){
098            lcTable = getTable(i);
099            if (lcTable.getAliasClause() != null){
100              if (lcTable.getAliasClause().getAliasName().toString().compareToIgnoreCase(crfObjectStr) == 0){
101                  crf.getObjectToken().setDbObjectType(EDbObjectType.table_alias);
102                  return i;
103              }
104            }else{
105               if (lcTable.getTableType() != ETableSource.objectname) {continue;}
106               String tableObjStr = lcTable.getTableName().getObjectToken().toString();
107               if (tableObjStr.compareToIgnoreCase(crfObjectStr) == 0){
108                  crf.getObjectToken().setDbObjType(TObjectName.ttobjTable);
109                   return i;
110               }
111               String s1 = TBaseType.getTextWithoutQuoted(tableObjStr);
112               if (s1.equalsIgnoreCase(crfUnquoted)) {
113                   crf.getObjectToken().setDbObjType(TObjectName.ttobjTable);
114                    return i;
115               }
116            }
117        }
118        return retval;
119    }
120
121    public int searchTableByNameOrAlias(String pTableName){
122        ensureIndex();
123        String key = pTableName.toLowerCase();
124        Integer idx = nameIndex.get(key);
125        if (idx != null) return idx;
126
127        // Fallback: linear scan for safety (covers edge cases index might miss)
128        TTable lcTable = null;
129        int iRet = -1;
130        for(int i=0; i<size();i++) {
131            lcTable = getTable(i);
132            if (lcTable.toString().equalsIgnoreCase(pTableName)){
133                iRet = i;
134                break;
135            }else if (lcTable.getAliasClause() != null){
136                if (lcTable.getAliasClause().toString().equalsIgnoreCase(pTableName)){
137                    iRet = i;
138                    break;
139                }
140            }
141        }
142        return iRet;
143    }
144
145}