view src/kryshen/tema/functions/Database.java @ 2:6c41a0b43e58

Tema 0.3 (imported from CVS).
author Mikhail Kryshen <mikhail@kryshen.net>
date Tue, 19 Feb 2008 20:32:17 +0300
parents
children e9d13c7ffeb1
line source
1 /*
2 * Copyright 2006-2008 Mikhail Kryshen
3 *
4 * This file is part of Tema.
5 *
6 * Tema is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * Tema is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the
17 * GNU Lesser General Public License along with Tema.
18 * If not, see <http://www.gnu.org/licenses/>.
19 *
20 * $Id: Database.java,v 1.12 2008/02/17 23:58:01 mikhail Exp $
21 */
23 package kryshen.tema.functions;
25 import java.io.IOException;
26 import java.io.Reader;
27 import java.io.StringReader;
28 import java.io.Writer;
29 import java.sql.Connection;
30 import java.sql.DriverManager;
31 import java.sql.PreparedStatement;
32 import java.sql.ResultSet;
33 import java.sql.ResultSetMetaData;
34 import java.sql.SQLException;
35 import java.util.HashMap;
36 import java.util.List;
37 import kryshen.tema.Context;
38 import kryshen.tema.Function;
39 import kryshen.tema.FunctionDataParser;
40 import kryshen.tema.TemplateException;
41 import kryshen.tema.TemplateParser;
42 import kryshen.tema.io.TemplateReader;
44 /**
45 * Data access functions.
46 *
47 * @author Mikhail Kryshen
48 */
49 public class Database {
50 /* db_connect:connection_name resource */
51 public static final Function CONNECT = new Function() {
52 public int invoke(FunctionDataParser fdp, Writer out)
53 throws IOException, TemplateException {
55 String arg0 = fdp.getNextArg();
56 String data = fdp.getData();
58 Connection connection;
60 try {
61 connection = DriverManager.getConnection(data);
62 } catch (SQLException e) {
63 throw new TemplateException
64 (e.getMessage(), e, fdp.getTemplateReader());
65 }
67 fdp.getContext().set(arg0, connection);
69 out.write(arg0);
70 return 1;
71 }
72 };
74 /* db_prepare:qury_name connection sql_statement */
75 public static final Function PREPARE = new Function() {
76 public int invoke(FunctionDataParser fdp, Writer out)
77 throws IOException, TemplateException {
79 String arg0 = fdp.getNextArg(); // resulting variable
80 String arg1 = fdp.getNextArg(); // connection
81 String data = fdp.getData(); // statement
83 Connection connection;
84 PreparedStatement statement;
86 try {
87 connection = (Connection) fdp.getContext().get(arg1);
88 statement = connection.prepareStatement(data);
89 } catch (ClassCastException e) {
90 throw new TemplateException
91 (e.getMessage(), e, fdp.getTemplateReader());
92 } catch (SQLException e) {
93 throw new TemplateException
94 (e.getMessage(), e, fdp.getTemplateReader());
95 }
97 fdp.getContext().set(arg0, statement);
99 out.write(arg0);
100 return 1;
101 }
102 };
104 /* db_query:sql_query template arg1 arg2 ... argN */
105 public static final Function QUERY = new Function() {
106 public int invoke(FunctionDataParser fdp, Writer out)
107 throws IOException, TemplateException {
109 String query = fdp.getNextArg();
110 String template = fdp.getNextArg();
111 List<String> args = fdp.getArgs();
113 TemplateParser tp = fdp.getTemplateParser();
114 Context context = fdp.getContext();
116 try {
117 PreparedStatement statement =
118 (PreparedStatement) context.get(query);
119 return query(template, fdp.getTemplateReader(),
120 statement, args, tp, out);
121 } catch (ClassCastException e) {
122 throw new TemplateException
123 (e.getMessage(), e, fdp.getTemplateReader());
124 } catch (SQLException e) {
125 throw new TemplateException
126 (e.getMessage(), e, fdp.getTemplateReader());
127 }
128 }
129 };
131 /**
132 * Process database query.
133 *
134 * @param template template to fill with data.
135 * @param parentReader parent TemplateReader.
136 * @param ps query statement to execute.
137 * @param args list of query parameters.
138 * @param superParser invoking object.
139 * @param out Writer to output processed data.
140 *
141 * @return number of processed rows in query result.
142 */
143 private static int query(String template,
144 TemplateReader parentReader,
145 PreparedStatement ps,
146 List<String> args,
147 TemplateParser superParser,
148 Writer out)
149 throws IOException, SQLException, TemplateException {
151 int i = 1;
153 for (String arg : args) {
154 ps.setString(i++, arg);
155 }
157 ResultSet resultSet = ps.executeQuery();
158 ResultSetMetaData metaData = resultSet.getMetaData();
159 int columnCount = metaData.getColumnCount();
161 String[] names = new String[columnCount];
163 for (int j = 0; j < columnCount; j++) {
164 names[j] = metaData.getColumnName(j + 1);
165 }
167 final TemplateParser p = new TemplateParser(superParser);
168 final HashMap<String, Object> fields = new HashMap<String, Object>();
170 p.getContext().set("db", new Function() {
171 public int invoke(FunctionDataParser fdp,
172 final Writer out)
173 throws IOException, TemplateException {
175 String name = fdp.getData();
176 Object value = fields.get(name);
178 return p.parseValue(value, out);
179 }
180 });
182 Reader input = new StringReader(template);
184 for (i = 1; resultSet.next(); i++) {
186 for (int j = 0; j < columnCount; j++) {
187 Object value = resultSet.getObject(j + 1);
188 if (resultSet.wasNull()) value = null;
190 fields.put(names[j], value);
191 }
193 p.getContext().set("db_row", i);
195 TemplateReader tr = new TemplateReader(input, parentReader);
197 p.parse(tr, out);
199 input.reset();
200 fields.clear();
201 }
203 resultSet.close();
204 input.close();
205 ps.clearParameters();
206 return i - 1;
207 }
208 }