From 5de4189aa4cfda7f78dfa642379bd71d5391bea7 Mon Sep 17 00:00:00 2001 From: Kenichi Ishigaki Date: Sun, 2 Sep 2012 18:48:53 +0000 Subject: [PATCH] implemented sqlite_table_column_metadata --- SQLite.xs | 14 ++++++++++++-- dbdimp.c | 37 ++++++++++++++++++++++++++++++++++++ dbdimp.h | 1 + lib/DBD/SQLite.pm | 1 + t/51_table_column_metadata.t | 35 ++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 t/51_table_column_metadata.t diff --git a/SQLite.xs b/SQLite.xs index decffa7..3eb1d60 100644 --- a/SQLite.xs +++ b/SQLite.xs @@ -224,8 +224,18 @@ backup_to_file(dbh, filename) OUTPUT: RETVAL - - +HV* +table_column_metadata(dbh, dbname, tablename, columnname) + SV* dbh + SV* dbname + SV* tablename + SV* columnname + ALIAS: + DBD::SQLite::db::sqlite_table_column_metadata = 1 + CODE: + RETVAL = sqlite_db_table_column_metadata(aTHX_ dbh, dbname, tablename, columnname); + OUTPUT: + RETVAL static int diff --git a/dbdimp.c b/dbdimp.c index 0091d5e..3e3d673 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -1412,6 +1412,43 @@ sqlite_db_enable_load_extension(pTHX_ SV *dbh, int onoff) #endif +HV* sqlite_db_table_column_metadata(pTHX_ SV *dbh, SV *dbname, SV *tablename, SV *columnname) +{ + D_imp_dbh(dbh); + const char *datatype, *collseq; + int notnull, primary, autoinc; + HV *metadata = newHV(); + + /* dbname may be NULL but (table|column)name may not be NULL */ + if (!tablename) { + sqlite_error(dbh, -2, "table_column_metadata requires a table name"); + return FALSE; + } + if (!columnname) { + sqlite_error(dbh, -2, "table_column_metadata requires a column name"); + return FALSE; + } + +#ifdef SQLITE_ENABLE_COLUMN_METADATA + int rc = sqlite3_table_column_metadata( + imp_dbh->db, + dbname ? SvPV_nolen(dbname) : NULL, + SvPV_nolen(tablename), + SvPV_nolen(columnname), + &datatype, &collseq, ¬null, &primary, &autoinc); +#endif + + if (rc == SQLITE_OK) { + hv_store(metadata, "data_type", 9, newSVpv(datatype, 0), 0); + hv_store(metadata, "collation_name", 14, newSVpv(collseq, 0), 0); + hv_store(metadata, "not_null", 8, newSViv(notnull), 0); + hv_store(metadata, "primary", 7, newSViv(primary), 0); + hv_store(metadata, "auto_increment", 14, newSViv(autoinc), 0); + } + + return metadata; +} + static void sqlite_db_aggr_new_dispatcher(pTHX_ sqlite3_context *context, aggrInfo *aggr_info) { diff --git a/dbdimp.h b/dbdimp.h index 40941be..c46464c 100644 --- a/dbdimp.h +++ b/dbdimp.h @@ -106,6 +106,7 @@ int sqlite_db_set_authorizer( pTHX_ SV *dbh, SV *authorizer ); AV* sqlite_compile_options(); int sqlite_db_trace(pTHX_ SV *dbh, SV *func); int sqlite_db_profile(pTHX_ SV *dbh, SV *func); +HV* sqlite_db_table_column_metadata(pTHX_ SV *dbh, SV *dbname, SV *tablename, SV *columnname); int sqlite_db_register_fts3_perl_tokenizer(pTHX_ SV *dbh); diff --git a/lib/DBD/SQLite.pm b/lib/DBD/SQLite.pm index 4447624..24c40d4 100644 --- a/lib/DBD/SQLite.pm +++ b/lib/DBD/SQLite.pm @@ -51,6 +51,7 @@ sub driver { DBD::SQLite::db->install_method('sqlite_register_fts3_perl_tokenizer'); DBD::SQLite::db->install_method('sqlite_trace'); DBD::SQLite::db->install_method('sqlite_profile'); + DBD::SQLite::db->install_method('sqlite_table_column_metadata'); $methods_are_installed++; } diff --git a/t/51_table_column_metadata.t b/t/51_table_column_metadata.t new file mode 100644 index 0000000..0a0752e --- /dev/null +++ b/t/51_table_column_metadata.t @@ -0,0 +1,35 @@ +#!/usr/bin/perl + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use t::lib::Test qw/connect_ok @CALL_FUNCS/; +use Test::More; +use Test::NoWarnings; + +plan tests => 11 * @CALL_FUNCS + 1; +for my $call_func (@CALL_FUNCS) { + my $dbh = connect_ok(); + $dbh->do('create table foo (id integer primary key autoincrement, "name space", unique_col integer unique)'); + + { + my $data = $dbh->$call_func(undef, 'foo', 'id', 'table_column_metadata'); + ok $data && ref $data eq ref {}, "got a metadata"; + ok $data->{auto_increment}, "id is auto incremental"; + is $data->{data_type} => 'integer', "data type is correct"; + ok $data->{primary}, "id is a primary key"; + ok !$data->{not_null}, "id is not null"; + } + + { + my $data = $dbh->$call_func(undef, 'foo', 'name space', 'table_column_metadata'); + ok $data && ref $data eq ref {}, "got a metadata"; + ok !$data->{auto_increment}, "name space is not auto incremental"; + is $data->{data_type} => undef, "data type is not defined"; + ok !$data->{primary}, "name space is not a primary key"; + ok !$data->{not_null}, "name space is not null"; + } +}