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