001 package railo.runtime.functions.query; 002 003 import java.util.Iterator; 004 import java.util.Map.Entry; 005 006 import railo.commons.lang.StringUtil; 007 import railo.runtime.PageContext; 008 import railo.runtime.exp.DatabaseException; 009 import railo.runtime.exp.FunctionException; 010 import railo.runtime.exp.PageException; 011 import railo.runtime.functions.BIF; 012 import railo.runtime.op.Caster; 013 import railo.runtime.op.Decision; 014 import railo.runtime.type.Array; 015 import railo.runtime.type.ArrayImpl; 016 import railo.runtime.type.Collection.Key; 017 import railo.runtime.type.Query; 018 import railo.runtime.type.QueryImpl; 019 import railo.runtime.type.Struct; 020 import railo.runtime.type.util.ListUtil; 021 import railo.runtime.type.util.QueryUtil; 022 023 /** 024 * Implements the CFML Function querynew 025 */ 026 public final class QueryNew extends BIF { 027 028 private static final long serialVersionUID = -4313766961671090938L; 029 030 public static railo.runtime.type.Query call(PageContext pc , String columnList) throws DatabaseException { 031 return new QueryImpl(ListUtil.listToArrayTrim(columnList,","),0,"query"); 032 } 033 public static railo.runtime.type.Query call(PageContext pc , String columnList, String columnTypeList) throws PageException { 034 if(StringUtil.isEmpty(columnTypeList)) return call(pc, columnList); 035 return new QueryImpl(ListUtil.listToArrayTrim(columnList,","),ListUtil.listToArrayTrim(columnTypeList,","),0,"query"); 036 } 037 038 public static railo.runtime.type.Query call(PageContext pc , String strColumnList, String strColumnTypeList, Object data) throws PageException { 039 Array columnList = ListUtil.listToArrayTrim(strColumnList,","); 040 railo.runtime.type.Query qry; 041 if(StringUtil.isEmpty(strColumnTypeList)) 042 qry= new QueryImpl(columnList,0,"query"); 043 else 044 qry= new QueryImpl(columnList,ListUtil.listToArrayTrim(strColumnTypeList,","),0,"query"); 045 046 if(data==null) return qry; 047 return populate(pc, qry, data); 048 } 049 050 @Override 051 public Object invoke(PageContext pc, Object[] args) throws PageException { 052 if(args.length==1)return call(pc,Caster.toString(args[0])); 053 if(args.length==2)return call(pc,Caster.toString(args[0]),Caster.toString(args[1])); 054 return call(pc,Caster.toString(args[0]),Caster.toString(args[1]),args[2]); 055 } 056 057 public static Query populate(PageContext pc, Query qry,Object data) throws PageException { 058 if(Decision.isArray(data)) 059 return _populate(pc,qry,Caster.toArray(data)); 060 else if(Decision.isStruct(data)) 061 return _populate(pc,qry,Caster.toStruct(data)); 062 else 063 throw new FunctionException(pc, "QueryNew", 3, "data", "the date must be defined as array of structs , array of arrays or struct of arrays"); 064 } 065 066 private static Query _populate(PageContext pc, Query qry,Struct data) throws PageException { 067 Iterator<Entry<Key, Object>> it = data.entryIterator(); 068 Entry<Key, Object> e; 069 Object v; 070 Array arr; 071 int rows = qry.getRecordcount(); 072 while(it.hasNext()){ 073 e = it.next(); 074 if(qry.getColumn(e.getKey(),null)!=null) { 075 v=e.getValue(); 076 arr = Caster.toArray(v,null); 077 if(arr==null) arr=new ArrayImpl(new Object[]{v}); 078 populateColumn(qry,e.getKey(),arr,rows); 079 } 080 } 081 return qry; 082 } 083 084 private static void populateColumn(Query qry, Key column, Array data,int rows) throws PageException { 085 Iterator<?> it = data.valueIterator(); 086 int row=rows; 087 while(it.hasNext()){ 088 row++; 089 if(row>qry.getRecordcount()) qry.addRow(); 090 qry.setAt(column, row, it.next()); 091 } 092 } 093 private static Query _populate(PageContext pc, Query qry,Array data) throws PageException { 094 /* 095 * 3 types of structures are supported 096 * array - ["Urs","Weber"] 097 * array of struct - [{firstname="Urs",lastname="Weber"},{firstname="Peter",lastname="Mueller"}] 098 * array of array - [["Urs","Weber"],["Peter","Mueller"]] 099 */ 100 101 // check if the array only contains simple values or mixed 102 Iterator<?> it = data.valueIterator(); 103 Object o; 104 boolean hasSimpleValues=false; 105 while(it.hasNext()){ 106 o=it.next(); 107 if(!Decision.isStruct(o) && !Decision.isArray(o)) hasSimpleValues=true; 108 } 109 110 111 if(hasSimpleValues) { 112 qry.addRow(); 113 populateRow(qry, data); 114 } 115 else { 116 it = data.valueIterator(); 117 while(it.hasNext()){ 118 o=it.next(); 119 qry.addRow(); 120 if(Decision.isStruct(o))populateRow(qry,Caster.toStruct(o)); 121 else if(Decision.isArray(o))populateRow(qry,Caster.toArray(o)); 122 else { 123 populateRow(qry,new ArrayImpl(new Object[]{o})); 124 } 125 } 126 } 127 return qry; 128 } 129 130 private static void populateRow(Query qry, Struct data) throws PageException { 131 Key[] columns = QueryUtil.getColumnNames(qry); 132 int row=qry.getRecordcount(); 133 Object value; 134 for(int i=0;i<columns.length;i++){ 135 value=data.get(columns[i],null); 136 if(value!=null) qry.setAt(columns[i], row, value); 137 } 138 139 } 140 private static void populateRow(Query qry, Array data) throws PageException { 141 Iterator<?> it = data.valueIterator(); 142 Key[] columns = QueryUtil.getColumnNames(qry); 143 int row=qry.getRecordcount(); 144 int index=-1; 145 while(it.hasNext()){ 146 index++; 147 if(index>=columns.length) break; 148 qry.setAt(columns[index], row, it.next()); 149 } 150 } 151 }