1414import org .junit .*;
1515import org .junit .rules .ExpectedException ;
1616import org .postgresql .util .PSQLException ;
17+ import static org .junit .Assert .assertEquals ;
1718
1819public class AlterTableTest extends PLTestBase {
1920 private Connection conn ;
@@ -32,6 +33,8 @@ public class AlterTableTest extends PLTestBase {
3233 private static final String SQL_RENAME_COLUMN =
3334 "ALTER TABLE foo RENAME year to month;" ;
3435
36+ private static final double EPSILON = 1e-6 ;
37+
3538
3639 @ Rule
3740 public ExpectedException thrown = ExpectedException .none ();
@@ -193,4 +196,207 @@ public void test_RenameCol_Concurrent() throws SQLException {
193196// conn2.commit();
194197// }
195198
199+ /**
200+ * Add a column to the table, and do some insertion.
201+ */
202+ @ Test
203+ public void test_AddCol_Basic () throws SQLException {
204+ String sql = "ALTER TABLE foo ADD month int;" ;
205+ conn .createStatement ().execute (sql );
206+ ResultSet rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
207+ rs .next ();
208+ checkRow (rs ,
209+ new String [] {"id" , "year" , "month" },
210+ new int [] {5 , 400 , 0 });
211+ assertNoMoreRows (rs );
212+
213+ String sql2 = "INSERT INTO foo VALUES (6, 500, 1);" ;
214+ conn .createStatement ().execute (sql2 );
215+ rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
216+ rs .next ();
217+ checkRow (rs ,
218+ new String [] {"id" , "year" , "month" },
219+ new int [] {5 , 400 , 0 });
220+ rs .next ();
221+ checkRow (rs ,
222+ new String [] {"id" , "year" , "month" },
223+ new int [] {6 , 500 , 1 });
224+ assertNoMoreRows (rs );
225+ }
226+
227+ /**
228+ * Add a column to a name that already exists, should throw exception
229+ */
230+ @ Test
231+ public void test_AddCol_Exist () throws SQLException {
232+ String sql = "ALTER TABLE foo ADD year int;" ;
233+
234+ // New column already exists
235+ thrown .expect (PSQLException .class );
236+ conn .createStatement ().execute (sql );
237+ }
238+
239+ /**
240+ * Drop a column from the table.
241+ */
242+ @ Test
243+ public void test_DropCol_Basic () throws SQLException {
244+ String sql = "ALTER TABLE foo DROP year;" ;
245+ conn .createStatement ().execute (sql );
246+ ResultSet rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
247+ rs .next ();
248+ checkRow (rs ,
249+ new String [] {"id" },
250+ new int [] {5 });
251+ assertNoMoreRows (rs );
252+
253+ String sql2 = "INSERT INTO foo VALUES (6);" ;
254+ conn .createStatement ().execute (sql2 );
255+ rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
256+ rs .next ();
257+ checkRow (rs ,
258+ new String [] {"id" },
259+ new int [] {5 });
260+ rs .next ();
261+ checkRow (rs ,
262+ new String [] {"id" },
263+ new int [] {6 });
264+ assertNoMoreRows (rs );
265+ }
266+
267+ /**
268+ * Drop a column that does not exists, should throw exception
269+ */
270+ @ Test
271+ public void test_DropCol_NotExist () throws SQLException {
272+ String sql = "ALTER TABLE foo DROP month;" ;
273+
274+ // Old column does not exist
275+ thrown .expect (PSQLException .class );
276+ conn .createStatement ().execute (sql );
277+ }
278+
279+ /**
280+ * Alter column type from int to float and then alter to int again.
281+ */
282+ @ Test
283+ public void test_AlterType_Basic () throws SQLException {
284+ String sql = "ALTER TABLE foo ALTER year TYPE float;" ;
285+ conn .createStatement ().execute (sql );
286+ ResultSet rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
287+ rs .next ();
288+ assertEquals (rs .getInt ("id" ), 5 );
289+ assertEquals (rs .getFloat ("year" ), 400 , EPSILON );
290+ assertNoMoreRows (rs );
291+
292+ String sql2 = "INSERT INTO foo VALUES (6, 3.5);" ;
293+ conn .createStatement ().execute (sql2 );
294+ rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
295+ rs .next ();
296+ assertEquals (rs .getInt ("id" ), 5 );
297+ assertEquals (rs .getFloat ("year" ), 400 , EPSILON );
298+ rs .next ();
299+ assertEquals (rs .getInt ("id" ), 6 );
300+ assertEquals (rs .getFloat ("year" ), 3.5 , EPSILON );
301+ assertNoMoreRows (rs );
302+
303+ String sql3 = "ALTER TABLE foo ALTER year TYPE int;" ;
304+ conn .createStatement ().execute (sql3 );
305+ rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
306+ rs .next ();
307+ assertEquals (rs .getInt ("id" ), 5 );
308+ assertEquals (rs .getInt ("year" ), 400 );
309+ rs .next ();
310+ assertEquals (rs .getInt ("id" ), 6 );
311+ assertEquals (rs .getInt ("year" ), 3 );
312+ assertNoMoreRows (rs );
313+ }
314+
315+ /**
316+ * Alter column type from int to varchar and backwards.
317+ */
318+ @ Test
319+ public void test_AlterType_Varchar () throws SQLException {
320+ String sql = "ALTER TABLE foo ALTER year TYPE varchar;" ;
321+ conn .createStatement ().execute (sql );
322+ ResultSet rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
323+ rs .next ();
324+ assertEquals (rs .getInt ("id" ), 5 );
325+ assertEquals (rs .getString ("year" ), Integer .toString (400 ));
326+ assertNoMoreRows (rs );
327+
328+ String sql2 = "ALTER TABLE foo ALTER year TYPE int;" ;
329+ conn .createStatement ().execute (sql2 );
330+ rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
331+ rs .next ();
332+ assertEquals (rs .getInt ("id" ), 5 );
333+ assertEquals (rs .getInt ("year" ), 400 );
334+ assertNoMoreRows (rs );
335+ }
336+
337+ /**
338+ * Alter type to column that does not exist
339+ */
340+ @ Test
341+ public void test_AlterType_NonExist () throws SQLException {
342+ String sql = "ALTER TABLE foo ALTER a TYPE int;" ;
343+
344+ thrown .expect (PSQLException .class );
345+ conn .createStatement ().execute (sql );
346+ }
347+
348+ /**
349+ * Alter to an unsupported column type
350+ */
351+ @ Test
352+ public void test_AlterType_UnSupported () throws SQLException {
353+ String sql = "ALTER TABLE foo ALTER year TYPE non;" ;
354+ thrown .expect (PSQLException .class );
355+ conn .createStatement ().execute (sql );
356+ }
357+
358+ /**
359+ * Add columns, drop columns, change column type in one sql statement
360+ */
361+ @ Test
362+ public void test_MultiOperation () throws SQLException {
363+ String sql =
364+ "ALTER TABLE foo ADD month INT, DROP year, ALTER id TYPE float;" ;
365+ conn .createStatement ().execute (sql );
366+ ResultSet rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
367+ rs .next ();
368+ assertEquals (rs .getFloat ("id" ), 5 , EPSILON );
369+ assertEquals (rs .getInt ("month" ), 0 );
370+ assertNoMoreRows (rs );
371+
372+ String sql2 = "INSERT INTO foo VALUES (4.5, 3);" ;
373+ conn .createStatement ().execute (sql2 );
374+ rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
375+ rs .next ();
376+ assertEquals (rs .getFloat ("id" ), 5 , EPSILON );
377+ assertEquals (rs .getInt ("month" ), 0 );
378+ rs .next ();
379+ assertEquals (rs .getFloat ("id" ), 4.5 , EPSILON );
380+ assertEquals (rs .getInt ("month" ), 3 );
381+ assertNoMoreRows (rs );
382+ }
383+
384+ /**
385+ * If multiple operations in one statement failed, schema will not change
386+ */
387+ @ Test
388+ public void test_MultiOperationFailed () throws SQLException {
389+ String sql =
390+ "ALTER TABLE foo ADD month int, DROP month, ALTER year TYPE float;" ;
391+
392+ thrown .expect (PSQLException .class );
393+ conn .createStatement ().execute (sql );
394+
395+ ResultSet rs = conn .createStatement ().executeQuery (SQL_SELECT_STAR );
396+ rs .next ();
397+ checkRow (rs ,
398+ new String [] {"id" , "year" },
399+ new int [] {5 , 400 });
400+ assertNoMoreRows (rs );
401+ }
196402}
0 commit comments