1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.types.TypeId; 25 26 import org.apache.derby.iapi.error.StandardException; 27 import org.apache.derby.iapi.reference.SQLState; 28 29 import org.apache.derby.iapi.services.sanity.SanityManager; 30 31 import org.apache.derby.iapi.sql.compile.NodeFactory; 32 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 33 34 import org.apache.derby.iapi.util.ReuseFactory; 35 36 45 public class OrderByColumn extends OrderedColumn { 46 47 private ResultColumn resultCol; 48 private boolean ascending = true; 49 private ValueNode expression; 50 55 private int addedColumnOffset = -1; 56 57 58 63 public void init(Object expression) 64 { 65 this.expression = (ValueNode)expression; 66 } 67 68 74 public String toString() { 75 if (SanityManager.DEBUG) { 76 return expression.toString(); 77 } else { 78 return ""; 79 } 80 } 81 82 85 public void setDescending() { 86 ascending = false; 87 } 88 89 95 public boolean isAscending() { 96 return ascending; 97 } 98 99 104 ResultColumn getResultColumn() 105 { 106 return resultCol; 107 } 108 109 113 ValueNode getNonRedundantExpression() 114 { 115 ResultColumn rc; 116 ValueNode value; 117 ColumnReference colref = null; 118 119 for (rc = resultCol; rc.isRedundant(); rc = colref.getSource()) 120 { 121 value = rc.getExpression(); 122 123 if (value instanceof ColumnReference) 124 { 125 colref = (ColumnReference) value; 126 } 127 else 128 { 129 if (SanityManager.DEBUG) 130 { 131 SanityManager.THROWASSERT( 132 "value should be a ColumnReference, but is a " + 133 value.getClass().getName()); 134 } 135 } 136 } 137 138 return rc.getExpression(); 139 } 140 141 149 public void bindOrderByColumn(ResultSetNode target) 150 throws StandardException 151 { 152 if(expression instanceof ColumnReference){ 153 154 ColumnReference cr = (ColumnReference) expression; 155 156 resultCol = resolveColumnReference(target, 157 cr); 158 159 columnPosition = resultCol.getColumnPosition(); 160 161 }else if(isReferedColByNum(expression)){ 162 163 ResultColumnList targetCols = target.getResultColumns(); 164 columnPosition = ((Integer )expression.getConstantValueAsObject()).intValue(); 165 resultCol = targetCols.getOrderByColumn(columnPosition); 166 167 if (resultCol == null) { 168 throw StandardException.newException(SQLState.LANG_COLUMN_OUT_OF_RANGE, 169 String.valueOf(columnPosition)); 170 } 171 172 }else{ 173 if( SanityManager.DEBUG) 174 SanityManager.ASSERT( addedColumnOffset >= 0, 175 "Order by expression was not pulled into the result column list"); 176 resolveAddedColumn(target); 177 } 178 179 resultCol.verifyOrderable(); 181 } 182 183 private void resolveAddedColumn(ResultSetNode target) 184 { 185 ResultColumnList targetCols = target.getResultColumns(); 186 columnPosition = targetCols.size() - targetCols.getOrderBySelect() + addedColumnOffset + 1; 187 resultCol = targetCols.getResultColumn( columnPosition); 188 } 189 190 196 public void pullUpOrderByColumn(ResultSetNode target) 197 throws StandardException 198 { 199 ResultColumnList targetCols = target.getResultColumns(); 200 201 if((target instanceof SelectNode) && ((SelectNode) target).getGeneratedForGroupbyClause()) 204 { 205 if( SanityManager.DEBUG) 206 SanityManager.ASSERT( target.getFromList().size() == 1 207 && (target.getFromList().elementAt(0) instanceof FromSubquery) 208 && targetCols.size() == 1 209 && targetCols.getResultColumn(1) instanceof AllResultColumn, 210 "Unexpected structure of selectNode generated for a group by clause"); 211 212 ResultSetNode subquery = ((FromSubquery) target.getFromList().elementAt(0)).getSubquery(); 213 pullUpOrderByColumn( subquery); 214 if( resultCol == null) return; 216 217 resultCol = null; 225 targetCols.copyOrderBySelect( subquery.getResultColumns()); 226 return; 227 } 228 229 if(expression instanceof ColumnReference){ 230 231 ColumnReference cr = (ColumnReference) expression; 232 233 resultCol = targetCols.getOrderByColumn(cr.getColumnName(), 234 cr.getTableNameNode()); 235 236 if(resultCol == null){ 237 resultCol = (ResultColumn) getNodeFactory().getNode(C_NodeTypes.RESULT_COLUMN, 238 cr.getColumnName(), 239 cr, 240 getContextManager()); 241 targetCols.addResultColumn(resultCol); 242 addedColumnOffset = targetCols.getOrderBySelect(); 243 targetCols.incOrderBySelect(); 244 } 245 246 }else if(!isReferedColByNum(expression)){ 247 resultCol = (ResultColumn) getNodeFactory().getNode(C_NodeTypes.RESULT_COLUMN, 248 null, 249 expression, 250 getContextManager()); 251 targetCols.addResultColumn(resultCol); 252 addedColumnOffset = targetCols.getOrderBySelect(); 253 targetCols.incOrderBySelect(); 254 } 255 } 256 257 263 void resetToSourceRC() 264 { 265 if (SanityManager.DEBUG) 266 { 267 if (! (resultCol.getExpression() instanceof VirtualColumnNode)) 268 { 269 SanityManager.THROWASSERT( 270 "resultCol.getExpression() expected to be instanceof VirtualColumnNode " + 271 ", not " + resultCol.getExpression().getClass().getName()); 272 } 273 } 274 275 VirtualColumnNode vcn = (VirtualColumnNode) resultCol.getExpression(); 276 resultCol = vcn.getSourceResultColumn(); 277 } 278 279 284 boolean constantColumn(PredicateList whereClause) 285 { 286 ValueNode sourceExpr = resultCol.getExpression(); 287 288 return sourceExpr.constantExpression(whereClause); 289 } 290 291 297 void remapColumnReferencesToExpressions() throws StandardException 298 { 299 resultCol.setExpression( 300 resultCol.getExpression().remapColumnReferencesToExpressions()); 301 } 302 303 private static boolean isReferedColByNum(ValueNode expression) 304 throws StandardException{ 305 306 if(!expression.isConstantExpression()){ 307 return false; 308 } 309 310 return expression.getConstantValueAsObject() instanceof Integer ; 311 } 312 313 314 private ResultColumn resolveColumnReference(ResultSetNode target, 315 ColumnReference cr) 316 throws StandardException{ 317 318 ResultColumn resultCol = null; 319 320 int sourceTableNumber = -1; 321 322 324 if (target instanceof SetOperatorNode && cr.getTableName() != null){ 325 String fullName = cr.getSQLColumnName(); 326 throw StandardException.newException(SQLState.LANG_QUALIFIED_COLUMN_NAME_NOT_ALLOWED, fullName); 327 } 328 329 if(cr.getTableNameNode() != null){ 330 TableName tableNameNode = cr.getTableNameNode(); 331 332 FromTable fromTable = target.getFromTableByName(tableNameNode.getTableName(), 333 (tableNameNode.hasSchema() ? 334 tableNameNode.getSchemaName():null), 335 true); 336 if(fromTable == null){ 337 fromTable = target.getFromTableByName(tableNameNode.getTableName(), 338 (tableNameNode.hasSchema() ? 339 tableNameNode.getSchemaName():null), 340 false); 341 if(fromTable == null){ 342 String fullName = cr.getTableNameNode().toString(); 343 throw StandardException.newException(SQLState.LANG_EXPOSED_NAME_NOT_FOUND, fullName); 344 } 345 } 346 347 352 if (target instanceof SetOperatorNode) 353 { 354 sourceTableNumber = ((FromTable) target).getTableNumber(); 355 } 356 else 357 { 358 sourceTableNumber = fromTable.getTableNumber(); 359 } 360 361 } 362 363 ResultColumnList targetCols = target.getResultColumns(); 364 365 resultCol = targetCols.getOrderByColumn(cr.getColumnName(), 366 cr.getTableNameNode(), 367 sourceTableNumber); 368 373 if( resultCol == null && addedColumnOffset >= 0) 374 resolveAddedColumn(target); 375 376 if (resultCol == null || resultCol.isNameGenerated()){ 377 String errString = cr.columnName; 378 throw StandardException.newException(SQLState.LANG_ORDER_BY_COLUMN_NOT_FOUND, errString); 379 } 380 381 return resultCol; 382 383 } 384 385 } 386 | Popular Tags |