2 Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 package com.mysql.clusterj.jpatest;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.nio.charset.Charset;
23 import java.nio.charset.CharsetEncoder;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
29 import com.mysql.clusterj.jpatest.model.ClobTypes;
33 drop table if exists charsetlatin1;
34 create table charsetlatin1 (
35 id int not null primary key,
36 smallcolumn varchar(200),
37 mediumcolumn varchar(500),
38 largecolumn text(10000)
40 ) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
43 public class ClobTest extends AbstractJPABaseTest {
45 /** The size of the clob column is 2 raised to the power i. */
46 private static final int NUMBER_TO_INSERT = 16;
48 /** The clob instances for testing. */
49 protected List<ClobTypes> clobs = new ArrayList<ClobTypes>();
51 /** Characters that can be encoded using latin1 character set */
52 private char[] chars = getChars(Charset.forName("latin1"));
54 /** Subclasses can override this method to get debugging info printed to System.out */
55 protected boolean getDebug() {
59 /** Create a char array with the first 128 encodable characters.
61 * @return the char array
63 private char[] getChars(Charset charset) {
64 CharsetEncoder encoder = charset.newEncoder();
65 char[] result = new char[128];
66 char current = (char)0;
67 for (int i = 0; i < result.length; ++i) {
68 current = nextChar(encoder, current);
74 /** Get the next char greater than the current char that is encodable
79 char nextChar(CharsetEncoder encoder, char current) {
81 if (encoder.canEncode(current)) {
84 return nextChar(encoder, current);
89 createClobInstances(NUMBER_TO_INSERT);
96 protected void remove() {
97 removeAll(ClobTypes.class);
100 protected void insert() {
102 tx = em.getTransaction();
107 for (int i = 0; i < NUMBER_TO_INSERT; ++i) {
108 // must be done with an active transaction
109 em.persist(clobs.get(i));
115 protected void update() {
119 for (int i = 1; i < NUMBER_TO_INSERT; ++i) {
120 // must be done with an active transaction
121 ClobTypes e = em.find(ClobTypes.class, i);
122 // see if it is the right one
123 int actualId = e.getId();
125 error("Expected ClobTypes.id " + i + " but got " + actualId);
127 String string = e.getLarge10000();
128 // make sure all fields were fetched properly
129 checkString("before update", string, i, false);
131 int position = getClobSizeFor(i)/2;
132 // only update if the length is correct
133 if (string.length() == (position * 2)) {
134 StringBuilder sb = new StringBuilder(string);
135 // modify the byte in the middle of the blob
136 sb.replace(position, position + 1, "!");
137 string = sb.toString();
138 checkString("after update", string, i, true);
140 e.setLarge10000(string);
145 for (int i = 1; i < NUMBER_TO_INSERT; ++i) {
146 // must be done with an active transaction
147 ClobTypes e = em.find(ClobTypes.class, i);
148 // see if it is the right one
149 int actualId = e.getId();
151 error("Expected ClobTypes.id " + i + " but got " + actualId);
153 String string = e.getLarge10000();
155 // check to see that the blob field has the right data
156 checkString("after commit", string, i, true);
161 protected void createClobInstances(int number) {
162 for (int i = 0; i < number; ++i) {
163 ClobTypes instance = new ClobTypes();
165 int length = getClobSizeFor(i);
166 instance.setLarge10000(getString(length));
167 // blob streams are not yet supported
168 // instance.setBlobstream(getBlobStream(length));
173 /** Create a new String of the specified size containing a pattern
174 * of characters in which each character is the value of encodable characters
175 * at position modulo 128. This pattern is easy to test.
176 * @param size the length of the returned string
177 * @return the string filled with the pattern
179 protected String getString(int size) {
180 char[] result = new char[size];
181 for (int i = 0; i < size; ++i) {
182 result[i] = chars [i%128];
184 return new String(result);
187 /** Check the string to be sure it matches the pattern in both size
190 * @param string the string to check
191 * @param number the expected length of the string
192 * @param updated whether the string is original or updated
194 protected void checkString(String where, String string, int number, boolean updated) {
195 if (getDebug()) dumpClob(where, string);
196 int expectedSize = getClobSizeFor(number);
197 int actualSize = string.length();
198 if (expectedSize != actualSize) {
200 + " wrong size of string; "
201 + "expected: " + expectedSize
202 + " actual: " + actualSize);
204 for (int i = 0; i < actualSize; ++i) {
206 int position = expectedSize/2;
207 if (updated && (i == position)) {
210 expected = chars[i%128];
212 char actual = string.charAt(i);
213 if (expected != actual) {
214 error("In " + where + " for size: " + actualSize
215 + " mismatch in string at position " + i
216 + " expected: " + (int)expected
217 + " actual: " + (int)actual);
223 protected InputStream getClobStream(final int i) {
224 return new InputStream() {
228 public int read() throws IOException {
232 return counter++ %256;
238 protected void dumpClob(String where, String string) {
239 System.out.println("In " + where + " dumpClob of size: " + string.length() + " " + Arrays.toString(string.getBytes()));
242 protected int getClobSizeFor(int i) {
243 int length = (int) Math.pow(2, i);