1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 package complex.connectivity;
23 
24 import com.sun.star.beans.XPropertySet;
25 import com.sun.star.lang.XMultiServiceFactory;
26 import com.sun.star.sdb.CommandType;
27 import com.sun.star.sdbc.SQLException;
28 import com.sun.star.util.Date;
29 import complexlib.ComplexTestCase;
30 import connectivity.tools.CsvDatabase;
31 import connectivity.tools.RowSet;
32 import java.io.File;
33 import java.io.FileOutputStream;
34 import java.io.PrintWriter;
35 import java.util.ArrayList;
36 import java.util.List;
37 
38 public class FlatFileAccess extends ComplexTestCase
39 {
FlatFileAccess()40     public FlatFileAccess()
41     {
42         super();
43     }
44 
45     @Override
getTestMethodNames()46     public String[] getTestMethodNames()
47     {
48         return new String[] {
49             "testBasicAccess",
50             "testCalendarFunctions",
51             "testSortingByFunction"
52         };
53     }
54 
55     @Override
getTestObjectName()56     public String getTestObjectName()
57     {
58         return "FlatFileAccess";
59     }
60 
before()61     public void before() throws Exception
62     {
63         m_database = new CsvDatabase( (XMultiServiceFactory)param.getMSF() );
64 
65         // proper settings
66         final XPropertySet dataSourceSettings = m_database.getDataSource().geSettings();
67         dataSourceSettings.setPropertyValue( "Extension", "csv" );
68         dataSourceSettings.setPropertyValue( "HeaderLine", Boolean.TRUE );
69         dataSourceSettings.setPropertyValue( "FieldDelimiter", " " );
70         m_database.store();
71 
72         // write the table(s) for our test
73         final String tableLocation = m_database.getTableFileLocation().getAbsolutePath();
74         final PrintWriter tableWriter = new PrintWriter( new FileOutputStream( tableLocation + File.separatorChar + "dates.csv", false ) );
75         tableWriter.println( "ID date" );
76         tableWriter.println( "1 2013-01-01" );
77         tableWriter.println( "2 2012-02-02" );
78         tableWriter.println( "3 2011-03-03" );
79         tableWriter.close();
80     }
81 
after()82     public void after()
83     {
84     }
85 
86     private class EqualityDate extends Date
87     {
EqualityDate( short i_day, short i_month, short i_year )88         EqualityDate( short i_day, short i_month, short i_year )
89         {
90             super( i_day, i_month, i_year );
91         }
92 
EqualityDate( Date i_date )93         EqualityDate( Date i_date )
94         {
95             super( i_date.Day, i_date.Month, i_date.Year );
96         }
97 
98         @Override
equals( Object i_compare )99         public boolean equals( Object i_compare )
100         {
101             if ( !( i_compare instanceof Date ) )
102                 return false;
103             return  Day   == ((Date)i_compare).Day
104                 &&  Month == ((Date)i_compare).Month
105                 &&  Year  == ((Date)i_compare).Year;
106         }
107     }
108 
109     /**
110      * ensures simple SELECTs from our table(s) work, and deliver the expected results
111      */
testBasicAccess()112     public void testBasicAccess()
113     {
114         testRowSetResults(
115             "SELECT * FROM \"dates\"",
116             new RowSetIntGetter(1),
117             new Integer[] { 1, 2, 3 },
118             "simple select", "wrong IDs"
119         );
120 
121         testRowSetResults(
122             "SELECT * FROM \"dates\"",
123             new RowSetDateGetter( 2 ),
124             new EqualityDate[] { new EqualityDate( (short)1, (short)1, (short)2013 ),
125                                  new EqualityDate( (short)2, (short)2, (short)2012 ),
126                                  new EqualityDate( (short)3, (short)3, (short)2011 )
127             },
128             "simple select", "wrong dates"
129         );
130         testRowSetResults(
131             "SELECT \"date\", \"ID\" FROM \"dates\" ORDER BY \"ID\" DESC",
132             new RowSetIntGetter( 2 ),
133             new Integer[] { 3, 2, 1 },
134             "explicit column selection, sorted by IDs", "wrong IDs"
135         );
136         testRowSetResults(
137             "SELECT * FROM \"dates\" ORDER BY \"date\"",
138             new RowSetIntGetter( 1 ),
139             new Integer[] { 3, 2, 1 },
140             "sorted by date", "wrong IDs"
141         );
142     }
143 
144     /**
145      * ensures the basic functionality for selecting calendar functions from a CSV table - this is a prerequisite for
146      * later tests.
147      */
testCalendarFunctions()148     public void testCalendarFunctions()
149     {
150         // simple check for proper results of the calendar functions (DATE/MONTH)
151         // The * at the first position is crucial here - there was code which wrongly calculated
152         // column positions of function columns when * was present in the statement
153         testRowSetResults(
154             "SELECT \"dates\".*, YEAR( \"date\" ) FROM \"dates\"",
155             new RowSetIntGetter( 3 ),
156             new Integer[] { 2013, 2012, 2011 },
157             "YEAR function", "wrong calculated years"
158         );
159         testRowSetResults(
160             "SELECT \"dates\".*, MONTH( \"date\" ) FROM \"dates\"",
161             new RowSetIntGetter( 3 ),
162             new Integer[] { 1, 2, 3 },
163             "MONTH function", "wrong calculated months"
164         );
165     }
166 
167     /**
168      * ensures that sorting by a function column works
169      */
testSortingByFunction()170     public void testSortingByFunction()
171     {
172         // most simple case: select a function, and sort by it
173         testRowSetResults(
174             "SELECT YEAR( \"date\" ) AS \"year\" FROM \"dates\" ORDER BY \"year\"",
175             new RowSetIntGetter(1),
176             new Integer[] { 2011, 2012, 2013 },
177             "single YEAR selection, sorted by years", "wrong calculated years"
178         );
179         // somewhat more "difficult" (this used to crash): Select all columns, plus a function, so the calculated
180         // column has a position greater than column count
181         testRowSetResults(
182             "SELECT \"dates\".*, YEAR( \"date\" ) AS \"year\" FROM \"dates\" ORDER BY \"year\" DESC",
183             new RowSetIntGetter(3),
184             new Integer[] { 2013, 2012, 2011 },
185             "extended YEAR selection, sorted by years", "wrong calculated years"
186         );
187     }
188 
189     private interface RowSetValueGetter
190     {
getValue( final RowSet i_rowSet )191         public Object getValue( final RowSet i_rowSet ) throws SQLException;
192     }
193 
194     private abstract class RowSetColumnValueGetter implements RowSetValueGetter
195     {
RowSetColumnValueGetter( final int i_columnIndex )196         RowSetColumnValueGetter( final int i_columnIndex )
197         {
198             m_columnIndex = i_columnIndex;
199         }
200 
201         protected final int m_columnIndex;
202     }
203 
204     private class RowSetIntGetter extends RowSetColumnValueGetter
205     {
RowSetIntGetter( final int i_columnIndex )206         RowSetIntGetter( final int i_columnIndex )
207         {
208             super( i_columnIndex );
209         }
210 
getValue( final RowSet i_rowSet )211         public Object getValue( final RowSet i_rowSet ) throws SQLException
212         {
213             return i_rowSet.getInt( m_columnIndex );
214         }
215     }
216 
217     private class RowSetDateGetter extends RowSetColumnValueGetter
218     {
RowSetDateGetter( final int i_columnIndex )219         RowSetDateGetter( final int i_columnIndex )
220         {
221             super( i_columnIndex );
222         }
223 
getValue( final RowSet i_rowSet )224         public Object getValue( final RowSet i_rowSet ) throws SQLException
225         {
226             return i_rowSet.getDate( m_columnIndex );
227         }
228     }
229 
testRowSetResults( String i_command, RowSetValueGetter i_getter, T[] i_expectedValues, String i_context, String i_failureDesc )230     private <T> void testRowSetResults( String i_command, RowSetValueGetter i_getter,
231         T[] i_expectedValues, String i_context, String i_failureDesc )
232     {
233         RowSet rowSet = null;
234         try
235         {
236             rowSet = m_database.createRowSet( CommandType.COMMAND, i_command );
237             rowSet.execute();
238 
239             List< T > values = new ArrayList< T >();
240             while ( rowSet.next() )
241             {
242                 values.add( (T)i_getter.getValue( rowSet ) );
243             }
244             assureEquals( i_context + ": " + i_failureDesc, i_expectedValues, values.toArray(), true );
245         }
246         catch( final SQLException e )
247         {
248             failed( i_context + ": caught an exception: " + e.toString(), false );
249         }
250         finally
251         {
252             if ( rowSet != null )
253                 rowSet.dispose();
254         }
255     }
256 
257     private CsvDatabase m_database = null;
258 }
259