6c648dd642
This is actually a fully functional build except: * All internal shared libraries are static linked to make sure there is no interference with ports (and to reduce build time). * It does not have the python/perl/etc plugin or API support. * By default, it installs as "svnlite" rather than "svn". * If WITH_SVN added in make.conf, you get "svn". * If WITHOUT_SVNLITE is in make.conf, this is completely disabled. To be absolutely clear, this is not intended for any use other than checking out freebsd source and committing, like we once did with cvs. It should be usable for small scale local repositories that don't need the python/perl plugin architecture.
408 lines
14 KiB
C
408 lines
14 KiB
C
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "apu.h"
|
|
#include "apr_pools.h"
|
|
#include "apr_dbd.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#define TEST(msg,func) \
|
|
printf("======== %s ========\n", msg); \
|
|
rv = func(pool, sql, driver); \
|
|
if (rv != 0) { \
|
|
printf("Error in %s: rc=%d\n\n", msg, rv); \
|
|
} \
|
|
else { \
|
|
printf("%s test successful\n\n", msg); \
|
|
} \
|
|
fflush(stdout);
|
|
|
|
static int create_table(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
int nrows;
|
|
const char *statement = "CREATE TABLE apr_dbd_test ("
|
|
"col1 varchar(40) not null,"
|
|
"col2 varchar(40),"
|
|
"col3 integer)" ;
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
return rv;
|
|
}
|
|
static int drop_table(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
int nrows;
|
|
const char *statement = "DROP TABLE apr_dbd_test" ;
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
return rv;
|
|
}
|
|
static int insert_rows(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int i;
|
|
int rv = 0;
|
|
int nrows;
|
|
int nerrors = 0;
|
|
const char *statement =
|
|
"INSERT into apr_dbd_test (col1) values ('foo');"
|
|
"INSERT into apr_dbd_test values ('wibble', 'other', 5);"
|
|
"INSERT into apr_dbd_test values ('wibble', 'nothing', 5);"
|
|
"INSERT into apr_dbd_test values ('qwerty', 'foo', 0);"
|
|
"INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);"
|
|
;
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
if (rv) {
|
|
const char* stmt[] = {
|
|
"INSERT into apr_dbd_test (col1) values ('foo');",
|
|
"INSERT into apr_dbd_test values ('wibble', 'other', 5);",
|
|
"INSERT into apr_dbd_test values ('wibble', 'nothing', 5);",
|
|
"INSERT into apr_dbd_test values ('qwerty', 'foo', 0);",
|
|
"INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);",
|
|
NULL
|
|
};
|
|
printf("Compound insert failed; trying statements one-by-one\n") ;
|
|
for (i=0; stmt[i] != NULL; ++i) {
|
|
statement = stmt[i];
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
if (rv) {
|
|
nerrors++;
|
|
}
|
|
}
|
|
if (nerrors) {
|
|
printf("%d single inserts failed too.\n", nerrors) ;
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
static int invalid_op(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
int nrows;
|
|
const char *statement = "INSERT into apr_dbd_test1 (col2) values ('foo')" ;
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
printf("invalid op returned %d (should be nonzero). Error msg follows\n", rv);
|
|
printf("'%s'\n", apr_dbd_error(driver, handle, rv));
|
|
statement = "INSERT into apr_dbd_test (col1, col2) values ('bar', 'foo')" ;
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
printf("valid op returned %d (should be zero; error shouldn't affect subsequent ops)\n", rv);
|
|
return rv;
|
|
}
|
|
static int select_sequential(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
int i = 0;
|
|
int n;
|
|
const char* entry;
|
|
const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
|
|
apr_dbd_results_t *res = NULL;
|
|
apr_dbd_row_t *row = NULL;
|
|
rv = apr_dbd_select(driver,pool,handle,&res,statement,0);
|
|
if (rv) {
|
|
printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
|
|
rv == 0;
|
|
rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
|
|
printf("ROW %d: ", ++i) ;
|
|
for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
|
|
entry = apr_dbd_get_entry(driver, row, n);
|
|
if (entry == NULL) {
|
|
printf("(null) ") ;
|
|
}
|
|
else {
|
|
printf("%s ", entry);
|
|
}
|
|
}
|
|
fputs("\n", stdout);
|
|
}
|
|
return (rv == -1) ? 0 : 1;
|
|
}
|
|
static int select_random(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
int n;
|
|
const char* entry;
|
|
const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
|
|
apr_dbd_results_t *res = NULL;
|
|
apr_dbd_row_t *row = NULL;
|
|
rv = apr_dbd_select(driver,pool,handle,&res,statement,1);
|
|
if (rv) {
|
|
printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
rv = apr_dbd_get_row(driver, pool, res, &row, 5) ;
|
|
if (rv) {
|
|
printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
printf("ROW 5: ");
|
|
for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
|
|
entry = apr_dbd_get_entry(driver, row, n);
|
|
if (entry == NULL) {
|
|
printf("(null) ") ;
|
|
}
|
|
else {
|
|
printf("%s ", entry);
|
|
}
|
|
}
|
|
fputs("\n", stdout);
|
|
rv = apr_dbd_get_row(driver, pool, res, &row, 1) ;
|
|
if (rv) {
|
|
printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
printf("ROW 1: ");
|
|
for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
|
|
entry = apr_dbd_get_entry(driver, row, n);
|
|
if (entry == NULL) {
|
|
printf("(null) ") ;
|
|
}
|
|
else {
|
|
printf("%s ", entry);
|
|
}
|
|
}
|
|
fputs("\n", stdout);
|
|
rv = apr_dbd_get_row(driver, pool, res, &row, 11) ;
|
|
if (rv != -1) {
|
|
printf("Oops! get_row out of range but thinks it succeeded!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return -1;
|
|
}
|
|
rv = 0;
|
|
|
|
return rv;
|
|
}
|
|
static int test_transactions(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
int nrows;
|
|
apr_dbd_transaction_t *trans = NULL;
|
|
const char* statement;
|
|
|
|
/* trans 1 - error out early */
|
|
printf("Transaction 1\n");
|
|
rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
|
|
if (rv) {
|
|
printf("Start transaction failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
statement = "UPDATE apr_dbd_test SET col2 = 'failed'";
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
if (rv) {
|
|
printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
|
|
apr_dbd_transaction_end(driver, pool, trans);
|
|
return rv;
|
|
}
|
|
printf("%d rows updated\n", nrows);
|
|
|
|
statement = "INSERT INTO apr_dbd_test1 (col3) values (3)";
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
if (!rv) {
|
|
printf("Oops, invalid op succeeded but shouldn't!\n");
|
|
}
|
|
statement = "INSERT INTO apr_dbd_test values ('zzz', 'aaa', 3)";
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
printf("Valid insert returned %d. Should be nonzero (fail) because transaction is bad\n", rv) ;
|
|
|
|
rv = apr_dbd_transaction_end(driver, pool, trans);
|
|
if (rv) {
|
|
printf("End transaction failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
printf("Transaction ended (should be rollback) - viewing table\n"
|
|
"A column of \"failed\" indicates transaction failed (no rollback)\n");
|
|
select_sequential(pool, handle, driver);
|
|
|
|
/* trans 2 - complete successfully */
|
|
printf("Transaction 2\n");
|
|
rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
|
|
if (rv) {
|
|
printf("Start transaction failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
statement = "UPDATE apr_dbd_test SET col2 = 'success'";
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
if (rv) {
|
|
printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
|
|
apr_dbd_transaction_end(driver, pool, trans);
|
|
return rv;
|
|
}
|
|
printf("%d rows updated\n", nrows);
|
|
statement = "INSERT INTO apr_dbd_test values ('aaa', 'zzz', 3)";
|
|
rv = apr_dbd_query(driver, handle, &nrows, statement);
|
|
printf("Valid insert returned %d. Should be zero (OK)\n", rv) ;
|
|
rv = apr_dbd_transaction_end(driver, pool, trans);
|
|
if (rv) {
|
|
printf("End transaction failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
printf("Transaction ended (should be commit) - viewing table\n");
|
|
select_sequential(pool, handle, driver);
|
|
return rv;
|
|
}
|
|
static int test_pselect(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
int i, n;
|
|
const char *query =
|
|
"SELECT * FROM apr_dbd_test WHERE col3 <= %s or col1 = 'bar'" ;
|
|
const char *label = "lowvalues";
|
|
apr_dbd_prepared_t *statement = NULL;
|
|
apr_dbd_results_t *res = NULL;
|
|
apr_dbd_row_t *row = NULL;
|
|
const char *entry = NULL;
|
|
|
|
rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
|
|
if (rv) {
|
|
printf("Prepare statement failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
rv = apr_dbd_pvselect(driver, pool, handle, &res, statement, 0, "3", NULL);
|
|
if (rv) {
|
|
printf("Exec of prepared statement failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
i = 0;
|
|
printf("Selecting rows where col3 <= 3 and bar row where it's unset.\nShould show four rows.\n");
|
|
for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
|
|
rv == 0;
|
|
rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
|
|
printf("ROW %d: ", ++i) ;
|
|
for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
|
|
entry = apr_dbd_get_entry(driver, row, n);
|
|
if (entry == NULL) {
|
|
printf("(null) ") ;
|
|
}
|
|
else {
|
|
printf("%s ", entry);
|
|
}
|
|
}
|
|
fputs("\n", stdout);
|
|
}
|
|
return (rv == -1) ? 0 : 1;
|
|
}
|
|
static int test_pquery(apr_pool_t* pool, apr_dbd_t* handle,
|
|
const apr_dbd_driver_t* driver)
|
|
{
|
|
int rv = 0;
|
|
const char *query = "INSERT INTO apr_dbd_test VALUES (%s, %s, %d)";
|
|
apr_dbd_prepared_t *statement = NULL;
|
|
const char *label = "testpquery";
|
|
int nrows;
|
|
apr_dbd_transaction_t *trans =0;
|
|
|
|
rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
|
|
/* rv = apr_dbd_prepare(driver, pool, handle, query, NULL, &statement); */
|
|
if (rv) {
|
|
printf("Prepare statement failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
apr_dbd_transaction_start(driver, pool, handle, &trans);
|
|
rv = apr_dbd_pvquery(driver, pool, handle, &nrows, statement,
|
|
"prepared", "insert", "2", NULL);
|
|
apr_dbd_transaction_end(driver, pool, trans);
|
|
if (rv) {
|
|
printf("Exec of prepared statement failed!\n%s\n",
|
|
apr_dbd_error(driver, handle, rv));
|
|
return rv;
|
|
}
|
|
printf("Showing table (should now contain row \"prepared insert 2\")\n");
|
|
select_sequential(pool, handle, driver);
|
|
return rv;
|
|
}
|
|
int main(int argc, char** argv)
|
|
{
|
|
const char *name;
|
|
const char *params;
|
|
apr_pool_t *pool = NULL;
|
|
apr_dbd_t *sql = NULL;
|
|
const apr_dbd_driver_t *driver = NULL;
|
|
int rv;
|
|
|
|
apr_initialize();
|
|
apr_pool_create(&pool, NULL);
|
|
|
|
if (argc >= 2 && argc <= 3) {
|
|
name = argv[1];
|
|
params = ( argc == 3 ) ? argv[2] : "";
|
|
apr_dbd_init(pool);
|
|
setbuf(stdout,NULL);
|
|
rv = apr_dbd_get_driver(pool, name, &driver);
|
|
switch (rv) {
|
|
case APR_SUCCESS:
|
|
printf("Loaded %s driver OK.\n", name);
|
|
break;
|
|
case APR_EDSOOPEN:
|
|
printf("Failed to load driver file apr_dbd_%s.so\n", name);
|
|
goto finish;
|
|
case APR_ESYMNOTFOUND:
|
|
printf("Failed to load driver apr_dbd_%s_driver.\n", name);
|
|
goto finish;
|
|
case APR_ENOTIMPL:
|
|
printf("No driver available for %s.\n", name);
|
|
goto finish;
|
|
default: /* it's a bug if none of the above happen */
|
|
printf("Internal error loading %s.\n", name);
|
|
goto finish;
|
|
}
|
|
rv = apr_dbd_open(driver, pool, params, &sql);
|
|
switch (rv) {
|
|
case APR_SUCCESS:
|
|
printf("Opened %s[%s] OK\n", name, params);
|
|
break;
|
|
case APR_EGENERAL:
|
|
printf("Failed to open %s[%s]\n", name, params);
|
|
goto finish;
|
|
default: /* it's a bug if none of the above happen */
|
|
printf("Internal error opening %s[%s]\n", name, params);
|
|
goto finish;
|
|
}
|
|
TEST("create table", create_table);
|
|
TEST("insert rows", insert_rows);
|
|
TEST("invalid op", invalid_op);
|
|
TEST("select random", select_random);
|
|
TEST("select sequential", select_sequential);
|
|
TEST("transactions", test_transactions);
|
|
TEST("prepared select", test_pselect);
|
|
TEST("prepared query", test_pquery);
|
|
TEST("drop table", drop_table);
|
|
apr_dbd_close(driver, sql);
|
|
}
|
|
else {
|
|
fprintf(stderr, "Usage: %s driver-name [params]\n", argv[0]);
|
|
}
|
|
finish:
|
|
apr_pool_destroy(pool);
|
|
apr_terminate();
|
|
return 0;
|
|
}
|