1package com.xtremelabs.robolectric.shadows;
2
3import android.database.sqlite.SQLiteDatabase;
4import android.database.sqlite.SQLiteProgram;
5import com.xtremelabs.robolectric.Robolectric;
6import com.xtremelabs.robolectric.internal.Implementation;
7import com.xtremelabs.robolectric.internal.Implements;
8import com.xtremelabs.robolectric.internal.RealObject;
9
10import java.sql.Connection;
11import java.sql.PreparedStatement;
12import java.sql.SQLException;
13import java.sql.Statement;
14
15@Implements(SQLiteProgram.class)
16public abstract class ShadowSQLiteProgram {
17	@RealObject	SQLiteProgram realSQLiteProgram;
18	protected SQLiteDatabase mDatabase;
19	Connection connection;
20	PreparedStatement actualDBstatement;
21	public void init(SQLiteDatabase db, String sql) {
22	 mDatabase = db;
23	 connection = Robolectric.shadowOf(db).getConnection();
24
25	 try {
26			actualDBstatement = connection.prepareStatement(sql,
27					Statement.RETURN_GENERATED_KEYS);
28		} catch (SQLException e) {
29			throw new RuntimeException(e);
30		}
31	}
32
33    /**
34     * Bind a NULL value to this statement. The value remains bound until
35     * {@link #clearBindings} is called.
36     *
37     * @param index The 1-based index to the parameter to bind null to
38     */
39	@Implementation
40    public void bindNull(int index) {
41		checkDatabaseIsOpen();
42		try {
43			// SQLite ignores typecode
44			// typecode is also ignored in H2 when using the two parameter setNUll()
45			actualDBstatement.setNull(index,java.sql.Types.NULL);
46		} catch (SQLException e) {
47			throw new RuntimeException(e);
48		}
49    }
50
51    /**
52     * Bind a long value to this statement. The value remains bound until
53     * {@link #clearBindings} is called.
54     *
55     * @param index The 1-based index to the parameter to bind
56     * @param value The value to bind
57     */
58    @Implementation
59    public void bindLong(int index, long value) {
60    	checkDatabaseIsOpen();
61
62    	try {
63			actualDBstatement.setLong(index,value);
64		} catch (SQLException e) {
65			throw new RuntimeException(e);
66		}
67    }
68
69    private void checkDatabaseIsOpen() {
70    	if (!mDatabase.isOpen()) {
71            throw new IllegalStateException("database " + mDatabase.getPath() + " already closed");
72        }
73    }
74
75    public PreparedStatement getStatement() {
76    	return actualDBstatement;
77    }
78
79    /**
80     * Bind a double value to this statement. The value remains bound until
81     * {@link #clearBindings} is called.
82     *
83     * @param index The 1-based index to the parameter to bind
84     * @param value The value to bind
85     */
86    @Implementation
87    public void bindDouble(int index, double value) {
88    	checkDatabaseIsOpen();
89    	try {
90			actualDBstatement.setDouble(index,value);
91		} catch (SQLException e) {
92			throw new RuntimeException(e);
93		}
94    }
95
96    /**
97     * Bind a String value to this statement. The value remains bound until
98     * {@link #clearBindings} is called.
99     *
100     * @param index The 1-based index to the parameter to bind
101     * @param value The value to bind
102     */
103    @Implementation
104    public void bindString(int index, String value) {
105        if (value == null) {
106            throw new IllegalArgumentException("the bind value at index " + index + " is null");
107        }
108        checkDatabaseIsOpen();
109        try {
110			actualDBstatement.setString(index,value);
111		} catch (SQLException e) {
112			throw new RuntimeException(e);
113		}
114    }
115
116    /**
117     * Bind a byte array value to this statement. The value remains bound until
118     * {@link #clearBindings} is called.
119     *
120     * @param index The 1-based index to the parameter to bind
121     * @param value The value to bind
122     */
123    @Implementation
124    public void bindBlob(int index, byte[] value) {
125        if (value == null) {
126            throw new IllegalArgumentException("the bind value at index " + index + " is null");
127        }
128        checkDatabaseIsOpen();
129        try {
130			actualDBstatement.setBytes(index,value);
131		} catch (SQLException e) {
132			throw new RuntimeException(e);
133		}
134
135    }
136
137    /**
138     * Clears all existing bindings. Unset bindings are treated as NULL.
139     */
140    @Implementation
141    public void clearBindings() {
142    	checkDatabaseIsOpen();
143
144    	try {
145			actualDBstatement.clearParameters();
146		} catch (SQLException e) {
147			throw new RuntimeException(e);
148		}
149    }
150}
151