View Javadoc

1   /*
2    * Copyright 2004-2007 Brian McCallister
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.skife.jdbi.v2;
18  
19  import org.skife.jdbi.v2.exceptions.ResultSetException;
20  import org.skife.jdbi.v2.exceptions.UnableToCreateStatementException;
21  import org.skife.jdbi.v2.exceptions.UnableToExecuteStatementException;
22  import org.skife.jdbi.v2.tweak.Argument;
23  import org.skife.jdbi.v2.tweak.RewrittenStatement;
24  import org.skife.jdbi.v2.tweak.SQLLog;
25  import org.skife.jdbi.v2.tweak.StatementBuilder;
26  import org.skife.jdbi.v2.tweak.StatementCustomizer;
27  import org.skife.jdbi.v2.tweak.StatementLocator;
28  import org.skife.jdbi.v2.tweak.StatementRewriter;
29  
30  import java.io.InputStream;
31  import java.io.Reader;
32  import java.math.BigDecimal;
33  import java.net.URL;
34  import java.sql.Blob;
35  import java.sql.Clob;
36  import java.sql.Connection;
37  import java.sql.PreparedStatement;
38  import java.sql.ResultSet;
39  import java.sql.SQLException;
40  import java.sql.Time;
41  import java.sql.Timestamp;
42  import java.sql.Types;
43  import java.util.ArrayList;
44  import java.util.Collection;
45  import java.util.Map;
46  
47  /**
48   * This class provides the common functions between <code>Query</code> and
49   * <code>Update</code>. It defines most of the argument binding functions
50   * used by its subclasses.
51   */
52  public abstract class SQLStatement<SelfType extends SQLStatement<SelfType>>
53  {
54      private final Binding params;
55      private final Connection connection;
56      private final String sql;
57      private final StatementRewriter rewriter;
58      private final StatementBuilder statementBuilder;
59      private final StatementLocator locator;
60      private final Collection<StatementCustomizer> customizers = new ArrayList<StatementCustomizer>();
61      private final StatementContext context;
62  
63      /**
64       * This will be set on execution, not before
65       */
66      private RewrittenStatement rewritten;
67      private PreparedStatement stmt;
68      private final SQLLog log;
69      private final TimingCollector timingCollector;
70  
71      SQLStatement(Binding params,
72                   StatementLocator locator,
73                   StatementRewriter rewriter,
74                   Connection conn,
75                   StatementBuilder preparedStatementCache,
76                   String sql,
77                   StatementContext ctx,
78                   SQLLog log,
79                   TimingCollector timingCollector,
80                   Collection<StatementCustomizer> statementCustomizers)
81      {
82          this.log = log;
83          assert (verifyOurNastyDowncastIsOkay());
84          this.context = ctx;
85          this.statementBuilder = preparedStatementCache;
86          this.rewriter = rewriter;
87          this.connection = conn;
88          this.sql = sql;
89          this.timingCollector = timingCollector;
90          this.params = params;
91          this.locator = locator;
92          this.customizers.addAll(statementCustomizers);
93  
94          ctx.setConnection(conn);
95          ctx.setRawSql(sql);
96          ctx.setBinding(params);
97      }
98  
99      protected Collection<StatementCustomizer> getStatementCustomizers()
100     {
101         return this.customizers;
102     }
103 
104     /**
105      * Define a value on the {@link StatementContext}
106      *
107      * @param key Key to acces this value from the StatementContext
108      * @param value Value to setAttribute on the StatementContext
109      * @return this
110      */
111     @SuppressWarnings("unchecked")
112     public SelfType define(String key, Object value)
113     {
114         getContext().setAttribute(key, value);
115         return (SelfType)this;
116     }
117 
118     /**
119      * Obtain the statement context associated with this statement
120      */
121     public StatementContext getContext() {
122         return context;
123     }
124 
125     /**
126      * Provides a means for custom statement modification. Common cusotmizations
127      * have their own methods, such as {@link Query#setMaxRows(int)}
128      *
129      * @param customizer instance to be used to cstomize a statement
130      *
131      * @return modified statement
132      */
133     @SuppressWarnings("unchecked")
134     public SelfType addStatementCustomizer(StatementCustomizer customizer)
135     {
136         this.customizers.add(customizer);
137         return (SelfType) this;
138     }
139 
140     private boolean verifyOurNastyDowncastIsOkay()
141     {
142         if (this.getClass().getTypeParameters().length == 0) {
143             return true;
144         }
145         else {
146             Class<?> parameterized_type = this.getClass().getTypeParameters()[0].getGenericDeclaration();
147             return parameterized_type.isAssignableFrom(this.getClass());
148         }
149     }
150 
151     protected StatementBuilder getStatementBuilder()
152     {
153         return statementBuilder;
154     }
155 
156     protected StatementLocator getStatementLocator()
157     {
158         return this.locator;
159     }
160 
161     protected StatementRewriter getRewriter()
162     {
163         return rewriter;
164     }
165 
166     protected Binding getParams()
167     {
168         return params;
169     }
170 
171     protected Connection getConnection()
172     {
173         return connection;
174     }
175 
176     /**
177      * The un-translated SQL used to create this statement
178      * @return
179      */
180     protected String getSql()
181     {
182         return sql;
183     }
184 
185     protected Binding getParameters()
186     {
187         return params;
188     }
189 
190     /**
191      * Used if you need to have some exotic parameter bound.
192      *
193      * @param position position to bindBinaryStream this argument, starting at 0
194      * @param argument exotic argument factory
195      *
196      * @return the same Query instance
197      */
198     @SuppressWarnings("unchecked")
199     public SelfType bind(int position, Argument argument)
200     {
201         params.addPositional(position, argument);
202         return (SelfType) this;
203     }
204 
205     /**
206      * Used if you need to have some exotic parameter bound.
207      *
208      * @param name     name to bindBinaryStream this argument
209      * @param argument exotic argument factory
210      *
211      * @return the same Query instance
212      */
213     @SuppressWarnings("unchecked")
214     public SelfType bind(String name, Argument argument)
215     {
216         params.addNamed(name, argument);
217         return (SelfType) this;
218     }
219 
220     /**
221      * Binds named parameters from JavaBean properties on o.
222      *
223      * @param o source of named parameter values to use as arguments
224      *
225      * @return modified statement
226      */
227     @SuppressWarnings("unchecked")
228     public SelfType bindFromProperties(Object o)
229     {
230         params.addLazyNamedArguments(new BeanPropertyArguments(o, context));
231         return (SelfType) this;
232     }
233 
234     /**
235      * Binds named parameters from a map of String to Object instances
236      *
237      * @param args map where keys are matched to named parameters in order to bind arguments
238      *
239      * @return modified statement
240      */
241     @SuppressWarnings("unchecked")
242     public SelfType bindFromMap(Map<String, ? extends Object> args)
243     {
244         params.addLazyNamedArguments(new MapArguments(args));
245         return (SelfType) this;
246     }
247 
248     /**
249      * Bind an argument positionally
250      *
251      * @param position position to bind the paramater at, starting at 0
252      * @param value    to bind
253      *
254      * @return the same Query instance
255      */
256     public final SelfType bind(int position, Character value)
257     {
258         if (value != null) {
259             return bind(position, new CharacterArgument(value));
260         }
261         else {
262             return bind(position, new NullArgument(Types.VARCHAR));
263         }
264     }
265 
266     /**
267      * Bind an argument by name
268      *
269      * @param name  token name to bind the parameter to
270      * @param value to bind
271      *
272      * @return the same Query instance
273      */
274     public final SelfType bind(String name, Character value)
275     {
276         if (value != null) {
277             return bind(name, new CharacterArgument(value));
278         }
279         else {
280             return bind(name, new NullArgument(Types.VARCHAR));
281         }
282     }
283 
284     /**
285      * Bind an argument positionally
286      *
287      * @param position position to bind the paramater at, starting at 0
288      * @param value    to bind
289      *
290      * @return the same Query instance
291      */
292     public final SelfType bind(int position, String value)
293     {
294         return bind(position, new StringArgument(value));
295     }
296 
297     /**
298      * Bind an argument by name
299      *
300      * @param name  token name to bind the paramater to
301      * @param value to bind
302      *
303      * @return the same Query instance
304      */
305     public final SelfType bind(String name, String value)
306     {
307         return bind(name, new StringArgument(value));
308     }
309 
310     /**
311      * Bind an argument positionally
312      *
313      * @param position position to bind the paramater at, starting at 0
314      * @param value    to bind
315      *
316      * @return the same Query instance
317      */
318     public final SelfType bind(int position, int value)
319     {
320         return bind(position, new IntegerArgument(value));
321     }
322 
323     /**
324      * Bind an argument positionally
325      *
326      * @param position position to bind the paramater at, starting at 0
327      * @param value    to bind
328      *
329      * @return the same Query instance
330      */
331     public final SelfType bind(int position, Integer value)
332     {
333         if (value != null) {
334             return bind(position, new IntegerArgument(value));
335         }
336         else {
337             return bind(position, new NullArgument(Types.INTEGER));
338         }
339     }
340 
341     /**
342      * Bind an argument by name
343      *
344      * @param name  name to bind the paramater to
345      * @param value to bind
346      *
347      * @return the same Query instance
348      */
349     public final SelfType bind(String name, int value)
350     {
351         return bind(name, new IntegerArgument(value));
352     }
353 
354     /**
355      * Bind an argument by name
356      *
357      * @param name  name to bind the paramater to
358      * @param value to bind
359      *
360      * @return the same Query instance
361      */
362     public final SelfType bind(String name, Integer value)
363     {
364         if (value != null) {
365             return bind(name, new IntegerArgument(value));
366         }
367         else {
368             return bind(name, new NullArgument(Types.INTEGER));
369         }
370     }
371 
372     /**
373      * Bind an argument positionally
374      *
375      * @param position position to bind the paramater at, starting at 0
376      * @param value    to bind
377      *
378      * @return the same Query instance
379      */
380     public final SelfType bind(int position, char value)
381     {
382         return bind(position, new CharacterArgument(value));
383     }
384 
385     /**
386      * Bind an argument by name
387      *
388      * @param name  name to bind the paramater to
389      * @param value to bind
390      *
391      * @return the same Query instance
392      */
393     public final SelfType bind(String name, char value)
394     {
395         return bind(name, new CharacterArgument(value));
396     }
397 
398     /**
399      * Bind an argument positionally
400      *
401      * @param position position to bind the paramater at, starting at 0
402      * @param value    to bind
403      * @param length   how long is the stream being bound?
404      *
405      * @return the same Query instance
406      */
407     public final SelfType bindASCIIStream(int position, InputStream value, int length)
408     {
409         return bind(position, new InputStreamArgument(value, length, true));
410     }
411 
412     /**
413      * Bind an argument by name
414      *
415      * @param name   token name to bind the paramater to
416      * @param value  to bind
417      * @param length bytes to read from value
418      *
419      * @return the same Query instance
420      */
421     public final SelfType bindASCIIStream(String name, InputStream value, int length)
422     {
423         return bind(name, new InputStreamArgument(value, length, true));
424     }
425 
426     /**
427      * Bind an argument positionally
428      *
429      * @param position position to bind the paramater at, starting at 0
430      * @param value    to bind
431      *
432      * @return the same Query instance
433      */
434     public final SelfType bind(int position, BigDecimal value)
435     {
436         return bind(position, new BigDecimalArgument(value));
437     }
438 
439     /**
440      * Bind an argument by name
441      *
442      * @param name  token name to bind the paramater to
443      * @param value to bind
444      *
445      * @return the same Query instance
446      */
447     public final SelfType bind(String name, BigDecimal value)
448     {
449         return bind(name, new BigDecimalArgument(value));
450     }
451 
452     /**
453      * Bind an argument positionally
454      *
455      * @param position position to bind the paramater at, starting at 0
456      * @param value    to bind
457      *
458      * @return the same Query instance
459      */
460     public final SelfType bindBinaryStream(int position, InputStream value, int length)
461     {
462         return bind(position, new InputStreamArgument(value, length, false));
463     }
464 
465     /**
466      * Bind an argument by name
467      *
468      * @param name   token name to bind the paramater to
469      * @param value  to bind
470      * @param length bytes to read from value
471      *
472      * @return the same Query instance
473      */
474     public final SelfType bindBinaryStream(String name, InputStream value, int length)
475     {
476         return bind(name, new InputStreamArgument(value, length, false));
477     }
478 
479     /**
480      * Bind an argument positionally
481      *
482      * @param position position to bind the paramater at, starting at 0
483      * @param value    to bind
484      *
485      * @return the same Query instance
486      */
487     public final SelfType bind(int position, Blob value)
488     {
489         return bind(position, new BlobArgument(value));
490     }
491 
492     /**
493      * Bind an argument by name
494      *
495      * @param name  token name to bind the paramater to
496      * @param value to bind
497      *
498      * @return the same Query instance
499      */
500     public final SelfType bind(String name, Blob value)
501     {
502         return bind(name, new BlobArgument(value));
503     }
504 
505     /**
506      * Bind an argument positionally
507      *
508      * @param position position to bind the paramater at, starting at 0
509      * @param value    to bind
510      *
511      * @return the same Query instance
512      */
513     public final SelfType bind(int position, boolean value)
514     {
515         return bind(position, new BooleanArgument(value));
516     }
517 
518     /**
519      * Bind an argument positionally
520      *
521      * @param position position to bind the paramater at, starting at 0
522      * @param value    to bind
523      *
524      * @return the same Query instance
525      */
526     public final SelfType bind(int position, Boolean value)
527     {
528         if (value != null) {
529             return bind(position, new BooleanArgument(value));
530         }
531         else {
532             return bind(position, new NullArgument(Types.BOOLEAN));
533         }
534     }
535 
536     /**
537      * Bind an argument by name
538      *
539      * @param name  token name to bind the paramater to
540      * @param value to bind
541      *
542      * @return the same Query instance
543      */
544     public final SelfType bind(String name, boolean value)
545     {
546         return bind(name, new BooleanArgument(value));
547     }
548 
549     /**
550      * Bind an argument by name
551      *
552      * @param name  token name to bind the paramater to
553      * @param value to bind
554      *
555      * @return the same Query instance
556      */
557     public final SelfType bind(String name, Boolean value)
558     {
559         if (value != null) {
560             return bind(name, new BooleanArgument(value));
561         }
562         else {
563             return bind(name, new NullArgument(Types.BOOLEAN));
564         }
565     }
566 
567     /**
568      * Bind an argument positionally
569      *
570      * @param position position to bind the paramater at, starting at 0
571      * @param value    to bind
572      *
573      * @return the same Query instance
574      */
575     public final SelfType bindAsInt(int position, boolean value)
576     {
577         return bind(position, new BooleanIntegerArgument(value));
578     }
579 
580     /**
581      * Bind an argument positionally
582      *
583      * @param position position to bind the paramater at, starting at 0
584      * @param value    to bind
585      *
586      * @return the same Query instance
587      */
588     public final SelfType bindAsInt(int position, Boolean value)
589     {
590         if (value != null) {
591             return bind(position, new BooleanIntegerArgument(value));
592         }
593         else {
594             return bind(position, new NullArgument(Types.INTEGER));
595         }
596     }
597 
598     /**
599      * Bind an argument by name
600      *
601      * @param name  token name to bind the paramater to
602      * @param value to bind
603      *
604      * @return the same Query instance
605      */
606     public final SelfType bindAsInt(String name, boolean value)
607     {
608         return bind(name, new BooleanIntegerArgument(value));
609     }
610 
611     /**
612      * Bind an argument by name
613      *
614      * @param name  token name to bind the paramater to
615      * @param value to bind
616      *
617      * @return the same Query instance
618      */
619     public final SelfType bindAsInt(String name, Boolean value)
620     {
621         if (value != null) {
622             return bind(name, new BooleanIntegerArgument(value));
623         }
624         else {
625             return bind(name, new NullArgument(Types.INTEGER));
626         }
627     }
628 
629     /**
630      * Bind an argument positionally
631      *
632      * @param position position to bind the paramater at, starting at 0
633      * @param value    to bind
634      *
635      * @return the same Query instance
636      */
637     public final SelfType bind(int position, byte value)
638     {
639         return bind(position, new ByteArgument(value));
640     }
641 
642     /**
643      * Bind an argument positionally
644      *
645      * @param position position to bind the paramater at, starting at 0
646      * @param value    to bind
647      *
648      * @return the same Query instance
649      */
650     public final SelfType bind(int position, Byte value)
651     {
652         if (value != null) {
653             return bind(position, new ByteArgument(value));
654         }
655         else {
656             return bind(position, new NullArgument(Types.TINYINT));
657         }
658     }
659 
660     /**
661      * Bind an argument by name
662      *
663      * @param name  token name to bind the paramater to
664      * @param value to bind
665      *
666      * @return the same Query instance
667      */
668     public final SelfType bind(String name, byte value)
669     {
670         return bind(name, new ByteArgument(value));
671     }
672 
673     /**
674      * Bind an argument by name
675      *
676      * @param name  token name to bind the paramater to
677      * @param value to bind
678      *
679      * @return the same Query instance
680      */
681     public final SelfType bind(String name, Byte value)
682     {
683         if (value != null) {
684             return bind(name, new ByteArgument(value));
685         }
686         else {
687             return bind(name, new NullArgument(Types.TINYINT));
688         }
689     }
690 
691     /**
692      * Bind an argument positionally
693      *
694      * @param position position to bind the paramater at, starting at 0
695      * @param value    to bind
696      *
697      * @return the same Query instance
698      */
699     public final SelfType bind(int position, byte[] value)
700     {
701         return bind(position, new ByteArrayArgument(value));
702     }
703 
704     /**
705      * Bind an argument by name
706      *
707      * @param name  token name to bind the paramater to
708      * @param value to bind
709      *
710      * @return the same Query instance
711      */
712     public final SelfType bind(String name, byte[] value)
713     {
714         return bind(name, new ByteArrayArgument(value));
715     }
716 
717     /**
718      * Bind an argument positionally
719      *
720      * @param position position to bind the paramater at, starting at 0
721      * @param value    to bind
722      * @param length   number of characters to read
723      *
724      * @return the same Query instance
725      */
726     public final SelfType bind(int position, Reader value, int length)
727     {
728         return bind(position, new CharacterStreamArgument(value, length));
729     }
730 
731     /**
732      * Bind an argument by name
733      *
734      * @param name   token name to bind the paramater to
735      * @param value  to bind
736      * @param length number of characters to read
737      *
738      * @return the same Query instance
739      */
740     public final SelfType bind(String name, Reader value, int length)
741     {
742         return bind(name, new CharacterStreamArgument(value, length));
743     }
744 
745     /**
746      * Bind an argument positionally
747      *
748      * @param position position to bind the paramater at, starting at 0
749      * @param value    to bind
750      *
751      * @return the same Query instance
752      */
753     public final SelfType bind(int position, Clob value)
754     {
755         return bind(position, new ClobArgument(value));
756     }
757 
758     /**
759      * Bind an argument by name
760      *
761      * @param name  token name to bind the paramater to
762      * @param value to bind
763      *
764      * @return the same Query instance
765      */
766     public final SelfType bind(String name, Clob value)
767     {
768         return bind(name, new ClobArgument(value));
769     }
770 
771     /**
772      * Bind an argument positionally
773      *
774      * @param position position to bind the paramater at, starting at 0
775      * @param value    to bind
776      *
777      * @return the same Query instance
778      */
779     public final SelfType bind(int position, java.sql.Date value)
780     {
781         return bind(position, new SqlDateArgument(value));
782     }
783 
784     /**
785      * Bind an argument by name
786      *
787      * @param name  token name to bind the paramater to
788      * @param value to bind
789      *
790      * @return the same Query instance
791      */
792     public final SelfType bind(String name, java.sql.Date value)
793     {
794         return bind(name, new SqlDateArgument(value));
795     }
796 
797     /**
798      * Bind an argument positionally
799      *
800      * @param position position to bind the paramater at, starting at 0
801      * @param value    to bind
802      *
803      * @return the same Query instance
804      */
805     public final SelfType bind(int position, java.util.Date value)
806     {
807         return bind(position, new JavaDateArgument(value));
808     }
809 
810     /**
811      * Bind an argument by name
812      *
813      * @param name  token name to bind the paramater to
814      * @param value to bind
815      *
816      * @return the same Query instance
817      */
818     public final SelfType bind(String name, java.util.Date value)
819     {
820         return bind(name, new JavaDateArgument(value));
821     }
822 
823     /**
824      * Bind an argument positionally
825      *
826      * @param position position to bind the paramater at, starting at 0
827      * @param value    to bind
828      *
829      * @return the same Query instance
830      */
831     public final SelfType bind(int position, double value)
832     {
833         return bind(position, new DoubleArgument(value));
834     }
835 
836     /**
837      * Bind an argument positionally
838      *
839      * @param position position to bind the paramater at, starting at 0
840      * @param value    to bind
841      *
842      * @return the same Query instance
843      */
844     public final SelfType bind(int position, Double value)
845     {
846         if (value != null) {
847             return bind(position, new DoubleArgument(value));
848         }
849         else {
850             return bind(position, new NullArgument(Types.DOUBLE));
851         }
852     }
853 
854     /**
855      * Bind an argument by name
856      *
857      * @param name  token name to bind the paramater to
858      * @param value to bind
859      *
860      * @return the same Query instance
861      */
862     public final SelfType bind(String name, double value)
863     {
864         return bind(name, new DoubleArgument(value));
865     }
866 
867     /**
868      * Bind an argument by name
869      *
870      * @param name  token name to bind the paramater to
871      * @param value to bind
872      *
873      * @return the same Query instance
874      */
875     public final SelfType bind(String name, Double value)
876     {
877         if (value != null) {
878             return bind(name, new DoubleArgument(value));
879         }
880         else {
881             return bind(name, new NullArgument(Types.DOUBLE));
882         }
883     }
884 
885     /**
886      * Bind an argument positionally
887      *
888      * @param position position to bind the paramater at, starting at 0
889      * @param value    to bind
890      *
891      * @return the same Query instance
892      */
893     public final SelfType bind(int position, float value)
894     {
895         return bind(position, new FloatArgument(value));
896     }
897 
898     /**
899      * Bind an argument positionally
900      *
901      * @param position position to bind the paramater at, starting at 0
902      * @param value    to bind
903      *
904      * @return the same Query instance
905      */
906     public final SelfType bind(int position, Float value)
907     {
908         if (value != null) {
909             return bind(position, new FloatArgument(value));
910         }
911         else {
912             return bind(position, new NullArgument(Types.FLOAT));
913         }
914     }
915 
916     /**
917      * Bind an argument by name
918      *
919      * @param name  token name to bind the paramater to
920      * @param value to bind
921      *
922      * @return the same Query instance
923      */
924     public final SelfType bind(String name, float value)
925     {
926         return bind(name, new FloatArgument(value));
927     }
928 
929     /**
930      * Bind an argument by name
931      *
932      * @param name  token name to bind the paramater to
933      * @param value to bind
934      *
935      * @return the same Query instance
936      */
937     public final SelfType bind(String name, Float value)
938     {
939         if (value != null) {
940             return bind(name, new FloatArgument(value));
941         }
942         else {
943             return bind(name, new NullArgument(Types.FLOAT));
944         }
945     }
946 
947     /**
948      * Bind an argument positionally
949      *
950      * @param position position to bind the paramater at, starting at 0
951      * @param value    to bind
952      *
953      * @return the same Query instance
954      */
955     public final SelfType bind(int position, long value)
956     {
957         return bind(position, new LongArgument(value));
958     }
959 
960     /**
961      * Bind an argument positionally
962      *
963      * @param position position to bind the paramater at, starting at 0
964      * @param value    to bind
965      *
966      * @return the same Query instance
967      */
968     public final SelfType bind(int position, Long value)
969     {
970         if (value != null) {
971             return bind(position, new LongArgument(value));
972         }
973         else {
974             return bind(position, new NullArgument(Types.BIGINT));
975         }
976     }
977 
978     /**
979      * Bind an argument by name
980      *
981      * @param name  token name to bind the paramater to
982      * @param value to bind
983      *
984      * @return the same Query instance
985      */
986     public final SelfType bind(String name, long value)
987     {
988         return bind(name, new LongArgument(value));
989     }
990 
991     /**
992      * Bind an argument by name
993      *
994      * @param name  token name to bind the paramater to
995      * @param value to bind
996      *
997      * @return the same Query instance
998      */
999     public final SelfType bind(String name, Long value)
1000     {
1001         if (value != null) {
1002             return bind(name, new LongArgument(value));
1003         }
1004         else {
1005             return bind(name, new NullArgument(Types.BIGINT));
1006         }
1007     }
1008 
1009     /**
1010      * Bind an argument positionally
1011      *
1012      * @param position position to bind the paramater at, starting at 0
1013      * @param value    to bind
1014      *
1015      * @return the same Query instance
1016      */
1017     public final SelfType bind(int position, Short value)
1018     {
1019         if (value != null) {
1020             return bind(position, new ShortArgument(value));
1021         }
1022         else {
1023             return bind(position, new NullArgument(Types.SMALLINT));
1024         }
1025     }
1026 
1027     /**
1028      * Bind an argument positionally
1029      *
1030      * @param position position to bind the paramater at, starting at 0
1031      * @param value    to bind
1032      *
1033      * @return the same Query instance
1034      */
1035     public final SelfType bind(int position, short value)
1036     {
1037         return bind(position, new ShortArgument(value));
1038     }
1039 
1040     /**
1041      * Bind an argument by name
1042      *
1043      * @param name  token name to bind the paramater to
1044      * @param value to bind
1045      *
1046      * @return the same Query instance
1047      */
1048     public final SelfType bind(String name, short value)
1049     {
1050         return bind(name, new ShortArgument(value));
1051     }
1052 
1053     /**
1054      * Bind an argument by name
1055      *
1056      * @param name  token name to bind the paramater to
1057      * @param value to bind
1058      *
1059      * @return the same Query instance
1060      */
1061     public final SelfType bind(String name, Short value)
1062     {
1063         if (value != null) {
1064             return bind(name, new ShortArgument(value));
1065         }
1066         else {
1067             return bind(name, new NullArgument(Types.SMALLINT));
1068         }
1069     }
1070 
1071     /**
1072      * Bind an argument positionally
1073      *
1074      * @param position position to bind the paramater at, starting at 0
1075      * @param value    to bind
1076      *
1077      * @return the same Query instance
1078      */
1079     public final SelfType bind(int position, Object value)
1080     {
1081         return bind(position, new ObjectArgument(value));
1082     }
1083 
1084     /**
1085      * Bind an argument by name
1086      *
1087      * @param name  token name to bind the paramater to
1088      * @param value to bind
1089      *
1090      * @return the same Query instance
1091      */
1092     public final SelfType bind(String name, Object value)
1093     {
1094         return bind(name, new ObjectArgument(value));
1095     }
1096 
1097     /**
1098      * Bind an argument positionally
1099      *
1100      * @param position position to bind the paramater at, starting at 0
1101      * @param value    to bind
1102      *
1103      * @return the same Query instance
1104      */
1105     public final SelfType bind(int position, Time value)
1106     {
1107         return bind(position, new TimeArgument(value));
1108     }
1109 
1110     /**
1111      * Bind an argument by name
1112      *
1113      * @param name  token name to bind the paramater to
1114      * @param value to bind
1115      *
1116      * @return the same Query instance
1117      */
1118     public final SelfType bind(String name, Time value)
1119     {
1120         return bind(name, new TimeArgument(value));
1121     }
1122 
1123     /**
1124      * Bind an argument positionally
1125      *
1126      * @param position position to bind the paramater at, starting at 0
1127      * @param value    to bind
1128      *
1129      * @return the same Query instance
1130      */
1131     public final SelfType bind(int position, Timestamp value)
1132     {
1133         return bind(position, new TimestampArgument(value));
1134     }
1135 
1136     /**
1137      * Bind an argument by name
1138      *
1139      * @param name  token name to bind the paramater to
1140      * @param value to bind
1141      *
1142      * @return the same Query instance
1143      */
1144     public final SelfType bind(String name, Timestamp value)
1145     {
1146         return bind(name, new TimestampArgument(value));
1147     }
1148 
1149     /**
1150      * Bind an argument positionally
1151      *
1152      * @param position position to bind the paramater at, starting at 0
1153      * @param value    to bind
1154      *
1155      * @return the same Query instance
1156      */
1157     public final SelfType bind(int position, URL value)
1158     {
1159         return bind(position, new URLArgument(value));
1160     }
1161 
1162     /**
1163      * Bind an argument by name
1164      *
1165      * @param name  token name to bind the paramater to
1166      * @param value to bind
1167      *
1168      * @return the same Query instance
1169      */
1170     public final SelfType bind(String name, URL value)
1171     {
1172         return bind(name, new URLArgument(value));
1173     }
1174 
1175     /**
1176      * Bind NULL to be set for a given argument.
1177      *
1178      * @param name Named parameter to bind to
1179      * @param sqlType The sqlType must be set and is a value from <code>java.sql.Types</code>
1180      * @return the same statement instance
1181      */
1182     public final SelfType bindNull(String name, int sqlType) {
1183         return bind(name, new NullArgument(sqlType));
1184     }
1185 
1186     /**
1187      * Bind NULL to be set for a given argument.
1188      *
1189      * @param position position to bind NULL to, starting at 0
1190      * @param sqlType The sqlType must be set and is a value from <code>java.sql.Types</code>
1191      * @return the same statement instance
1192      */
1193     public final SelfType bindNull(int position, int sqlType) {
1194         return bind(position, new NullArgument(sqlType));
1195     }
1196 
1197     /**
1198      * Bind a value using a specific type from <code>java.sql.Types</code> via
1199      * PreparedStatement#setObject(int, Object, int)
1200      *
1201      * @param name Named parameter to bind at
1202      * @param value Value to bind
1203      * @param sqlType The sqlType from java.sql.Types
1204      * @return self
1205      */
1206     public final SelfType bindBySqlType(String name, Object value, int sqlType) {
1207         return bind(name, new SqlTypeArgument(value, sqlType));
1208     }
1209 
1210     /**
1211      * Bind a value using a specific type from <code>java.sql.Types</code> via
1212      * PreparedStatement#setObject(int, Object, int)
1213      *
1214      * @param position position to bind NULL to, starting at 0
1215      * @param value Value to bind
1216      * @param sqlType The sqlType from java.sql.Types
1217      * @return self
1218      */
1219     public final SelfType bindBySqlType(int position, Object value, int sqlType) {
1220         return bind(position, new SqlTypeArgument(value, sqlType));
1221     }
1222 
1223     private String wrapLookup(String sql)
1224     {
1225         try {
1226             return locator.locate(sql, this.getContext());
1227         }
1228         catch (Exception e) {
1229             throw new UnableToCreateStatementException("Exception thrown while looking for statement", e, context);
1230         }
1231     }
1232 
1233     protected <Result> Result internalExecute(final QueryPreperator prep,
1234                                               final QueryResultMunger<Result> munger,
1235                                               final QueryPostMungeCleanup cleanup)
1236     {
1237         final String located_sql = wrapLookup(sql);
1238         this.context.setLocatedSql(located_sql);
1239         rewritten = rewriter.rewrite(located_sql, getParameters(), this.context);
1240         this.context.setRewrittenSql(rewritten.getSql());
1241         ResultSet rs = null;
1242         try {
1243             try {
1244 	            if (getClass().isAssignableFrom(Call.class)) {
1245 		            stmt = statementBuilder.createCall(this.getConnection(), rewritten.getSql(), context);
1246 	            }
1247 	            else {
1248                     stmt = statementBuilder.create(this.getConnection(), rewritten.getSql(), context);
1249 	            }
1250             }
1251             catch (SQLException e) {
1252                 throw new UnableToCreateStatementException(e,context);
1253             }
1254 
1255             this.context.setStatement(stmt);
1256             try {
1257                 rewritten.bind(getParameters(), stmt);
1258             }
1259             catch (SQLException e) {
1260                 throw new UnableToExecuteStatementException("Unable to bind parameters to query", e, context);
1261             }
1262 
1263             try {
1264                 prep.prepare(stmt);
1265             }
1266             catch (SQLException e) {
1267                 throw new UnableToExecuteStatementException("Unable to prepare JDBC statement", e, context);
1268             }
1269 
1270             for (StatementCustomizer customizer : customizers) {
1271                 try {
1272                     customizer.beforeExecution(stmt, context);
1273                 }
1274                 catch (SQLException e) {
1275                     throw new UnableToExecuteStatementException("Exception thrown in statement customization", e, context);
1276                 }
1277             }
1278 
1279             try {
1280                 final long start = System.nanoTime();
1281                 stmt.execute();
1282                 final long elapsedTime = System.nanoTime() - start;
1283                 log.logSQL(elapsedTime / 1000000L,  rewritten.getSql());
1284                 timingCollector.collect(elapsedTime, context);
1285             }
1286             catch (SQLException e) {
1287                 throw new UnableToExecuteStatementException(e, context);
1288             }
1289 
1290             for (StatementCustomizer customizer : customizers) {
1291                 try {
1292                     customizer.afterExecution(stmt, context);
1293                 }
1294                 catch (SQLException e) {
1295                     throw new UnableToExecuteStatementException("Exception thrown in statement customization", e, context);
1296                 }
1297             }
1298 
1299             try {
1300                 rs = stmt.getResultSet();
1301                 return munger.munge(stmt);
1302             }
1303             catch (SQLException e) {
1304                 throw new ResultSetException("Exception thrown while attempting to traverse the result set", e, context);
1305             }
1306         }
1307         finally {
1308             cleanup.cleanup(this, null, rs);
1309         }
1310     }
1311 
1312     void close() throws SQLException
1313     {
1314         this.statementBuilder.close(getConnection(), rewritten.getSql(), stmt);
1315     }
1316 
1317     protected SQLLog getLog()
1318     {
1319         return log;
1320     }
1321 
1322     protected TimingCollector getTimingCollector()
1323     {
1324         return timingCollector;
1325     }
1326 }