view src/kryshen/tema/functions/Database.java @ 15:e9d13c7ffeb1

Update header comment.
author Mikhail Kryshen <mikhail@kryshen.net>
date Tue, 24 Mar 2009 18:51:47 +0300
parents 6c41a0b43e58
children
line source
1 /*
2 * Copyright 2006-2009 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 */
21 package kryshen.tema.functions;
23 import java.io.IOException;
24 import java.io.Reader;
25 import java.io.StringReader;
26 import java.io.Writer;
27 import java.sql.Connection;
28 import java.sql.DriverManager;
29 import java.sql.PreparedStatement;
30 import java.sql.ResultSet;
31 import java.sql.ResultSetMetaData;
32 import java.sql.SQLException;
33 import java.util.HashMap;
34 import java.util.List;
35 import kryshen.tema.Context;
36 import kryshen.tema.Function;
37 import kryshen.tema.FunctionDataParser;
38 import kryshen.tema.TemplateException;
39 import kryshen.tema.TemplateParser;
40 import kryshen.tema.io.TemplateReader;
42 /**
43 * Data access functions.
44 *
45 * @author Mikhail Kryshen
46 */
47 public class Database {
48 /* db_connect:connection_name resource */
49 public static final Function CONNECT = new Function() {
50 public int invoke(FunctionDataParser fdp, Writer out)
51 throws IOException, TemplateException {
53 String arg0 = fdp.getNextArg();
54 String data = fdp.getData();
56 Connection connection;
58 try {
59 connection = DriverManager.getConnection(data);
60 } catch (SQLException e) {
61 throw new TemplateException
62 (e.getMessage(), e, fdp.getTemplateReader());
63 }
65 fdp.getContext().set(arg0, connection);
67 out.write(arg0);
68 return 1;
69 }
70 };
72 /* db_prepare:qury_name connection sql_statement */
73 public static final Function PREPARE = new Function() {
74 public int invoke(FunctionDataParser fdp, Writer out)
75 throws IOException, TemplateException {
77 String arg0 = fdp.getNextArg(); // resulting variable
78 String arg1 = fdp.getNextArg(); // connection
79 String data = fdp.getData(); // statement
81 Connection connection;
82 PreparedStatement statement;
84 try {
85 connection = (Connection) fdp.getContext().get(arg1);
86 statement = connection.prepareStatement(data);
87 } catch (ClassCastException e) {
88 throw new TemplateException
89 (e.getMessage(), e, fdp.getTemplateReader());
90 } catch (SQLException e) {
91 throw new TemplateException
92 (e.getMessage(), e, fdp.getTemplateReader());
93 }
95 fdp.getContext().set(arg0, statement);
97 out.write(arg0);
98 return 1;
99 }
100 };
102 /* db_query:sql_query template arg1 arg2 ... argN */
103 public static final Function QUERY = new Function() {
104 public int invoke(FunctionDataParser fdp, Writer out)
105 throws IOException, TemplateException {
107 String query = fdp.getNextArg();
108 String template = fdp.getNextArg();
109 List<String> args = fdp.getArgs();
111 TemplateParser tp = fdp.getTemplateParser();
112 Context context = fdp.getContext();
114 try {
115 PreparedStatement statement =
116 (PreparedStatement) context.get(query);
117 return query(template, fdp.getTemplateReader(),
118 statement, args, tp, out);
119 } catch (ClassCastException e) {
120 throw new TemplateException
121 (e.getMessage(), e, fdp.getTemplateReader());
122 } catch (SQLException e) {
123 throw new TemplateException
124 (e.getMessage(), e, fdp.getTemplateReader());
125 }
126 }
127 };
129 /**
130 * Process database query.
131 *
132 * @param template template to fill with data.
133 * @param parentReader parent TemplateReader.
134 * @param ps query statement to execute.
135 * @param args list of query parameters.
136 * @param superParser invoking object.
137 * @param out Writer to output processed data.
138 *
139 * @return number of processed rows in query result.
140 */
141 private static int query(String template,
142 TemplateReader parentReader,
143 PreparedStatement ps,
144 List<String> args,
145 TemplateParser superParser,
146 Writer out)
147 throws IOException, SQLException, TemplateException {
149 int i = 1;
151 for (String arg : args) {
152 ps.setString(i++, arg);
153 }
155 ResultSet resultSet = ps.executeQuery();
156 ResultSetMetaData metaData = resultSet.getMetaData();
157 int columnCount = metaData.getColumnCount();
159 String[] names = new String[columnCount];
161 for (int j = 0; j < columnCount; j++) {
162 names[j] = metaData.getColumnName(j + 1);
163 }
165 final TemplateParser p = new TemplateParser(superParser);
166 final HashMap<String, Object> fields = new HashMap<String, Object>();
168 p.getContext().set("db", new Function() {
169 public int invoke(FunctionDataParser fdp,
170 final Writer out)
171 throws IOException, TemplateException {
173 String name = fdp.getData();
174 Object value = fields.get(name);
176 return p.parseValue(value, out);
177 }
178 });
180 Reader input = new StringReader(template);
182 for (i = 1; resultSet.next(); i++) {
184 for (int j = 0; j < columnCount; j++) {
185 Object value = resultSet.getObject(j + 1);
186 if (resultSet.wasNull()) value = null;
188 fields.put(names[j], value);
189 }
191 p.getContext().set("db_row", i);
193 TemplateReader tr = new TemplateReader(input, parentReader);
195 p.parse(tr, out);
197 input.reset();
198 fields.clear();
199 }
201 resultSet.close();
202 input.close();
203 ps.clearParameters();
204 return i - 1;
205 }
206 }