Merge pull request #2 from eatkins/master

add toBlob for SqlBlob objects
fix memory leak in bind_blob

In the bind_blob method, the arguments that were passed into
ReleaseByteArrayElements made absolutely no sense, but caused neither a
compiler error nor a runtime error. They did, however, cause a memory
leak since they native byte arrays that were being heap allocated were
never freed.
fix blob type

The previous implementation broke the equals operator for SqlValue case
classes. Arrays get compared by object while Seqs get compared
elementwise. Before this change, the following could occur

val x = SqlBlob("foo".getBytes)
val y = SqlBlob("foo".getBytes)
x == y -> false

Now since each byte in the sequence gets compared, the x == y comparison
returns true (scala implicitly converts Array[Byte] to Seq[Byte] in the
SqlBlob constructor).

Since toBlob now returns a Seq, rather than an Array[Byte],
it may be necessary to make replacements like

val x = row(0).toBlob =>
val x = row(0).toBlob.toArray

but generally only if one needs to call a Java function that takes a
byte[] argument.
SqliteDb.scala -- fix spacing in error message
Sqlite3C.cc: bind blobs as text

It turns out that using sqlite3_bind_blob to insert a column into an
Sqlite database causes the Sqlite vdb to treat the column as a blob
column. This is generally not desirable because it won't properly handle
string comparisons of text columns. As an example, the following code
won't work as expected:

scala> val db = new SqliteDb(":memory")
db: org.srhea.scalaqlite.SqliteDb = org.srhea.scalaqlite.SqliteDb@126828b
scala> db.execute("CREATE TEMP TABLE foo (i INT, t TEXT)")
scala> db.prepare("INSERT INTO foo (i, t) VALUES (0, ?1)") { stmt =>
         stmt.execute(SqlBlob("bar".map(_.toByte)))
       }
scala> db.foreachRow("SELECT * FROM foo")(println)
Vector(0, bar)
scala> db.foreachRow("SELECT COUNT(*) FROM foo WHERE t = 'bar'")(println)
Vector(0)

With libscalaqlite built with this change, the last query returns
Vector(1) as expected.

Note that it is still possible to get the SqliteDb to interpret the
result of an insert as a blob. It now just requires that a blob literal
is used:
db.execute("INSERT INTO foo (i, t) VALUES (1, X'626172')")
db.foreachRow("SELECT * FROM foo")(println)
Vector(0, bar)
Vector(1, bar)
db.foreachRow("SELECT COUNT(*) FROM foo WHERE t = 'bar'")(println)
Vector(1)
SqliteDbSpec.scala: add test for binding SqlBlobs

This test makes sure that a blob column that is inserted as a bound
parameter is interpreted by Sqlite as a text column if it is composed of
printable characters.
Merge pull request #7 from eatkins/blob

Looks good!
prepare: throw exception instead of assertion

There are cases where you may want to be able to recover from a failure
to prepare a statement. As an example, the prepare may fail because it
uses a foreign data table that Sqlite is currently unaware of. By
throwing an exception, it is possible to recover from the failure,
update the db and retry.

Reviewed-by: srhea@meraki.com
Merge pull request #8 from eatkins/exception

prepare: throw exception instead of assertion
Separate TEXT and BLOB types

In most cases it is perfectly fine to interchange use BLOB columns to
represent TEXT columns. Occasionally, however, you will get strange
behavior when comparing BLOB and TEXT columns. The reason that there was
a single type of string column was for compatibility with a foreign
table that was added as a virtual table to Sqlite that did not
distinguish between string types. It is a real headache to debug the
subtle errors that can crop up when you need to compare the different
types of string columns, so we are making them distinct in Scalaqlite
once again.

With this change, queries that return columns of TEXT type will now
return a SqlText object, not a SqlBlob as before. This usually will be a
functional no op because the toString method of SqlBlob should return
the same string as the toString method of the SqlText object that is
instantiated with a ByteArray.
SqliteDb: add parameters to db methods

It is convenient to run SQL queries with formal parameters even for
one-off queries where you don't want to store the prepared statement.
For example, if you have the SqlValue
val foobar = SqlText("foobar"),
it is more convenient to run
db.foreachRow("SELECT * FROM foo WHERE bar = ?1, foobar)(println)
instead of either
db.foreachRow("SELECT * FROM foo WHERE bar = " + foobar.toString)(println)
or
db.prepare("SELECT * FROM foo WHERE bar = ?1")(_.foreachRow(foobar)(println))
and the string concatenation approach is also vulnerable to SQL
injection.

This is a functional no op for all existing calls to these three
methods.

Bonus: remove some unnecessary dummy variables and curly braces
SqliteDb.scala: add mapRows and getRows methods

One often wants to run a query and cache the results in memory. These
two methods should make this a bit more straightforward. The mapRows
and getRows methods are just syntactic sugar to reduce the indentation
by one level whenever one wants a set of all the rows returned by a
query or if one wants to apply a mapping to these rows and cache the
results.

Bonus: I removed the ListBuffer import because it isn't used anywhere.
SqliteDbSpec.scala: replace type affinity test

There was an existing test that checked that BLOB columns were bound as
TEXT that was an artifact of when we only had a single string type for
both BLOBs and TEXTs. That test started failing with the change to bind
BLOBs as BLOBs and to return TEXT columns as TEXT. I've replaced that
test with a new test that verifies that a number of BLOB/BLOB,
BLOB/TEXT and TEXT/TEXT comparisons work as expected. It tests
comparisons between sets of bound parameters, comparisons between bound
parameters and constants and comparisons between db columns.
Merge pull request #9 from eatkins/separateblobtext

Separateblobtext
add sqlite3_changes native function

This function can be used to get the number of rows inserted or updated
by the last executed statement.
Merge pull request #10 from eatkins/changes

add sqlite3_changes native function
Change SqlText bind method

We discovered recently that Scalaqlite didn't correctly bind UTF-8
strings that contained non-ascii characters, e.g. Chinese characters.
One fix would be to change the line in
Java_org_srhea_scalaqlite_Sqlite3C_bind_1text from

jint len = env->GetStringLength(jvalue);

to

jint len = env->GetStringUTFLength(jvalue);

but, from the documenation, getStringUTFLength returns the length in
bytes of the modified UTF-8 representation of a string. It feels cleaner
to just work directly with the byte array, hence this change.