24
24
import scriptella .spi .QueryCallback ;
25
25
import scriptella .spi .Resource ;
26
26
27
+ import java .io .InputStream ;
28
+ import java .io .Reader ;
27
29
import java .util .ArrayList ;
30
+ import java .util .HashMap ;
28
31
import java .util .List ;
32
+ import java .util .Map ;
29
33
import java .util .logging .Level ;
30
34
import java .util .logging .Logger ;
31
35
@@ -71,15 +75,15 @@ public void execute(final DynamicContext ctx) {
71
75
}
72
76
final QueryCtxDecorator ctxDecorator = new QueryCtxDecorator (ctx );
73
77
if (LOG .isLoggable (Level .FINE )) {
74
- LOG .fine ("Executing query " + getLocation ());
78
+ LOG .fine ("Executing query " + getLocation ());
75
79
}
76
80
c .executeQuery (content , ctx ,
77
81
new QueryCallback () {
78
82
public void processRow (final ParametersCallback params ) {
79
83
ctxDecorator .rownum ++;
80
84
ctxDecorator .setParams (params );
81
85
if (LOG .isLoggable (Level .FINE )) {
82
- LOG .fine ("Processing row #" + ctxDecorator .rownum + " for query " + getLocation ());
86
+ LOG .fine ("Processing row #" + ctxDecorator .rownum + " for query " + getLocation ());
83
87
}
84
88
85
89
for (ExecutableElement exec : nestedElements ) {
@@ -88,7 +92,12 @@ public void processRow(final ParametersCallback params) {
88
92
}
89
93
});
90
94
if (LOG .isLoggable (Level .FINE )) {
91
- LOG .fine ("Query " +getLocation ()+" process completed" );
95
+ if (ctxDecorator .rownum == 0 ) {
96
+ LOG .fine ("Query " + getLocation () + " returned no results." );
97
+ } else {
98
+ LOG .fine ("Query " + getLocation () + " processed." );
99
+ }
100
+
92
101
}
93
102
94
103
}
@@ -105,23 +114,52 @@ public static ExecutableElement prepare(final QueryEl queryEl) {
105
114
}
106
115
107
116
private static final class QueryCtxDecorator extends DynamicContextDecorator {
117
+ private static final Object NULL = new Object (); //NULL object flag
108
118
private ParametersCallback params ;
109
119
private int rownum ; //current row number
120
+ private Map <String , Object > cachedParams ;
121
+
110
122
111
123
public QueryCtxDecorator (DynamicContext context ) {
112
124
super (context );
113
125
}
114
126
115
127
void setParams (final ParametersCallback params ) {
116
128
this .params = params ;
129
+ if (cachedParams != null ) {
130
+ cachedParams .clear ();
131
+ }
117
132
}
118
133
119
134
@ Override
120
135
public final Object getParameter (final String name ) {
121
136
if ("rownum" .equals (name )) { //return current row number
122
137
return rownum ;
123
138
}
124
- return params .getParameter (name );
139
+ Object res = cachedParams ==null ?null :cachedParams .get (name );
140
+ if (res == null ) {
141
+ res = params .getParameter (name );
142
+ if (res == null ) {
143
+ res = NULL ;
144
+ }
145
+ if (isCacheable (res )) {
146
+ if (cachedParams ==null ) {
147
+ cachedParams =new HashMap <String , Object >();
148
+ }
149
+ cachedParams .put (name , res );
150
+ }
151
+ }
152
+ return res == NULL ? null : res ;
125
153
}
154
+
155
+ /**
156
+ * Check if object is cacheable, i.e. no need to fetch it again.
157
+ * @param o object to check.
158
+ * @return true if object is cacheable.
159
+ */
160
+ private boolean isCacheable (Object o ) {
161
+ return !(o instanceof InputStream || o instanceof Reader );
162
+ }
163
+
126
164
}
127
165
}
0 commit comments