DBD-SQLite2-0.36/0000755000175000017500000000000012130556472012625 5ustar rurbanrurbanDBD-SQLite2-0.36/t/0000755000175000017500000000000012130556467013074 5ustar rurbanrurbanDBD-SQLite2-0.36/t/dbdadmin.t0000644000175000017500000001272112126353147015021 0ustar rurbanrurban#!/usr/local/bin/perl # # Test suite for the admin functions of DBD::mSQL and DBD::mysql. # # # Make -w happy # $test_dsn = $test_user = $test_password = $verbose = ''; $| = 1; # # Include lib.pl # $DBI::errstr = ''; # Make -w happy require DBI; $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl", "DBD-~DBD_DRIVER~/t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } sub InDsnList($@) { my($dsn, @dsnList) = @_; my($d); foreach $d (@dsnList) { if ($d =~ /^dbi:[^:]+:$dsn\b/i) { return 1; } } 0; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # Check if the server is awake. $dbh = undef; Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ServerError(); Test($state or (@dsn = DBI->data_sources($mdriver)) >= 0); if (!$state && $verbose) { my $d; print "List of $mdriver data sources:\n"; foreach $d (@dsn) { print " $d\n"; } print "List ends.\n"; } my $drh; Test($state or ($drh = DBI->install_driver($mdriver))) or print STDERR ("Cannot obtain drh: " . $DBI::errstr); # # Check the ping method. # Test($state or $dbh->ping()) or ErrMsgF("Ping failed: %s.\n", $dbh->errstr); if ($mdriver eq 'mSQL' or $mdriver eq 'mysql') { my($testdsn) = "testaa"; my($testdsn1, $testdsn2); my($accessDenied) = 0; my($warning); my($warningSub) = sub { $warning = shift }; if (!$state) { while (InDsnList($testdsn, @dsn)) { ++$testdsn; } $testdsn1 = $testdsn; ++$testdsn1; while (InDsnList($testdsn1, @dsn)) { ++$testdsn1; } $testdsn2 = $testdsn1; ++$testdsn2; while (InDsnList($testdsn2, @dsn)) { ++$testdsn2; } $SIG{__WARN__} = $warningSub; $warning = ''; if (!($result = $drh->func($testdsn, '_CreateDB')) and ($drh->errstr =~ /(access|permission) denied/i)) { $accessDenied = 1; $result = 1; } $SIG{__WARN__} = 'DEFAULT'; } Test($state or $result) or print STDERR ("Error while executing _CreateDB: " . $drh->errstr); Test($state or ($warning =~ /deprecated/)) or print STDERR ("Expected warning, got '$warning'.\n"); Test($state or $accessDenied or InDsnList($testdsn, DBI->data_sources($mdriver))) or print STDERR ("New DB not in DSN list\n"); $SIG{__WARN__} = $warningSub; $warning = ''; Test($state or $accessDenied or $drh->func($testdsn, '_DropDB')) or print STDERR ("Error while executing _DropDB: " . $drh->errstr); Test($state or $accessDenied or ($warning =~ /deprecated/)) or print STDERR ("Expected warning, got '$warning'\n"); $SIG{__WARN__} = 'DEFAULT'; Test($state or $accessDenied or !InDsnList($testdsn, DBI->data_sources($mdriver))) or print STDERR ("New DB not removed from DSN list\n"); my($mayShutdown) = $ENV{'DB_SHUTDOWN_ALLOWED'}; Test($state or $accessDenied or $drh->func('createdb', $testdsn1, 'admin')) or printf STDERR ("\$drh->admin('createdb') failed: %s\n", $drh->errstr); Test($state or $accessDenied or InDsnList($testdsn1, DBI->data_sources($mdriver))) or printf STDERR ("DSN $testdsn1 not in DSN list.\n"); Test($state or $accessDenied or $drh->func('dropdb', $testdsn1, 'admin')) or printf STDERR ("\$drh->admin('dropdb') failed: %s\n", $drh->errstr); Test($state or $accessDenied or !InDsnList($testdsn1, DBI->data_sources($mdriver))) or printf STDERR ("DSN $testdsn1 not removed from DSN list.\n"); Test($state or $accessDenied or $drh->func('createdb', $testdsn2, 'admin')) or printf STDERR ("\$drh->admin('createdb') failed: %s\n", $drh->errstr); Test($state or $accessDenied or InDsnList($testdsn2, DBI->data_sources($mdriver))) or printf STDERR ("DSN $testdsn2 not in DSN list.\n"); Test($state or $accessDenied or $drh->func('dropdb', $testdsn2, 'admin')) or printf STDERR ("\$drh->admin('dropdb') failed: %s\n", $drh->errstr); Test($state or $accessDenied or !InDsnList($testdsn2, DBI->data_sources($mdriver))) or printf STDERR ("DSN $testdsn2 not removed from DSN list.\n"); if ($mdriver eq 'mysql') { # # Try to do a shutdown. # Test($state or !$mayShutdown or $accessDenied or $dbh->func("shutdown", "admin")) or ErrMsgF("Cannot shutdown database: %s.\n", $dbh->errstr); if (!$state) { sleep 10; } # # Pinging should fail now. # Test($state or !$mayShutdown or $accessDenied or !$dbh->ping()) or print STDERR ("Shutdown failed (ping succeeded)"); # # Restart the database # if (!$state && $mayShutdown && !$accessDenied) { if (fork() == 0) { close STDIN; close STDOUT; close STDERR; exec "safe_mysqld &"; } } sleep 5; # # Try DBD::mysql's automatic reconnect # Test($state or $dbh->ping()) or ErrMsgF("Reconnect failed: %s.\n", $dbh->errstr); } Test($state or $dbh->disconnect); } } DBD-SQLite2-0.36/t/08create_function.t0000644000175000017500000000614612126364675016613 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 19 } use DBI; sub now { return time(); } sub add2 { my ( $a, $b ) = @_; return $a + $b; } sub my_sum { my $sum = 0; foreach my $x (@_) { $sum += $x; } return $sum; } sub error { die "function is dying: ", @_, "\n"; } sub void_return { } sub return2 { return ( 1, 2 ); } sub return_null { return undef; } sub my_defined { return defined $_[0]; } sub noop { return $_[0]; } my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", "", { PrintError => 0 } ); ok($dbh); $dbh->func( "now", 0, \&now, "create_function" ); my $result = $dbh->selectrow_arrayref( "SELECT now()" ); ok( $result->[0] ); $dbh->do( 'CREATE TEMP TABLE func_test ( a, b )' ); $dbh->do( 'INSERT INTO func_test VALUES ( 1, 3 )' ); $dbh->do( 'INSERT INTO func_test VALUES ( 0, 4 )' ); $dbh->func( "add2", 2, \&add2, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT add2(1,3)" ); ok( $result->[0] == 4 ); $result = $dbh->selectall_arrayref( "SELECT add2(a,b) FROM func_test" ); ok( $result->[0][0] = 4 && $result->[1][0] == 4 ); $dbh->func( "my_sum", -1, \&my_sum, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT my_sum( '2', 3, 4, '5')" ); ok( $result->[0] == 14 ); $dbh->func( "error", -1, \&error, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT error( 'I died' )" ); ok( !$result ); ok( $DBI::errstr =~ /function is dying: I died/ ); $dbh->func( "void_return", -1, \&void_return, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT void_return( 'I died' )" ); ok( $result && !defined $result->[0] ); $dbh->func( "return_null", -1, \&return_null, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT return_null()" ); ok( $result && !defined $result->[0] ); $dbh->func( "return2", -1, \&return2, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT return2()" ); ok( $result && $result->[0] == 2 ); $dbh->func( "my_defined", 1, \&my_defined, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT my_defined(1)" ); ok( $result && $result->[0] ); $result = $dbh->selectrow_arrayref( "SELECT my_defined('')" ); ok( $result && $result->[0] ); $result = $dbh->selectrow_arrayref( "SELECT my_defined('abc')" ); ok( $result && $result->[0] ); $result = $dbh->selectrow_arrayref( "SELECT my_defined(NULL)" ); ok( $result && !$result->[0] ); $dbh->func( "noop", 1, \&noop, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT noop(NULL)" ); ok( $result && !defined $result->[0] ); $result = $dbh->selectrow_arrayref( "SELECT noop(1)" ); ok( $result && $result->[0] == 1); $result = $dbh->selectrow_arrayref( "SELECT noop('')" ); ok( $result && $result->[0] eq '' ); $result = $dbh->selectrow_arrayref( "SELECT noop(1.1)" ); ok( $result && $result->[0] == 1.1 ); { use Config; sub return_big { return 2**32; } $dbh->func( "bignumber", 0, \&return_big, "create_function" ); $result = $dbh->selectrow_arrayref( "SELECT bignumber()" ); # [RT #28448] int overflow with use64bitint and !use64bitall ok ($result && $$result[0] > 0); } $dbh->disconnect; DBD-SQLite2-0.36/t/50commit.t0000644000175000017500000001444112126353147014715 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 50commit.t,v 1.1.1.1 2004/08/08 15:03:59 matt Exp $ # # This is testing the transaction support. # $^W = 1; # # Include lib.pl # require DBI; $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } if ($mdriver eq 'whatever') { print "1..0\n"; exit 0; } use vars qw($gotWarning); sub CatchWarning ($) { $gotWarning = 1; } sub NumRows($$$) { my($dbh, $table, $num) = @_; my($sth, $got); if (!($sth = $dbh->prepare("SELECT * FROM $table"))) { return "Failed to prepare: err " . $dbh->err . ", errstr " . $dbh->errstr; } if (!$sth->execute) { return "Failed to execute: err " . $dbh->err . ", errstr " . $dbh->errstr; } $got = 0; while ($sth->fetchrow_arrayref) { ++$got; } if ($got ne $num) { return "Wrong result: Expected $num rows, got $got.\n"; } return ''; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password)), 'connect', "Attempting to connect.\n") or ErrMsgF("Cannot connect: Error %s.\n\n" . "Make sure, your database server is up and running.\n" . "Check that '$test_dsn' references a valid database" . " name.\nDBI error message: %s\n", $DBI::err, $DBI::errstr); # # Find a possible new table name # Test($state or $table = FindNewTable($dbh)) or ErrMsgF("Cannot determine a legal table name: Error %s.\n", $dbh->errstr); # # Create a new table # Test($state or ($def = TableDefinition($table, ["id", "INTEGER", 4, 0], ["name", "CHAR", 64, 0]), $dbh->do($def))) or ErrMsgF("Cannot create table: Error %s.\n", $dbh->errstr); Test($state or $dbh->{AutoCommit}) or ErrMsg("AutoCommit is off\n", 'AutoCommint on'); # # Tests for databases that do support transactions # if (HaveTransactions()) { # Turn AutoCommit off $dbh->{AutoCommit} = 0; Test($state or (!$dbh->err && !$dbh->errstr && !$dbh->{AutoCommit})) or ErrMsgF("Failed to turn AutoCommit off: err %s, errstr %s\n", $dbh->err, $dbh->errstr); # Check rollback Test($state or $dbh->do("INSERT INTO $table VALUES (1, 'Jochen')")) or ErrMsgF("Failed to insert value: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); my $msg; Test($state or !($msg = NumRows($dbh, $table, 1))) or ErrMsg($msg); Test($state or $dbh->rollback) or ErrMsgF("Failed to rollback: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); Test($state or !($msg = NumRows($dbh, $table, 0))) or ErrMsg($msg); # Check commit Test($state or $dbh->do("DELETE FROM $table WHERE id = 1")) or ErrMsgF("Failed to insert value: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); Test($state or !($msg = NumRows($dbh, $table, 0))) or ErrMsg($msg); Test($state or $dbh->commit) or ErrMsgF("Failed to rollback: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); Test($state or !($msg = NumRows($dbh, $table, 0))) or ErrMsg($msg); # Check auto rollback after disconnect Test($state or $dbh->do("INSERT INTO $table VALUES (1, 'Jochen')")) or ErrMsgF("Failed to insert: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); Test($state or !($msg = NumRows($dbh, $table, 1))) or ErrMsg($msg); Test($state or $dbh->disconnect) or ErrMsgF("Failed to disconnect: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ErrMsgF("Failed to reconnect: err %s, errstr %s.\n", $DBI::err, $DBI::errstr); Test($state or !($msg = NumRows($dbh, $table, 0))) or ErrMsg($msg); # Check whether AutoCommit is on again Test($state or $dbh->{AutoCommit}) or ErrMsg("AutoCommit is off\n"); # # Tests for databases that don't support transactions # } else { if (!$state) { $@ = ''; eval { $dbh->{AutoCommit} = 0; } } Test($state or $@) or ErrMsg("Expected fatal error for AutoCommit => 0\n", 'AutoCommit off -> error'); } # Check whether AutoCommit mode works. Test($state or $dbh->do("INSERT INTO $table VALUES (1, 'Jochen')")) or ErrMsgF("Failed to delete: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); Test($state or !($msg = NumRows($dbh, $table, 1)), 'NumRows') or ErrMsg($msg); Test($state or $dbh->disconnect, 'disconnect') or ErrMsgF("Failed to disconnect: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ErrMsgF("Failed to reconnect: err %s, errstr %s.\n", $DBI::err, $DBI::errstr); Test($state or !($msg = NumRows($dbh, $table, 1))) or ErrMsg($msg); # Check whether commit issues a warning in AutoCommit mode Test($state or $dbh->do("INSERT INTO $table VALUES (2, 'Tim')")) or ErrMsgF("Failed to insert: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); my $result; if (!$state) { $@ = ''; $SIG{__WARN__} = \&CatchWarning; $gotWarning = 0; eval { $result = $dbh->commit; }; $SIG{__WARN__} = 'DEFAULT'; } Test($state or $gotWarning) or ErrMsg("Missing warning when committing in AutoCommit mode"); # Check whether rollback issues a warning in AutoCommit mode # We accept error messages as being legal, because the DBI # requirement of just issueing a warning seems scary. Test($state or $dbh->do("INSERT INTO $table VALUES (3, 'Alligator')")) or ErrMsgF("Failed to insert: err %s, errstr %s.\n", $dbh->err, $dbh->errstr); if (!$state) { $@ = ''; $SIG{__WARN__} = \&CatchWarning; $gotWarning = 0; eval { $result = $dbh->rollback; }; $SIG{__WARN__} = 'DEFAULT'; } Test($state or $gotWarning or $dbh->err) or ErrMsg("Missing warning when rolling back in AutoCommit mode"); # # Finally drop the test table. # Test($state or $dbh->do("DROP TABLE $table")) or ErrMsgF("Cannot DROP test table $table: %s.\n", $dbh->errstr); Test($state or $dbh->disconnect()) or ErrMsgF("Cannot DROP test table $table: %s.\n", $dbh->errstr); } DBD-SQLite2-0.36/t/60metadata.t0000644000175000017500000000261512126353147015206 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 24 } use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", "", { }); ok($dbh); $dbh->{PrintError} = 0; $dbh->do("drop table meta$_") for 1..4; $dbh->{PrintError} = 1; ok $dbh->do("create table meta1 (f1 varchar(2) PRIMARY KEY, f2 char(1))"); ok $dbh->do("create table meta2 (f1 varchar(2), f2 char(1), PRIMARY KEY (f1))"); ok $dbh->do("create table meta3 (f2 char(1), f1 varchar(2) PRIMARY KEY)"); $dbh->trace(0); $DBI::neat_maxlen = 4000; my $sth = $dbh->primary_key_info('', '', '%'); ok $sth; my $pki = $sth->fetchall_hashref('TABLE_NAME'); ok $pki; #use Data::Dumper; print Dumper($pki); ok keys %$pki == 3; ok $_->{COLUMN_NAME} eq 'f1' for values %$pki; ok $dbh->do("create table meta4 (f1 varchar(2), f2 char(1), PRIMARY KEY (f1,f2))"); $sth = $dbh->primary_key_info('', '', 'meta4'); ok $sth; $pki = $sth->fetchall_hashref('COLUMN_NAME'); ok $pki; #use Data::Dumper; print Dumper($pki); ok keys %$pki == 2; ok $pki->{f1}->{KEY_SEQ} == 1; ok $pki->{f2}->{KEY_SEQ} == 2; my @pk = $dbh->primary_key('','','meta4'); ok @pk == 2; ok "@pk" eq "f1 f2"; ok $dbh->do("insert into meta4 values ('xyz', 'b')"); $sth = $dbh->prepare("select * from meta4"); ok $sth; ok $sth->execute(); my $types = $sth->{TYPE}; my $names = $sth->{NAME}; ok( @$types == @$names ); print "# Types: @$types\n"; print "# Names: @$names\n"; ok($types->[0] eq 'varchar(2)'); ok($types->[1] eq 'char(1)'); DBD-SQLite2-0.36/t/00basic.t0000644000175000017500000000023112126353147014471 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 1 } END { ok($loaded) } use DBD::SQLite2; $loaded++; unlink("foo", "output/foo", "output/database", "output/datbase"); DBD-SQLite2-0.36/t/40bindparam.t0000644000175000017500000001316712126353147015365 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 40bindparam.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This is a skeleton test. For writing new tests, take this file # and modify/extend it. # $^W = 1; # # Make -w happy # $test_dsn = ''; $test_user = ''; $test_password = ''; # # Include lib.pl # require DBI; use vars qw($COL_NULLABLE); $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } if ($mdriver eq 'pNET') { print "1..0\n"; exit 0; } sub ServerError() { my $err = $DBI::errstr; # Hate -w ... print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } if (!defined(&SQL_VARCHAR)) { eval "sub SQL_VARCHAR { 12 }"; } if (!defined(&SQL_INTEGER)) { eval "sub SQL_INTEGER { 4 }"; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password), 'connect') or ServerError(); # For some reason this test is fscked with the utf8 flag on. # It seems to be because the string "K\x{00f6}nig" which to # me looks like unicode, should set the UTF8 flag on that # scalar. But no. It doesn't. Stupid fscking piece of crap. # (the test works if I manually set that flag with utf8::upgrade()) # $dbh->{NoUTF8Flag} = 1 if $] > 5.007; # # Find a possible new table name # Test($state or $table = FindNewTable($dbh), 'FindNewTable') or DbiError($dbh->err, $dbh->errstr); # # Create a new table; EDIT THIS! # Test($state or ($def = TableDefinition($table, ["id", "INTEGER", 4, 0], ["name", "CHAR", 64, $COL_NULLABLE]) and $dbh->do($def)), 'create', $def) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor = $dbh->prepare("INSERT INTO $table" . " VALUES (?, ?)"), 'prepare') or DbiError($dbh->err, $dbh->errstr); # # Insert some rows # my $konig = "Andreas K\xf6nig"; # warn("Konig: $konig\n"); # Automatic type detection my $numericVal = 1; my $charVal = "Alligator Descartes"; Test($state or $cursor->execute($numericVal, $charVal), 'execute insert 1') or DbiError($dbh->err, $dbh->errstr); # Does the driver remember the automatically detected type? Test($state or $cursor->execute("3", "Jochen Wiedmann"), 'execute insert num as string') or DbiError($dbh->err, $dbh->errstr); $numericVal = 2; $charVal = "Tim Bunce"; Test($state or $cursor->execute($numericVal, $charVal), 'execute insert 2') or DbiError($dbh->err, $dbh->errstr); # Now try the explicit type settings Test($state or $cursor->bind_param(1, " 4", SQL_INTEGER()), 'bind 1') or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->bind_param(2, $konig), 'bind 2') or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute, 'execute binds') or DbiError($dbh->err, $dbh->errstr); # Works undef -> NULL? Test($state or $cursor->bind_param(1, 5, SQL_INTEGER())) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->bind_param(2, undef)) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor -> finish, 'finish'); Test($state or undef $cursor || 1, 'undef cursor'); Test($state or $dbh -> disconnect, 'disconnect'); Test($state or undef $dbh || 1, 'undef dbh'); # # And now retreive the rows using bind_columns # # # Connect to the database # Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password), 'connect for read') or ServerError(); # $dbh->{NoUTF8Flag} = 1 if $] > 5.007; Test($state or $cursor = $dbh->prepare("SELECT * FROM $table" . " ORDER BY id")) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->bind_columns(undef, \$id, \$name)) or DbiError($dbh->err, $dbh->errstr); Test($state or ($ref = $cursor->fetch) && $id == 1 && $name eq 'Alligator Descartes') or printf("Query returned id = %s, name = %s, ref = %s, %d\n", $id, $name, $ref, scalar(@$ref)); Test($state or (($ref = $cursor->fetch) && $id == 2 && $name eq 'Tim Bunce')) or printf("Query returned id = %s, name = %s, ref = %s, %d\n", $id, $name, $ref, scalar(@$ref)); Test($state or (($ref = $cursor->fetch) && $id == 3 && $name eq 'Jochen Wiedmann')) or printf("Query returned id = %s, name = %s, ref = %s, %d\n", $id, $name, $ref, scalar(@$ref)); # warn("Konig: $konig\n"); Test($state or (($ref = $cursor->fetch) && $id == 4 && $name eq $konig)) or printf("Query returned id = %s, name = %s, ref = %s, %d\n", $id, $name, $ref, scalar(@$ref)); # warn("$konig == $name ?\n"); Test($state or (($ref = $cursor->fetch) && $id == 5 && !defined($name))) or printf("Query returned id = %s, name = %s, ref = %s, %d\n", $id, $name, $ref, scalar(@$ref)); Test($state or undef $cursor or 1); # # Finally drop the test table. # Test($state or $dbh->do("DROP TABLE $table")) or DbiError($dbh->err, $dbh->errstr); } DBD-SQLite2-0.36/t/SQLite2.dbtest0000644000175000017500000000564112126353147015527 0ustar rurbanrurban# Hej, Emacs, give us -*- perl -*- mode here! # # $Id: SQLite2.dbtest,v 1.1.1.1 2004/08/08 15:03:59 matt Exp $ # # database specific definitions for a 'CSV' database # This function generates a mapping of ANSI type names to # database specific type names; it is called by TableDefinition(). # sub AnsiTypeToDb ($;$) { my ($type, $size) = @_; my ($ret); if ((lc $type) eq 'char' || (lc $type) eq 'varchar') { $size ||= 1; return (uc $type) . " ($size)"; } elsif ((lc $type) eq 'blob' || (lc $type) eq 'real' || (lc $type) eq 'integer') { return uc $type; } elsif ((lc $type) eq 'int') { return 'INTEGER'; } else { warn "Unknown type $type\n"; $ret = $type; } $ret; } # # This function generates a table definition based on an # input list. The input list consists of references, each # reference referring to a single column. The column # reference consists of column name, type, size and a bitmask of # certain flags, namely # # $COL_NULLABLE - true, if this column may contain NULL's # $COL_KEY - true, if this column is part of the table's # primary key # # Hopefully there's no big need for you to modify this function, # if your database conforms to ANSI specifications. # sub TableDefinition ($@) { my($tablename, @cols) = @_; my($def); # # Should be acceptable for most ANSI conformant databases; # # msql 1 uses a non-ANSI definition of the primary key: A # column definition has the attribute "PRIMARY KEY". On # the other hand, msql 2 uses the ANSI fashion ... # my($col, @keys, @colDefs, $keyDef); # # Count number of keys # @keys = (); foreach $col (@cols) { if ($$col[2] & $::COL_KEY) { push(@keys, $$col[0]); } } foreach $col (@cols) { my $colDef = $$col[0] . " " . AnsiTypeToDb($$col[1], $$col[2]); if (!($$col[3] & $::COL_NULLABLE)) { $colDef .= " NOT NULL"; } push(@colDefs, $colDef); } if (@keys) { $keyDef = ", PRIMARY KEY (" . join(", ", @keys) . ")"; } else { $keyDef = ""; } $def = sprintf("CREATE TABLE %s (%s%s)", $tablename, join(", ", @colDefs), $keyDef); } # # This function generates a list of tables associated to a # given DSN. # sub ListTables(@) { my($dbh) = shift; my(@tables); @tables = $dbh->func('list_tables'); if ($dbh->errstr) { die "Cannot create table list: " . $dbh->errstr; } @tables; } # # This function is called by DBD::pNET; given a hostname and a # dsn without hostname, return a dsn for connecting to dsn at # host. sub HostDsn ($$) { my($hostname, $dsn) = @_; "$dsn:$hostname"; } # # Return a string for checking, whether a given column is NULL. # sub IsNull($) { my($var) = @_; "$var IS NULL"; } # # Return TRUE, if database supports transactions # sub HaveTransactions () { 1; } if (! -d "output") { mkdir "output", 0755; } 1; DBD-SQLite2-0.36/t/02cr_table.t0000644000175000017500000000065612126353147015200 0ustar rurbanrurbanuse strict; use Test; BEGIN { plan tests => 4 } use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", ""); ok($dbh); $dbh->{AutoCommit} = 1; $dbh->do("CREATE TABLE f (f1, f2, f3)"); my $sth = $dbh->prepare("SELECT f.f1, f.* FROM f"); ok($sth->execute()); my $names = $sth->{NAME}; ok(@$names == 4); print(join(', ', @$names), "\n"); ok($names->[0] eq "f1"); # make sure the "f." is removed $sth->finish; $dbh->disconnect; DBD-SQLite2-0.36/t/04select.t0000644000175000017500000000056312126353147014703 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 7 } use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", "", { RaiseError => 1 }); ok($dbh); my $sth = $dbh->prepare("SELECT * FROM f"); ok($sth); ok($sth->execute); my $row = $sth->fetch; ok($row); ok(@$row, 3); print join(", ", @$row), "\n"; my $rows = $sth->execute; ok($rows); ok($sth->fetch); $sth->finish; $dbh->disconnect; DBD-SQLite2-0.36/t/30insertfetch.t0000644000175000017500000000732212126353147015741 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 30insertfetch.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This is a simple insert/fetch test. # $^W = 1; # # Make -w happy # $test_dsn = ''; $test_user = ''; $test_password = ''; # # Include lib.pl # use DBI; $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl", "DBD-~DBD_DRIVER~/t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password), 'connect') or ServerError(); # # Find a possible new table name # Test($state or $table = FindNewTable($dbh), 'FindNewTable') or DbiError($dbh->err, $dbh->errstr); # # Create a new table; EDIT THIS! # Test($state or ($def = TableDefinition($table, ["id", "INTEGER", 4, 0], ["name", "CHAR", 64, 0], ["val", "INTEGER", 4, 0], ["txt", "CHAR", 64, 0]) and $dbh->do($def)), 'create', $def) or DbiError($dbh->err, $dbh->errstr); # # Insert a row into the test table....... # Test($state or $dbh->do("INSERT INTO $table" . " VALUES(1, 'Alligator Descartes', 1111," . " 'Some Text')"), 'insert') or DbiError($dbh->err, $dbh->errstr); # # Now, try SELECT'ing the row out. # Test($state or $cursor = $dbh->prepare("SELECT * FROM $table" . " WHERE id = 1"), 'prepare select') or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute, 'execute select') or DbiError($cursor->err, $cursor->errstr); my ($row, $errstr); Test($state or (defined($row = $cursor->fetchrow_arrayref) && !($cursor->errstr)), 'fetch select') or DbiError($cursor->err, $cursor->errstr); Test($state or ($row->[0] == 1 && $row->[1] eq 'Alligator Descartes' && $row->[2] == 1111 && $row->[3] eq 'Some Text'), 'compare select') or DbiError($cursor->err, $cursor->errstr); Test($state or $cursor->finish, 'finish select') or DbiError($cursor->err, $cursor->errstr); Test($state or undef $cursor || 1, 'undef select'); # # ...and delete it........ # Test($state or $dbh->do("DELETE FROM $table WHERE id = 1"), 'delete') or DbiError($dbh->err, $dbh->errstr); # # Now, try SELECT'ing the row out. This should fail. # Test($state or $cursor = $dbh->prepare("SELECT * FROM $table" . " WHERE id = 1"), 'prepare select deleted') or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute, 'execute select deleted') or DbiError($cursor->err, $cursor->errstr); Test($state or (!defined($row = $cursor->fetchrow_arrayref) && (!defined($errstr = $cursor->errstr) || $cursor->errstr eq '')), 'fetch select deleted') or DbiError($cursor->err, $cursor->errstr); Test($state or $cursor->finish, 'finish select deleted') or DbiError($cursor->err, $cursor->errstr); Test($state or undef $cursor || 1, 'undef select deleted'); # # Finally drop the test table. # Test($state or $dbh->do("DROP TABLE $table"), 'drop') or DbiError($dbh->err, $dbh->errstr); } DBD-SQLite2-0.36/t/05tran.t0000644000175000017500000000174212126353147014371 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 2 } use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", "", {AutoCommit => 0, RaiseError => 1}); ok($dbh); $dbh->do("CREATE TABLE MST (id, lbl)"); $dbh->do("CREATE TABLE TRN (no, id, qty)"); $dbh->commit; #not work? $dbh->do("INSERT INTO MST VALUES(1, 'ITEM1')"); $dbh->do("INSERT INTO MST VALUES(2, 'ITEM2')"); $dbh->do("INSERT INTO MST VALUES(3, 'ITEM3')"); $dbh->do("INSERT INTO TRN VALUES('A', 1, 5)"); $dbh->do("INSERT INTO TRN VALUES('B', 2, 2)"); $dbh->do("INSERT INTO TRN VALUES('C', 1, 4)"); $dbh->do("INSERT INTO TRN VALUES('D', 3, 3)"); $dbh->rollback; #not work? my $sth = $dbh->prepare( "SELECT TRN.id AS ID, MST.LBL AS TITLE, SUM(qty) AS TOTAL FROM TRN,MST WHERE TRN.ID = MST.ID GROUP BY TRN.ID ORDER BY TRN.ID DESC"); my $rows = $sth->execute(); ok($rows, "0E0"); my $names = $sth->{NAME}; print(join(', ', @$names), "\n"); while(my $raD = $sth->fetchrow_arrayref()) { print join(":", @$raD), "\n"; } $dbh->disconnect; DBD-SQLite2-0.36/t/90cppcomments.t0000644000175000017500000000077212126353147015763 0ustar rurbanrurbanuse Test; use DBI; use Fatal qw(open); my @c_files = <*.c>, <*.xs>; plan tests => scalar(@c_files); FILE: foreach my $file (@c_files) { open(F, $file); my $line = 0; while () { $line++; if (/^(.*)\/\//) { my $m = $1; if ($m !~ /\*/) { # skip the // in c++ comment in parse.c ok(0, 1, "C++ comment in $file line $line"); next FILE; } } } ok(1,1,"$file has no C++ comments"); close(F); } DBD-SQLite2-0.36/t/40blobs.t0000644000175000017500000000747512126353147014536 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 40blobs.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This is a test for correct handling of BLOBS; namely $dbh->quote # is expected to work correctly. # $^W = 1; # # Make -w happy # $test_dsn = ''; $test_user = ''; $test_password = ''; # # Include lib.pl # require DBI; $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } if ($dbdriver eq 'mSQL' || $dbdriver eq 'mSQL1') { print "1..0\n"; exit 0; } sub ServerError() { my $err = $DBI::errstr; # Hate -w ... print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } sub ShowBlob($) { my ($blob) = @_; print("showblob length: ", length($blob), "\n"); if ($ENV{SHOW_BLOBS}) { open(OUT, ">>$ENV{SHOW_BLOBS}") } my $i = 0; while (1) { if (defined($blob) && length($blob) > ($i*32)) { $b = substr($blob, $i*32); } else { $b = ""; last; } if ($ENV{SHOW_BLOBS}) { printf OUT "%08lx %s\n", $i*32, unpack("H64", $b) } else { printf("%08lx %s\n", $i*32, unpack("H64", $b)) } $i++; last if $i == 8; } if ($ENV{SHOW_BLOBS}) { close(OUT) } } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password)) or ServerError(); $dbh->{sqlite_handle_binary_nulls} = 1; # # Find a possible new table name # Test($state or $table = FindNewTable($dbh)) or DbiError($dbh->error, $dbh->errstr); my($def); foreach $size (128) { # # Create a new table # if (!$state) { $def = TableDefinition($table, ["id", "INTEGER", 4, 0], ["name", "BLOB", $size, 0]); print "Creating table:\n$def\n"; } Test($state or $dbh->do($def)) or DbiError($dbh->err, $dbh->errstr); # # Create a blob # my ($blob, $qblob) = ""; if (!$state) { my $b = ""; for ($j = 0; $j < 256; $j++) { $b .= chr($j); } for ($i = 0; $i < $size; $i++) { $blob .= $b; } if ($mdriver eq 'pNET') { # Quote manually, no remote quote $qblob = eval "DBD::" . $dbdriver . "::db->quote(\$blob)"; } else { $qblob = $dbh->quote($blob); } } # # Insert a row into the test table....... # my($query); if (!$state) { $query = "INSERT INTO $table VALUES (1, ?)"; if ($ENV{'SHOW_BLOBS'} && open(OUT, ">" . $ENV{'SHOW_BLOBS'})) { print OUT $query, "\n"; close(OUT); } } Test($state or $dbh->do($query,undef,$blob)) or DbiError($dbh->err, $dbh->errstr); # # Now, try SELECT'ing the row out. # Test($state or $cursor = $dbh->prepare("SELECT * FROM $table" . " WHERE id = 1")) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($dbh->err, $dbh->errstr); Test($state or (defined($row = $cursor->fetchrow_arrayref))) or DbiError($cursor->err, $cursor->errstr); Test($state or (@$row == 2 && $$row[0] == 1 && $$row[1] eq $blob)) or (ShowBlob($blob), ShowBlob(defined($$row[1]) ? $$row[1] : "")); Test($state or $cursor->finish) or DbiError($cursor->err, $cursor->errstr); Test($state or undef $cursor || 1) or DbiError($cursor->err, $cursor->errstr); # # Finally drop the test table. # Test($state or $dbh->do("DROP TABLE $table")) or DbiError($dbh->err, $dbh->errstr); } } DBD-SQLite2-0.36/t/20createdrop.t0000644000175000017500000000352012126353147015546 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 20createdrop.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This is a skeleton test. For writing new tests, take this file # and modify/extend it. # use strict; use vars qw($test_dsn $test_user $test_password $mdriver $dbdriver); $DBI::errstr = ''; # Make -w happy require DBI; # # Include lib.pl # $mdriver = ""; my $file; foreach $file ("lib.pl", "t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } # # Main loop; leave this untouched, put tests into the loop # use vars qw($state); while (Testing()) { # # Connect to the database my $dbh; Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password)) or ServerError(); # # Find a possible new table name # my $table; Test($state or $table = FindNewTable($dbh)) or DbiError($dbh->err, $dbh->errstr); # # Create a new table # my $def; if (!$state) { ($def = TableDefinition($table, ["id", "INTEGER", 4, 0], ["name", "CHAR", 64, 0])); print "Creating table:\n$def\n"; } Test($state or $dbh->do($def)) or DbiError($dbh->err, $dbh->errstr); # # ... and drop it. # Test($state or $dbh->do("DROP TABLE $table")) or DbiError($dbh->err, $dbh->errstr); # # Finally disconnect. # Test($state or $dbh->disconnect()) or DbiError($dbh->err, $dbh->errstr); } DBD-SQLite2-0.36/t/40numrows.t0000644000175000017500000000775112126363474015150 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 40numrows.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This tests, whether the number of rows can be retrieved. # $^W = 1; $| = 1; # # Make -w happy # $test_dsn = ''; $test_user = ''; $test_password = ''; # # Include lib.pl # use DBI; $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl", "DBD-~DBD_DRIVER~/t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } sub TrueRows($) { my ($sth) = @_; my $count = 0; while ($sth->fetchrow_arrayref) { ++$count; } $count; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ServerError(); # # Find a possible new table name # Test($state or ($table = FindNewTable($dbh))) or DbiError($dbh->err, $dbh->errstr); # # Create a new table; EDIT THIS! # Test($state or ($def = TableDefinition($table, ["id", "INTEGER", 4, 0], ["name", "CHAR", 64, 0]), $dbh->do($def))) or DbiError($dbh->err, $dbh->errstr); # # This section should exercise the sth->rows # method by preparing a statement, then finding the # number of rows within it. # Prior to execution, this should fail. After execution, the # number of rows affected by the statement will be returned. # Test($state or $dbh->do("INSERT INTO $table" . " VALUES( 1, 'Alligator Descartes' )")) or DbiError($dbh->err, $dbh->errstr); Test($state or ($cursor = $dbh->prepare("SELECT * FROM $table" . " WHERE id = 1"))) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($dbh->err, $dbh->errstr); Test($state or ($numrows = TrueRows($cursor)) == 1) or ErrMsgF("Expected to fetch 1 rows, got %s.\n", $numrows); Test($state or $cursor->finish) or DbiError($dbh->err, $dbh->errstr); Test($state or undef $cursor or 1); Test($state or $dbh->do("INSERT INTO $table" . " VALUES( 2, 'Jochen Wiedmann' )")) or DbiError($dbh->err, $dbh->errstr); Test($state or ($cursor = $dbh->prepare("SELECT * FROM $table" . " WHERE id >= 1"))) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($dbh->err, $dbh->errstr); Test($state or ($numrows = TrueRows($cursor)) == 2) or ErrMsgF("Expected to fetch 2 rows, got %s.\n", $numrows); Test($state or $cursor->finish) or DbiError($dbh->err, $dbh->errstr); Test($state or undef $cursor or 1); Test($state or $dbh->do("INSERT INTO $table" . " VALUES(3, 'Tim Bunce')")) or DbiError($dbh->err, $dbh->errstr); Test($state or ($cursor = $dbh->prepare("SELECT * FROM $table" . " WHERE id >= 2"))) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($dbh->err, $dbh->errstr); Test($state or ($numrows = TrueRows($cursor)) == 2) or ErrMsgF("Expected to fetch 2 rows, got %s.\n", $numrows); # RT #16451 fetchrow() is called again after it has returned an # empty list Test($state or !TrueRows($cursor)) or ErrMsgF("Expected to fetch 0 rows\n"); Test($state or $cursor->finish) or DbiError($dbh->err, $dbh->errstr); Test($state or undef $cursor or 1); # # Finally drop the test table. # Test($state or $dbh->do("DROP TABLE $table")) or DbiError($dbh->err, $dbh->errstr); } DBD-SQLite2-0.36/t/06error.t0000644000175000017500000000074412126353147014560 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 2 } use DBI; unlink('foo'); my $db = DBI->connect('dbi:SQLite2:foo', '', '', { RaiseError => 1, PrintError => 0 }); eval { $db->do('ssdfsdf sdf sd sdfsdfdsf sdfsdf'); }; ok($@); $db->do('create table testerror (a, b)'); $db->do('insert into testerror values (1, 2)'); $db->do('insert into testerror values (3, 4)'); $db->do('create unique index testerror_idx on testerror (a)'); eval { $db->do('insert into testerror values (1, 5)'); }; ok($@); DBD-SQLite2-0.36/t/98_pod-coverage.t0000644000175000017500000000067312126410334016145 0ustar rurbanrurban# -*- perl -*- use strict; use warnings; use Test::More; plan skip_all => 'done_testing requires 5.8.6' if $] <= 5.008005; plan skip_all => 'This test is only run for the module author' unless -d '.git' || $ENV{IS_MAINTAINER}; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; pod_coverage_ok( "DBD::SQLite2", { trustme => [ qw( driver )]}); done_testing(); DBD-SQLite2-0.36/t/50chopblanks.t0000644000175000017500000000754412126353147015557 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 50chopblanks.t,v 1.1.1.1 2004/08/08 15:03:59 matt Exp $ # # This driver should check whether 'ChopBlanks' works. # # # Make -w happy # use vars qw($test_dsn $test_user $test_password $mdriver $verbose $state $dbdriver); use vars qw($COL_NULLABLE $COL_KEY); $test_dsn = ''; $test_user = ''; $test_password = ''; # # Include lib.pl # use DBI; use strict; $mdriver = ""; { my $file; foreach $file ("lib.pl", "t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } } sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { my ($dbh, $sth, $query); # # Connect to the database Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ServerError(); # # Find a possible new table name # my $table = ''; Test($state or $table = FindNewTable($dbh)) or ErrMsgF("Cannot determine a legal table name: Error %s.\n", $dbh->errstr); # # Create a new table; EDIT THIS! # Test($state or ($query = TableDefinition($table, ["id", "INTEGER", 4, $COL_NULLABLE], ["name", "CHAR", 64, $COL_NULLABLE]), $dbh->do($query))) or ErrMsgF("Cannot create table: Error %s.\n", $dbh->errstr); # # and here's the right place for inserting new tests: # my @rows = ([1, 'NULL'], [2, ' '], [3, ' a b c ']); my $ref; foreach $ref (@rows) { my ($id, $name) = @$ref; if (!$state) { $query = sprintf("INSERT INTO $table (id, name) VALUES ($id, %s)", $dbh->quote($name)); } Test($state or $dbh->do($query)) or ErrMsgF("INSERT failed: query $query, error %s.\n", $dbh->errstr); $query = "SELECT id, name FROM $table WHERE id = $id\n"; Test($state or ($sth = $dbh->prepare($query))) or ErrMsgF("prepare failed: query $query, error %s.\n", $dbh->errstr); # First try to retreive without chopping blanks. $sth->{'ChopBlanks'} = 0; Test($state or $sth->execute) or ErrMsgF("execute failed: query %s, error %s.\n", $query, $sth->errstr); Test($state or defined($ref = $sth->fetchrow_arrayref)) or ErrMsgF("fetch failed: query $query, error %s.\n", $sth->errstr); Test($state or ($$ref[1] eq $name) or ($name =~ /^$$ref[1]\s+$/ && ($dbdriver eq 'mysql' || $dbdriver eq 'ODBC'))) or ErrMsgF("problems with ChopBlanks = 0:" . " expected '%s', got '%s'.\n", $name, $$ref[1]); Test($state or $sth->finish()); # Now try to retreive with chopping blanks. $sth->{'ChopBlanks'} = 1; Test($state or $sth->execute) or ErrMsg("execute failed: query $query, error %s.\n", $sth->errstr); my $n = $name; $n =~ s/\s+$//; Test($state or ($ref = $sth->fetchrow_arrayref)) or ErrMsgF("fetch failed: query $query, error %s.\n", $sth->errstr); Test($state or ($$ref[1] eq $n)) or ErrMsgF("problems with ChopBlanks = 1:" . " expected '%s', got '%s'.\n", $n, $$ref[1]); Test($state or $sth->finish) or ErrMsgF("Cannot finish: %s.\n", $sth->errstr); } # # Finally drop the test table. # Test($state or $dbh->do("DROP TABLE $table")) or ErrMsgF("Cannot DROP test table $table: %s.\n", $dbh->errstr); # ... and disconnect Test($state or $dbh->disconnect) or ErrMsgF("Cannot disconnect: %s.\n", $dbh->errmsg); } DBD-SQLite2-0.36/t/98_meta.t0000644000175000017500000000127612126410203014513 0ustar rurbanrurban# -*- perl -*- # Test that our META.yml file matches the current specification. use strict; BEGIN { $| = 1; $^W = 1; } my $MODULE = 'Test::CPAN::Meta 0.12'; # Don't run tests for installs use Test::More; use Config; plan skip_all => 'This test is only run for the module author' unless -d '.git' || $ENV{IS_MAINTAINER}; plan skip_all => 'Test::CPAN::Meta fails with clang -faddress-sanitizer' if $Config{ccflags} =~ /-faddress-sanitizer/; # Load the testing module eval "use $MODULE;"; if ( $@ ) { plan( skip_all => "$MODULE not available for testing" ); die "Failed to load required release-testing module $MODULE 0.12" if -d '.git' || $ENV{IS_MAINTAINER}; } meta_yaml_ok(); DBD-SQLite2-0.36/t/98_pod.t0000644000175000017500000000022512126410203014340 0ustar rurbanrurban# -*- perl -*- use Test::More; eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); DBD-SQLite2-0.36/t/40nulls.t0000644000175000017500000000510412126353147014555 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 40nulls.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This is a test for correctly handling NULL values. # # # Make -w happy # $test_dsn = ''; $test_user = ''; $test_password = ''; # # Include lib.pl # use DBI; use vars qw($COL_NULLABLE); $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password)) or ServerError(); # # Find a possible new table name # Test($state or $table = FindNewTable($dbh)) or DbiError($dbh->err, $dbh->errstr); # # Create a new table; EDIT THIS! # Test($state or ($def = TableDefinition($table, ["id", "INTEGER", 4, $COL_NULLABLE], ["name", "CHAR", 64, 0]), $dbh->do($def))) or DbiError($dbh->err, $dbh->errstr); # # Test whether or not a field containing a NULL is returned correctly # as undef, or something much more bizarre # Test($state or $dbh->do("INSERT INTO $table VALUES" . " ( NULL, 'NULL-valued id' )")) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor = $dbh->prepare("SELECT * FROM $table" . " WHERE " . IsNull("id"))) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($dbh->err, $dbh->errstr); Test($state or ($rv = $cursor->fetchrow_arrayref) or $dbdriver eq 'CSV' or $dbdriver eq 'ConfFile') or DbiError($dbh->err, $dbh->errstr); Test($state or (!defined($$rv[0]) and defined($$rv[1])) or $dbdriver eq 'CSV' or $dbdriver eq 'ConfFile') or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->finish) or DbiError($dbh->err, $dbh->errstr); Test($state or undef $cursor || 1); # # Finally drop the test table. # Test($state or $dbh->do("DROP TABLE $table")) or DbiError($dbh->err, $dbh->errstr); } DBD-SQLite2-0.36/t/03insert.t0000644000175000017500000000075512126353147014732 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 9 } use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", ""); ok($dbh); my $sth = $dbh->prepare("INSERT INTO f VALUES (?, ?, ?)"); ok($sth); ok(my $rows = $sth->execute("Fred", "Bloggs", "fred\@bloggs.com")); ok($rows == 1); ok($dbh->func('last_insert_rowid')); ok($sth->execute("test", "test", "1")); ok($sth->execute("test", "test", "2")); ok($sth->execute("test", "test", "3")); ok($dbh->do("delete from f where f1='test'") == 3); $dbh->disconnect; DBD-SQLite2-0.36/t/40listfields.t0000644000175000017500000000644212126353147015570 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 40listfields.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This is a test for statement attributes being present appropriately. # # # Make -w happy # $test_dsn = ''; $test_user = ''; $test_password = ''; $COL_KEY = ''; # # Include lib.pl # use DBI; use vars qw($verbose); $dbdriver = ""; foreach $file ("lib.pl", "t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($dbdriver ne '') { last; } } @table_def = ( ["id", "INTEGER", 4, $COL_KEY], ["name", "CHAR", 64, $COL_NULLABLE] ); sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database Test($state or $dbh = DBI->connect($test_dsn, $test_user, $test_password)) or ServerError(); # # Find a possible new table name # Test($state or $table = FindNewTable($dbh)) or DbiError($dbh->err, $dbh->errstr); # # Create a new table # Test($state or ($def = TableDefinition($table, @table_def), $dbh->do($def))) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor = $dbh->prepare("SELECT * FROM $table")) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($cursor->err, $cursor->errstr); my $res; Test($state or (($res = $cursor->{'NUM_OF_FIELDS'}) == @table_def)) or DbiError($cursor->err, $cursor->errstr); if (!$state && $verbose) { printf("Number of fields: %s\n", defined($res) ? $res : "undef"); } Test($state or ($ref = $cursor->{'NAME'}) && @$ref == @table_def && (lc $$ref[0]) eq $table_def[0][0] && (lc $$ref[1]) eq $table_def[1][0]) or DbiError($cursor->err, $cursor->errstr); if (!$state && $verbose) { print "Names:\n"; for ($i = 0; $i < @$ref; $i++) { print " ", $$ref[$i], "\n"; } } Test($state or ($dbdriver eq 'CSV') or ($dbdriver eq 'ConfFile') or ($dbdriver eq 'SQLite2') or ($ref = $cursor->{'NULLABLE'}) && @$ref == @table_def && !($$ref[0] xor ($table_def[0][3] & $COL_NULLABLE)) && !($$ref[1] xor ($table_def[1][3] & $COL_NULLABLE))) or DbiError($cursor->err, $cursor->errstr); if (!$state && $verbose) { print "Nullable:\n"; for ($i = 0; $i < @$ref; $i++) { print " ", ($$ref[$i] & $COL_NULLABLE) ? "yes" : "no", "\n"; } } Test($state or undef $cursor || 1); # # Drop the test table # Test($state or ($cursor = $dbh->prepare("DROP TABLE $table"))) or DbiError($dbh->err, $dbh->errstr); Test($state or $cursor->execute) or DbiError($cursor->err, $cursor->errstr); # NUM_OF_FIELDS should be zero (Non-Select) Test($state or ($cursor->{'NUM_OF_FIELDS'} == 0)) or !$verbose or printf("NUM_OF_FIELDS is %s, not zero.\n", $cursor->{'NUM_OF_FIELDS'}); Test($state or (undef $cursor) or 1); } DBD-SQLite2-0.36/t/01logon.t0000644000175000017500000000042712126353147014536 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 3 } use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", ""); ok($dbh); ok($dbh->{sqlite_version}); ok($dbh->{sqlite_encoding}); print "sqlite_version=$dbh->{sqlite_version}, sqlite_encoding=$dbh->{sqlite_encoding}\n"; $dbh->disconnect; DBD-SQLite2-0.36/t/99cleanup.t0000644000175000017500000000012112126353147015057 0ustar rurbanrurbanuse Test; BEGIN { plan tests => 2 } ok(-e 'foo'); unlink('foo'); ok(!-e 'foo'); DBD-SQLite2-0.36/t/ak-dbd.t0000644000175000017500000003227212126353147014404 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: ak-dbd.t,v 1.1.1.1 2004/08/08 15:03:59 matt Exp $ # # This is a skeleton test. For writing new tests, take this file # and modify/extend it. # $^W = 1; $| = 1; # # Make -w happy # use vars qw($test_dsn $test_user $test_password $dbdriver $mdriver $verbose $state); use vars qw($COL_NULLABLE $COL_KEY); $test_dsn = ''; $test_user = ''; $test_password = ''; # # Include lib.pl # use DBI; use strict; $dbdriver = ""; { my $file; foreach $file ("lib.pl", "t/lib.pl", "DBD-~DBD_DRIVER~/t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($dbdriver ne '') { last; } } } my $test_db = ''; my $test_hostname = $ENV{DBI_HOST} || 'localhost'; if ($test_dsn =~ /^DBI\:[^\:]+\:/) { $test_db = $'; if ($test_db =~ /:/) { $test_db = $`; $test_hostname = $'; } } # # Main loop; leave this untouched, put tests after creating # the new table. # while (Testing()) { # # Connect to the database my($dbh, $sth, $test_table, $query); $test_table = ''; # Avoid warnings for undefined variables. Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ErrMsg("Cannot connect: $DBI::errstr.\n"); # # Verify whether constants work # if ($mdriver eq 'mysql') { my ($val); Test($state or (($val = &DBD::mysql::FIELD_TYPE_STRING()) == 254)) or ErrMsg("Wrong value for FIELD_TYPE_STRING:" . " Expected 254, got $val\n"); Test($state or (($val = &DBD::mysql::FIELD_TYPE_SHORT()) == 2)) or ErrMsg("Wrong value for FIELD_TYPE_SHORT:" . " Expected 2, got $val\n"); } elsif ($mdriver eq 'mSQL') { my ($val); Test($state or (($val = &DBD::mSQL::CHAR_TYPE()) == 2)) or ErrMsg("Wrong value for CHAR_TYPE: Expected 2, got $val\n"); Test($state or (($val = &DBD::mSQL::INT_TYPE()) == 1)) or ErrMsg("Wrong value for INT_TYPE: Expected 1, got $val\n"); } # # Find a possible new table name # Test($state or $test_table = FindNewTable($dbh)) or !$verbose or ErrMsg("Cannot get table name: $dbh->errstr.\n"); # # Create a new table; EDIT THIS! # Test($state or ($query = TableDefinition($test_table, ["id", "INTEGER", 4, $COL_NULLABLE], ["name", "CHAR", 64, $COL_NULLABLE]), $dbh->do($query))) or ErrMsg("Cannot create table: query $query error $dbh->errstr.\n"); # # and here's the right place for inserting new tests: # Test($state or $dbh->quote('tast1')) or ErrMsgF("quote('tast1') returned %s.\n", $dbh->quote('tast1')); ### ...and disconnect Test($state or $dbh->disconnect) or ErrMsg("\$dbh->disconnect() failed!\n", "Make sure your server is still functioning", "correctly, and check to make\n", "sure your network isn\'t malfunctioning in the", "case of the server running on a remote machine.\n"); ### Now, re-connect again so that we can do some more complicated stuff.. Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ErrMsg("reconnect failed: $DBI::errstr\n"); ### List all the tables in the selected database........ ### This test for mSQL and mysql only. if ($mdriver eq 'mysql' or $mdriver eq 'mSQL' or $mdriver eq 'mSQL1') { Test($state or $dbh->func('_ListTables')) or ErrMsgF("_ListTables failed: $dbh->errstr.\n" . "This could be due to the fact you have no tables," . " but I hope not. You\n" . "could try running '%s -h %s %s' and see if it\n" . "reports any information about your database," . " or errors.\n", ($mdriver eq 'mysql') ? "mysqlshow" : "relshow", $test_hostname, $test_db); } Test($state or $dbh->do("DROP TABLE $test_table")) or ErrMsg("Dropping table failed: $dbh->errstr.\n"); Test($state or ($query = TableDefinition($test_table, ["id", "INTEGER", 4, $COL_NULLABLE], ["name", "CHAR", 64, $COL_NULLABLE]), $dbh->do($query))) or ErrMsg("create failed, query $query, error $dbh->errstr.\n"); ### Get some meta-data for the table we've just created... if ($mdriver eq 'mysql' or $mdriver eq 'mSQL1' or $mdriver eq 'mSQL') { my $ref; Test($state or ($ref = $dbh->prepare("LISTFIELDS $test_table"))) or ErrMsg("listfields failed: $dbh->errstr.\n"); Test($state or $ref->execute); } ### Insert a row into the test table....... print "Inserting a row...\n"; Test($state or ($dbh->do("INSERT INTO $test_table VALUES(1," . " 'Alligator Descartes')"))) or ErrMsg("INSERT failed: $dbh->errstr.\n"); ### ...and delete it........ print "Deleting a row...\n"; Test($state or $dbh->do("DELETE FROM $test_table WHERE id = 1")) or ErrMsg("Cannot delete row: $dbh->errstr.\n"); Test($state or ($sth = $dbh->prepare("SELECT * FROM $test_table" . " WHERE id = 1"))) or ErrMsg("Cannot select: $dbh->errstr.\n"); # This should fail with error message: We "forgot" execute. my($pe) = $sth->{'PrintError'}; $sth->{'PrintError'} = 0; Test($state or !eval { $sth->fetchrow() }) or ErrMsg("Missing error report from fetchrow.\n"); $sth->{'PrintError'} = $pe; Test($state or $sth->execute) or ErrMsg("execute SELECT failed: $dbh->errstr.\n"); # This should fail without error message: No rows returned. my(@row, $ref); { local($^W) = 0; Test($state or !defined($ref = $sth->fetch)) or ErrMsgF("Unexpected row returned by fetchrow: $ref\n". scalar(@row)); } # Now try a "finish" Test($state or $sth->finish) or ErrMsg("sth->finish failed: $sth->errstr.\n"); # Call destructors: Test($state or (undef $sth || 1)); ### This section should exercise the sth->func( '_NumRows' ) private ### method by preparing a statement, then finding the number of rows ### within it. Prior to execution, this should fail. After execution, ### the number of rows affected by the statement will be returned. Test($state or ($dbh->do($query = "INSERT INTO $test_table VALUES" . " (1, 'Alligator Descartes' )"))) or ErrMsgF("INSERT failed: query $query, error %s.\n", $dbh->errstr); Test($state or ($sth = $dbh->prepare($query = "SELECT * FROM $test_table" . " WHERE id = 1"))) or ErrMsgF("prepare failed: query $query, error %s.\n", $dbh->errstr); if ($dbdriver eq 'mysql' || $dbdriver eq 'mSQL' || $dbdriver eq 'mSQL1') { Test($state or defined($sth->rows)) or ErrMsg("sth->rows returning result before 'execute'.\n"); } if (!$state) { print "Test 19: Setting \$debug_me to TRUE\n"; $::debug_me = 1; } Test($state or $sth->execute) or ErrMsgF("execute failed: query $query, error %s.\n", $sth->errstr); Test($state or ($sth->rows == 1) or ($sth->rows == -1)) or ErrMsgF("sth->rows returned wrong result %s after 'execute'.\n", $sth->rows); Test($state or $sth->finish) or ErrMsgF("finish failed: %s.\n", $sth->errstr); Test($state or (undef $sth or 1)); ### Test whether or not a field containing a NULL is returned correctly ### as undef, or something much more bizarre $query = "INSERT INTO $test_table VALUES ( NULL, 'NULL-valued id' )"; Test($state or $dbh->do($query)) or ErrMsgF("INSERT failed: query $query, error %s.\n", $dbh->errstr); $query = "SELECT id FROM $test_table WHERE " . IsNull("id"); Test($state or ($sth = $dbh->prepare($query))) or ErrMsgF("Cannot prepare, query = $query, error %s.\n", $dbh->errstr); if (!$state) { print "Test 25: Setting \$debug_me to TRUE\n"; $::debug_me = 1; } Test($state or $sth->execute) or ErrMsgF("Cannot execute, query = $query, error %s.\n", $dbh->errstr); my $rv; Test($state or defined($rv = $sth->fetch) or $dbdriver eq 'CSV' or $dbdriver eq 'ConfFile') or ErrMsgF("fetch failed, error %s.\n", $dbh->errstr); Test($state or !defined($$rv[0])) or ErrMsgF("Expected NULL value, got %s.\n", $$rv[0]); Test($state or $sth->finish) or ErrMsgF("finish failed: %s.\n", $sth->errstr); Test($state or undef $sth or 1); ### Delete the test row from the table $query = "DELETE FROM $test_table WHERE id = NULL AND" . " name = 'NULL-valued id'"; Test($state or ($rv = $dbh->do($query))) or ErrMsg("DELETE failed: query $query, error %s.\n", $dbh->errstr); ### Test whether or not a char field containing a blank is returned ### correctly as blank, or something much more bizarre $query = "INSERT INTO $test_table VALUES (2, NULL)"; Test($state or $dbh->do($query)) or ErrMsg("INSERT failed: query $query, error %s.\n", $dbh->errstr); $query = "SELECT name FROM $test_table WHERE id = 2 AND name IS NULL"; Test($state or ($sth = $dbh->prepare($query))) or ErrMsg("prepare failed: query $query, error %s.\n", $dbh->errstr); Test($state or $sth->execute) or ErrMsg("execute failed: query $query, error %s.\n", $dbh->errstr); $rv = undef; Test($state or defined($ref = $sth->fetch)) or ErrMsgF("fetchrow failed: query $query, error %s.\n", $sth->errstr); Test($state or !defined($$ref[0]) ) or ErrMsgF("blank value returned as [%s].\n", $$ref[0]); Test($state or $sth->finish) or ErrMsg("finish failed: $sth->errmsg.\n"); Test($state or undef $sth or 1); ### Delete the test row from the table $query = "DELETE FROM $test_table WHERE id = 2 AND name IS NULL"; Test($state or $dbh->do($query)) or ErrMsg("DELETE failed: query $query, error $dbh->errstr.\n"); ### Test the new funky routines to list the fields applicable to a SELECT ### statement, and not necessarily just those in a table... $query = "SELECT * FROM $test_table"; Test($state or ($sth = $dbh->prepare($query))) or ErrMsg("prepare failed: query $query, error $dbh->errstr.\n"); Test($state or $sth->execute) or ErrMsg("execute failed: query $query, error $dbh->errstr.\n"); if ($mdriver eq 'mysql' || $mdriver eq 'mSQL' || $mdriver eq 'mSQL1') { my($warning); $SIG{__WARN__} = sub { $warning = shift; }; Test($state or ($ref = $sth->func('_ListSelectedFields'))) or ErrMsg("_ListSelectedFields failed, error $sth->errstr.\n"); Test($state or ($warning =~ /deprecated/)) or ErrMsg("Expected warning from _ListSelectedFields"); $SIG{__WARN__} = 'DEFAULT'; } Test($state or $sth->execute, 'execute 284') or ErrMsg("re-execute failed: query $query, error $dbh->errstr.\n"); Test($state or (@row = $sth->fetchrow_array), 'fetchrow 286') or ErrMsg("Query returned no result, query $query,", " error $sth->errstr.\n"); Test($state or $sth->finish) or ErrMsg("finish failed: $sth->errmsg.\n"); Test($state or undef $sth or 1); ### Insert some more data into the test table......... $query = "INSERT INTO $test_table VALUES( 2, 'Gary Shea' )"; Test($state or $dbh->do($query)) or ErrMsg("INSERT failed: query $query, error $dbh->errstr.\n"); $query = "UPDATE $test_table SET id = 3 WHERE name = 'Gary Shea'"; Test($state or ($sth = $dbh->prepare($query))) or ErrMsg("prepare failed: query $query, error $sth->errmsg.\n"); # This should fail: We "forgot" execute. if ($mdriver eq 'mysql' || $mdriver eq 'mSQL' || $mdriver eq 'mSQL1') { Test($state or !defined($sth->{'NAME'})) or ErrMsg("Expected error without execute, got $ref.\n"); } Test($state or undef $sth or 1); ### Drop the test table out of our database to clean up......... $query = "DROP TABLE $test_table"; Test($state or $dbh->do($query)) or ErrMsg("DROP failed: query $query, error $dbh->errstr.\n"); Test($state or $dbh->disconnect) or ErrMsg("disconnect failed: $dbh->errstr.\n"); # # Try mysql's insertid feature # if ($dbdriver eq 'mysql') { my ($sth, $table); Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ErrMsgF("connect failed: %s.\n", $DBI::errstr); Test($state or ($table = FindNewTable($dbh))); Test($state or $dbh->do("CREATE TABLE $table (" . " id integer AUTO_INCREMENT PRIMARY KEY," . " country char(30) NOT NULL)")) or printf("Error while executing query: %s\n", $dbh->errstr); Test($state or ($sth = $dbh->prepare("INSERT INTO $table VALUES (NULL, 'a')"))) or printf("Error while preparing query: %s\n", $dbh->errstr); Test($state or $sth->execute) or printf("Error while executing query: %s\n", $sth->errstr); Test($state or $sth->finish) or printf("Error while finishing query: %s\n", $sth->errstr); Test($state or ($sth = $dbh->prepare("INSERT INTO $table VALUES (NULL, 'b')"))) or printf("Error while preparing query: %s\n", $dbh->errstr); Test($state or $sth->execute) or printf("Error while executing query: %s\n", $sth->errstr); Test($state or $sth->{insertid} =~ /\d+/) or printf("insertid generated incorrect result: %s\n", $sth->insertid); Test($state or $sth->finish) or printf("Error while finishing query: %s\n", $sth->errstr); Test($state or $dbh->do("DROP TABLE $table")); Test($state or $dbh->disconnect) or ErrMsg("disconnect failed: $dbh->errstr.\n"); } } DBD-SQLite2-0.36/t/lib.pl0000644000175000017500000001412012126353147014170 0ustar rurbanrurban# Hej, Emacs, give us -*- perl mode here! # # $Id: lib.pl,v 1.1.1.1 2004/08/08 15:03:59 matt Exp $ # # lib.pl is the file where database specific things should live, # whereever possible. For example, you define certain constants # here and the like. # require 5.003; use strict; use vars qw($mdriver $dbdriver $childPid $test_dsn $test_user $test_password $haveFileSpec); # # Driver names; EDIT THIS! # $mdriver = 'SQLite2'; $dbdriver = $mdriver; # $dbdriver is usually just the same as $mdriver. # The exception is DBD::pNET where we have to # to separate between local driver (pNET) and # the remote driver ($dbdriver) # # DSN being used; do not edit this, edit "$dbdriver.dbtest" instead # $haveFileSpec = eval { require File::Spec }; my $table_dir = $haveFileSpec ? File::Spec->catdir(File::Spec->curdir(), 'output', 'foo') : 'output/foo'; $test_dsn = $ENV{'DBI_DSN'} || "DBI:$dbdriver:dbname=$table_dir"; $test_user = $ENV{'DBI_USER'} || ""; $test_password = $ENV{'DBI_PASS'} || ""; $::COL_NULLABLE = 1; $::COL_KEY = 2; my $file; if (-f ($file = "t/$dbdriver.dbtest") || -f ($file = "$dbdriver.dbtest") || -f ($file = "../tests/$dbdriver.dbtest") || -f ($file = "tests/$dbdriver.dbtest")) { eval { require $file; }; if ($@) { print STDERR "Cannot execute $file: $@.\n"; print "1..0\n"; exit 0; } } if (-f ($file = "t/$mdriver.mtest") || -f ($file = "$mdriver.mtest") || -f ($file = "../tests/$mdriver.mtest") || -f ($file = "tests/$mdriver.mtest")) { eval { require $file; }; if ($@) { print STDERR "Cannot execute $file: $@.\n"; print "1..0\n"; exit 0; } } open (STDERR, ">&STDOUT") || die "Cannot redirect stderr" ; select (STDERR) ; $| = 1 ; select (STDOUT) ; $| = 1 ; # # The Testing() function builds the frame of the test; it can be called # in many ways, see below. # # Usually there's no need for you to modify this function. # # Testing() (without arguments) indicates the beginning of the # main loop; it will return, if the main loop should be # entered (which will happen twice, once with $state = 1 and # once with $state = 0) # Testing('off') disables any further tests until the loop ends # Testing('group') indicates the begin of a group of tests; you # may use this, for example, if there's a certain test within # the group that should make all other tests fail. # Testing('disable') disables further tests within the group; must # not be called without a preceding Testing('group'); by default # tests are enabled # Testing('enabled') reenables tests after calling Testing('disable') # Testing('finish') terminates a group; any Testing('group') must # be paired with Testing('finish') # # You may nest test groups. # { # Note the use of the pairing {} in order to get local, but static, # variables. my (@stateStack, $count, $off); $count = 0; sub Testing(;$) { my ($command) = shift; if (!defined($command)) { @stateStack = (); $off = 0; if ($count == 0) { ++$count; $::state = 1; } elsif ($count == 1) { my($d); if ($off) { print "1..0\n"; exit 0; } ++$count; $::state = 0; print "1..$::numTests\n"; } else { return 0; } if ($off) { $::state = 1; } $::numTests = 0; } elsif ($command eq 'off') { $off = 1; $::state = 0; } elsif ($command eq 'group') { push(@stateStack, $::state); } elsif ($command eq 'disable') { $::state = 0; } elsif ($command eq 'enable') { if ($off) { $::state = 0; } else { my $s; $::state = 1; foreach $s (@stateStack) { if (!$s) { $::state = 0; last; } } } return; } elsif ($command eq 'finish') { $::state = pop(@stateStack); } else { die("Testing: Unknown argument\n"); } return 1; } # # Read a single test result # sub Test ($;$$) { my($result, $error, $diag) = @_; ++$::numTests; if ($count == 2) { if (defined($diag)) { printf("$diag%s", (($diag =~ /\n$/) ? "" : "\n")); } if ($::state || $result) { print "ok $::numTests ". (defined($error) ? "$error\n" : "\n"); return 1; } else { print("not ok $::numTests - " . (defined($error) ? "$error\n" : "\n")); print("FAILED Test $::numTests - " . (defined($error) ? "$error\n" : "\n")); return 0; } } return 1; } } # # Print a DBI error message # sub DbiError ($$) { my($rc, $err) = @_; $rc ||= 0; $err ||= ''; print "Test $::numTests: DBI error $rc, $err\n"; } # # This functions generates a list of possible DSN's aka # databases and returns a possible table name for a new # table being created. # # Problem is, we have two different situations here: Test scripts # call us by pasing a dbh, which is fine for most situations. # From within DBD::pNET, however, the dbh isn't that meaningful. # Thus we are working with the global variable $listTablesHook: # Once defined, we call &$listTablesHook instead of ListTables. # # See DBD::pNET/t/pNET.mtest for details. # { use vars qw($listTablesHook); my(@tables, $testtable, $listed); $testtable = "testaa"; $listed = 0; sub FindNewTable($) { my($dbh) = @_; if (!$listed) { if (defined($listTablesHook)) { @tables = &$listTablesHook($dbh); } elsif (defined(&ListTables)) { @tables = &ListTables($dbh); } else { die "Fatal: ListTables not implemented.\n"; } $listed = 1; } # A small loop to find a free test table we can use to mangle stuff in # and out of. This starts at testaa and loops until testaz, then testba # - testbz and so on until testzz. my $foundtesttable = 1; my $table; while ($foundtesttable) { $foundtesttable = 0; foreach $table (@tables) { if ($table eq $testtable) { $testtable++; $foundtesttable = 1; } } } $table = $testtable; $testtable++; $table; } } sub ErrMsg { print (@_); } sub ErrMsgF { printf (@_); } 1; DBD-SQLite2-0.36/t/09create_aggregate.t0000644000175000017500000000742712126353147016710 0ustar rurbanrurbanuse strict; package count_aggr; sub new { bless { count => 0 }, shift; } sub step { $_[0]{count}++; return; } sub finalize { my $c = $_[0]{count}; $_[0]{count} = undef; return $c; } package obj_aggregate; sub new { bless { count => 0 }, shift; } sub step { $_[0]{count}++ if defined $_[1]; } sub finalize { my $c = $_[0]{count}; $_[0]{count} = undef; return $c; } package fail_aggregate; sub new { my $class = shift; if ( ref $class ) { die "new() failed on request" if $class->{'fail'} eq 'new'; return undef if $class->{'fail'} eq 'undef'; return bless { %$class }, ref $class; } else { return bless { 'fail' => $_[0] }, $class; } } sub step { die "step() failed on request" if $_[0]{fail} eq 'step'; } sub finalize { die "finalize() failed on request" if $_[0]{fail} eq 'finalize'; } package main; use Test; BEGIN { plan tests => 15 } use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=foo", "", "", { PrintError => 0 } ); ok($dbh); $dbh->do( "DROP TABLE aggr_test;" ); $dbh->do( "CREATE TABLE aggr_test ( field )" ); foreach my $val ( qw/NULL 1 'test'/ ) { $dbh->do( "INSERT INTO aggr_test VALUES ( $val )" ); } $dbh->func( "newcount", 0, "count_aggr", "create_aggregate" ); my $result = $dbh->selectrow_arrayref( "SELECT newcount() FROM aggr_test" ); ok( $result && $result->[0] == 3 ); # Make sure that the init() function is called correctly $result = $dbh->selectall_arrayref( "SELECT newcount() FROM aggr_test GROUP BY field" ); ok( @$result == 3 && $result->[0][0] == 1 && $result->[1][0] == 1 ); # Test aggregate on empty table $dbh->do( "DROP TABLE aggr_empty_test;" ); $dbh->do( "CREATE TABLE aggr_empty_test ( field )" ); $result = $dbh->selectrow_arrayref( "SELECT newcount() FROM aggr_empty_test" ); ok( $result && !$result->[0] ); # Make sure that the init() function is called correctly $result = $dbh->selectrow_arrayref( "SELECT newcount() FROM aggr_empty_test" ); ok( $result && !$result->[0] ); $dbh->func( "defined", 1, 'obj_aggregate', "create_aggregate" ); $result = $dbh->selectrow_arrayref( "SELECT defined(field) FROM aggr_test" ); ok( $result && $result->[0] == 2 ); $result = $dbh->selectrow_arrayref( "SELECT defined(field) FROM aggr_test" ); ok( $result && $result->[0] == 2 ); $result = $dbh->selectrow_arrayref( "SELECT defined(field) FROM aggr_empty_test" ); ok( $result && !$result->[0] ); $result = $dbh->selectrow_arrayref( "SELECT defined(field) FROM aggr_empty_test" ); ok( $result && !$result->[0] ); my $last_warn; local $SIG{__WARN__} = sub { $last_warn = join "", @_ }; foreach my $fail ( qw/ new step finalize/ ) { $last_warn = ''; my $aggr = new fail_aggregate( $fail ); $dbh->func( "fail_$fail", -1, $aggr, 'create_aggregate' ); $result = $dbh->selectrow_arrayref( "SELECT fail_$fail() FROM aggr_test" ); # ok( !$result && $DBI::errstr =~ /$fail\(\) failed on request/ ); ok( !defined $result->[0] && $last_warn =~ /$fail\(\) failed on request/ ); # No need to check this one, since step() will never be called # on an empty table next if $fail eq 'step'; $result = $dbh->selectrow_arrayref( "SELECT fail_$fail() FROM aggr_empty_test" ); # ok( !$result && $DBI::errstr =~ /$fail\(\) failed on request/ ); ok( !defined $result->[0] && $last_warn =~ /$fail\(\) failed on request/ ); } my $aggr = new fail_aggregate( 'undef' ); $last_warn = ''; $dbh->func( "fail_undef", -1, $aggr, 'create_aggregate' ); $result = $dbh->selectrow_arrayref( "SELECT fail_undef() FROM aggr_test" ); # ok( !$result && $DBI::errstr =~ /new\(\) should return a blessed reference/ ); ok( !defined $result->[0] && $last_warn =~ /new\(\) should return a blessed reference/ ); DBD-SQLite2-0.36/t/98_perl_minimum_version.t0000644000175000017500000000137112126410203020023 0ustar rurbanrurban#!/usr/bin/perl # Test that our declared minimum Perl version matches our syntax use strict; BEGIN { $| = 1; $^W = 1; } my @MODULES = ( 'Perl::MinimumVersion 1.20', 'Test::MinimumVersion 0.008', ); # Don't run tests during end-user installs use Test::More; unless (-d '.git' || $ENV{IS_MAINTAINER}) { plan( skip_all => "Author tests not required for installation" ); } # Load the testing modules foreach my $MODULE ( @MODULES ) { eval "use $MODULE"; if ( $@ ) { plan( skip_all => "$MODULE not available for testing" ); die "Failed to load required release-testing module $MODULE" if -d '.git' || $ENV{IS_MAINTAINER}; } } # Note: constant_hash requires 5.8 but works okay with 5.6.2 here all_minimum_version_ok("5.008"); 1; DBD-SQLite2-0.36/t/10dsnlist.t0000644000175000017500000000375312126353147015105 0ustar rurbanrurban#!/usr/local/bin/perl # # $Id: 10dsnlist.t,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ # # This test creates a database and drops it. Should be executed # after listdsn. # # # Include lib.pl # require DBI; $mdriver = ""; foreach $file ("lib.pl", "t/lib.pl", "DBD-~DBD_DRIVER~/t/lib.pl") { do $file; if ($@) { print STDERR "Error while executing lib.pl: $@\n"; exit 10; } if ($mdriver ne '') { last; } } if ($mdriver eq 'pNET' || $mdriver eq 'Adabas') { print "1..0\n"; exit 0; } print "Driver is $mdriver\n"; sub ServerError() { print STDERR ("Cannot connect: ", $DBI::errstr, "\n", "\tEither your server is not up and running or you have no\n", "\tpermissions for acessing the DSN $test_dsn.\n", "\tThis test requires a running server and write permissions.\n", "\tPlease make sure your server is running and you have\n", "\tpermissions, then retry.\n"); exit 10; } # # Main loop; leave this untouched, put tests into the loop # while (Testing()) { # Check if the server is awake. $dbh = undef; Test($state or ($dbh = DBI->connect($test_dsn, $test_user, $test_password))) or ServerError(); Test($state or (@dsn = DBI->data_sources($mdriver)) >= 0); if (!$state) { my $d; print "List of $mdriver data sources:\n"; foreach $d (@dsn) { print " $d\n"; } print "List ends.\n"; } Test($state or $dbh->disconnect()); # # Try different DSN's # my(@dsnList); if (($mdriver eq 'mysql' or $mdriver eq 'mSQL') and $test_dsn eq "DBI:$mdriver:test") { @dsnList = ("DBI:$mdriver:test:localhost", "DBI:$mdriver:test;localhost", "DBI:$mdriver:database=test;host=localhost"); } my($dsn); foreach $dsn (@dsnList) { Test($state or ($dbh = DBI->connect($dsn, $test_user, $test_password))) or print "Cannot connect to DSN $dsn: ${DBI::errstr}\n"; Test($state or $dbh->disconnect()); } } exit 0; # Hate -w :-) $test_dsn = $test_user = $test_password = $DBI::errstr; DBD-SQLite2-0.36/t/98_kwalitee.t0000644000175000017500000000112612126410203015364 0ustar rurbanrurban# -*- perl -*- use strict; use warnings; use Test::More; use Config; plan skip_all => 'This test is only run for the module author' unless -d '.git' || $ENV{IS_MAINTAINER}; plan skip_all => 'Test::Kwalitee fails with clang -faddress-sanitizer' if $Config{ccflags} =~ /-faddress-sanitizer/; use File::Copy 'cp'; cp('MYMETA.yml','META.yml') if -e 'MYMETA.yml' and !-e 'META.yml'; eval { require Test::Kwalitee; Test::Kwalitee->import( tests => [ qw( -use_strict -has_test_pod -has_test_pod_coverage)]); }; plan skip_all => "Test::Kwalitee needed for testing kwalitee" if $@; DBD-SQLite2-0.36/vdbeInt.h0000644000175000017500000003120612126353147014372 0ustar rurbanrurban/* ** 2003 September 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for information that is private to the ** VDBE. This information used to all be at the top of the single ** source code file "vdbe.c". When that file became too big (over ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. */ /* ** When converting from the native format to the key format and back ** again, in addition to changing the byte order we invert the high-order ** bit of the most significant byte. This causes negative numbers to ** sort before positive numbers in the memcmp() function. */ #define keyToInt(X) (sqliteVdbeByteSwap(X) ^ 0x80000000) #define intToKey(X) (sqliteVdbeByteSwap((X) ^ 0x80000000)) /* ** The makefile scans this source file and creates the following ** array of string constants which are the names of all VDBE opcodes. ** This array is defined in a separate source code file named opcode.c ** which is automatically generated by the makefile. */ extern char *sqliteOpcodeNames[]; /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance ** of the following structure. */ typedef struct VdbeOp Op; /* ** Boolean values */ typedef unsigned char Bool; /* ** A cursor is a pointer into a single BTree within a database file. ** The cursor can seek to a BTree entry with a particular key, or ** loop over all entries of the Btree. You can also insert new BTree ** entries or retrieve the key or data from the entry that the cursor ** is currently pointing to. ** ** Every cursor that the virtual machine has open is represented by an ** instance of the following structure. ** ** If the Cursor.isTriggerRow flag is set it means that this cursor is ** really a single row that represents the NEW or OLD pseudo-table of ** a row trigger. The data for the row is stored in Cursor.pData and ** the rowid is in Cursor.iKey. */ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ int lastRecno; /* Last recno from a Next or NextIdx operation */ int nextRowid; /* Next rowid returned by OP_NewRowid */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool nextRowidValid; /* True if the nextRowid field is valid */ Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */ Bool deferredMoveto; /* A call to sqliteBtreeMoveto() is needed */ int movetoTarget; /* Argument to the deferred sqliteBtreeMoveto() */ Btree *pBt; /* Separate file holding temporary table */ int nData; /* Number of bytes in pData */ char *pData; /* Data for a NEW or OLD pseudo-table */ int iKey; /* Key for the NEW or OLD pseudo-table row */ }; typedef struct Cursor Cursor; /* ** A sorter builds a list of elements to be sorted. Each element of ** the list is an instance of the following structure. */ typedef struct Sorter Sorter; struct Sorter { int nKey; /* Number of bytes in the key */ char *zKey; /* The key by which we will sort */ int nData; /* Number of bytes in the data */ char *pData; /* The data associated with this key */ Sorter *pNext; /* Next in the list */ }; /* ** Number of buckets used for merge-sort. */ #define NSORT 30 /* ** Number of bytes of string storage space available to each stack ** layer without having to malloc. NBFS is short for Number of Bytes ** For Strings. */ #define NBFS 32 /* ** A single level of the stack or a single memory cell ** is an instance of the following structure. */ struct Mem { int i; /* Integer value */ int n; /* Number of characters in string value, including '\0' */ int flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ double r; /* Real value */ char *z; /* String value */ char zShort[NBFS]; /* Space for short strings */ }; typedef struct Mem Mem; /* ** Allowed values for Mem.flags */ #define MEM_Null 0x0001 /* Value is NULL */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Dyn 0x0010 /* Need to call sqliteFree() on Mem.z */ #define MEM_Static 0x0020 /* Mem.z points to a static string */ #define MEM_Ephem 0x0040 /* Mem.z points to an ephemeral string */ #define MEM_Short 0x0080 /* Mem.z points to Mem.zShort */ /* The following MEM_ value appears only in AggElem.aMem.s.flag fields. ** It indicates that the corresponding AggElem.aMem.z points to a ** aggregate function context that needs to be finalized. */ #define MEM_AggCtx 0x0100 /* Mem.z points to an agg function context */ /* ** The "context" argument for a installable function. A pointer to an ** instance of this structure is the first argument to the routines used ** implement the SQL functions. ** ** There is a typedef for this structure in sqlite.h. So all routines, ** even the public interface to SQLite, can use a pointer to this structure. ** But this file is the only place where the internal details of this ** structure are known. ** ** This structure is defined inside of vdbe.c because it uses substructures ** (Mem) which are only defined there. */ struct sqlite_func { FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */ Mem s; /* The return value is stored here */ void *pAgg; /* Aggregate context */ u8 isError; /* Set to true for an error */ u8 isStep; /* Current in the step function */ int cnt; /* Number of times that the step function has been called */ }; /* ** An Agg structure describes an Aggregator. Each Agg consists of ** zero or more Aggregator elements (AggElem). Each AggElem contains ** a key and one or more values. The values are used in processing ** aggregate functions in a SELECT. The key is used to implement ** the GROUP BY clause of a select. */ typedef struct Agg Agg; typedef struct AggElem AggElem; struct Agg { int nMem; /* Number of values stored in each AggElem */ AggElem *pCurrent; /* The AggElem currently in focus */ HashElem *pSearch; /* The hash element for pCurrent */ Hash hash; /* Hash table of all aggregate elements */ FuncDef **apFunc; /* Information about aggregate functions */ }; struct AggElem { char *zKey; /* The key to this AggElem */ int nKey; /* Number of bytes in the key, including '\0' at end */ Mem aMem[1]; /* The values for this AggElem */ }; /* ** A Set structure is used for quick testing to see if a value ** is part of a small set. Sets are used to implement code like ** this: ** x.y IN ('hi','hoo','hum') */ typedef struct Set Set; struct Set { Hash hash; /* A set is just a hash table */ HashElem *prev; /* Previously accessed hash elemen */ }; /* ** A Keylist is a bunch of keys into a table. The keylist can ** grow without bound. The keylist stores the ROWIDs of database ** records that need to be deleted or updated. */ typedef struct Keylist Keylist; struct Keylist { int nKey; /* Number of slots in aKey[] */ int nUsed; /* Next unwritten slot in aKey[] */ int nRead; /* Next unread slot in aKey[] */ Keylist *pNext; /* Next block of keys */ int aKey[1]; /* One or more keys. Extra space allocated as needed */ }; /* ** A Context stores the last insert rowid, the last statement change count, ** and the current statement change count (i.e. changes since last statement). ** Elements of Context structure type make up the ContextStack, which is ** updated by the ContextPush and ContextPop opcodes (used by triggers) */ typedef struct Context Context; struct Context { int lastRowid; /* Last insert rowid (from db->lastRowid) */ int lsChange; /* Last statement change count (from db->lsChange) */ int csChange; /* Current statement change count (from db->csChange) */ }; /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite_vm" structure pointer that is returned by sqlite_compile() ** is really a pointer to an instance of this structure. */ struct Vdbe { sqlite *db; /* The whole database */ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ FILE *trace; /* Write an execution trace here, if not NULL */ int nOp; /* Number of instructions in the program */ int nOpAlloc; /* Number of slots allocated for aOp[] */ Op *aOp; /* Space to hold the virtual machine's program */ int nLabel; /* Number of labels used */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */ int *aLabel; /* Space to hold the labels */ Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ char **zArgv; /* Text values used by the callback */ char **azColName; /* Becomes the 4th parameter to callbacks */ int nCursor; /* Number of slots in aCsr[] */ Cursor *aCsr; /* One element of this array for each open cursor */ Sorter *pSort; /* A linked list of objects to be sorted */ FILE *pFile; /* At most one open file handler */ int nField; /* Number of file fields */ char **azField; /* Data for each file field */ int nVar; /* Number of entries in azVariable[] */ char **azVar; /* Values for the OP_Variable opcode */ int *anVar; /* Length of each value in azVariable[] */ u8 *abVar; /* TRUE if azVariable[i] needs to be sqliteFree()ed */ char *zLine; /* A single line from the input file */ int nLineAlloc; /* Number of spaces allocated for zLine */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nSet; /* Number of sets allocated */ Set *aSet; /* An array of sets */ int nCallback; /* Number of callbacks invoked so far */ Keylist *pList; /* A list of ROWIDs */ int keylistStackDepth; /* The size of the "keylist" stack */ Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ int errorAction; /* Recovery action to do in case of an error */ int undoTransOnError; /* If error, either ROLLBACK or COMMIT */ int inTempTrans; /* True if temp database is transactioned */ int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */ int returnDepth; /* Next unused element in returnStack[] */ int nResColumn; /* Number of columns in one row of the result set */ char **azResColumn; /* Values for one row of result */ int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ u8 explain; /* True if EXPLAIN present on SQL command */ }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ /* ** Function prototypes */ void sqliteVdbeCleanupCursor(Cursor*); void sqliteVdbeSorterReset(Vdbe*); void sqliteVdbeAggReset(Agg*); void sqliteVdbeKeylistFree(Keylist*); void sqliteVdbePopStack(Vdbe*,int); int sqliteVdbeCursorMoveto(Cursor*); int sqliteVdbeByteSwap(int); #if !defined(NDEBUG) || defined(VDBE_PROFILE) void sqliteVdbePrintOp(FILE*, int, Op*); #endif DBD-SQLite2-0.36/Changes0000644000175000017500000001125212130555352014115 0ustar rurbanrurbanRevision history for Perl extension DBD::SQLite2. 0.36 2013-04-08 rurban - Fix mingw32 off_t redefinition. [cpan #84492] Use a private sql_off_t typedef for the sqlite internal off_t type. - cygwin is now a OS_UNIX, not OS_WIN. 0.35 2013-04-01 rurban - Fix SEGV when fetchrow() is called again after it has returned an empty list ie. the query has completed. [cpan #16451] - Add testcases for [cpan #26775] and [cpan #28448] - Fixed [cpan #26775]: Remove () in names with DISTINCT(t.name) - Honor -g in $Config{optimize} - Add META and POD tests, and META info for EUMM 0.34 2013-04-01 rurban - Fix SEGV in t/ak-dbd.t with asan, concurrent _sqlite2_fetch_row [cpan #55636] - Add return value for dbd_bind_ph() - bind_param with handle - Add declaration for sqlite2_busy_timeout() - Fix clang -Wparentheses and -Wint-conversion warnings 0.33 - Set HAVE_USLEEP appropriately. This massively improves concurrent access to your SQLite DB. 0.32 - Renamed to DBD::SQLite2 to allow backwards compatibility - Implemented busy_timeout API - Add internal line number to error reporting 0.31 - Fixed a free() bug on Win32 - Silence warnings in test suite - Updated to sqlite 2.8.12 0.30 - Updated to sqlite 2.8.11 - A few minor bugs fixed 0.29 - Updated to sqlite 2.8.7 - A number of bugs fixed 0.28 - Perl 5.8.0 removed long deprecated SvOK_off() - Aliases for perl_call_* - Updated to sqlite 2.8.6 - use sqlite_freemem everywhere 0.27 - Changed API to use sqlite streaming API. This makes things slightly slower for large result sets, at the benefit of being more "sane" internally. 0.26 - Update to sqlite 2.8.5 - Automatic binary encoding added (via a flag) - Better getsqlite.pl - now deals with new files - Extension functions and aggregates can be created in perl space now. 0.25 - Fixed Makefile.PL to no longer try creating a .c file to determine the OS ptrsize - use Config.pm directly in the DEFINE - Major updates from Tim Bunce to bring DBD::SQLite in line with the DBI spec and other drivers, including: - Support for table_info_all() and primary_key_info() - $sth->{NAME} updates - execute() returns number of rows updated - $dbh->{sqlite_version} returns the SQLite version in use - $dbh->{sqlite_encoding} returns the SQLite encoding in use - Improved trace debugging - Improved error handling (many MANY thanks to Tim for all these patches!) - Updated to sqlite 2.8.0 0.24 - Fixed major crash bug affecting Mac OS X - Removed test.pl from distribution - Upgraded to sqlite 2.7.6 0.23 - Fixed unicode tests 0.22 - Merge with sqlite 2.7.4 0.21 - Ooops - forgot new opcodes files from MANIFEST 0.20 - Port to SQLite 2.7.2 - Fixed bug in not freeing memory if you re-execute a $sth 0.19 - Upgrade to SQLite 2.6.3 - this now allows databases to work across different endian architectures. 0.18 - Upgraded to SQLite 2.5.6 - All users are advised to upgrade due to a corruption bug in SQLite 2.4.0 - 2.5.6 0.17 - Upgraded to SQLite 2.5.3 - Fixed getsqlite.pl 0.16 - Upgraded to SQLite 2.5.0 0.15 - Upgraded to SQLite 2.4.5 0.14 - Added NoUTF8Flag option, so that returned strings don't get flagged with SvUTF8_on() - needed when you're storing non-unicode in the database 0.13 - Upgraded to SQLite 2.4.3 - Added script to download sqlite core library when it's upgraded 0.12 - Upgraded to SQLite 2.4.2 0.11 - Upgraded to SQLite 2.4.0, which adds views, subqueries, new builtin functions, performance, and even sheds some weight - Changed transaction support to only BEGIN TRAN when you execute some SQL, which should improve locking problems. 0.10 - Fixed missing SQLiteXS.h from 0.09 0.09 - Updated to SQLite 2.3.3, and some file cleanups to make that easier next time. 0.08 - Last of the mem leaks fixed - Doc fix on last_insert_rowid 0.07 - Memory leak fixes (though still leaks some, beware) - Some API cleanups and test cleanups - Added last_insert_rowid() method and docs 0.06 - Win32 and 5.00404 build fixes - Added some more performance tests to test.pl - Make sure to set $sth->{Active} only on selects 0.05 - Added all DBD::CSV tests (ported, of course) - Fixed bugs that the above revealed. 0.04 - Fix multiple placeholders bug 0.03 - Fixed multiple execute on single $sth 0.02 - Fixed transactions 0.01 Sat Feb 16 16:10:42 2002 - original version; created by h2xs 1.20 with options -A -X -n DBD::SQLite DBD-SQLite2-0.36/main.c0000644000175000017500000011060212126353147013714 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include "sqliteInt.h" #include "os.h" #include /* ** A pointer to this structure is used to communicate information ** from sqliteInit into the sqliteInitCallback. */ typedef struct { sqlite *db; /* The database being initialized */ char **pzErrMsg; /* Error message stored here */ } InitData; /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ static void corruptSchema(InitData *pData, const char *zExtra){ sqliteSetString(pData->pzErrMsg, "malformed database schema", zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); } /* ** This is the callback routine for the code that initializes the ** database. See sqliteInit() below for additional information. ** ** Each callback contains the following information: ** ** argv[0] = "file-format" or "schema-cookie" or "table" or "index" ** argv[1] = table or index name or meta statement type. ** argv[2] = root page number for table or index. NULL for meta. ** argv[3] = SQL text for a CREATE TABLE or CREATE INDEX statement. ** argv[4] = "1" for temporary files, "0" for main database, "2" or more ** for auxiliary database files. ** */ static int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){ InitData *pData = (InitData*)pInit; int nErr = 0; assert( argc==5 ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[0]==0 ){ corruptSchema(pData, 0); return 1; } switch( argv[0][0] ){ case 'v': case 'i': case 't': { /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */ sqlite *db = pData->db; if( argv[2]==0 || argv[4]==0 ){ corruptSchema(pData, 0); return 1; } if( argv[3] && argv[3][0] ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data ** structures that describe the table, index, or view. */ char *zErr; assert( db->init.busy ); db->init.iDb = atoi(argv[4]); assert( db->init.iDb>=0 && db->init.iDbnDb ); db->init.newTnum = atoi(argv[2]); if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){ corruptSchema(pData, zErr); sqlite_freemem(zErr); } db->init.iDb = 0; }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE ** constraint for a CREATE TABLE. The index should have already ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ int iDb; Index *pIndex; iDb = atoi(argv[4]); assert( iDb>=0 && iDbnDb ); pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName); if( pIndex==0 || pIndex->tnum!=0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since ** the permanent table is hidden by the TEMP table, we can also ** safely ignore the index on the permanent table. */ /* Do Nothing */; }else{ pIndex->tnum = atoi(argv[2]); } } break; } default: { /* This can not happen! */ nErr = 1; assert( nErr==0 ); } } return nErr; } /* ** This is a callback procedure used to reconstruct a table. The ** name of the table to be reconstructed is passed in as argv[0]. ** ** This routine is used to automatically upgrade a database from ** format version 1 or 2 to version 3. The correct operation of ** this routine relys on the fact that no indices are used when ** copying a table out to a temporary file. ** ** The change from version 2 to version 3 occurred between SQLite ** version 2.5.6 and 2.6.0 on 2002-July-18. */ static int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){ InitData *pData = (InitData*)pInit; int rc; Table *pTab; Trigger *pTrig; char *zErr = 0; pTab = sqliteFindTable(pData->db, argv[0], 0); assert( pTab!=0 ); assert( sqliteStrICmp(pTab->zName, argv[0])==0 ); if( pTab ){ pTrig = pTab->pTrigger; pTab->pTrigger = 0; /* Disable all triggers before rebuilding the table */ } rc = sqlite_exec_printf(pData->db, "CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; " "DELETE FROM '%q'; " "INSERT INTO '%q' SELECT * FROM sqlite_x; " "DROP TABLE sqlite_x;", 0, 0, &zErr, argv[0], argv[0], argv[0]); if( zErr ){ if( *pData->pzErrMsg ) sqlite_freemem(*pData->pzErrMsg); *pData->pzErrMsg = zErr; } /* If an error occurred in the SQL above, then the transaction will ** rollback which will delete the internal symbol tables. This will ** cause the structure that pTab points to be deleted. In case that ** happened, we need to refetch pTab. */ pTab = sqliteFindTable(pData->db, argv[0], 0); if( pTab ){ assert( sqliteStrICmp(pTab->zName, argv[0])==0 ); pTab->pTrigger = pTrig; /* Re-enable triggers */ } return rc!=SQLITE_OK; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){ int rc; BtCursor *curMain; int size; Table *pTab; char const *azArg[6]; char zDbNum[30]; int meta[SQLITE_N_BTREE_META]; InitData initData; char const *zMasterSchema; char const *zMasterName; char *zSql = 0; /* ** The master database table has a structure like this */ static char master_schema[] = "CREATE TABLE sqlite_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" ; static char temp_master_schema[] = "CREATE TEMP TABLE sqlite_temp_master(\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")" ; assert( iDb>=0 && iDbnDb ); /* zMasterSchema and zInitScript are set to point at the master schema ** and initialisation script appropriate for the database being ** initialised. zMasterName is the name of the master table. */ if( iDb==1 ){ zMasterSchema = temp_master_schema; zMasterName = TEMP_MASTER_NAME; }else{ zMasterSchema = master_schema; zMasterName = MASTER_NAME; } /* Construct the schema table. */ sqliteSafetyOff(db); azArg[0] = "table"; azArg[1] = zMasterName; azArg[2] = "2"; azArg[3] = zMasterSchema; sprintf(zDbNum, "%d", iDb); azArg[4] = zDbNum; azArg[5] = 0; initData.db = db; initData.pzErrMsg = pzErrMsg; sqliteInitCallback(&initData, 5, (char **)azArg, 0); pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName); if( pTab ){ pTab->readOnly = 1; }else{ return SQLITE_NOMEM; } sqliteSafetyOn(db); /* Create a cursor to hold the database open */ if( db->aDb[iDb].pBt==0 ) return SQLITE_OK; rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain); if( rc ){ sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0); return rc; } /* Get the database meta information */ rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta); if( rc ){ sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0); sqliteBtreeCloseCursor(curMain); return rc; } db->aDb[iDb].schema_cookie = meta[1]; if( iDb==0 ){ db->next_cookie = meta[1]; db->file_format = meta[2]; size = meta[3]; if( size==0 ){ size = MAX_PAGES; } db->cache_size = size; db->safety_level = meta[4]; if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){ db->temp_store = meta[6]; } if( db->safety_level==0 ) db->safety_level = 2; /* ** file_format==1 Version 2.1.0. ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. ** file_format==3 Version 2.6.0. Fix empty-string index bug. ** file_format==4 Version 2.7.0. Add support for separate numeric and ** text datatypes. */ if( db->file_format==0 ){ /* This happens if the database was initially empty */ db->file_format = 4; }else if( db->file_format>4 ){ sqliteBtreeCloseCursor(curMain); sqliteSetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){ assert( db->file_format>=4 ); if( meta[2]==0 ){ sqliteSetString(pzErrMsg, "cannot attach empty database: ", db->aDb[iDb].zName, (char*)0); }else{ sqliteSetString(pzErrMsg, "incompatible file format in auxiliary " "database: ", db->aDb[iDb].zName, (char*)0); } sqliteBtreeClose(db->aDb[iDb].pBt); db->aDb[iDb].pBt = 0; return SQLITE_FORMAT; } sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size); sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]); /* Read the schema information out of the schema tables */ assert( db->init.busy ); sqliteSafetyOff(db); /* The following SQL will read the schema from the master tables. ** The first version works with SQLite file formats 2 or greater. ** The second version is for format 1 files. ** ** Beginning with file format 2, the rowid for new table entries ** (including entries in sqlite_master) is an increasing integer. ** So for file format 2 and later, we can play back sqlite_master ** and all the CREATE statements will appear in the right order. ** But with file format 1, table entries were random and so we ** have to make sure the CREATE TABLEs occur before their corresponding ** CREATE INDEXs. (We don't have to deal with CREATE VIEW or ** CREATE TRIGGER in file format 1 because those constructs did ** not exist then.) */ if( db->file_format>=2 ){ sqliteSetString(&zSql, "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", db->aDb[iDb].zName, "\".", zMasterName, (char*)0); }else{ sqliteSetString(&zSql, "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", db->aDb[iDb].zName, "\".", zMasterName, " WHERE type IN ('table', 'index')" " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0); } rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0); sqliteFree(zSql); sqliteSafetyOn(db); sqliteBtreeCloseCursor(curMain); if( sqlite_malloc_failed ){ sqliteSetString(pzErrMsg, "out of memory", (char*)0); rc = SQLITE_NOMEM; sqliteResetInternalSchema(db, 0); } if( rc==SQLITE_OK ){ DbSetProperty(db, iDb, DB_SchemaLoaded); }else{ sqliteResetInternalSchema(db, iDb); } return rc; } /* ** Initialize all database files - the main database file, the file ** used to store temporary tables, and any additional database files ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** ** After the database is initialized, the SQLITE_Initialized ** bit is set in the flags field of the sqlite structure. An ** attempt is made to initialize the database as soon as it ** is opened. If that fails (perhaps because another process ** has the sqlite_master table locked) than another attempt ** is made the first time the database is accessed. */ int sqliteInit(sqlite *db, char **pzErrMsg){ int i, rc; if( db->init.busy ) return SQLITE_OK; assert( (db->flags & SQLITE_Initialized)==0 ); rc = SQLITE_OK; db->init.busy = 1; for(i=0; rc==SQLITE_OK && inDb; i++){ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqliteInitOne(db, i, pzErrMsg); if( rc ){ sqliteResetInternalSchema(db, i); } } /* Once all the other databases have been initialised, load the schema ** for the TEMP database. This is loaded last, as the TEMP database ** schema may contain references to objects in other databases. */ if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqliteInitOne(db, 1, pzErrMsg); if( rc ){ sqliteResetInternalSchema(db, 1); } } db->init.busy = 0; if( rc==SQLITE_OK ){ db->flags |= SQLITE_Initialized; sqliteCommitInternalChanges(db); } /* If the database is in formats 1 or 2, then upgrade it to ** version 3. This will reconstruct all indices. If the ** upgrade fails for any reason (ex: out of disk space, database ** is read only, interrupt received, etc.) then fail the init. */ if( rc==SQLITE_OK && db->file_format<3 ){ char *zErr = 0; InitData initData; int meta[SQLITE_N_BTREE_META]; db->magic = SQLITE_MAGIC_OPEN; initData.db = db; initData.pzErrMsg = &zErr; db->file_format = 3; rc = sqlite_exec(db, "BEGIN; SELECT name FROM sqlite_master WHERE type='table';", upgrade_3_callback, &initData, &zErr); if( rc==SQLITE_OK ){ sqliteBtreeGetMeta(db->aDb[0].pBt, meta); meta[2] = 4; sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta); sqlite_exec(db, "COMMIT", 0, 0, 0); } if( rc!=SQLITE_OK ){ sqliteSetString(pzErrMsg, "unable to upgrade database to the version 2.6 format", zErr ? ": " : 0, zErr, (char*)0); } sqlite_freemem(zErr); } if( rc!=SQLITE_OK ){ db->flags &= ~SQLITE_Initialized; } return rc; } /* ** The version of the library */ const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; const char sqlite_version[] = SQLITE_VERSION; /* ** Does the library expect data to be encoded as UTF-8 or iso8859? The ** following global constant always lets us know. */ #ifdef SQLITE_UTF8 const char sqlite_encoding[] = "UTF-8"; #else const char sqlite_encoding[] = "iso8859"; #endif /* ** Open a new SQLite database. Construct an "sqlite" structure to define ** the state of this database and return a pointer to that structure. ** ** An attempt is made to initialize the in-memory data structures that ** hold the database schema. But if this fails (because the schema file ** is locked) then that step is deferred until the first call to ** sqlite_exec(). */ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ sqlite *db; int rc, i; /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ) goto no_mem_on_open; db->onError = OE_Default; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; db->aDb = db->aDbStatic; /* db->flags |= SQLITE_ShortColNames; */ sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1); for(i=0; inDb; i++){ sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1); } /* Open the backend database driver */ if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){ db->temp_store = 2; } rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); if( rc!=SQLITE_OK ){ switch( rc ){ default: { sqliteSetString(pzErrMsg, "unable to open database: ", zFilename, (char*)0); } } sqliteFree(db); sqliteStrRealloc(pzErrMsg); return 0; } db->aDb[0].zName = "main"; db->aDb[1].zName = "temp"; /* Attempt to read the schema */ sqliteRegisterBuiltinFunctions(db); rc = sqliteInit(db, pzErrMsg); db->magic = SQLITE_MAGIC_OPEN; if( sqlite_malloc_failed ){ sqlite_close(db); goto no_mem_on_open; }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ sqlite_close(db); sqliteStrRealloc(pzErrMsg); return 0; }else if( pzErrMsg ){ sqliteFree(*pzErrMsg); *pzErrMsg = 0; } /* Return a pointer to the newly opened database structure */ return db; no_mem_on_open: sqliteSetString(pzErrMsg, "out of memory", (char*)0); sqliteStrRealloc(pzErrMsg); return 0; } /* ** Return the ROWID of the most recent insert */ int sqlite_last_insert_rowid(sqlite *db){ return db->lastRowid; } /* ** Return the number of changes in the most recent call to sqlite_exec(). */ int sqlite_changes(sqlite *db){ return db->nChange; } /* ** Return the number of changes produced by the last INSERT, UPDATE, or ** DELETE statement to complete execution. The count does not include ** changes due to SQL statements executed in trigger programs that were ** triggered by that statement */ int sqlite_last_statement_changes(sqlite *db){ return db->lsChange; } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ HashElem *i; int j; db->want_to_close = 1; if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ return; } db->magic = SQLITE_MAGIC_CLOSED; for(j=0; jnDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqliteBtreeClose(pDb->pBt); pDb->pBt = 0; } } sqliteResetInternalSchema(db, 0); assert( db->nDb<=2 ); assert( db->aDb==db->aDbStatic ); for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ FuncDef *pFunc, *pNext; for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ pNext = pFunc->pNext; sqliteFree(pFunc); } } sqliteHashClear(&db->aFunc); sqliteFree(db); } /* ** Rollback all database files. */ void sqliteRollbackAll(sqlite *db){ int i; for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ sqliteBtreeRollback(db->aDb[i].pBt); db->aDb[i].inTrans = 0; } } sqliteResetInternalSchema(db, 0); /* sqliteRollbackInternalChanges(db); */ } /* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result ** the xCallback() function is called. pArg becomes the first ** argument to xCallback(). If xCallback=NULL then no callback ** is invoked, even for queries. */ int sqlite_exec( sqlite *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE_OK; const char *zLeftover; sqlite_vm *pVm; int nRetry = 0; int nChange = 0; int nCallback; if( zSql==0 ) return SQLITE_OK; while( rc==SQLITE_OK && zSql[0] ){ pVm = 0; rc = sqlite_compile(db, zSql, &zLeftover, &pVm, pzErrMsg); if( rc!=SQLITE_OK ){ assert( pVm==0 || sqlite_malloc_failed ); return rc; } if( pVm==0 ){ /* This happens if the zSql input contained only whitespace */ break; } db->nChange += nChange; nCallback = 0; while(1){ int nArg; char **azArg, **azCol; rc = sqlite_step(pVm, &nArg, (const char***)&azArg,(const char***)&azCol); if( rc==SQLITE_ROW ){ if( xCallback!=0 && xCallback(pArg, nArg, azArg, azCol) ){ sqlite_finalize(pVm, 0); return SQLITE_ABORT; } nCallback++; }else{ if( rc==SQLITE_DONE && nCallback==0 && (db->flags & SQLITE_NullCallback)!=0 && xCallback!=0 ){ xCallback(pArg, nArg, azArg, azCol); } rc = sqlite_finalize(pVm, pzErrMsg); if( rc==SQLITE_SCHEMA && nRetry<2 ){ nRetry++; rc = SQLITE_OK; break; } if( db->pVdbe==0 ){ nChange = db->nChange; } nRetry = 0; zSql = zLeftover; while( isspace(zSql[0]) ) zSql++; break; } } } return rc; } /* ** Compile a single statement of SQL into a virtual machine. Return one ** of the SQLITE_ success/failure codes. Also write an error message into ** memory obtained from malloc() and make *pzErrMsg point to that message. */ int sqlite_compile( sqlite *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ const char **pzTail, /* OUT: Next statement after the first */ sqlite_vm **ppVm, /* OUT: The virtual machine */ char **pzErrMsg /* OUT: Write error messages here */ ){ Parse sParse; if( pzErrMsg ) *pzErrMsg = 0; if( sqliteSafetyOn(db) ) goto exec_misuse; if( !db->init.busy ){ if( (db->flags & SQLITE_Initialized)==0 ){ int rc, cnt = 1; while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY && db->xBusyCallback && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){} if( rc!=SQLITE_OK ){ sqliteStrRealloc(pzErrMsg); sqliteSafetyOff(db); return rc; } if( pzErrMsg ){ sqliteFree(*pzErrMsg); *pzErrMsg = 0; } } if( db->file_format<3 ){ sqliteSafetyOff(db); sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0); return SQLITE_ERROR; } } assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy ); if( db->pVdbe==0 ){ db->nChange = 0; } memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sqliteRunParser(&sParse, zSql, pzErrMsg); if( db->xTrace && !db->init.busy ){ /* Trace only the statment that was compiled. ** Make a copy of that part of the SQL string since zSQL is const ** and we must pass a zero terminated string to the trace function ** The copy is unnecessary if the tail pointer is pointing at the ** beginnig or end of the SQL string. */ if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){ char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql); if( tmpSql ){ db->xTrace(db->pTraceArg, tmpSql); free(tmpSql); }else{ /* If a memory error occurred during the copy, ** trace entire SQL string and fall through to the ** sqlite_malloc_failed test to report the error. */ db->xTrace(db->pTraceArg, zSql); } }else{ db->xTrace(db->pTraceArg, zSql); } } if( sqlite_malloc_failed ){ sqliteSetString(pzErrMsg, "out of memory", (char*)0); sParse.rc = SQLITE_NOMEM; sqliteRollbackAll(db); sqliteResetInternalSchema(db, 0); db->flags &= ~SQLITE_InTrans; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){ sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), (char*)0); } sqliteStrRealloc(pzErrMsg); if( sParse.rc==SQLITE_SCHEMA ){ sqliteResetInternalSchema(db, 0); } assert( ppVm ); *ppVm = (sqlite_vm*)sParse.pVdbe; if( pzTail ) *pzTail = sParse.zTail; if( sqliteSafetyOff(db) ) goto exec_misuse; return sParse.rc; exec_misuse: if( pzErrMsg ){ *pzErrMsg = 0; sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0); sqliteStrRealloc(pzErrMsg); } return SQLITE_MISUSE; } /* ** The following routine destroys a virtual machine that is created by ** the sqlite_compile() routine. ** ** The integer returned is an SQLITE_ success/failure code that describes ** the result of executing the virtual machine. An error message is ** written into memory obtained from malloc and *pzErrMsg is made to ** point to that error if pzErrMsg is not NULL. The calling routine ** should use sqlite_freemem() to delete the message when it has finished ** with it. */ int sqlite_finalize( sqlite_vm *pVm, /* The virtual machine to be destroyed */ char **pzErrMsg /* OUT: Write error messages here */ ){ int rc = sqliteVdbeFinalize((Vdbe*)pVm, pzErrMsg); sqliteStrRealloc(pzErrMsg); return rc; } /* ** Terminate the current execution of a virtual machine then ** reset the virtual machine back to its starting state so that it ** can be reused. Any error message resulting from the prior execution ** is written into *pzErrMsg. A success code from the prior execution ** is returned. */ int sqlite_reset( sqlite_vm *pVm, /* The virtual machine to be destroyed */ char **pzErrMsg /* OUT: Write error messages here */ ){ int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg); sqliteVdbeMakeReady((Vdbe*)pVm, -1, 0); sqliteStrRealloc(pzErrMsg); return rc; } /* ** Return a static string that describes the kind of error specified in the ** argument. */ const char *sqlite_error_string(int rc){ const char *z; switch( rc ){ case SQLITE_OK: z = "not an error"; break; case SQLITE_ERROR: z = "SQL logic error or missing database"; break; case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break; case SQLITE_PERM: z = "access permission denied"; break; case SQLITE_ABORT: z = "callback requested query abort"; break; case SQLITE_BUSY: z = "database is locked"; break; case SQLITE_LOCKED: z = "database table is locked"; break; case SQLITE_NOMEM: z = "out of memory"; break; case SQLITE_READONLY: z = "attempt to write a readonly database"; break; case SQLITE_INTERRUPT: z = "interrupted"; break; case SQLITE_IOERR: z = "disk I/O error"; break; case SQLITE_CORRUPT: z = "database disk image is malformed"; break; case SQLITE_NOTFOUND: z = "table or record not found"; break; case SQLITE_FULL: z = "database is full"; break; case SQLITE_CANTOPEN: z = "unable to open database file"; break; case SQLITE_PROTOCOL: z = "database locking protocol failure"; break; case SQLITE_EMPTY: z = "table contains no data"; break; case SQLITE_SCHEMA: z = "database schema has changed"; break; case SQLITE_TOOBIG: z = "too much data for one table row"; break; case SQLITE_CONSTRAINT: z = "constraint failed"; break; case SQLITE_MISMATCH: z = "datatype mismatch"; break; case SQLITE_MISUSE: z = "library routine called out of sequence";break; case SQLITE_NOLFS: z = "kernel lacks large file support"; break; case SQLITE_AUTH: z = "authorization denied"; break; case SQLITE_FORMAT: z = "auxiliary database format error"; break; case SQLITE_RANGE: z = "bind index out of range"; break; case SQLITE_NOTADB: z = "file is encrypted or is not a database";break; default: z = "unknown error"; break; } return z; } /* ** This routine implements a busy callback that sleeps and tries ** again until a timeout value is reached. The timeout value is ** an integer number of milliseconds passed in as the first ** argument. */ static int sqliteDefaultBusyCallback( void *Timeout, /* Maximum amount of time to wait */ const char *NotUsed, /* The name of the table that is busy */ int count /* Number of times table has been busy */ ){ #if SQLITE_MIN_SLEEP_MS==1 static const char delays[] = { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 50, 100}; static const short int totals[] = { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287}; # define NDELAY (sizeof(delays)/sizeof(delays[0])) int timeout = (int)(long)Timeout; int delay, prior; if( count <= NDELAY ){ delay = delays[count-1]; prior = totals[count-1]; }else{ delay = delays[NDELAY-1]; prior = totals[NDELAY-1] + delay*(count-NDELAY-1); } if( prior + delay > timeout ){ delay = timeout - prior; if( delay<=0 ) return 0; } sqliteOsSleep(delay); return 1; #else int timeout = (int)(long)Timeout; if( (count+1)*1000 > timeout ){ return 0; } sqliteOsSleep(1000); return 1; #endif } /* ** This routine sets the busy callback for an Sqlite database to the ** given callback function with the given argument. */ void sqlite_busy_handler( sqlite *db, int (*xBusy)(void*,const char*,int), void *pArg ){ db->xBusyCallback = xBusy; db->pBusyArg = pArg; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* ** This routine sets the progress callback for an Sqlite database to the ** given callback function with the given argument. The progress callback will ** be invoked every nOps opcodes. */ void sqlite_progress_handler( sqlite *db, int nOps, int (*xProgress)(void*), void *pArg ){ if( nOps>0 ){ db->xProgress = xProgress; db->nProgressOps = nOps; db->pProgressArg = pArg; }else{ db->xProgress = 0; db->nProgressOps = 0; db->pProgressArg = 0; } } #endif /* ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ void sqlite_busy_timeout(sqlite *db, int ms){ if( ms>0 ){ sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms); }else{ sqlite_busy_handler(db, 0, 0); } } /* ** Cause any pending operation to stop at its earliest opportunity. */ void sqlite_interrupt(sqlite *db){ db->flags |= SQLITE_Interrupt; } /* ** Windows systems should call this routine to free memory that ** is returned in the in the errmsg parameter of sqlite_open() when ** SQLite is a DLL. For some reason, it does not work to call free() ** directly. ** ** Note that we need to call free() not sqliteFree() here, since every ** string that is exported from SQLite should have already passed through ** sqliteStrRealloc(). */ void sqlite_freemem(void *p){ free(p); } /* ** Windows systems need functions to call to return the sqlite_version ** and sqlite_encoding strings since they are unable to access constants ** within DLLs. */ const char *sqlite_libversion(void){ return sqlite_version; } const char *sqlite_libencoding(void){ return sqlite_encoding; } /* ** Create new user-defined functions. The sqlite_create_function() ** routine creates a regular function and sqlite_create_aggregate() ** creates an aggregate function. ** ** Passing a NULL xFunc argument or NULL xStep and xFinalize arguments ** disables the function. Calling sqlite_create_function() with the ** same name and number of arguments as a prior call to ** sqlite_create_aggregate() disables the prior call to ** sqlite_create_aggregate(), and vice versa. ** ** If nArg is -1 it means that this function will accept any number ** of arguments, including 0. The maximum allowed value of nArg is 127. */ int sqlite_create_function( sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */ void *pUserData /* User data */ ){ FuncDef *p; int nName; if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1; if( nArg<-1 || nArg>127 ) return 1; nName = strlen(zName); if( nName>255 ) return 1; p = sqliteFindFunction(db, zName, nName, nArg, 1); if( p==0 ) return 1; p->xFunc = xFunc; p->xStep = 0; p->xFinalize = 0; p->pUserData = pUserData; return 0; } int sqlite_create_aggregate( sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xStep)(sqlite_func*,int,const char**), /* The step function */ void (*xFinalize)(sqlite_func*), /* The finalizer */ void *pUserData /* User data */ ){ FuncDef *p; int nName; if( db==0 || zName==0 || sqliteSafetyCheck(db) ) return 1; if( nArg<-1 || nArg>127 ) return 1; nName = strlen(zName); if( nName>255 ) return 1; p = sqliteFindFunction(db, zName, nName, nArg, 1); if( p==0 ) return 1; p->xFunc = 0; p->xStep = xStep; p->xFinalize = xFinalize; p->pUserData = pUserData; return 0; } /* ** Change the datatype for all functions with a given name. See the ** header comment for the prototype of this function in sqlite.h for ** additional information. */ int sqlite_function_type(sqlite *db, const char *zName, int dataType){ FuncDef *p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, strlen(zName)); while( p ){ p->dataType = dataType; p = p->pNext; } return SQLITE_OK; } /* ** Register a trace function. The pArg from the previously registered trace ** is returned. ** ** A NULL trace function means that no tracing is executes. A non-NULL ** trace is a pointer to a function that is invoked at the start of each ** sqlite_exec(). */ void *sqlite_trace(sqlite *db, void (*xTrace)(void*,const char*), void *pArg){ void *pOld = db->pTraceArg; db->xTrace = xTrace; db->pTraceArg = pArg; return pOld; } /*** EXPERIMENTAL *** ** ** Register a function to be invoked when a transaction comments. ** If either function returns non-zero, then the commit becomes a ** rollback. */ void *sqlite_commit_hook( sqlite *db, /* Attach the hook to this database */ int (*xCallback)(void*), /* Function to invoke on each commit */ void *pArg /* Argument to the function */ ){ void *pOld = db->pCommitArg; db->xCommitCallback = xCallback; db->pCommitArg = pArg; return pOld; } /* ** This routine is called to create a connection to a database BTree ** driver. If zFilename is the name of a file, then that file is ** opened and used. If zFilename is the magic name ":memory:" then ** the database is stored in memory (and is thus forgotten as soon as ** the connection is closed.) If zFilename is NULL then the database ** is for temporary use only and is deleted as soon as the connection ** is closed. ** ** A temporary database can be either a disk file (that is automatically ** deleted when the file is closed) or a set of red-black trees held in memory, ** depending on the values of the TEMP_STORE compile-time macro and the ** db->temp_store variable, according to the following chart: ** ** TEMP_STORE db->temp_store Location of temporary database ** ---------- -------------- ------------------------------ ** 0 any file ** 1 1 file ** 1 2 memory ** 1 0 file ** 2 1 file ** 2 2 memory ** 2 0 memory ** 3 any memory */ int sqliteBtreeFactory( const sqlite *db, /* Main database when opening aux otherwise 0 */ const char *zFilename, /* Name of the file containing the BTree database */ int omitJournal, /* if TRUE then do not journal this file */ int nCache, /* How many pages in the page cache */ Btree **ppBtree){ /* Pointer to new Btree object written here */ assert( ppBtree != 0); #ifndef SQLITE_OMIT_INMEMORYDB if( zFilename==0 ){ if (TEMP_STORE == 0) { /* Always use file based temporary DB */ return sqliteBtreeOpen(0, omitJournal, nCache, ppBtree); } else if (TEMP_STORE == 1 || TEMP_STORE == 2) { /* Switch depending on compile-time and/or runtime settings. */ int location = db->temp_store==0 ? TEMP_STORE : db->temp_store; if (location == 1) { return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree); } else { return sqliteRbtreeOpen(0, 0, 0, ppBtree); } } else { /* Always use in-core DB */ return sqliteRbtreeOpen(0, 0, 0, ppBtree); } }else if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){ return sqliteRbtreeOpen(0, 0, 0, ppBtree); }else #endif { return sqliteBtreeOpen(zFilename, omitJournal, nCache, ppBtree); } } DBD-SQLite2-0.36/build.c0000644000175000017500000020314112126353147014070 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the SQLite parser ** when syntax rules are reduced. The routines in this file handle the ** following kinds of SQL syntax: ** ** CREATE TABLE ** DROP TABLE ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include "sqliteInt.h" #include /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs ** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables. ** If it does, then read it. */ void sqliteBeginParse(Parse *pParse, int explainFlag){ sqlite *db = pParse->db; int i; pParse->explain = explainFlag; if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){ int rc = sqliteInit(db, &pParse->zErrMsg); if( rc!=SQLITE_OK ){ pParse->rc = rc; pParse->nErr++; } } for(i=0; inDb; i++){ DbClearProperty(db, i, DB_Locked); if( !db->aDb[i].inTrans ){ DbClearProperty(db, i, DB_Cookie); } } pParse->nVar = 0; } /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the VDBE code to implement ** that statement. Prior action routines should have already ** constructed VDBE code to do the work of the SQL statement. ** This routine just has to execute the VDBE code. ** ** Note that if an error occurred, it might be the case that ** no VDBE code was generated. */ void sqliteExec(Parse *pParse){ sqlite *db = pParse->db; Vdbe *v = pParse->pVdbe; if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){ sqliteVdbeAddOp(v, OP_Halt, 0, 0); } if( sqlite_malloc_failed ) return; if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqliteVdbeTrace(v, trace); sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain); pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } pParse->nTab = 0; pParse->nMem = 0; pParse->nSet = 0; pParse->nAgg = 0; pParse->nVar = 0; } /* ** Locate the in-memory structure that describes ** a particular database table given the name ** of that table and (optionally) the name of the database ** containing the table. Return NULL if not found. ** ** If zDatabase is 0, all databases are searched for the ** table and the first matching table is returned. (No checking ** for duplicate table names is done.) The search order is ** TEMP first, then MAIN, then any auxiliary databases added ** using the ATTACH command. ** ** See also sqliteLocateTable(). */ Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; for(i=0; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue; p = sqliteHashFind(&db->aDb[j].tblHash, zName, strlen(zName)+1); if( p ) break; } return p; } /* ** Locate the in-memory structure that describes ** a particular database table given the name ** of that table and (optionally) the name of the database ** containing the table. Return NULL if not found. ** Also leave an error message in pParse->zErrMsg. ** ** The difference between this routine and sqliteFindTable() ** is that this routine leaves an error message in pParse->zErrMsg ** where sqliteFindTable() does not. */ Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){ Table *p; p = sqliteFindTable(pParse->db, zName, zDbase); if( p==0 ){ if( zDbase ){ sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); }else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){ sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"", zName, zDbase); }else{ sqliteErrorMsg(pParse, "no such table: %s", zName); } } return p; } /* ** Locate the in-memory structure that describes ** a particular index given the name of that index ** and the name of the database that contains the index. ** Return NULL if not found. ** ** If zDatabase is 0, all databases are searched for the ** table and the first matching index is returned. (No checking ** for duplicate index names is done.) The search order is ** TEMP first, then MAIN, then any auxiliary databases added ** using the ATTACH command. */ Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){ Index *p = 0; int i; for(i=0; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue; p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1); if( p ) break; } return p; } /* ** Remove the given index from the index hash table, and free ** its memory structures. ** ** The index is removed from the database hash tables but ** it is not unlinked from the Table that it indexes. ** Unlinking from the Table must be done by the calling function. */ static void sqliteDeleteIndex(sqlite *db, Index *p){ Index *pOld; assert( db!=0 && p->zName!=0 ); pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName, strlen(p->zName)+1, 0); if( pOld!=0 && pOld!=p ){ sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName, strlen(pOld->zName)+1, pOld); } sqliteFree(p); } /* ** Unlink the given index from its table, then remove ** the index from the index hash table and free its memory ** structures. */ void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *pIndex){ if( pIndex->pTable->pIndex==pIndex ){ pIndex->pTable->pIndex = pIndex->pNext; }else{ Index *p; for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} if( p && p->pNext==pIndex ){ p->pNext = pIndex->pNext; } } sqliteDeleteIndex(db, pIndex); } /* ** Erase all schema information from the in-memory hash tables of ** database connection. This routine is called to reclaim memory ** before the connection closes. It is also called during a rollback ** if there were schema changes during the transaction. ** ** If iDb<=0 then reset the internal schema tables for all database ** files. If iDb>=2 then reset the internal schema for only the ** single file indicated. */ void sqliteResetInternalSchema(sqlite *db, int iDb){ HashElem *pElem; Hash temp1; Hash temp2; int i, j; assert( iDb>=0 && iDbnDb ); db->flags &= ~SQLITE_Initialized; for(i=iDb; inDb; i++){ Db *pDb = &db->aDb[i]; temp1 = pDb->tblHash; temp2 = pDb->trigHash; sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); sqliteHashClear(&pDb->aFKey); sqliteHashClear(&pDb->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ Trigger *pTrigger = sqliteHashData(pElem); sqliteDeleteTrigger(pTrigger); } sqliteHashClear(&temp2); sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); sqliteDeleteTable(db, pTab); } sqliteHashClear(&temp1); DbClearProperty(db, i, DB_SchemaLoaded); if( iDb>0 ) return; } assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; /* If one or more of the auxiliary database files has been closed, ** then remove then from the auxiliary database list. We take the ** opportunity to do this here since we have just deleted all of the ** schema hash tables and therefore do not have to make any changes ** to any of those tables. */ for(i=0; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); pDb->pAux = 0; } } for(i=j=2; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ sqliteFree(pDb->zName); pDb->zName = 0; continue; } if( jaDb[j] = db->aDb[i]; } j++; } memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); db->nDb = j; if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); sqliteFree(db->aDb); db->aDb = db->aDbStatic; } } /* ** This routine is called whenever a rollback occurs. If there were ** schema changes during the transaction, then we have to reset the ** internal hash tables and reload them from disk. */ void sqliteRollbackInternalChanges(sqlite *db){ if( db->flags & SQLITE_InternChanges ){ sqliteResetInternalSchema(db, 0); } } /* ** This routine is called when a commit occurs. */ void sqliteCommitInternalChanges(sqlite *db){ db->aDb[0].schema_cookie = db->next_cookie; db->flags &= ~SQLITE_InternChanges; } /* ** Remove the memory data structures associated with the given ** Table. No changes are made to disk by this routine. ** ** This routine just deletes the data structure. It does not unlink ** the table data structure from the hash table. Nor does it remove ** foreign keys from the sqlite.aFKey hash table. But it does destroy ** memory structures of the indices and foreign keys associated with ** the table. ** ** Indices associated with the table are unlinked from the "db" ** data structure if db!=NULL. If db==NULL, indices attached to ** the table are deleted, but it is assumed they have already been ** unlinked. */ void sqliteDeleteTable(sqlite *db, Table *pTable){ int i; Index *pIndex, *pNext; FKey *pFKey, *pNextFKey; if( pTable==0 ) return; /* Delete all indices associated with this table */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) ); sqliteDeleteIndex(db, pIndex); } /* Delete all foreign keys associated with this table. The keys ** should have already been unlinked from the db->aFKey hash table */ for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ pNextFKey = pFKey->pNextFrom; assert( pTable->iDbnDb ); assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey, pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); sqliteFree(pFKey); } /* Delete the Table structure itself. */ for(i=0; inCol; i++){ sqliteFree(pTable->aCol[i].zName); sqliteFree(pTable->aCol[i].zDflt); sqliteFree(pTable->aCol[i].zType); } sqliteFree(pTable->zName); sqliteFree(pTable->aCol); sqliteSelectDelete(pTable->pSelect); sqliteFree(pTable); } /* ** Unlink the given table from the hash tables and the delete the ** table structure with all its indices and foreign keys. */ static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){ Table *pOld; FKey *pF1, *pF2; int i = p->iDb; assert( db!=0 ); pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0); assert( pOld==0 || pOld==p ); for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ int nTo = strlen(pF1->zTo) + 1; pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo); if( pF2==pF1 ){ sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo); }else{ while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } if( pF2 ){ pF2->pNextTo = pF1->pNextTo; } } } sqliteDeleteTable(db, p); } /* ** Construct the name of a user table or index from a token. ** ** Space to hold the name is obtained from sqliteMalloc() and must ** be freed by the calling function. */ char *sqliteTableNameFromToken(Token *pName){ char *zName = sqliteStrNDup(pName->z, pName->n); sqliteDequote(zName); return zName; } /* ** Generate code to open the appropriate master table. The table ** opened will be SQLITE_MASTER for persistent tables and ** SQLITE_TEMP_MASTER for temporary tables. The table is opened ** on cursor 0. */ void sqliteOpenMasterTable(Vdbe *v, int isTemp){ sqliteVdbeAddOp(v, OP_Integer, isTemp, 0); sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2); } /* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response ** to a CREATE TABLE statement. In particular, this routine is called ** after seeing tokens "CREATE" and "TABLE" and the table name. The ** pStart token is the CREATE and pName is the table name. The isTemp ** flag is true if the table should be stored in the auxiliary database ** file instead of in the main database file. This is normally the case ** when the "TEMP" or "TEMPORARY" keyword occurs in between ** CREATE and TABLE. ** ** The new table record is initialized and put in pParse->pNewTable. ** As more of the CREATE TABLE statement is parsed, additional action ** routines will be called to add more information to this record. ** At the end of the CREATE TABLE statement, the sqliteEndTable() routine ** is called to complete the construction of the new table record. */ void sqliteStartTable( Parse *pParse, /* Parser context */ Token *pStart, /* The "CREATE" token */ Token *pName, /* Name of table or view to create */ int isTemp, /* True if this is a TEMP table */ int isView /* True if this is a VIEW */ ){ Table *pTable; Index *pIdx; char *zName; sqlite *db = pParse->db; Vdbe *v; int iDb; pParse->sFirstToken = *pStart; zName = sqliteTableNameFromToken(pName); if( zName==0 ) return; if( db->init.iDb==1 ) isTemp = 1; #ifndef SQLITE_OMIT_AUTHORIZATION assert( (isTemp & 1)==isTemp ); { int code; char *zDb = isTemp ? "temp" : "main"; if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ sqliteFree(zName); return; } if( isView ){ if( isTemp ){ code = SQLITE_CREATE_TEMP_VIEW; }else{ code = SQLITE_CREATE_VIEW; } }else{ if( isTemp ){ code = SQLITE_CREATE_TEMP_TABLE; }else{ code = SQLITE_CREATE_TABLE; } } if( sqliteAuthCheck(pParse, code, zName, 0, zDb) ){ sqliteFree(zName); return; } } #endif /* Before trying to create a temporary table, make sure the Btree for ** holding temporary tables is open. */ if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){ int rc = sqliteBtreeFactory(db, 0, 0, MAX_PAGES, &db->aDb[1].pBt); if( rc!=SQLITE_OK ){ sqliteErrorMsg(pParse, "unable to open a temporary database " "file for storing temporary tables"); pParse->nErr++; return; } if( db->flags & SQLITE_InTrans ){ rc = sqliteBtreeBeginTrans(db->aDb[1].pBt); if( rc!=SQLITE_OK ){ sqliteErrorMsg(pParse, "unable to get a write lock on " "the temporary database file"); return; } } } /* Make sure the new table name does not collide with an existing ** index or table name. Issue an error message if it does. ** ** If we are re-reading the sqlite_master table because of a schema ** change and a new permanent table is found whose name collides with ** an existing temporary table, that is not an error. */ pTable = sqliteFindTable(db, zName, 0); iDb = isTemp ? 1 : db->init.iDb; if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){ sqliteErrorMsg(pParse, "table %T already exists", pName); sqliteFree(zName); return; } if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 && (pIdx->iDb==0 || !db->init.busy) ){ sqliteErrorMsg(pParse, "there is already an index named %s", zName); sqliteFree(zName); return; } pTable = sqliteMalloc( sizeof(Table) ); if( pTable==0 ){ sqliteFree(zName); return; } pTable->zName = zName; pTable->nCol = 0; pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; pTable->iDb = iDb; if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; /* Begin generating the code that will insert the table record into ** the SQLITE_MASTER table. Note in particular that we must go ahead ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ** indices to be created and the table record must come before the ** indices. Hence, the record number for the table must be allocated ** now. */ if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){ sqliteBeginWriteOperation(pParse, 0, isTemp); if( !isTemp ){ sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0); sqliteVdbeAddOp(v, OP_SetCookie, 0, 1); } sqliteOpenMasterTable(v, isTemp); sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); } } /* ** Add a new column to the table currently being constructed. ** ** The parser calls this routine once for each column declaration ** in a CREATE TABLE statement. sqliteStartTable() gets called ** first to get things going. Then this routine is called for each ** column. */ void sqliteAddColumn(Parse *pParse, Token *pName){ Table *p; int i; char *z = 0; Column *pCol; if( (p = pParse->pNewTable)==0 ) return; sqliteSetNString(&z, pName->z, pName->n, 0); if( z==0 ) return; sqliteDequote(z); for(i=0; inCol; i++){ if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){ sqliteErrorMsg(pParse, "duplicate column name: %s", z); sqliteFree(z); return; } } if( (p->nCol & 0x7)==0 ){ Column *aNew; aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); if( aNew==0 ) return; p->aCol = aNew; } pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; pCol->sortOrder = SQLITE_SO_NUM; p->nCol++; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has ** been seen on a column. This routine sets the notNull flag on ** the column currently under construction. */ void sqliteAddNotNull(Parse *pParse, int onError){ Table *p; int i; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i>=0 ) p->aCol[i].notNull = onError; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. The pFirst token is the first ** token in the sequence of tokens that describe the type of the ** column currently under construction. pLast is the last token ** in the sequence. Use this information to construct a string ** that contains the typename of the column and store that string ** in zType. */ void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ Table *p; int i, j; int n; char *z, **pz; Column *pCol; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i<0 ) return; pCol = &p->aCol[i]; pz = &pCol->zType; n = pLast->n + Addr(pLast->z) - Addr(pFirst->z); sqliteSetNString(pz, pFirst->z, n, 0); z = *pz; if( z==0 ) return; for(i=j=0; z[i]; i++){ int c = z[i]; if( isspace(c) ) continue; z[j++] = c; } z[j] = 0; if( pParse->db->file_format>=4 ){ pCol->sortOrder = sqliteCollateType(z, n); }else{ pCol->sortOrder = SQLITE_SO_NUM; } } /* ** The given token is the default value for the last column added to ** the table currently under construction. If "minusFlag" is true, it ** means the value token was preceded by a minus sign. ** ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. */ void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){ Table *p; int i; char **pz; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i<0 ) return; pz = &p->aCol[i].zDflt; if( minusFlag ){ sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0); }else{ sqliteSetNString(pz, pVal->z, pVal->n, 0); } sqliteDequote(*pz); } /* ** Designate the PRIMARY KEY for the table. pList is a list of names ** of columns that form the primary key. If pList is NULL, then the ** most recently added column of the table is the primary key. ** ** A table can have at most one primary key. If the table already has ** a primary key (and this is the second primary key) then create an ** error. ** ** If the PRIMARY KEY is on a single column whose datatype is INTEGER, ** then we will try to use that column as the row id. (Exception: ** For backwards compatibility with older databases, do not do this ** if the file format version number is less than 1.) Set the Table.iPKey ** field of the table under construction to be the index of the ** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is ** no INTEGER PRIMARY KEY. ** ** If the key is not an INTEGER PRIMARY KEY, then create a unique ** index for the key. No index is created for INTEGER PRIMARY KEYs. */ void sqliteAddPrimaryKey(Parse *pParse, IdList *pList, int onError){ Table *pTab = pParse->pNewTable; char *zType = 0; int iCol = -1, i; if( pTab==0 ) goto primary_key_exit; if( pTab->hasPrimKey ){ sqliteErrorMsg(pParse, "table \"%s\" has more than one primary key", pTab->zName); goto primary_key_exit; } pTab->hasPrimKey = 1; if( pList==0 ){ iCol = pTab->nCol - 1; pTab->aCol[iCol].isPrimKey = 1; }else{ for(i=0; inId; i++){ for(iCol=0; iColnCol; iCol++){ if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break; } if( iColnCol ) pTab->aCol[iCol].isPrimKey = 1; } if( pList->nId>1 ) iCol = -1; } if( iCol>=0 && iColnCol ){ zType = pTab->aCol[iCol].zType; } if( pParse->db->file_format>=1 && zType && sqliteStrICmp(zType, "INTEGER")==0 ){ pTab->iPKey = iCol; pTab->keyConf = onError; }else{ sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0); pList = 0; } primary_key_exit: sqliteIdListDelete(pList); return; } /* ** Return the appropriate collating type given a type name. ** ** The collation type is text (SQLITE_SO_TEXT) if the type ** name contains the character stream "text" or "blob" or ** "clob". Any other type name is collated as numeric ** (SQLITE_SO_NUM). */ int sqliteCollateType(const char *zType, int nType){ int i; for(i=0; ipNewTable)==0 ) return; i = p->nCol-1; if( i>=0 ) p->aCol[i].sortOrder = collType; } /* ** Come up with a new random value for the schema cookie. Make sure ** the new value is different from the old. ** ** The schema cookie is used to determine when the schema for the ** database changes. After each schema change, the cookie value ** changes. When a process first reads the schema it records the ** cookie. Thereafter, whenever it goes to access the database, ** it checks the cookie to make sure the schema has not changed ** since it was last read. ** ** This plan is not completely bullet-proof. It is possible for ** the schema to change multiple times and for the cookie to be ** set back to prior value. But schema changes are infrequent ** and the probability of hitting the same cookie value is only ** 1 chance in 2^32. So we're safe enough. */ void sqliteChangeCookie(sqlite *db, Vdbe *v){ if( db->next_cookie==db->aDb[0].schema_cookie ){ unsigned char r; sqliteRandomness(1, &r); db->next_cookie = db->aDb[0].schema_cookie + r + 1; db->flags |= SQLITE_InternChanges; sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0); sqliteVdbeAddOp(v, OP_SetCookie, 0, 0); } } /* ** Measure the number of characters needed to output the given ** identifier. The number returned includes any quotes used ** but does not include the null terminator. */ static int identLength(const char *z){ int n; int needQuote = 0; for(n=0; *z; n++, z++){ if( *z=='\'' ){ n++; needQuote=1; } } return n + needQuote*2; } /* ** Write an identifier onto the end of the given string. Add ** quote characters as needed. */ static void identPut(char *z, int *pIdx, char *zIdent){ int i, j, needQuote; i = *pIdx; for(j=0; zIdent[j]; j++){ if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break; } needQuote = zIdent[j]!=0 || isdigit(zIdent[0]) || sqliteKeywordCode(zIdent, j)!=TK_ID; if( needQuote ) z[i++] = '\''; for(j=0; zIdent[j]; j++){ z[i++] = zIdent[j]; if( zIdent[j]=='\'' ) z[i++] = '\''; } if( needQuote ) z[i++] = '\''; z[i] = 0; *pIdx = i; } /* ** Generate a CREATE TABLE statement appropriate for the given ** table. Memory to hold the text of the statement is obtained ** from sqliteMalloc() and must be freed by the calling function. */ static char *createTableStmt(Table *p){ int i, k, n; char *zStmt; char *zSep, *zSep2, *zEnd; n = 0; for(i=0; inCol; i++){ n += identLength(p->aCol[i].zName); } n += identLength(p->zName); if( n<40 ){ zSep = ""; zSep2 = ","; zEnd = ")"; }else{ zSep = "\n "; zSep2 = ",\n "; zEnd = "\n)"; } n += 35 + 6*p->nCol; zStmt = sqliteMallocRaw( n ); if( zStmt==0 ) return 0; strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE "); k = strlen(zStmt); identPut(zStmt, &k, p->zName); zStmt[k++] = '('; for(i=0; inCol; i++){ strcpy(&zStmt[k], zSep); k += strlen(&zStmt[k]); zSep = zSep2; identPut(zStmt, &k, p->aCol[i].zName); } strcpy(&zStmt[k], zEnd); return zStmt; } /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** ** The table structure that other action routines have been building ** is added to the internal hash tables, assuming no errors have ** occurred. ** ** An entry for the table is made in the master table on disk, unless ** this is a temporary table or db->init.busy==1. When db->init.busy==1 ** it means we are reading the sqlite_master table because we just ** connected to the database or because the sqlite_master table has ** recently changes, so the entry for this table already exists in ** the sqlite_master table. We do not want to create it again. ** ** If the pSelect argument is not NULL, it means that this routine ** was called to create a table generated from a ** "CREATE TABLE ... AS SELECT ..." statement. The column names of ** the new table will match the result set of the SELECT. */ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){ Table *p; sqlite *db = pParse->db; if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite_malloc_failed ) return; p = pParse->pNewTable; if( p==0 ) return; /* If the table is generated from a SELECT, then construct the ** list of columns and the text of the table. */ if( pSelect ){ Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect); if( pSelTab==0 ) return; assert( p->aCol==0 ); p->nCol = pSelTab->nCol; p->aCol = pSelTab->aCol; pSelTab->nCol = 0; pSelTab->aCol = 0; sqliteDeleteTable(0, pSelTab); } /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number ** for the table from the db->init.newTnum field. (The page number ** should have been put there by the sqliteOpenCb routine.) */ if( db->init.busy ){ p->tnum = db->init.newTnum; } /* If not initializing, then create a record for the new table ** in the SQLITE_MASTER table of the database. The record number ** for the new table entry should already be on the stack. ** ** If this is a TEMPORARY table, write the entry into the auxiliary ** file instead of into the main database file. */ if( !db->init.busy ){ int n; Vdbe *v; v = sqliteGetVdbe(pParse); if( v==0 ) return; if( p->pSelect==0 ){ /* A regular table */ sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER); }else{ /* A view */ sqliteVdbeAddOp(v, OP_Integer, 0, 0); } p->tnum = 0; sqliteVdbeAddOp(v, OP_Pull, 1, 0); sqliteVdbeOp3(v, OP_String, 0, 0, p->pSelect==0?"table":"view", P3_STATIC); sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqliteVdbeOp3(v, OP_String, 0, 0, p->zName, 0); sqliteVdbeAddOp(v, OP_Dup, 4, 0); sqliteVdbeAddOp(v, OP_String, 0, 0); if( pSelect ){ char *z = createTableStmt(p); n = z ? strlen(z) : 0; sqliteVdbeChangeP3(v, -1, z, n); sqliteFree(z); }else{ assert( pEnd!=0 ); n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1; sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n); } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); if( !p->iDb ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); if( pSelect ){ sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0); sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0); } sqliteEndWriteOperation(pParse); } /* Add the table to the in-memory representation of the database. */ if( pParse->explain==0 && pParse->nErr==0 ){ Table *pOld; FKey *pFKey; pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash, p->zName, strlen(p->zName)+1, p); if( pOld ){ assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ return; } for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ int nTo = strlen(pFKey->zTo) + 1; pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo); sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey); } pParse->pNewTable = 0; db->nTable++; db->flags |= SQLITE_InternChanges; } } /* ** The parser calls this routine in order to create a new VIEW */ void sqliteCreateView( Parse *pParse, /* The parsing context */ Token *pBegin, /* The CREATE token that begins the statement */ Token *pName, /* The token that holds the name of the view */ Select *pSelect, /* A SELECT statement that will become the new view */ int isTemp /* TRUE for a TEMPORARY view */ ){ Table *p; int n; const char *z; Token sEnd; DbFixer sFix; sqliteStartTable(pParse, pBegin, pName, isTemp, 1); p = pParse->pNewTable; if( p==0 || pParse->nErr ){ sqliteSelectDelete(pSelect); return; } if( sqliteFixInit(&sFix, pParse, p->iDb, "view", pName) && sqliteFixSelect(&sFix, pSelect) ){ sqliteSelectDelete(pSelect); return; } /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite_exec() call returns. */ p->pSelect = sqliteSelectDup(pSelect); sqliteSelectDelete(pSelect); if( !pParse->db->init.busy ){ sqliteViewGetColumnNames(pParse, p); } /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. */ sEnd = pParse->sLastToken; if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ sEnd.z += sEnd.n; } sEnd.n = 0; n = sEnd.z - pBegin->z; z = pBegin->z; while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } sEnd.z = &z[n-1]; sEnd.n = 1; /* Use sqliteEndTable() to add the view to the SQLITE_MASTER table */ sqliteEndTable(pParse, &sEnd, 0); return; } /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number ** of errors. If an error is seen leave an error message in pParse->zErrMsg. */ int sqliteViewGetColumnNames(Parse *pParse, Table *pTable){ ExprList *pEList; Select *pSel; Table *pSelTab; int nErr = 0; assert( pTable ); /* A positive nCol means the columns names for this view are ** already known. */ if( pTable->nCol>0 ) return 0; /* A negative nCol is a special marker meaning that we are currently ** trying to compute the column names. If we enter this routine with ** a negative nCol, it means two or more views form a loop, like this: ** ** CREATE VIEW one AS SELECT * FROM two; ** CREATE VIEW two AS SELECT * FROM one; ** ** Actually, this error is caught previously and so the following test ** should always fail. But we will leave it in place just to be safe. */ if( pTable->nCol<0 ){ sqliteErrorMsg(pParse, "view %s is circularly defined", pTable->zName); return 1; } /* If we get this far, it means we need to compute the table names. */ assert( pTable->pSelect ); /* If nCol==0, then pTable must be a VIEW */ pSel = pTable->pSelect; /* Note that the call to sqliteResultSetOfSelect() will expand any ** "*" elements in this list. But we will need to restore the list ** back to its original configuration afterwards, so we save a copy of ** the original in pEList. */ pEList = pSel->pEList; pSel->pEList = sqliteExprListDup(pEList); if( pSel->pEList==0 ){ pSel->pEList = pEList; return 1; /* Malloc failed */ } pTable->nCol = -1; pSelTab = sqliteResultSetOfSelect(pParse, 0, pSel); if( pSelTab ){ assert( pTable->aCol==0 ); pTable->nCol = pSelTab->nCol; pTable->aCol = pSelTab->aCol; pSelTab->nCol = 0; pSelTab->aCol = 0; sqliteDeleteTable(0, pSelTab); DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); }else{ pTable->nCol = 0; nErr++; } sqliteSelectUnbind(pSel); sqliteExprListDelete(pSel->pEList); pSel->pEList = pEList; return nErr; } /* ** Clear the column names from the VIEW pTable. ** ** This routine is called whenever any other table or view is modified. ** The view passed into this routine might depend directly or indirectly ** on the modified or deleted table so we need to clear the old column ** names so that they will be recomputed. */ static void sqliteViewResetColumnNames(Table *pTable){ int i; Column *pCol; assert( pTable!=0 && pTable->pSelect!=0 ); for(i=0, pCol=pTable->aCol; inCol; i++, pCol++){ sqliteFree(pCol->zName); sqliteFree(pCol->zDflt); sqliteFree(pCol->zType); } sqliteFree(pTable->aCol); pTable->aCol = 0; pTable->nCol = 0; } /* ** Clear the column names from every VIEW in database idx. */ static void sqliteViewResetAll(sqlite *db, int idx){ HashElem *i; if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){ Table *pTab = sqliteHashData(i); if( pTab->pSelect ){ sqliteViewResetColumnNames(pTab); } } DbClearProperty(db, idx, DB_UnresetViews); } /* ** Given a token, look up a table with that name. If not found, leave ** an error for the parser to find and return NULL. */ Table *sqliteTableFromToken(Parse *pParse, Token *pTok){ char *zName; Table *pTab; zName = sqliteTableNameFromToken(pTok); if( zName==0 ) return 0; pTab = sqliteFindTable(pParse->db, zName, 0); sqliteFree(zName); if( pTab==0 ){ sqliteErrorMsg(pParse, "no such table: %T", pTok); } return pTab; } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ void sqliteDropTable(Parse *pParse, Token *pName, int isView){ Table *pTable; Vdbe *v; int base; sqlite *db = pParse->db; int iDb; if( pParse->nErr || sqlite_malloc_failed ) return; pTable = sqliteTableFromToken(pParse, pName); if( pTable==0 ) return; iDb = pTable->iDb; assert( iDb>=0 && iDbnDb ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code; const char *zTab = SCHEMA_TABLE(pTable->iDb); const char *zDb = db->aDb[pTable->iDb].zName; if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ return; } if( isView ){ if( iDb==1 ){ code = SQLITE_DROP_TEMP_VIEW; }else{ code = SQLITE_DROP_VIEW; } }else{ if( iDb==1 ){ code = SQLITE_DROP_TEMP_TABLE; }else{ code = SQLITE_DROP_TABLE; } } if( sqliteAuthCheck(pParse, code, pTable->zName, 0, zDb) ){ return; } if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTable->zName, 0, zDb) ){ return; } } #endif if( pTable->readOnly ){ sqliteErrorMsg(pParse, "table %s may not be dropped", pTable->zName); pParse->nErr++; return; } if( isView && pTable->pSelect==0 ){ sqliteErrorMsg(pParse, "use DROP TABLE to delete table %s", pTable->zName); return; } if( !isView && pTable->pSelect ){ sqliteErrorMsg(pParse, "use DROP VIEW to delete view %s", pTable->zName); return; } /* Generate code to remove the table from the master table ** on disk. */ v = sqliteGetVdbe(pParse); if( v ){ static VdbeOpList dropTable[] = { { OP_Rewind, 0, ADDR(8), 0}, { OP_String, 0, 0, 0}, /* 1 */ { OP_MemStore, 1, 1, 0}, { OP_MemLoad, 1, 0, 0}, /* 3 */ { OP_Column, 0, 2, 0}, { OP_Ne, 0, ADDR(7), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(3), 0}, /* 7 */ }; Index *pIdx; Trigger *pTrigger; sqliteBeginWriteOperation(pParse, 0, pTable->iDb); /* Drop all triggers associated with the table being dropped */ pTrigger = pTable->pTrigger; while( pTrigger ){ assert( pTrigger->iDb==pTable->iDb || pTrigger->iDb==1 ); sqliteDropTriggerPtr(pParse, pTrigger, 1); if( pParse->explain ){ pTrigger = pTrigger->pNext; }else{ pTrigger = pTable->pTrigger; } } /* Drop all SQLITE_MASTER entries that refer to the table */ sqliteOpenMasterTable(v, pTable->iDb); base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); sqliteVdbeChangeP3(v, base+1, pTable->zName, 0); /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */ if( pTable->iDb!=1 ){ sqliteOpenMasterTable(v, 1); base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable); sqliteVdbeChangeP3(v, base+1, pTable->zName, 0); } if( pTable->iDb==0 ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); if( !isView ){ sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb); for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb); } } sqliteEndWriteOperation(pParse); } /* Delete the in-memory description of the table. ** ** Exception: if the SQL statement began with the EXPLAIN keyword, ** then no changes should be made. */ if( !pParse->explain ){ sqliteUnlinkAndDeleteTable(db, pTable); db->flags |= SQLITE_InternChanges; } sqliteViewResetAll(db, iDb); } /* ** This routine constructs a P3 string suitable for an OP_MakeIdxKey ** opcode and adds that P3 string to the most recently inserted instruction ** in the virtual machine. The P3 string consists of a single character ** for each column in the index pIdx of table pTab. If the column uses ** a numeric sort order, then the P3 string character corresponding to ** that column is 'n'. If the column uses a text sort order, then the ** P3 string is 't'. See the OP_MakeIdxKey opcode documentation for ** additional information. See also the sqliteAddKeyType() routine. */ void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){ char *zType; Table *pTab; int i, n; assert( pIdx!=0 && pIdx->pTable!=0 ); pTab = pIdx->pTable; n = pIdx->nColumn; zType = sqliteMallocRaw( n+1 ); if( zType==0 ) return; for(i=0; iaiColumn[i]; assert( iCol>=0 && iColnCol ); if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ zType[i] = 't'; }else{ zType[i] = 'n'; } } zType[n] = 0; sqliteVdbeChangeP3(v, -1, zType, n); sqliteFree(zType); } /* ** This routine is called to create a new foreign key on the table ** currently under construction. pFromCol determines which columns ** in the current table point to the foreign key. If pFromCol==0 then ** connect the key to the last column inserted. pTo is the name of ** the table referred to. pToCol is a list of tables in the other ** pTo table that the foreign key points to. flags contains all ** information about the conflict resolution algorithms specified ** in the ON DELETE, ON UPDATE and ON INSERT clauses. ** ** An FKey structure is created and added to the table currently ** under construction in the pParse->pNewTable field. The new FKey ** is not linked into db->aFKey at this point - that does not happen ** until sqliteEndTable(). ** ** The foreign key is set for IMMEDIATE processing. A subsequent call ** to sqliteDeferForeignKey() might change this to DEFERRED. */ void sqliteCreateForeignKey( Parse *pParse, /* Parsing context */ IdList *pFromCol, /* Columns in this table that point to other table */ Token *pTo, /* Name of the other table */ IdList *pToCol, /* Columns in the other table */ int flags /* Conflict resolution algorithms. */ ){ Table *p = pParse->pNewTable; int nByte; int i; int nCol; char *z; FKey *pFKey = 0; assert( pTo!=0 ); if( p==0 || pParse->nErr ) goto fk_end; if( pFromCol==0 ){ int iCol = p->nCol-1; if( iCol<0 ) goto fk_end; if( pToCol && pToCol->nId!=1 ){ sqliteErrorMsg(pParse, "foreign key on %s" " should reference only one column of table %T", p->aCol[iCol].zName, pTo); goto fk_end; } nCol = 1; }else if( pToCol && pToCol->nId!=pFromCol->nId ){ sqliteErrorMsg(pParse, "number of columns in foreign key does not match the number of " "columns in the referenced table"); goto fk_end; }else{ nCol = pFromCol->nId; } nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1; if( pToCol ){ for(i=0; inId; i++){ nByte += strlen(pToCol->a[i].zName) + 1; } } pFKey = sqliteMalloc( nByte ); if( pFKey==0 ) goto fk_end; pFKey->pFrom = p; pFKey->pNextFrom = p->pFKey; z = (char*)&pFKey[1]; pFKey->aCol = (struct sColMap*)z; z += sizeof(struct sColMap)*nCol; pFKey->zTo = z; memcpy(z, pTo->z, pTo->n); z[pTo->n] = 0; z += pTo->n+1; pFKey->pNextTo = 0; pFKey->nCol = nCol; if( pFromCol==0 ){ pFKey->aCol[0].iFrom = p->nCol-1; }else{ for(i=0; inCol; j++){ if( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ pFKey->aCol[i].iFrom = j; break; } } if( j>=p->nCol ){ sqliteErrorMsg(pParse, "unknown column \"%s\" in foreign key definition", pFromCol->a[i].zName); goto fk_end; } } } if( pToCol ){ for(i=0; ia[i].zName); pFKey->aCol[i].zCol = z; memcpy(z, pToCol->a[i].zName, n); z[n] = 0; z += n+1; } } pFKey->isDeferred = 0; pFKey->deleteConf = flags & 0xff; pFKey->updateConf = (flags >> 8 ) & 0xff; pFKey->insertConf = (flags >> 16 ) & 0xff; /* Link the foreign key to the table as the last step. */ p->pFKey = pFKey; pFKey = 0; fk_end: sqliteFree(pFKey); sqliteIdListDelete(pFromCol); sqliteIdListDelete(pToCol); } /* ** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED ** clause is seen as part of a foreign key definition. The isDeferred ** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. ** The behavior of the most recently created foreign key is adjusted ** accordingly. */ void sqliteDeferForeignKey(Parse *pParse, int isDeferred){ Table *pTab; FKey *pFKey; if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; pFKey->isDeferred = isDeferred; } /* ** Create a new index for an SQL table. pIndex is the name of the index ** and pTable is the name of the table that is to be indexed. Both will ** be NULL for a primary key or an index that is created to satisfy a ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable ** as the table to be indexed. pParse->pNewTable is a table that is ** currently being constructed by a CREATE TABLE statement. ** ** pList is a list of columns to be indexed. pList will be NULL if this ** is a primary key or unique-constraint on the most recent column added ** to the table currently under construction. */ void sqliteCreateIndex( Parse *pParse, /* All information about this parse */ Token *pName, /* Name of the index. May be NULL */ SrcList *pTable, /* Name of the table to index. Use pParse->pNewTable if 0 */ IdList *pList, /* A list of columns to be indexed */ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */ Token *pEnd /* The ")" that closes the CREATE INDEX statement */ ){ Table *pTab; /* Table to be indexed */ Index *pIndex; /* The index to be created */ char *zName = 0; int i, j; Token nullId; /* Fake token for an empty ID list */ DbFixer sFix; /* For assigning database names to pTable */ int isTemp; /* True for a temporary index */ sqlite *db = pParse->db; if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index; if( db->init.busy && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName) && sqliteFixSrcList(&sFix, pTable) ){ goto exit_create_index; } /* ** Find the table that is to be indexed. Return early if not found. */ if( pTable!=0 ){ assert( pName!=0 ); assert( pTable->nSrc==1 ); pTab = sqliteSrcListLookup(pParse, pTable); }else{ assert( pName==0 ); pTab = pParse->pNewTable; } if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } if( pTab->iDb>=2 && db->init.busy==0 ){ sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName); goto exit_create_index; } if( pTab->pSelect ){ sqliteErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; } isTemp = pTab->iDb==1; /* ** Find the name of the index. Make sure there is not already another ** index or table with the same name. ** ** Exception: If we are reading the names of permanent indices from the ** sqlite_master table (because some other process changed the schema) and ** one of the index names collides with the name of a temporary table or ** index, then we will continue to process this index. ** ** If pName==0 it means that we are ** dealing with a primary key or UNIQUE constraint. We have to invent our ** own name. */ if( pName && !db->init.busy ){ Index *pISameName; /* Another index with the same name */ Table *pTSameName; /* A table with same name as the index */ zName = sqliteTableNameFromToken(pName); if( zName==0 ) goto exit_create_index; if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){ sqliteErrorMsg(pParse, "index %s already exists", zName); goto exit_create_index; } if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){ sqliteErrorMsg(pParse, "there is already a table named %s", zName); goto exit_create_index; } }else if( pName==0 ){ char zBuf[30]; int n; Index *pLoop; for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} sprintf(zBuf,"%d)",n); zName = 0; sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0); if( zName==0 ) goto exit_create_index; }else{ zName = sqliteStrNDup(pName->z, pName->n); } /* Check for authorization to create an index. */ #ifndef SQLITE_OMIT_AUTHORIZATION { const char *zDb = db->aDb[pTab->iDb].zName; assert( pTab->iDb==db->init.iDb || isTemp ); if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto exit_create_index; } i = SQLITE_CREATE_INDEX; if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX; if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){ goto exit_create_index; } } #endif /* If pList==0, it means this routine was called to make a primary ** key out of the last column added to the table under construction. ** So create a fake list to simulate this. */ if( pList==0 ){ nullId.z = pTab->aCol[pTab->nCol-1].zName; nullId.n = strlen(nullId.z); pList = sqliteIdListAppend(0, &nullId); if( pList==0 ) goto exit_create_index; } /* ** Allocate the index structure. */ pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + sizeof(int)*pList->nId ); if( pIndex==0 ) goto exit_create_index; pIndex->aiColumn = (int*)&pIndex[1]; pIndex->zName = (char*)&pIndex->aiColumn[pList->nId]; strcpy(pIndex->zName, zName); pIndex->pTable = pTab; pIndex->nColumn = pList->nId; pIndex->onError = onError; pIndex->autoIndex = pName==0; pIndex->iDb = isTemp ? 1 : db->init.iDb; /* Scan the names of the columns of the table to be indexed and ** load the column indices into the Index structure. Report an error ** if any column is not found. */ for(i=0; inId; i++){ for(j=0; jnCol; j++){ if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break; } if( j>=pTab->nCol ){ sqliteErrorMsg(pParse, "table %s has no column named %s", pTab->zName, pList->a[i].zName); sqliteFree(pIndex); goto exit_create_index; } pIndex->aiColumn[i] = j; } /* Link the new Index structure to its table and to the other ** in-memory database structures. */ if( !pParse->explain ){ Index *p; p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash, pIndex->zName, strlen(pIndex->zName)+1, pIndex); if( p ){ assert( p==pIndex ); /* Malloc must have failed */ sqliteFree(pIndex); goto exit_create_index; } db->flags |= SQLITE_InternChanges; } /* When adding an index to the list of indices for a table, make ** sure all indices labeled OE_Replace come after all those labeled ** OE_Ignore. This is necessary for the correct operation of UPDATE ** and INSERT. */ if( onError!=OE_Replace || pTab->pIndex==0 || pTab->pIndex->onError==OE_Replace){ pIndex->pNext = pTab->pIndex; pTab->pIndex = pIndex; }else{ Index *pOther = pTab->pIndex; while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ pOther = pOther->pNext; } pIndex->pNext = pOther->pNext; pOther->pNext = pIndex; } /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" table on the disk. So do not write to the disk ** again. Extract the table number from the db->init.newTnum field. */ if( db->init.busy && pTable!=0 ){ pIndex->tnum = db->init.newTnum; } /* If the db->init.busy is 0 then create the index on disk. This ** involves writing the index into the master table and filling in the ** index with the current table contents. ** ** The db->init.busy is 0 when the user first enters a CREATE INDEX ** command. db->init.busy is 1 when a database is opened and ** CREATE INDEX statements are read out of the master table. In ** the latter case the index already exists on disk, which is why ** we don't want to recreate it. ** ** If pTable==0 it means this index is generated as a primary key ** or UNIQUE constraint of a CREATE TABLE statement. Since the table ** has just been created, it contains no data and the index initialization ** step can be skipped. */ else if( db->init.busy==0 ){ int n; Vdbe *v; int lbl1, lbl2; int i; int addr; v = sqliteGetVdbe(pParse); if( v==0 ) goto exit_create_index; if( pTable!=0 ){ sqliteBeginWriteOperation(pParse, 0, isTemp); sqliteOpenMasterTable(v, isTemp); } sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC); sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0); sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER); pIndex->tnum = 0; if( pTable ){ sqliteVdbeCode(v, OP_Dup, 0, 0, OP_Integer, isTemp, 0, OP_OpenWrite, 1, 0, 0); } addr = sqliteVdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ n = Addr(pEnd->z) - Addr(pStart->z) + 1; sqliteVdbeChangeP3(v, addr, pStart->z, n); } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); if( pTable ){ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0); lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); for(i=0; inColumn; i++){ int iCol = pIndex->aiColumn[i]; if( pTab->iPKey==iCol ){ sqliteVdbeAddOp(v, OP_Dup, i, 0); }else{ sqliteVdbeAddOp(v, OP_Column, 2, iCol); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex); sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None, "indexed columns are not unique", P3_STATIC); sqliteVdbeAddOp(v, OP_Next, 2, lbl1); sqliteVdbeResolveLabel(v, lbl2); sqliteVdbeAddOp(v, OP_Close, 2, 0); sqliteVdbeAddOp(v, OP_Close, 1, 0); } if( pTable!=0 ){ if( !isTemp ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteEndWriteOperation(pParse); } } /* Clean up before exiting */ exit_create_index: sqliteIdListDelete(pList); sqliteSrcListDelete(pTable); sqliteFree(zName); return; } /* ** This routine will drop an existing named index. This routine ** implements the DROP INDEX statement. */ void sqliteDropIndex(Parse *pParse, SrcList *pName){ Index *pIndex; Vdbe *v; sqlite *db = pParse->db; if( pParse->nErr || sqlite_malloc_failed ) return; assert( pName->nSrc==1 ); pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ sqliteErrorMsg(pParse, "no such index: %S", pName, 0); goto exit_drop_index; } if( pIndex->autoIndex ){ sqliteErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } if( pIndex->iDb>1 ){ sqliteErrorMsg(pParse, "cannot alter schema of attached " "databases", 0); goto exit_drop_index; } #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[pIndex->iDb].zName; const char *zTab = SCHEMA_TABLE(pIndex->iDb); if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; } if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX; if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ goto exit_drop_index; } } #endif /* Generate code to remove the index and from the master table */ v = sqliteGetVdbe(pParse); if( v ){ static VdbeOpList dropIndex[] = { { OP_Rewind, 0, ADDR(9), 0}, { OP_String, 0, 0, 0}, /* 1 */ { OP_MemStore, 1, 1, 0}, { OP_MemLoad, 1, 0, 0}, /* 3 */ { OP_Column, 0, 1, 0}, { OP_Eq, 0, ADDR(8), 0}, { OP_Next, 0, ADDR(3), 0}, { OP_Goto, 0, ADDR(9), 0}, { OP_Delete, 0, 0, 0}, /* 8 */ }; int base; sqliteBeginWriteOperation(pParse, 0, pIndex->iDb); sqliteOpenMasterTable(v, pIndex->iDb); base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0); if( pIndex->iDb==0 ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); sqliteEndWriteOperation(pParse); } /* Delete the in-memory description of this index. */ if( !pParse->explain ){ sqliteUnlinkAndDeleteIndex(db, pIndex); db->flags |= SQLITE_InternChanges; } exit_drop_index: sqliteSrcListDelete(pName); } /* ** Append a new element to the given IdList. Create a new IdList if ** need be. ** ** A new IdList is returned, or NULL if malloc() fails. */ IdList *sqliteIdListAppend(IdList *pList, Token *pToken){ if( pList==0 ){ pList = sqliteMalloc( sizeof(IdList) ); if( pList==0 ) return 0; pList->nAlloc = 0; } if( pList->nId>=pList->nAlloc ){ struct IdList_item *a; pList->nAlloc = pList->nAlloc*2 + 5; a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) ); if( a==0 ){ sqliteIdListDelete(pList); return 0; } pList->a = a; } memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); if( pToken ){ char **pz = &pList->a[pList->nId].zName; sqliteSetNString(pz, pToken->z, pToken->n, 0); if( *pz==0 ){ sqliteIdListDelete(pList); return 0; }else{ sqliteDequote(*pz); } } pList->nId++; return pList; } /* ** Append a new table name to the given SrcList. Create a new SrcList if ** need be. A new entry is created in the SrcList even if pToken is NULL. ** ** A new SrcList is returned, or NULL if malloc() fails. ** ** If pDatabase is not null, it means that the table has an optional ** database name prefix. Like this: "database.table". The pDatabase ** points to the table name and the pTable points to the database name. ** The SrcList.a[].zName field is filled with the table name which might ** come from pTable (if pDatabase is NULL) or from pDatabase. ** SrcList.a[].zDatabase is filled with the database name from pTable, ** or with NULL if no database is specified. ** ** In other words, if call like this: ** ** sqliteSrcListAppend(A,B,0); ** ** Then B is a table name and the database name is unspecified. If called ** like this: ** ** sqliteSrcListAppend(A,B,C); ** ** Then C is the table name and B is the database name. */ SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ if( pList==0 ){ pList = sqliteMalloc( sizeof(SrcList) ); if( pList==0 ) return 0; pList->nAlloc = 1; } if( pList->nSrc>=pList->nAlloc ){ SrcList *pNew; pList->nAlloc *= 2; pNew = sqliteRealloc(pList, sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); if( pNew==0 ){ sqliteSrcListDelete(pList); return 0; } pList = pNew; } memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0])); if( pDatabase && pDatabase->z==0 ){ pDatabase = 0; } if( pDatabase && pTable ){ Token *pTemp = pDatabase; pDatabase = pTable; pTable = pTemp; } if( pTable ){ char **pz = &pList->a[pList->nSrc].zName; sqliteSetNString(pz, pTable->z, pTable->n, 0); if( *pz==0 ){ sqliteSrcListDelete(pList); return 0; }else{ sqliteDequote(*pz); } } if( pDatabase ){ char **pz = &pList->a[pList->nSrc].zDatabase; sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0); if( *pz==0 ){ sqliteSrcListDelete(pList); return 0; }else{ sqliteDequote(*pz); } } pList->a[pList->nSrc].iCursor = -1; pList->nSrc++; return pList; } /* ** Assign cursors to all tables in a SrcList */ void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; for(i=0; inSrc; i++){ if( pList->a[i].iCursor<0 ){ pList->a[i].iCursor = pParse->nTab++; } } } /* ** Add an alias to the last identifier on the given identifier list. */ void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){ if( pList && pList->nSrc>0 ){ int i = pList->nSrc - 1; sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0); sqliteDequote(pList->a[i].zAlias); } } /* ** Delete an IdList. */ void sqliteIdListDelete(IdList *pList){ int i; if( pList==0 ) return; for(i=0; inId; i++){ sqliteFree(pList->a[i].zName); } sqliteFree(pList->a); sqliteFree(pList); } /* ** Return the index in pList of the identifier named zId. Return -1 ** if not found. */ int sqliteIdListIndex(IdList *pList, const char *zName){ int i; if( pList==0 ) return -1; for(i=0; inId; i++){ if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i; } return -1; } /* ** Delete an entire SrcList including all its substructure. */ void sqliteSrcListDelete(SrcList *pList){ int i; if( pList==0 ) return; for(i=0; inSrc; i++){ sqliteFree(pList->a[i].zDatabase); sqliteFree(pList->a[i].zName); sqliteFree(pList->a[i].zAlias); if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){ sqliteDeleteTable(0, pList->a[i].pTab); } sqliteSelectDelete(pList->a[i].pSelect); sqliteExprDelete(pList->a[i].pOn); sqliteIdListDelete(pList->a[i].pUsing); } sqliteFree(pList); } /* ** Begin a transaction */ void sqliteBeginTransaction(Parse *pParse, int onError){ sqlite *db; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; if( db->flags & SQLITE_InTrans ){ sqliteErrorMsg(pParse, "cannot start a transaction within a transaction"); return; } sqliteBeginWriteOperation(pParse, 0, 0); if( !pParse->explain ){ db->flags |= SQLITE_InTrans; db->onError = onError; } } /* ** Commit a transaction */ void sqliteCommitTransaction(Parse *pParse){ sqlite *db; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; if( (db->flags & SQLITE_InTrans)==0 ){ sqliteErrorMsg(pParse, "cannot commit - no transaction is active"); return; } if( !pParse->explain ){ db->flags &= ~SQLITE_InTrans; } sqliteEndWriteOperation(pParse); if( !pParse->explain ){ db->onError = OE_Default; } } /* ** Rollback a transaction */ void sqliteRollbackTransaction(Parse *pParse){ sqlite *db; Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; if( (db->flags & SQLITE_InTrans)==0 ){ sqliteErrorMsg(pParse, "cannot rollback - no transaction is active"); return; } v = sqliteGetVdbe(pParse); if( v ){ sqliteVdbeAddOp(v, OP_Rollback, 0, 0); } if( !pParse->explain ){ db->flags &= ~SQLITE_InTrans; db->onError = OE_Default; } } /* ** Generate VDBE code that will verify the schema cookie for all ** named database files. */ void sqliteCodeVerifySchema(Parse *pParse, int iDb){ sqlite *db = pParse->db; Vdbe *v = sqliteGetVdbe(pParse); assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){ sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie); DbSetProperty(db, iDb, DB_Cookie); } } /* ** Generate VDBE code that prepares for doing an operation that ** might change the database. ** ** This routine starts a new transaction if we are not already within ** a transaction. If we are already within a transaction, then a checkpoint ** is set if the setCheckpoint parameter is true. A checkpoint should ** be set for operations that might fail (due to a constraint) part of ** the way through and which will need to undo some writes without having to ** rollback the whole transaction. For operations where all constraints ** can be checked before any changes are made to the database, it is never ** necessary to undo a write and the checkpoint should not be set. ** ** Only database iDb and the temp database are made writable by this call. ** If iDb==0, then the main and temp databases are made writable. If ** iDb==1 then only the temp database is made writable. If iDb>1 then the ** specified auxiliary database and the temp database are made writable. */ void sqliteBeginWriteOperation(Parse *pParse, int setCheckpoint, int iDb){ Vdbe *v; sqlite *db = pParse->db; if( DbHasProperty(db, iDb, DB_Locked) ) return; v = sqliteGetVdbe(pParse); if( v==0 ) return; if( !db->aDb[iDb].inTrans ){ sqliteVdbeAddOp(v, OP_Transaction, iDb, 0); DbSetProperty(db, iDb, DB_Locked); sqliteCodeVerifySchema(pParse, iDb); if( iDb!=1 ){ sqliteBeginWriteOperation(pParse, setCheckpoint, 1); } }else if( setCheckpoint ){ sqliteVdbeAddOp(v, OP_Checkpoint, iDb, 0); DbSetProperty(db, iDb, DB_Locked); } } /* ** Generate code that concludes an operation that may have changed ** the database. If a statement transaction was started, then emit ** an OP_Commit that will cause the changes to be committed to disk. ** ** Note that checkpoints are automatically committed at the end of ** a statement. Note also that there can be multiple calls to ** sqliteBeginWriteOperation() but there should only be a single ** call to sqliteEndWriteOperation() at the conclusion of the statement. */ void sqliteEndWriteOperation(Parse *pParse){ Vdbe *v; sqlite *db = pParse->db; if( pParse->trigStack ) return; /* if this is in a trigger */ v = sqliteGetVdbe(pParse); if( v==0 ) return; if( db->flags & SQLITE_InTrans ){ /* A BEGIN has executed. Do not commit until we see an explicit ** COMMIT statement. */ }else{ sqliteVdbeAddOp(v, OP_Commit, 0, 0); } } DBD-SQLite2-0.36/MANIFEST0000644000175000017500000000223612130556467013765 0ustar rurbanrurbanChanges MANIFEST MANIFEST.SKIP Makefile.PL README SQLite2.xs SQLiteXS.h attach.c auth.c btree.c btree.h btree_rb.c build.c copy.c date.c dbdimp.c dbdimp.h delete.c encode.c expr.c func.c getsqlite.pl hash.c hash.h insert.c lib/DBD/SQLite2.pm main.c opcodes.c opcodes.h os.c os.h pager.c pager.h parse.c parse.h pragma.c printf.c random.c select.c sqlite.h sqliteInt.h t/00basic.t t/01logon.t t/02cr_table.t t/03insert.t t/04select.t t/05tran.t t/06error.t t/08create_function.t t/09create_aggregate.t t/10dsnlist.t t/20createdrop.t t/30insertfetch.t t/40bindparam.t t/40blobs.t t/40listfields.t t/40nulls.t t/40numrows.t t/50chopblanks.t t/50commit.t t/60metadata.t t/90cppcomments.t t/98_kwalitee.t t/98_meta.t t/98_perl_minimum_version.t t/98_pod-coverage.t t/98_pod.t t/99cleanup.t t/SQLite2.dbtest t/ak-dbd.t t/dbdadmin.t t/lib.pl table.c tokenize.c trigger.c update.c util.c vacuum.c vdbe.c vdbe.h vdbeaux.c vdbeInt.h where.c META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) SIGNATURE Public-key signature (added by MakeMaker) DBD-SQLite2-0.36/btree.h0000644000175000017500000001476312126353147014111 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* ** Forward declarations of structure */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; typedef struct BtOps BtOps; typedef struct BtCursorOps BtCursorOps; /* ** An instance of the following structure contains pointers to all ** methods against an open BTree. Alternative BTree implementations ** (examples: file based versus in-memory) can be created by substituting ** different methods. Users of the BTree cannot tell the difference. ** ** In C++ we could do this by defining a virtual base class and then ** creating subclasses for each different implementation. But this is ** C not C++ so we have to be a little more explicit. */ struct BtOps { int (*Close)(Btree*); int (*SetCacheSize)(Btree*, int); int (*SetSafetyLevel)(Btree*, int); int (*BeginTrans)(Btree*); int (*Commit)(Btree*); int (*Rollback)(Btree*); int (*BeginCkpt)(Btree*); int (*CommitCkpt)(Btree*); int (*RollbackCkpt)(Btree*); int (*CreateTable)(Btree*, int*); int (*CreateIndex)(Btree*, int*); int (*DropTable)(Btree*, int); int (*ClearTable)(Btree*, int); int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur); int (*GetMeta)(Btree*, int*); int (*UpdateMeta)(Btree*, int*); char *(*IntegrityCheck)(Btree*, int*, int); const char *(*GetFilename)(Btree*); int (*Copyfile)(Btree*,Btree*); struct Pager *(*Pager)(Btree*); #ifdef SQLITE_TEST int (*PageDump)(Btree*, int, int); #endif }; /* ** An instance of this structure defines all of the methods that can ** be executed against a cursor. */ struct BtCursorOps { int (*Moveto)(BtCursor*, const void *pKey, int nKey, int *pRes); int (*Delete)(BtCursor*); int (*Insert)(BtCursor*, const void *pKey, int nKey, const void *pData, int nData); int (*First)(BtCursor*, int *pRes); int (*Last)(BtCursor*, int *pRes); int (*Next)(BtCursor*, int *pRes); int (*Previous)(BtCursor*, int *pRes); int (*KeySize)(BtCursor*, int *pSize); int (*Key)(BtCursor*, int offset, int amt, char *zBuf); int (*KeyCompare)(BtCursor*, const void *pKey, int nKey, int nIgnore, int *pRes); int (*DataSize)(BtCursor*, int *pSize); int (*Data)(BtCursor*, int offset, int amt, char *zBuf); int (*CloseCursor)(BtCursor*); #ifdef SQLITE_TEST int (*CursorDump)(BtCursor*, int*); #endif }; /* ** The number of 4-byte "meta" values contained on the first page of each ** database file. */ #define SQLITE_N_BTREE_META 10 int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); int sqliteRbtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); #define btOps(pBt) (*((BtOps **)(pBt))) #define btCOps(pCur) (*((BtCursorOps **)(pCur))) #define sqliteBtreeClose(pBt) (btOps(pBt)->Close(pBt)) #define sqliteBtreeSetCacheSize(pBt, sz) (btOps(pBt)->SetCacheSize(pBt, sz)) #define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl)) #define sqliteBtreeBeginTrans(pBt) (btOps(pBt)->BeginTrans(pBt)) #define sqliteBtreeCommit(pBt) (btOps(pBt)->Commit(pBt)) #define sqliteBtreeRollback(pBt) (btOps(pBt)->Rollback(pBt)) #define sqliteBtreeBeginCkpt(pBt) (btOps(pBt)->BeginCkpt(pBt)) #define sqliteBtreeCommitCkpt(pBt) (btOps(pBt)->CommitCkpt(pBt)) #define sqliteBtreeRollbackCkpt(pBt) (btOps(pBt)->RollbackCkpt(pBt)) #define sqliteBtreeCreateTable(pBt,piTable)\ (btOps(pBt)->CreateTable(pBt,piTable)) #define sqliteBtreeCreateIndex(pBt, piIndex)\ (btOps(pBt)->CreateIndex(pBt, piIndex)) #define sqliteBtreeDropTable(pBt, iTable) (btOps(pBt)->DropTable(pBt, iTable)) #define sqliteBtreeClearTable(pBt, iTable)\ (btOps(pBt)->ClearTable(pBt, iTable)) #define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\ (btOps(pBt)->Cursor(pBt, iTable, wrFlag, ppCur)) #define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\ (btCOps(pCur)->Moveto(pCur, pKey, nKey, pRes)) #define sqliteBtreeDelete(pCur) (btCOps(pCur)->Delete(pCur)) #define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \ (btCOps(pCur)->Insert(pCur, pKey, nKey, pData, nData)) #define sqliteBtreeFirst(pCur, pRes) (btCOps(pCur)->First(pCur, pRes)) #define sqliteBtreeLast(pCur, pRes) (btCOps(pCur)->Last(pCur, pRes)) #define sqliteBtreeNext(pCur, pRes) (btCOps(pCur)->Next(pCur, pRes)) #define sqliteBtreePrevious(pCur, pRes) (btCOps(pCur)->Previous(pCur, pRes)) #define sqliteBtreeKeySize(pCur, pSize) (btCOps(pCur)->KeySize(pCur, pSize) ) #define sqliteBtreeKey(pCur, offset, amt, zBuf)\ (btCOps(pCur)->Key(pCur, offset, amt, zBuf)) #define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\ (btCOps(pCur)->KeyCompare(pCur, pKey, nKey, nIgnore, pRes)) #define sqliteBtreeDataSize(pCur, pSize) (btCOps(pCur)->DataSize(pCur, pSize)) #define sqliteBtreeData(pCur, offset, amt, zBuf)\ (btCOps(pCur)->Data(pCur, offset, amt, zBuf)) #define sqliteBtreeCloseCursor(pCur) (btCOps(pCur)->CloseCursor(pCur)) #define sqliteBtreeGetMeta(pBt, aMeta) (btOps(pBt)->GetMeta(pBt, aMeta)) #define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta)) #define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\ (btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot)) #define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt)) #define sqliteBtreeCopyFile(pBt1, pBt2) (btOps(pBt1)->Copyfile(pBt1, pBt2)) #define sqliteBtreePager(pBt) (btOps(pBt)->Pager(pBt)) #ifdef SQLITE_TEST #define sqliteBtreePageDump(pBt, pgno, recursive)\ (btOps(pBt)->PageDump(pBt, pgno, recursive)) #define sqliteBtreeCursorDump(pCur, aResult)\ (btCOps(pCur)->CursorDump(pCur, aResult)) int btree_native_byte_order; #endif /* SQLITE_TEST */ #endif /* _BTREE_H_ */ DBD-SQLite2-0.36/auth.c0000644000175000017500000001562012126353147013735 0ustar rurbanrurban/* ** 2003 January 11 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the sqlite_set_authorizer() ** API. This facility is an optional feature of the library. Embedded ** systems that do not need this facility may omit it by recompiling ** the library with -DSQLITE_OMIT_AUTHORIZATION=1 ** ** $Id: auth.c,v 1.1.1.1 2004/08/08 15:03:56 matt Exp $ */ #include "sqliteInt.h" /* ** All of the code in this file may be omitted by defining a single ** macro. */ #ifndef SQLITE_OMIT_AUTHORIZATION /* ** Set or clear the access authorization function. ** ** The access authorization function is be called during the compilation ** phase to verify that the user has read and/or write access permission on ** various fields of the database. The first argument to the auth function ** is a copy of the 3rd argument to this routine. The second argument ** to the auth function is one of these constants: ** ** SQLITE_COPY ** SQLITE_CREATE_INDEX ** SQLITE_CREATE_TABLE ** SQLITE_CREATE_TEMP_INDEX ** SQLITE_CREATE_TEMP_TABLE ** SQLITE_CREATE_TEMP_TRIGGER ** SQLITE_CREATE_TEMP_VIEW ** SQLITE_CREATE_TRIGGER ** SQLITE_CREATE_VIEW ** SQLITE_DELETE ** SQLITE_DROP_INDEX ** SQLITE_DROP_TABLE ** SQLITE_DROP_TEMP_INDEX ** SQLITE_DROP_TEMP_TABLE ** SQLITE_DROP_TEMP_TRIGGER ** SQLITE_DROP_TEMP_VIEW ** SQLITE_DROP_TRIGGER ** SQLITE_DROP_VIEW ** SQLITE_INSERT ** SQLITE_PRAGMA ** SQLITE_READ ** SQLITE_SELECT ** SQLITE_TRANSACTION ** SQLITE_UPDATE ** ** The third and fourth arguments to the auth function are the name of ** the table and the column that are being accessed. The auth function ** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If ** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY ** means that the SQL statement will never-run - the sqlite_exec() call ** will return with an error. SQLITE_IGNORE means that the SQL statement ** should run but attempts to read the specified column will return NULL ** and attempts to write the column will be ignored. ** ** Setting the auth function to NULL disables this hook. The default ** setting of the auth function is NULL. */ int sqlite_set_authorizer( sqlite *db, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pArg ){ db->xAuth = xAuth; db->pAuthArg = pArg; return SQLITE_OK; } /* ** Write an error message into pParse->zErrMsg that explains that the ** user-supplied authorization function returned an illegal value. */ static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ sqliteErrorMsg(pParse, "illegal return value (%d) from the " "authorization function - should be SQLITE_OK, SQLITE_IGNORE, " "or SQLITE_DENY", rc); pParse->rc = SQLITE_MISUSE; } /* ** The pExpr should be a TK_COLUMN expression. The table referred to ** is in pTabList or else it is the NEW or OLD table of a trigger. ** Check to see if it is OK to read this particular column. ** ** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN ** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, ** then generate an error. */ void sqliteAuthRead( Parse *pParse, /* The parser context */ Expr *pExpr, /* The expression to check authorization on */ SrcList *pTabList /* All table that pExpr might refer to */ ){ sqlite *db = pParse->db; int rc; Table *pTab; /* The table being read */ const char *zCol; /* Name of the column of the table */ int iSrc; /* Index in pTabList->a[] of table being read */ const char *zDBase; /* Name of database being accessed */ if( db->xAuth==0 ) return; assert( pExpr->op==TK_COLUMN ); for(iSrc=0; iSrcnSrc; iSrc++){ if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; } if( iSrc>=0 && iSrcnSrc ){ pTab = pTabList->a[iSrc].pTab; }else{ /* This must be an attempt to read the NEW or OLD pseudo-tables ** of a trigger. */ TriggerStack *pStack; /* The stack of current triggers */ pStack = pParse->trigStack; assert( pStack!=0 ); assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx ); pTab = pStack->pTab; } if( pTab==0 ) return; if( pExpr->iColumn>=0 ){ assert( pExpr->iColumnnCol ); zCol = pTab->aCol[pExpr->iColumn].zName; }else if( pTab->iPKey>=0 ){ assert( pTab->iPKeynCol ); zCol = pTab->aCol[pTab->iPKey].zName; }else{ zCol = "ROWID"; } assert( pExpr->iDbnDb ); zDBase = db->aDb[pExpr->iDb].zName; rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, pParse->zAuthContext); if( rc==SQLITE_IGNORE ){ pExpr->op = TK_NULL; }else if( rc==SQLITE_DENY ){ if( db->nDb>2 || pExpr->iDb!=0 ){ sqliteErrorMsg(pParse, "access to %s.%s.%s is prohibited", zDBase, pTab->zName, zCol); }else{ sqliteErrorMsg(pParse, "access to %s.%s is prohibited", pTab->zName,zCol); } pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_OK ){ sqliteAuthBadReturnCode(pParse, rc); } } /* ** Do an authorization check using the code and arguments given. Return ** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY ** is returned, then the error count and error message in pParse are ** modified appropriately. */ int sqliteAuthCheck( Parse *pParse, int code, const char *zArg1, const char *zArg2, const char *zArg3 ){ sqlite *db = pParse->db; int rc; if( db->init.busy || db->xAuth==0 ){ return SQLITE_OK; } rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext); if( rc==SQLITE_DENY ){ sqliteErrorMsg(pParse, "not authorized"); pParse->rc = SQLITE_AUTH; }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ rc = SQLITE_DENY; sqliteAuthBadReturnCode(pParse, rc); } return rc; } /* ** Push an authorization context. After this routine is called, the ** zArg3 argument to authorization callbacks will be zContext until ** popped. Or if pParse==0, this routine is a no-op. */ void sqliteAuthContextPush( Parse *pParse, AuthContext *pContext, const char *zContext ){ pContext->pParse = pParse; if( pParse ){ pContext->zAuthContext = pParse->zAuthContext; pParse->zAuthContext = zContext; } } /* ** Pop an authorization context that was previously pushed ** by sqliteAuthContextPush */ void sqliteAuthContextPop(AuthContext *pContext){ if( pContext->pParse ){ pContext->pParse->zAuthContext = pContext->zAuthContext; pContext->pParse = 0; } } #endif /* SQLITE_OMIT_AUTHORIZATION */ DBD-SQLite2-0.36/dbdimp.c0000644000175000017500000006052612126373327014242 0ustar rurbanrurban/* $Id: dbdimp.c,v 1.2 2004/08/09 13:17:59 matt Exp $ */ #include "SQLiteXS.h" DBISTATE_DECLARE; #ifndef SvPV_nolen #define SvPV_nolen(x) SvPV(x,PL_na) #endif #ifndef call_method #define call_method(x,y) perl_call_method(x,y) #endif #ifndef call_sv #define call_sv(x,y) perl_call_sv(x,y) #endif #define sqlite2_error(h,xxh,rc,what) _sqlite2_error(__FILE__, __LINE__, h, xxh, rc, what) void sqlite2_init(dbistate_t *dbistate) { dTHR; DBIS = dbistate; } static void _sqlite2_error(char *file, int line, SV *h, imp_xxh_t *imp_xxh, int rc, char *what) { dTHR; SV *errstr = DBIc_ERRSTR(imp_xxh); sv_setiv(DBIc_ERR(imp_xxh), (IV)rc); sv_setpv(errstr, what); sv_catpvf(errstr, "(%d) at %s line %d", rc, file, line); if (DBIS->debug >= 3) { PerlIO_printf(DBILOGFP, "sqlite error %d recorded: %s at %s line %d\n", rc, what, file, line); } } int sqlite2_db_login(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pass) { dTHR; int retval; char *errmsg = NULL; if (DBIS->debug >= 3) { PerlIO_printf(DBILOGFP, " login '%s' (version %s, encoding %s)\n", dbname, sqlite_version, sqlite_encoding); } if ((imp_dbh->db = sqlite_open(dbname, 0, &errmsg)) == NULL) { sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, 1, errmsg); sqlite_freemem(errmsg); return FALSE; } DBIc_IMPSET_on(imp_dbh); imp_dbh->in_tran = FALSE; imp_dbh->no_utf8_flag = FALSE; imp_dbh->functions = newAV(); imp_dbh->aggregates = newAV(); imp_dbh->timeout = SQL_TIMEOUT; imp_dbh->handle_binary_nulls = FALSE; sqlite_busy_timeout(imp_dbh->db, SQL_TIMEOUT); if ((retval = sqlite_exec(imp_dbh->db, "PRAGMA empty_result_callbacks = ON", NULL, NULL, &errmsg) != SQLITE_OK)) { /* warn("failed to set pragma: %s\n", errmsg); */ sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); sqlite_freemem(errmsg); return FALSE; } if ((retval = sqlite_exec(imp_dbh->db, "PRAGMA show_datatypes = ON", NULL, NULL, &errmsg) != SQLITE_OK)) { /* warn("failed to set pragma: %s\n", errmsg); */ sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); sqlite_freemem(errmsg); return FALSE; } DBIc_ACTIVE_on(imp_dbh); return TRUE; } int sqlite2_busy_timeout ( SV *dbh, int timeout ) { D_imp_dbh(dbh); if (timeout) { imp_dbh->timeout = timeout; sqlite_busy_timeout(imp_dbh->db, timeout); } return imp_dbh->timeout; } int sqlite2_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh) { dTHR; DBIc_ACTIVE_off(imp_dbh); if (DBIc_is(imp_dbh, DBIcf_AutoCommit) == FALSE) { sqlite2_db_rollback(dbh, imp_dbh); } sqlite_close(imp_dbh->db); imp_dbh->db = NULL; av_undef(imp_dbh->functions); imp_dbh->functions = (AV *)NULL; av_undef(imp_dbh->aggregates); imp_dbh->aggregates = (AV *)NULL; return TRUE; } void sqlite2_db_destroy (SV *dbh, imp_dbh_t *imp_dbh) { dTHR; if (DBIc_ACTIVE(imp_dbh)) { sqlite2_db_disconnect(dbh, imp_dbh); } DBIc_IMPSET_off(imp_dbh); } int sqlite2_db_rollback(SV *dbh, imp_dbh_t *imp_dbh) { dTHR; int retval; char *errmsg; if (imp_dbh->in_tran) { if ((retval = sqlite_exec(imp_dbh->db, "ROLLBACK TRANSACTION", NULL, NULL, &errmsg) != SQLITE_OK)) { sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); sqlite_freemem(errmsg); return FALSE; } imp_dbh->in_tran = FALSE; } return TRUE; } int sqlite2_db_commit(SV *dbh, imp_dbh_t *imp_dbh) { dTHR; int retval; char *errmsg; if (DBIc_is(imp_dbh, DBIcf_AutoCommit)) { warn("commit ineffective with AutoCommit"); return TRUE; } if (imp_dbh->in_tran) { if ((retval = sqlite_exec(imp_dbh->db, "COMMIT TRANSACTION", NULL, NULL, &errmsg) != SQLITE_OK)) { sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); sqlite_freemem(errmsg); return FALSE; } imp_dbh->in_tran = FALSE; } return TRUE; } int sqlite2_discon_all(SV *drh, imp_drh_t *imp_drh) { dTHR; return FALSE; /* no way to do this */ } void sqlite2_st_parse_sql(imp_sth_t *imp_sth, char *statement) { D_imp_dbh_from_sth; bool in_literal = FALSE; SV *chunk; int num_params = 0; chunk = NEWSV(0, strlen(statement)); sv_setpv(chunk, ""); /* warn("parsing: %s\n", statement); */ while (*statement) { /* warn("parse: %c => %s\n", *statement, SvPV_nolen(chunk)); */ if (*statement == '\'') { if (in_literal) { /* either end of literal, or escape */ if (statement[1] && statement[1] == '\'') { statement++; sv_catpvn(chunk, "''", 2); } else { sv_catpvn(chunk, "'", 1); in_literal = FALSE; } } else { in_literal = TRUE; sv_catpvn(chunk, "'", 1); } } else if (*statement == '?') { if (in_literal) { sv_catpvn(chunk, "?", 1); } else { num_params++; if (!imp_dbh->no_utf8_flag) { /* sv_utf8_encode(chunk); */ } av_push(imp_sth->sql, chunk); chunk = NEWSV(0, 20); sv_setpvn(chunk, "", 0); } } else { sv_catpvn(chunk, statement, 1); } statement++; } av_push(imp_sth->sql, chunk); DBIc_NUM_PARAMS(imp_sth) = num_params; } int sqlite2_st_prepare (SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) { dTHR; D_imp_dbh_from_sth; if (!DBIc_ACTIVE(imp_dbh)) { die("prepare on an inactive database handle"); } /* warn("prepare statement\n"); */ imp_sth->nrow = 0; imp_sth->ncols = 0; imp_sth->params = newAV(); imp_sth->sql = newAV(); imp_sth->results = 0; imp_sth->coldata = 0; imp_sth->retval = SQLITE_OK; sqlite2_st_parse_sql(imp_sth, statement); return TRUE; } char * sqlite2_quote(imp_dbh_t *imp_dbh, SV *val) { STRLEN len; char *cval = SvPV(val, len); SV *ret = sv_2mortal(NEWSV(0, SvCUR(val) + 2)); sv_setpvn(ret, "", 0); while (len) { switch (*cval) { case '\'': sv_catpvn(ret, "''", 2); break; case 0: if (imp_dbh->handle_binary_nulls) { sv_catpvn(ret, "\\0", 2); break; } else { die("attempt to quote binary null without sqlite_handle_binary_nulls on"); } case '\\': if (imp_dbh->handle_binary_nulls) { sv_catpvn(ret, "\\\\", 2); break; } default: sv_catpvn(ret, cval, 1); } *cval++; len--; } return SvPV_nolen(ret); } char * sqlite2_decode(imp_dbh_t *imp_dbh, char *input, size_t *len) { char *ret; char *swit; New(1, ret, *len, char); swit = ret; while (*input) { switch (*input) { case '\\': if (imp_dbh->handle_binary_nulls && input[1] && input[1] == '0') { *swit++ = '\0'; *input++; (*len)--; break; } else if (imp_dbh->handle_binary_nulls && input[1] && input[1] == '\\') { *swit++ = '\\'; *input++; (*len)--; break; } default: *swit++ = *input; } *input++; } return ret; } int _sqlite2_fetch_row (imp_sth_t *imp_sth) { while (1) { if (imp_sth->vm) imp_sth->retval = sqlite_step(imp_sth->vm, &(imp_sth->ncols), (const char ***)&(imp_sth->results), (const char ***)&(imp_sth->coldata)); if (imp_sth->retval == SQLITE_BUSY) { break; /* We should never get "busy" here because we set sqlite_timeout, so assume error */ } break; } /* warn("step got: %d\nCol1: %s\n", imp_sth->retval, imp_sth->coldata[0]); */ return imp_sth->retval; } int sqlite2_st_execute (SV *sth, imp_sth_t *imp_sth) { dTHR; D_imp_dbh_from_sth; SV *sql; I32 pos = 0; char *errmsg; int num_params = DBIc_NUM_PARAMS(imp_sth); I32 i; int retval; /* warn("execute\n"); */ if (DBIc_ACTIVE(imp_sth)) { sqlite2_st_finish(sth, imp_sth); } sql = sv_2mortal(newSVsv(AvARRAY(imp_sth->sql)[pos++])); for (i = 0; i < num_params; i++) { SV *value = av_shift(imp_sth->params); if (value && SvOK(value)) { /* warn("binding param: %s\n", SvPV_nolen(value); */ sv_catpvn(sql, "'", 1); sv_catpv(sql, sqlite2_quote(imp_dbh, value)); sv_catpvn(sql, "'", 1); /* warn("inserting string length: %d\n", SvCUR(sql)); */ } else { /* warn("binding NULL\n"); */ sv_catpvn(sql, "NULL", 4); } if (value) { SvREFCNT_dec(value); } sv_catsv(sql, AvARRAY(imp_sth->sql)[pos++]); } /* warn("Executing: %s;\n", SvPV_nolen(sql)); */ if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (!imp_dbh->in_tran) ) { if ((retval = sqlite_exec(imp_dbh->db, "BEGIN TRANSACTION", NULL, NULL, &errmsg) != SQLITE_OK)) { sqlite2_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg); sqlite_freemem(errmsg); return -2; } imp_dbh->in_tran = TRUE; } imp_sth->results = NULL; if ((retval = sqlite_compile(imp_dbh->db, SvPV_nolen(sql), 0, &(imp_sth->vm), &errmsg) != SQLITE_OK)) { sqlite2_error(sth, (imp_xxh_t*)imp_sth, retval, errmsg); sqlite_freemem(errmsg); return -2; } if (_sqlite2_fetch_row(imp_sth) == SQLITE_ERROR) { sqlite_finalize(imp_sth->vm, &errmsg); sqlite2_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg); sqlite_freemem(errmsg); return -2; } DBIc_NUM_FIELDS(imp_sth) = imp_sth->ncols; imp_sth->nrow = -1; /* warn("Execute returned %d cols\n", imp_sth->ncols); */ if (imp_sth->ncols == 0) { sqlite_finalize(imp_sth->vm, 0); imp_sth->nrow = sqlite_changes(imp_dbh->db); DBIc_IMPSET_on(imp_sth); return imp_sth->nrow; } DBIc_ACTIVE_on(imp_sth); /* warn("exec ok - %d rows, %d cols\n", imp_sth->nrow, imp_sth->ncols); */ DBIc_IMPSET_on(imp_sth); return 0; } int sqlite2_st_rows (SV *sth, imp_sth_t *imp_sth) { return imp_sth->nrow; } int sqlite2_bind_ph (SV *sth, imp_sth_t *imp_sth, SV *param, SV *value, IV sql_type, SV *attribs, int is_inout, IV maxlen) { if (is_inout) { croak("InOut bind params not implemented"); } /* warn("bind: %s => %s\n", SvPV_nolen(param), SvPV_nolen(value)); */ if (sql_type >= SQL_NUMERIC && sql_type <= SQL_DOUBLE) { return av_store(imp_sth->params, SvIV(param) - 1, newSVnv(SvNV(value))) ? 1 : 0; } else { return av_store(imp_sth->params, SvIV(param) - 1, SvREFCNT_inc(value)) ? 1 : 0; } } AV * sqlite2_st_fetch (SV *sth, imp_sth_t *imp_sth) { AV *av; D_imp_dbh_from_sth; int numFields = DBIc_NUM_FIELDS(imp_sth); int chopBlanks = DBIc_is(imp_sth, DBIcf_ChopBlanks); int i; /* warn("current_entry == %d\nnumFields == %d\nnrow == %d", current_entry, numFields, imp_sth->nrow); */ if (!DBIc_ACTIVE(imp_sth)) { /* [cpan #16451] */ return Nullav; } if ((imp_sth->retval == SQLITE_DONE) || (imp_sth->retval == SQLITE_ERROR)) { sqlite2_st_finish(sth, imp_sth); return Nullav; } if (imp_sth->nrow == -1) { imp_sth->nrow++; } imp_sth->nrow++; av = DBIS->get_fbav(imp_sth); for (i = 0; i < numFields; i++) { char *val = imp_sth->results[i]; /* warn("fetching: %d == %s\n", i, val); */ if (val != NULL) { size_t len = strlen(val); char *decoded; if (chopBlanks) { val = savepv(val); while(len > 0 && val[len-1] == ' ') { len--; } val[len] = '\0'; } decoded = sqlite2_decode(imp_dbh, val, &len); sv_setpvn(AvARRAY(av)[i], decoded, len); Safefree(decoded); if (chopBlanks) Safefree(val); /* if (!imp_dbh->no_utf8_flag) { sv_utf8_encode(AvARRAY(av)[i]); } */ } else { sv_setsv(AvARRAY(av)[i], &PL_sv_undef); } } _sqlite2_fetch_row(imp_sth); return av; } int sqlite2_st_finish (SV *sth, imp_sth_t *imp_sth) { /* warn("finish statement\n"); */ if (DBIc_ACTIVE(imp_sth)) { char *errmsg; DBIc_ACTIVE_off(imp_sth); if ((imp_sth->retval = sqlite_finalize(imp_sth->vm, &errmsg) == SQLITE_ERROR)) { warn("finalize failed! %s\n", errmsg); sqlite2_error(sth, (imp_xxh_t*)imp_sth, imp_sth->retval, errmsg); sqlite_freemem(errmsg); return FALSE; } } return TRUE; } void sqlite2_st_destroy (SV *sth, imp_sth_t *imp_sth) { /* warn("destroy statement\n"); */ if (DBIc_ACTIVE(imp_sth)) { sqlite2_st_finish(sth, imp_sth); } SvREFCNT_dec((SV*)imp_sth->sql); SvREFCNT_dec((SV*)imp_sth->params); DBIc_IMPSET_off(imp_sth); } int sqlite2_st_blob_read (SV *sth, imp_sth_t *imp_sth, int field, long offset, long len, SV *destrv, long destoffset) { return 0; } int sqlite2_db_STORE_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) { dTHR; char *key = SvPV_nolen(keysv); char *errmsg; int retval; if (strEQ(key, "AutoCommit")) { if (SvTRUE(valuesv)) { /* commit tran? */ if ( (!DBIc_is(imp_dbh, DBIcf_AutoCommit)) && (imp_dbh->in_tran) ) { if ((retval = sqlite_exec(imp_dbh->db, "COMMIT TRANSACTION", NULL, NULL, &errmsg) != SQLITE_OK)) { sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg); sqlite_freemem(errmsg); return TRUE; } imp_dbh->in_tran = FALSE; } } DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv)); return TRUE; } else if (strEQ(key, "sqlite_no_utf8_flag") || strEQ(key, "NoUTF8Flag")) { warn("NoUTF8Flag is deprecated due to perl unicode weirdness\n"); if (SvTRUE(valuesv)) { imp_dbh->no_utf8_flag = TRUE; } else { imp_dbh->no_utf8_flag = FALSE; } return TRUE; } else if (strEQ(key, "sqlite_handle_binary_nulls")) { if (SvTRUE(valuesv)) { imp_dbh->handle_binary_nulls = TRUE; } else { imp_dbh->handle_binary_nulls = FALSE; } return TRUE; } return FALSE; } SV * sqlite2_db_FETCH_attrib (SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) { dTHR; char *key = SvPV_nolen(keysv); if (strEQ(key, "sqlite_no_utf8_flag") || strEQ(key, "NoUTF8Flag")) { return newSViv(imp_dbh->no_utf8_flag ? 1 : 0); } if (strEQ(key, "sqlite_version")) { return newSVpv(sqlite_version, strlen(sqlite_version)); } if (strEQ(key, "sqlite_encoding")) { return newSVpv(sqlite_encoding, strlen(sqlite_encoding)); } return NULL; } int sqlite2_st_STORE_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv) { char *key = SvPV_nolen(keysv); return FALSE; } SV * sqlite2_st_FETCH_attrib (SV *sth, imp_sth_t *imp_sth, SV *keysv) { char *key = SvPV_nolen(keysv); SV *retsv = NULL; int i; if (!imp_sth->coldata) { return retsv; } i = DBIc_NUM_FIELDS(imp_sth); if (strEQ(key, "NAME")) { AV *av = newAV(); av_extend(av, i); retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); while (--i >= 0) { char *fieldname = imp_sth->coldata[i]; int len = strlen(fieldname); char *dot; /* RT#26775: DISTINCT(t.name) returns "(t.name)" */ if (fieldname[0] == '(' && fieldname[len-1] == ')') { fieldname[len-1] = '\0'; fieldname++; } dot = instr(fieldname, "."); /* warn("Name [%d]: %s\n", i, fieldname); */ if (dot) /* drop table name from field name */ fieldname = ++dot; av_store(av, i, newSVpv(fieldname, 0)); } } else if (strEQ(key, "PRECISION")) { AV *av = newAV(); retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); } else if (strEQ(key, "TYPE")) { int i_base = i; AV *av = newAV(); av_extend(av, i); retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); i = i * 2; while (--i >= i_base) { char *fieldname = imp_sth->coldata[i]; /* warn("Type [%d]: %s\n", i, fieldname); */ char *dot = instr(fieldname, "."); if (dot) /* drop table name from field name */ fieldname = ++dot; av_store(av, i - i_base, newSVpv(fieldname, 0)); } } else if (strEQ(key, "NULLABLE")) { AV *av = newAV(); retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); } else if (strEQ(key, "SCALE")) { AV *av = newAV(); retsv = sv_2mortal(newRV(sv_2mortal((SV*)av))); } else if (strEQ(key, "NUM_OF_FIELDS")) { retsv = sv_2mortal(newSViv(i)); } return retsv; } static void sqlite2_db_set_result(sqlite_func *context, SV *result, int is_error ) { STRLEN len; char *s; if ( is_error ) { s = SvPV(result, len); sqlite_set_result_error( context, s, len ); return; } if ( !SvOK(result) ) { sqlite_set_result_string( context, NULL, -1 ); } else if( SvIOK(result) ) { sqlite_set_result_int( context, SvIV(result)); } else if ( !is_error && SvIOK(result) ) { sqlite_set_result_double( context, SvNV(result)); } else { s = SvPV(result, len); sqlite_set_result_string( context, s, len ); } } static void sqlite2_db_func_dispatcher(sqlite_func *context, int argc, const char **argv) { dSP; int count; int i; SV *func; func = sqlite_user_data(context); ENTER; SAVETMPS; PUSHMARK(SP); for ( i=0; i < argc; i++ ) { SV *arg; if ( !argv[i] ) { arg = &PL_sv_undef; } else { arg = sv_2mortal( newSVpv(argv[i], 0)); } XPUSHs(arg); } PUTBACK; count = call_sv(func, G_SCALAR|G_EVAL); SPAGAIN; /* Check for an error */ if (SvTRUE(ERRSV) ) { sqlite2_db_set_result( context, ERRSV, 1); POPs; } else if ( count != 1 ) { SV *err = sv_2mortal(newSVpvf( "function should return 1 argument, got %d", count )); sqlite2_db_set_result( context, err, 1); /* Clear the stack */ for ( i=0; i < count; i++ ) { POPs; } } else { sqlite2_db_set_result( context, POPs, 0 ); } PUTBACK; FREETMPS; LEAVE; } void sqlite2_db_create_function( SV *dbh, const char *name, int argc, SV *func ) { D_imp_dbh(dbh); int rv; /* Copy the function reference */ SV *func_sv = newSVsv(func); av_push( imp_dbh->functions, func_sv ); rv = sqlite_create_function( imp_dbh->db, name, argc, sqlite2_db_func_dispatcher, func_sv ); if ( rv != SQLITE_OK ) { croak( "sqlite_create_function failed with error %s", sqlite_error_string(rv) ); } } typedef struct aggrInfo aggrInfo; struct aggrInfo { SV *aggr_inst; SV *err; int inited; }; static void sqlite2_db_aggr_new_dispatcher( sqlite_func *context, aggrInfo *aggr_info ) { dSP; SV *pkg = NULL; int count = 0; aggr_info->err = NULL; aggr_info->aggr_inst = NULL; pkg = sqlite_user_data(context); if ( !pkg ) return; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs( sv_2mortal( newSVsv(pkg) ) ); PUTBACK; count = call_method ("new", G_EVAL|G_SCALAR); SPAGAIN; aggr_info->inited = 1; if ( SvTRUE( ERRSV ) ) { aggr_info->err = newSVpvf ("error during aggregator's new(): %s", SvPV_nolen (ERRSV)); POPs; } else if ( count != 1 ) { int i; aggr_info->err = newSVpvf( "new() should return one value, got %d", count ); /* Clear the stack */ for ( i=0; i < count; i++ ) { POPs; } } else { SV *aggr = POPs; if ( SvROK(aggr) ) { aggr_info->aggr_inst = newSVsv(aggr); } else{ aggr_info->err = newSVpvf( "new() should return a blessed reference" ); } } PUTBACK; FREETMPS; LEAVE; return; } static void sqlite2_db_aggr_step_dispatcher (sqlite_func *context, int argc, const char **argv) { dSP; int i; aggrInfo *aggr; aggr = sqlite_aggregate_context (context, sizeof (aggrInfo)); if ( !aggr ) return; ENTER; SAVETMPS; /* initialize on first step */ if ( !aggr->inited ) { sqlite2_db_aggr_new_dispatcher( context, aggr ); } if ( aggr->err || !aggr->aggr_inst ) goto cleanup; PUSHMARK(SP); XPUSHs( sv_2mortal( newSVsv( aggr->aggr_inst ) )); for ( i=0; i < argc; i++ ) { SV *arg; if ( !argv[i] ) { arg = &PL_sv_undef; } else { arg = sv_2mortal( newSVpv(argv[i], 0)); } XPUSHs(arg); } PUTBACK; call_method ("step", G_SCALAR|G_EVAL|G_DISCARD); /* Check for an error */ if (SvTRUE(ERRSV) ) { aggr->err = newSVpvf( "error during aggregator's step(): %s", SvPV_nolen(ERRSV)); POPs; } cleanup: FREETMPS; LEAVE; } static void sqlite2_db_aggr_finalize_dispatcher( sqlite_func *context ) { dSP; aggrInfo *aggr, myAggr; int count = 0; aggr = sqlite_aggregate_context (context, sizeof (aggrInfo)); ENTER; SAVETMPS; if ( !aggr ) { /* SQLite seems to refuse to create a context structure from finalize() */ aggr = &myAggr; aggr->aggr_inst = NULL; aggr->err = NULL; sqlite2_db_aggr_new_dispatcher (context, aggr); } if ( ! aggr->err && aggr->aggr_inst ) { PUSHMARK(SP); XPUSHs( sv_2mortal( newSVsv( aggr->aggr_inst )) ); PUTBACK; count = call_method( "finalize", G_SCALAR|G_EVAL ); SPAGAIN; if ( SvTRUE(ERRSV) ) { aggr->err = newSVpvf ("error during aggregator's finalize(): %s", SvPV_nolen(ERRSV) ) ; POPs; } else if ( count != 1 ) { int i; aggr->err = newSVpvf( "finalize() should return 1 value, got %d", count ); /* Clear the stack */ for ( i=0; ierr ) { warn( "DBD::SQLite: error in aggregator cannot be reported to SQLite: %s", SvPV_nolen( aggr->err ) ); /* sqlite2_db_set_result( context, aggr->err, 1 ); */ SvREFCNT_dec( aggr->err ); aggr->err = NULL; } if ( aggr->aggr_inst ) { SvREFCNT_dec( aggr->aggr_inst ); aggr->aggr_inst = NULL; } FREETMPS; LEAVE; } void sqlite2_db_create_aggregate( SV *dbh, const char *name, int argc, SV *aggr_pkg ) { D_imp_dbh(dbh); int rv; /* Copy the aggregate reference */ SV *aggr_pkg_copy = newSVsv(aggr_pkg); av_push( imp_dbh->aggregates, aggr_pkg_copy ); rv = sqlite_create_aggregate( imp_dbh->db, name, argc, sqlite2_db_aggr_step_dispatcher, sqlite2_db_aggr_finalize_dispatcher, aggr_pkg_copy ); if ( rv != SQLITE_OK ) { croak( "sqlite_create_aggregate failed with error %s", sqlite_error_string(rv) ); } } /* end */ DBD-SQLite2-0.36/tokenize.c0000644000175000017500000005123612126353147014627 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include /* ** All the keywords of the SQL language are stored as in a hash ** table composed of instances of the following structure. */ typedef struct Keyword Keyword; struct Keyword { char *zName; /* The keyword name */ u8 tokenType; /* Token value for this keyword */ u8 len; /* Length of this keyword */ u8 iNext; /* Index in aKeywordTable[] of next with same hash */ }; /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", TK_ABORT, }, { "AFTER", TK_AFTER, }, { "ALL", TK_ALL, }, { "AND", TK_AND, }, { "AS", TK_AS, }, { "ASC", TK_ASC, }, { "ATTACH", TK_ATTACH, }, { "BEFORE", TK_BEFORE, }, { "BEGIN", TK_BEGIN, }, { "BETWEEN", TK_BETWEEN, }, { "BY", TK_BY, }, { "CASCADE", TK_CASCADE, }, { "CASE", TK_CASE, }, { "CHECK", TK_CHECK, }, { "CLUSTER", TK_CLUSTER, }, { "COLLATE", TK_COLLATE, }, { "COMMIT", TK_COMMIT, }, { "CONFLICT", TK_CONFLICT, }, { "CONSTRAINT", TK_CONSTRAINT, }, { "COPY", TK_COPY, }, { "CREATE", TK_CREATE, }, { "CROSS", TK_JOIN_KW, }, { "DATABASE", TK_DATABASE, }, { "DEFAULT", TK_DEFAULT, }, { "DEFERRED", TK_DEFERRED, }, { "DEFERRABLE", TK_DEFERRABLE, }, { "DELETE", TK_DELETE, }, { "DELIMITERS", TK_DELIMITERS, }, { "DESC", TK_DESC, }, { "DETACH", TK_DETACH, }, { "DISTINCT", TK_DISTINCT, }, { "DROP", TK_DROP, }, { "END", TK_END, }, { "EACH", TK_EACH, }, { "ELSE", TK_ELSE, }, { "EXCEPT", TK_EXCEPT, }, { "EXPLAIN", TK_EXPLAIN, }, { "FAIL", TK_FAIL, }, { "FOR", TK_FOR, }, { "FOREIGN", TK_FOREIGN, }, { "FROM", TK_FROM, }, { "FULL", TK_JOIN_KW, }, { "GLOB", TK_GLOB, }, { "GROUP", TK_GROUP, }, { "HAVING", TK_HAVING, }, { "IGNORE", TK_IGNORE, }, { "IMMEDIATE", TK_IMMEDIATE, }, { "IN", TK_IN, }, { "INDEX", TK_INDEX, }, { "INITIALLY", TK_INITIALLY, }, { "INNER", TK_JOIN_KW, }, { "INSERT", TK_INSERT, }, { "INSTEAD", TK_INSTEAD, }, { "INTERSECT", TK_INTERSECT, }, { "INTO", TK_INTO, }, { "IS", TK_IS, }, { "ISNULL", TK_ISNULL, }, { "JOIN", TK_JOIN, }, { "KEY", TK_KEY, }, { "LEFT", TK_JOIN_KW, }, { "LIKE", TK_LIKE, }, { "LIMIT", TK_LIMIT, }, { "MATCH", TK_MATCH, }, { "NATURAL", TK_JOIN_KW, }, { "NOT", TK_NOT, }, { "NOTNULL", TK_NOTNULL, }, { "NULL", TK_NULL, }, { "OF", TK_OF, }, { "OFFSET", TK_OFFSET, }, { "ON", TK_ON, }, { "OR", TK_OR, }, { "ORDER", TK_ORDER, }, { "OUTER", TK_JOIN_KW, }, { "PRAGMA", TK_PRAGMA, }, { "PRIMARY", TK_PRIMARY, }, { "RAISE", TK_RAISE, }, { "REFERENCES", TK_REFERENCES, }, { "REPLACE", TK_REPLACE, }, { "RESTRICT", TK_RESTRICT, }, { "RIGHT", TK_JOIN_KW, }, { "ROLLBACK", TK_ROLLBACK, }, { "ROW", TK_ROW, }, { "SELECT", TK_SELECT, }, { "SET", TK_SET, }, { "STATEMENT", TK_STATEMENT, }, { "TABLE", TK_TABLE, }, { "TEMP", TK_TEMP, }, { "TEMPORARY", TK_TEMP, }, { "THEN", TK_THEN, }, { "TRANSACTION", TK_TRANSACTION, }, { "TRIGGER", TK_TRIGGER, }, { "UNION", TK_UNION, }, { "UNIQUE", TK_UNIQUE, }, { "UPDATE", TK_UPDATE, }, { "USING", TK_USING, }, { "VACUUM", TK_VACUUM, }, { "VALUES", TK_VALUES, }, { "VIEW", TK_VIEW, }, { "WHEN", TK_WHEN, }, { "WHERE", TK_WHERE, }, }; /* ** This is the hash table */ #define KEY_HASH_SIZE 101 static u8 aiHashTable[KEY_HASH_SIZE]; /* ** This function looks up an identifier to determine if it is a ** keyword. If it is a keyword, the token code of that keyword is ** returned. If the input is not a keyword, TK_ID is returned. */ int sqliteKeywordCode(const char *z, int n){ int h, i; Keyword *p; static char needInit = 1; if( needInit ){ /* Initialize the keyword hash table */ sqliteOsEnterMutex(); if( needInit ){ int nk; nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]); for(i=0; iiNext){ p = &aKeywordTable[i-1]; if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){ return p->tokenType; } } return TK_ID; } /* ** If X is a character that can be used in an identifier and ** X&0x80==0 then isIdChar[X] will be 1. If X&0x80==0x80 then ** X is always an identifier character. (Hence all UTF-8 ** characters can be part of an identifier). isIdChar[X] will ** be 0 for every character in the lower 128 ASCII characters ** that cannot be used as part of an identifier. ** ** In this implementation, an identifier can be a string of ** alphabetic characters, digits, and "_" plus any character ** with the high-order bit set. The latter rule means that ** any sequence of UTF-8 characters or characters taken from ** an extended ISO8859 character set can form an identifier. */ static const char isIdChar[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ }; /* ** Return the length of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ static int sqliteGetToken(const unsigned char *z, int *tokenType){ int i; switch( *z ){ case ' ': case '\t': case '\n': case '\f': case '\r': { for(i=1; isspace(z[i]); i++){} *tokenType = TK_SPACE; return i; } case '-': { if( z[1]=='-' ){ for(i=2; z[i] && z[i]!='\n'; i++){} *tokenType = TK_COMMENT; return i; } *tokenType = TK_MINUS; return 1; } case '(': { *tokenType = TK_LP; return 1; } case ')': { *tokenType = TK_RP; return 1; } case ';': { *tokenType = TK_SEMI; return 1; } case '+': { *tokenType = TK_PLUS; return 1; } case '*': { *tokenType = TK_STAR; return 1; } case '/': { if( z[1]!='*' || z[2]==0 ){ *tokenType = TK_SLASH; return 1; } for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){} if( z[i] ) i++; *tokenType = TK_COMMENT; return i; } case '%': { *tokenType = TK_REM; return 1; } case '=': { *tokenType = TK_EQ; return 1 + (z[1]=='='); } case '<': { if( z[1]=='=' ){ *tokenType = TK_LE; return 2; }else if( z[1]=='>' ){ *tokenType = TK_NE; return 2; }else if( z[1]=='<' ){ *tokenType = TK_LSHIFT; return 2; }else{ *tokenType = TK_LT; return 1; } } case '>': { if( z[1]=='=' ){ *tokenType = TK_GE; return 2; }else if( z[1]=='>' ){ *tokenType = TK_RSHIFT; return 2; }else{ *tokenType = TK_GT; return 1; } } case '!': { if( z[1]!='=' ){ *tokenType = TK_ILLEGAL; return 2; }else{ *tokenType = TK_NE; return 2; } } case '|': { if( z[1]!='|' ){ *tokenType = TK_BITOR; return 1; }else{ *tokenType = TK_CONCAT; return 2; } } case ',': { *tokenType = TK_COMMA; return 1; } case '&': { *tokenType = TK_BITAND; return 1; } case '~': { *tokenType = TK_BITNOT; return 1; } case '\'': case '"': { int delim = z[0]; for(i=1; z[i]; i++){ if( z[i]==delim ){ if( z[i+1]==delim ){ i++; }else{ break; } } } if( z[i] ) i++; *tokenType = TK_STRING; return i; } case '.': { *tokenType = TK_DOT; return 1; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { *tokenType = TK_INTEGER; for(i=1; isdigit(z[i]); i++){} if( z[i]=='.' && isdigit(z[i+1]) ){ i += 2; while( isdigit(z[i]) ){ i++; } *tokenType = TK_FLOAT; } if( (z[i]=='e' || z[i]=='E') && ( isdigit(z[i+1]) || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2])) ) ){ i += 2; while( isdigit(z[i]) ){ i++; } *tokenType = TK_FLOAT; } return i; } case '[': { for(i=1; z[i] && z[i-1]!=']'; i++){} *tokenType = TK_ID; return i; } case '?': { *tokenType = TK_VARIABLE; return 1; } default: { if( (*z&0x80)==0 && !isIdChar[*z] ){ break; } for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){} *tokenType = sqliteKeywordCode((char*)z, i); return i; } } *tokenType = TK_ILLEGAL; return 1; } /* ** Run the parser on the given SQL string. The parser structure is ** passed in. An SQLITE_ status code is returned. If an error occurs ** and pzErrMsg!=NULL then an error message might be written into ** memory obtained from malloc() and *pzErrMsg made to point to that ** error message. Or maybe not. */ int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ int nErr = 0; int i; void *pEngine; int tokenType; int lastTokenParsed = -1; sqlite *db = pParse->db; extern void *sqliteParserAlloc(void*(*)(int)); extern void sqliteParserFree(void*, void(*)(void*)); extern int sqliteParser(void*, int, Token, Parse*); db->flags &= ~SQLITE_Interrupt; pParse->rc = SQLITE_OK; i = 0; pEngine = sqliteParserAlloc((void*(*)(int))malloc); if( pEngine==0 ){ sqliteSetString(pzErrMsg, "out of memory", (char*)0); return 1; } pParse->sLastToken.dyn = 0; pParse->zTail = zSql; while( sqlite_malloc_failed==0 && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; assert( pParse->sLastToken.dyn==0 ); pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType); i += pParse->sLastToken.n; switch( tokenType ){ case TK_SPACE: case TK_COMMENT: { if( (db->flags & SQLITE_Interrupt)!=0 ){ pParse->rc = SQLITE_INTERRUPT; sqliteSetString(pzErrMsg, "interrupt", (char*)0); goto abort_parse; } break; } case TK_ILLEGAL: { sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0); nErr++; goto abort_parse; } case TK_SEMI: { pParse->zTail = &zSql[i]; /* Fall thru into the default case */ } default: { sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse); lastTokenParsed = tokenType; if( pParse->rc!=SQLITE_OK ){ goto abort_parse; } break; } } } abort_parse: if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ if( lastTokenParsed!=TK_SEMI ){ sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } sqliteParser(pEngine, 0, pParse->sLastToken, pParse); } sqliteParserFree(pEngine, free); if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc), (char*)0); } if( pParse->zErrMsg ){ if( pzErrMsg && *pzErrMsg==0 ){ *pzErrMsg = pParse->zErrMsg; }else{ sqliteFree(pParse->zErrMsg); } pParse->zErrMsg = 0; if( !nErr ) nErr++; } if( pParse->pVdbe && pParse->nErr>0 ){ sqliteVdbeDelete(pParse->pVdbe); pParse->pVdbe = 0; } if( pParse->pNewTable ){ sqliteDeleteTable(pParse->db, pParse->pNewTable); pParse->pNewTable = 0; } if( pParse->pNewTrigger ){ sqliteDeleteTrigger(pParse->pNewTrigger); pParse->pNewTrigger = 0; } if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } return nErr; } /* ** Token types used by the sqlite_complete() routine. See the header ** comments on that procedure for additional information. */ #define tkEXPLAIN 0 #define tkCREATE 1 #define tkTEMP 2 #define tkTRIGGER 3 #define tkEND 4 #define tkSEMI 5 #define tkWS 6 #define tkOTHER 7 /* ** Return TRUE if the given SQL string ends in a semicolon. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** ** This implementation uses a state machine with 7 states: ** ** (0) START At the beginning or end of an SQL statement. This routine ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** ** (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (2) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (3) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (4) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (6) END We've seen the ";END" of the ";END;" that occurs at the end ** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** ** (0) tkEXPLAIN The "explain" keyword. ** (1) tkCREATE The "create" keyword. ** (2) tkTEMP The "temp" or "temporary" keyword. ** (3) tkTRIGGER The "trigger" keyword. ** (4) tkEND The "end" keyword. ** (5) tkSEMI A semicolon. ** (6) tkWS Whitespace ** (7) tkOTHER Any other SQL token. ** ** Whitespace never causes a state transition and is always ignored. */ int sqlite_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ /* The following matrix defines the transition from one state to another ** according to what token is seen. trans[state][token] returns the ** next state. */ static const u8 trans[7][8] = { /* Token: */ /* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */ /* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, }, /* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, }, /* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, }, /* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, }, /* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, }, /* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, }, /* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, }, }; while( *zSql ){ switch( *zSql ){ case ';': { /* A semicolon */ token = tkSEMI; break; } case ' ': case '\r': case '\t': case '\n': case '\f': { /* White space is ignored */ token = tkWS; break; } case '/': { /* C-style comments */ if( zSql[1]!='*' ){ token = tkOTHER; break; } zSql += 2; while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } if( zSql[0]==0 ) return 0; zSql++; token = tkWS; break; } case '-': { /* SQL-style comments from "--" to end of line */ if( zSql[1]!='-' ){ token = tkOTHER; break; } while( *zSql && *zSql!='\n' ){ zSql++; } if( *zSql==0 ) return state==0; token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zSql++; while( *zSql && *zSql!=']' ){ zSql++; } if( *zSql==0 ) return 0; token = tkOTHER; break; } case '"': /* single- and double-quoted strings */ case '\'': { int c = *zSql; zSql++; while( *zSql && *zSql!=c ){ zSql++; } if( *zSql==0 ) return 0; token = tkOTHER; break; } default: { if( isIdChar[(u8)*zSql] ){ /* Keywords and unquoted identifiers */ int nId; for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){} switch( *zSql ){ case 'c': case 'C': { if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){ token = tkCREATE; }else{ token = tkOTHER; } break; } case 't': case 'T': { if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){ token = tkTRIGGER; }else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){ token = tkTEMP; }else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){ token = tkTEMP; }else{ token = tkOTHER; } break; } case 'e': case 'E': { if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){ token = tkEND; }else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){ token = tkEXPLAIN; }else{ token = tkOTHER; } break; } default: { token = tkOTHER; break; } } zSql += nId-1; }else{ /* Operators and special symbols */ token = tkOTHER; } break; } } state = trans[state][token]; zSql++; } return state==0; } DBD-SQLite2-0.36/pragma.c0000644000175000017500000006107312126353147014246 0ustar rurbanrurban/* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** ** $Id: pragma.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include "sqliteInt.h" #include /* ** Interpret the given string as a boolean value. */ static int getBoolean(const char *z){ static char *azTrue[] = { "yes", "on", "true" }; int i; if( z[0]==0 ) return 0; if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){ return atoi(z); } for(i=0; i='0' && z[0]<='2' ){ return z[0] - '0'; }else if( sqliteStrICmp(z, "file")==0 ){ return 1; }else if( sqliteStrICmp(z, "memory")==0 ){ return 2; }else{ return 0; } } /* ** If the TEMP database is open, close it and mark the database schema ** as needing reloading. This must be done when using the TEMP_STORE ** or DEFAULT_TEMP_STORE pragmas. */ static int changeTempStorage(Parse *pParse, const char *zStorageType){ int ts = getTempStore(zStorageType); sqlite *db = pParse->db; if( db->temp_store==ts ) return SQLITE_OK; if( db->aDb[1].pBt!=0 ){ if( db->flags & SQLITE_InTrans ){ sqliteErrorMsg(pParse, "temporary storage cannot be changed " "from within a transaction"); return SQLITE_ERROR; } sqliteBtreeClose(db->aDb[1].pBt); db->aDb[1].pBt = 0; sqliteResetInternalSchema(db, 0); } db->temp_store = ts; return SQLITE_OK; } /* ** Check to see if zRight and zLeft refer to a pragma that queries ** or changes one of the flags in db->flags. Return 1 if so and 0 if not. ** Also, implement the pragma. */ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ static const struct { const char *zName; /* Name of the pragma */ int mask; /* Mask for the db->flags value */ } aPragma[] = { { "vdbe_trace", SQLITE_VdbeTrace }, { "full_column_names", SQLITE_FullColNames }, { "short_column_names", SQLITE_ShortColNames }, { "show_datatypes", SQLITE_ReportTypes }, { "count_changes", SQLITE_CountRows }, { "empty_result_callbacks", SQLITE_NullCallback }, }; int i; for(i=0; idb; Vdbe *v; if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){ sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC); sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC); sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0, OP_Callback, 1, 0, 0); }else if( getBoolean(zRight) ){ db->flags |= aPragma[i].mask; }else{ db->flags &= ~aPragma[i].mask; } return 1; } } return 0; } /* ** Process a pragma statement. ** ** Pragmas are of this form: ** ** PRAGMA id = value ** ** The identifier might also be a string. The value is a string, and ** identifier, or a number. If minusFlag is true, then the value is ** a number that was preceded by a minus sign. */ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ char *zLeft = 0; char *zRight = 0; sqlite *db = pParse->db; Vdbe *v = sqliteGetVdbe(pParse); if( v==0 ) return; zLeft = sqliteStrNDup(pLeft->z, pLeft->n); sqliteDequote(zLeft); if( minusFlag ){ zRight = 0; sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0); }else{ zRight = sqliteStrNDup(pRight->z, pRight->n); sqliteDequote(zRight); } if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){ sqliteFree(zLeft); sqliteFree(zRight); return; } /* ** PRAGMA default_cache_size ** PRAGMA default_cache_size=N ** ** The first form reports the current persistent setting for the ** page cache size. The value returned is the maximum number of ** pages in the page cache. The second form sets both the current ** page cache size value and the persistent page cache size value ** stored in the database file. ** ** The default cache size is stored in meta-value 2 of page 1 of the ** database file. The cache size is actually the absolute value of ** this memory location. The sign of meta-value 2 determines the ** synchronous setting. A negative value means synchronous is off ** and a positive value means synchronous is on. */ if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){ static VdbeOpList getCacheSize[] = { { OP_ReadCookie, 0, 2, 0}, { OP_AbsValue, 0, 0, 0}, { OP_Dup, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 6, 0}, { OP_Integer, 0, 0, 0}, /* 5 */ { OP_ColumnName, 0, 1, "cache_size"}, { OP_Callback, 1, 0, 0}, }; int addr; if( pRight->z==pLeft->z ){ addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqliteVdbeChangeP1(v, addr+5, MAX_PAGES); }else{ int size = atoi(zRight); if( size<0 ) size = -size; sqliteBeginWriteOperation(pParse, 0, 0); sqliteVdbeAddOp(v, OP_Integer, size, 0); sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeAddOp(v, OP_Ge, 0, addr+3); sqliteVdbeAddOp(v, OP_Negative, 0, 0); sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); sqliteEndWriteOperation(pParse); db->cache_size = db->cache_size<0 ? -size : size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); } }else /* ** PRAGMA cache_size ** PRAGMA cache_size=N ** ** The first form reports the current local setting for the ** page cache size. The local setting can be different from ** the persistent cache size value that is stored in the database ** file itself. The value returned is the maximum number of ** pages in the page cache. The second form sets the local ** page cache size value. It does not change the persistent ** cache size stored on the disk so the cache size will revert ** to its default value when the database is closed and reopened. ** N should be a positive integer. */ if( sqliteStrICmp(zLeft,"cache_size")==0 ){ static VdbeOpList getCacheSize[] = { { OP_ColumnName, 0, 1, "cache_size"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ int size = db->cache_size;; if( size<0 ) size = -size; sqliteVdbeAddOp(v, OP_Integer, size, 0); sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); }else{ int size = atoi(zRight); if( size<0 ) size = -size; if( db->cache_size<0 ) size = -size; db->cache_size = size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); } }else /* ** PRAGMA default_synchronous ** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL ** ** The first form returns the persistent value of the "synchronous" setting ** that is stored in the database. This is the synchronous setting that ** is used whenever the database is opened unless overridden by a separate ** "synchronous" pragma. The second form changes the persistent and the ** local synchronous setting to the value given. ** ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls ** to make sure data is committed to disk. Write operations are very fast, ** but a power failure can leave the database in an inconsistent state. ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to ** make sure data is being written to disk. The risk of corruption due to ** a power loss in this mode is negligible but non-zero. If synchronous ** is FULL, extra fsync()s occur to reduce the risk of corruption to near ** zero, but with a write performance penalty. The default mode is NORMAL. */ if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){ static VdbeOpList getSync[] = { { OP_ColumnName, 0, 1, "synchronous"}, { OP_ReadCookie, 0, 3, 0}, { OP_Dup, 0, 0, 0}, { OP_If, 0, 0, 0}, /* 3 */ { OP_ReadCookie, 0, 2, 0}, { OP_Integer, 0, 0, 0}, { OP_Lt, 0, 5, 0}, { OP_AddImm, 1, 0, 0}, { OP_Callback, 1, 0, 0}, { OP_Halt, 0, 0, 0}, { OP_AddImm, -1, 0, 0}, /* 10 */ { OP_Callback, 1, 0, 0} }; if( pRight->z==pLeft->z ){ int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync); sqliteVdbeChangeP2(v, addr+3, addr+10); }else{ int addr; int size = db->cache_size; if( size<0 ) size = -size; sqliteBeginWriteOperation(pParse, 0, 0); sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2); sqliteVdbeAddOp(v, OP_Dup, 0, 0); addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeAddOp(v, OP_Ne, 0, addr+3); sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0); sqliteVdbeAddOp(v, OP_AbsValue, 0, 0); db->safety_level = getSafetyLevel(zRight)+1; if( db->safety_level==1 ){ sqliteVdbeAddOp(v, OP_Negative, 0, 0); size = -size; } sqliteVdbeAddOp(v, OP_SetCookie, 0, 2); sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0); sqliteVdbeAddOp(v, OP_SetCookie, 0, 3); sqliteEndWriteOperation(pParse); db->cache_size = size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); } }else /* ** PRAGMA synchronous ** PRAGMA synchronous=OFF|ON|NORMAL|FULL ** ** Return or set the local value of the synchronous flag. Changing ** the local value does not make changes to the disk file and the ** default value will be restored the next time the database is ** opened. */ if( sqliteStrICmp(zLeft,"synchronous")==0 ){ static VdbeOpList getSync[] = { { OP_ColumnName, 0, 1, "synchronous"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0); sqliteVdbeAddOpList(v, ArraySize(getSync), getSync); }else{ int size = db->cache_size; if( size<0 ) size = -size; db->safety_level = getSafetyLevel(zRight)+1; if( db->safety_level==1 ) size = -size; db->cache_size = size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size); sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); } }else #ifndef NDEBUG if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){ if( getBoolean(zRight) ){ always_code_trigger_setup = 1; }else{ always_code_trigger_setup = 0; } }else #endif if( flagPragma(pParse, zLeft, zRight) ){ /* The flagPragma() call also generates any necessary code */ }else if( sqliteStrICmp(zLeft, "table_info")==0 ){ Table *pTab; pTab = sqliteFindTable(db, zRight, 0); if( pTab ){ static VdbeOpList tableInfoPreface[] = { { OP_ColumnName, 0, 0, "cid"}, { OP_ColumnName, 1, 0, "name"}, { OP_ColumnName, 2, 0, "type"}, { OP_ColumnName, 3, 0, "notnull"}, { OP_ColumnName, 4, 0, "dflt_value"}, { OP_ColumnName, 5, 1, "pk"}, }; int i; sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); sqliteViewGetColumnNames(pParse, pTab); for(i=0; inCol; i++){ sqliteVdbeAddOp(v, OP_Integer, i, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0); sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0); sqliteVdbeAddOp(v, OP_Callback, 6, 0); } } }else if( sqliteStrICmp(zLeft, "index_info")==0 ){ Index *pIdx; Table *pTab; pIdx = sqliteFindIndex(db, zRight, 0); if( pIdx ){ static VdbeOpList tableInfoPreface[] = { { OP_ColumnName, 0, 0, "seqno"}, { OP_ColumnName, 1, 0, "cid"}, { OP_ColumnName, 2, 1, "name"}, }; int i; pTab = pIdx->pTable; sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); for(i=0; inColumn; i++){ int cnum = pIdx->aiColumn[i]; sqliteVdbeAddOp(v, OP_Integer, i, 0); sqliteVdbeAddOp(v, OP_Integer, cnum, 0); assert( pTab->nCol>cnum ); sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0); sqliteVdbeAddOp(v, OP_Callback, 3, 0); } } }else if( sqliteStrICmp(zLeft, "index_list")==0 ){ Index *pIdx; Table *pTab; pTab = sqliteFindTable(db, zRight, 0); if( pTab ){ v = sqliteGetVdbe(pParse); pIdx = pTab->pIndex; } if( pTab && pIdx ){ int i = 0; static VdbeOpList indexListPreface[] = { { OP_ColumnName, 0, 0, "seq"}, { OP_ColumnName, 1, 0, "name"}, { OP_ColumnName, 2, 1, "unique"}, }; sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); while(pIdx){ sqliteVdbeAddOp(v, OP_Integer, i, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0); sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0); sqliteVdbeAddOp(v, OP_Callback, 3, 0); ++i; pIdx = pIdx->pNext; } } }else if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){ FKey *pFK; Table *pTab; pTab = sqliteFindTable(db, zRight, 0); if( pTab ){ v = sqliteGetVdbe(pParse); pFK = pTab->pFKey; } if( pTab && pFK ){ int i = 0; static VdbeOpList indexListPreface[] = { { OP_ColumnName, 0, 0, "id"}, { OP_ColumnName, 1, 0, "seq"}, { OP_ColumnName, 2, 0, "table"}, { OP_ColumnName, 3, 0, "from"}, { OP_ColumnName, 4, 1, "to"}, }; sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); while(pFK){ int j; for(j=0; jnCol; j++){ sqliteVdbeAddOp(v, OP_Integer, i, 0); sqliteVdbeAddOp(v, OP_Integer, j, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[pFK->aCol[j].iFrom].zName, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0); sqliteVdbeAddOp(v, OP_Callback, 5, 0); } ++i; pFK = pFK->pNextFrom; } } }else if( sqliteStrICmp(zLeft, "database_list")==0 ){ int i; static VdbeOpList indexListPreface[] = { { OP_ColumnName, 0, 0, "seq"}, { OP_ColumnName, 1, 0, "name"}, { OP_ColumnName, 2, 1, "file"}, }; sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; assert( db->aDb[i].zName!=0 ); sqliteVdbeAddOp(v, OP_Integer, i, 0); sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0); sqliteVdbeOp3(v, OP_String, 0, 0, sqliteBtreeGetFilename(db->aDb[i].pBt), 0); sqliteVdbeAddOp(v, OP_Callback, 3, 0); } }else /* ** PRAGMA temp_store ** PRAGMA temp_store = "default"|"memory"|"file" ** ** Return or set the local value of the temp_store flag. Changing ** the local value does not make changes to the disk file and the default ** value will be restored the next time the database is opened. ** ** Note that it is possible for the library compile-time options to ** override this setting */ if( sqliteStrICmp(zLeft, "temp_store")==0 ){ static VdbeOpList getTmpDbLoc[] = { { OP_ColumnName, 0, 1, "temp_store"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0); sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); }else{ changeTempStorage(pParse, zRight); } }else /* ** PRAGMA default_temp_store ** PRAGMA default_temp_store = "default"|"memory"|"file" ** ** Return or set the value of the persistent temp_store flag. Any ** change does not take effect until the next time the database is ** opened. ** ** Note that it is possible for the library compile-time options to ** override this setting */ if( sqliteStrICmp(zLeft, "default_temp_store")==0 ){ static VdbeOpList getTmpDbLoc[] = { { OP_ColumnName, 0, 1, "temp_store"}, { OP_ReadCookie, 0, 5, 0}, { OP_Callback, 1, 0, 0}}; if( pRight->z==pLeft->z ){ sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); }else{ sqliteBeginWriteOperation(pParse, 0, 0); sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0); sqliteVdbeAddOp(v, OP_SetCookie, 0, 5); sqliteEndWriteOperation(pParse); } }else #ifndef NDEBUG if( sqliteStrICmp(zLeft, "parser_trace")==0 ){ extern void sqliteParserTrace(FILE*, char *); if( getBoolean(zRight) ){ sqliteParserTrace(stdout, "parser: "); }else{ sqliteParserTrace(0, 0); } }else #endif if( sqliteStrICmp(zLeft, "integrity_check")==0 ){ int i, j, addr; /* Code that initializes the integrity check program. Set the ** error count 0 */ static VdbeOpList initCode[] = { { OP_Integer, 0, 0, 0}, { OP_MemStore, 0, 1, 0}, { OP_ColumnName, 0, 1, "integrity_check"}, }; /* Code to do an BTree integrity check on a single database file. */ static VdbeOpList checkDb[] = { { OP_SetInsert, 0, 0, "2"}, { OP_Integer, 0, 0, 0}, /* 1 */ { OP_OpenRead, 0, 2, 0}, { OP_Rewind, 0, 7, 0}, /* 3 */ { OP_Column, 0, 3, 0}, /* 4 */ { OP_SetInsert, 0, 0, 0}, { OP_Next, 0, 4, 0}, /* 6 */ { OP_IntegrityCk, 0, 0, 0}, /* 7 */ { OP_Dup, 0, 1, 0}, { OP_String, 0, 0, "ok"}, { OP_StrEq, 0, 12, 0}, /* 10 */ { OP_MemIncr, 0, 0, 0}, { OP_String, 0, 0, "*** in database "}, { OP_String, 0, 0, 0}, /* 13 */ { OP_String, 0, 0, " ***\n"}, { OP_Pull, 3, 0, 0}, { OP_Concat, 4, 1, 0}, { OP_Callback, 1, 0, 0}, }; /* Code that appears at the end of the integrity check. If no error ** messages have been generated, output OK. Otherwise output the ** error message */ static VdbeOpList endCode[] = { { OP_MemLoad, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 0, 0}, /* 2 */ { OP_String, 0, 0, "ok"}, { OP_Callback, 1, 0, 0}, }; /* Initialize the VDBE program */ sqliteVdbeAddOpList(v, ArraySize(initCode), initCode); /* Do an integrity check on each database file */ for(i=0; inDb; i++){ HashElem *x; /* Do an integrity check of the B-Tree */ addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb); sqliteVdbeChangeP1(v, addr+1, i); sqliteVdbeChangeP2(v, addr+3, addr+7); sqliteVdbeChangeP2(v, addr+6, addr+4); sqliteVdbeChangeP2(v, addr+7, i); sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb)); sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC); /* Make sure all the indices are constructed correctly. */ sqliteCodeVerifySchema(pParse, i); for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; int loopTop; if( pTab->pIndex==0 ) continue; sqliteVdbeAddOp(v, OP_Integer, i, 0); sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ if( pIdx->tnum==0 ) continue; sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0); sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0); } sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeAddOp(v, OP_MemStore, 1, 1); loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0); sqliteVdbeAddOp(v, OP_MemIncr, 1, 0); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int k, jmp2; static VdbeOpList idxErr[] = { { OP_MemIncr, 0, 0, 0}, { OP_String, 0, 0, "rowid "}, { OP_Recno, 1, 0, 0}, { OP_String, 0, 0, " missing from index "}, { OP_String, 0, 0, 0}, /* 4 */ { OP_Concat, 4, 0, 0}, { OP_Callback, 1, 0, 0}, }; sqliteVdbeAddOp(v, OP_Recno, 1, 0); for(k=0; knColumn; k++){ int idx = pIdx->aiColumn[k]; if( idx==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Recno, 1, 0); }else{ sqliteVdbeAddOp(v, OP_Column, 1, idx); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx); jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0); addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr); sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC); sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v)); } sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1); sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v)); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ static VdbeOpList cntIdx[] = { { OP_Integer, 0, 0, 0}, { OP_MemStore, 2, 1, 0}, { OP_Rewind, 0, 0, 0}, /* 2 */ { OP_MemIncr, 2, 0, 0}, { OP_Next, 0, 0, 0}, /* 4 */ { OP_MemLoad, 1, 0, 0}, { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 7 */ { OP_MemIncr, 0, 0, 0}, { OP_String, 0, 0, "wrong # of entries in index "}, { OP_String, 0, 0, 0}, /* 10 */ { OP_Concat, 2, 0, 0}, { OP_Callback, 1, 0, 0}, }; if( pIdx->tnum==0 ) continue; addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx); sqliteVdbeChangeP1(v, addr+2, j+2); sqliteVdbeChangeP2(v, addr+2, addr+5); sqliteVdbeChangeP1(v, addr+4, j+2); sqliteVdbeChangeP2(v, addr+4, addr+3); sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx)); sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC); } } } addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode); sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode)); }else {} sqliteFree(zLeft); sqliteFree(zRight); } DBD-SQLite2-0.36/lib/0000755000175000017500000000000012130556467013377 5ustar rurbanrurbanDBD-SQLite2-0.36/lib/DBD/0000755000175000017500000000000012130556467013770 5ustar rurbanrurbanDBD-SQLite2-0.36/lib/DBD/SQLite2.pm0000644000175000017500000003426712130555371015556 0ustar rurbanrurban# $Id: SQLite2.pm,v 1.2 2004/09/10 15:43:39 matt Exp $ package DBD::SQLite2; use strict; use DBI; use vars qw($err $errstr $state $drh $VERSION @ISA); $VERSION = '0.36'; use DynaLoader(); @ISA = ('DynaLoader'); __PACKAGE__->bootstrap($VERSION); $drh = undef; sub driver { return $drh if $drh; my ($class, $attr) = @_; $class .= "::dr"; $drh = DBI::_new_drh($class, { Name => 'SQLite2', Version => $VERSION, Attribution => 'DBD::SQLite2 by Matt Sergeant', }); return $drh; } sub CLONE { undef $drh; } package DBD::SQLite2::dr; sub connect { my ($drh, $dbname, $user, $auth, $attr) = @_; my $dbh = DBI::_new_dbh($drh, { Name => $dbname, }); my $real_dbname = $dbname; if ($dbname =~ /=/) { foreach my $attrib (split(/;/, $dbname)) { my ($k, $v) = split(/=/, $attrib, 2); if ($k eq 'dbname') { $real_dbname = $v; } else { # TODO: add to attribs } } } DBD::SQLite2::db::_login($dbh, $real_dbname, $user, $auth) or return undef; return $dbh; } package DBD::SQLite2::db; sub prepare { my ($dbh, $statement, @attribs) = @_; my $sth = DBI::_new_sth($dbh, { Statement => $statement, }); DBD::SQLite2::st::_prepare($sth, $statement, @attribs) or return undef; return $sth; } sub table_info { my ($dbh, $CatVal, $SchVal, $TblVal, $TypVal) = @_; # SQL/CLI (ISO/IEC JTC 1/SC 32 N 0595), 6.63 Tables # Based on DBD::Oracle's # See also http://www.ch-werner.de/sqliteodbc/html/sqliteodbc_8c.html#a117 my @Where = (); my $Sql; if ( defined($CatVal) && $CatVal eq '%' && defined($SchVal) && $SchVal eq '' && defined($TblVal) && $TblVal eq '') { # Rule 19a $Sql = <<'SQL'; SELECT NULL TABLE_CAT , NULL TABLE_SCHEM , NULL TABLE_NAME , NULL TABLE_TYPE , NULL REMARKS SQL } elsif ( defined($SchVal) && $SchVal eq '%' && defined($CatVal) && $CatVal eq '' && defined($TblVal) && $TblVal eq '') { # Rule 19b $Sql = <<'SQL'; SELECT NULL TABLE_CAT , NULL TABLE_SCHEM , NULL TABLE_NAME , NULL TABLE_TYPE , NULL REMARKS SQL } elsif ( defined($TypVal) && $TypVal eq '%' && defined($CatVal) && $CatVal eq '' && defined($SchVal) && $SchVal eq '' && defined($TblVal) && $TblVal eq '') { # Rule 19c $Sql = <<'SQL'; SELECT NULL TABLE_CAT , NULL TABLE_SCHEM , NULL TABLE_NAME , t.tt TABLE_TYPE , NULL REMARKS FROM ( SELECT 'TABLE' tt UNION SELECT 'VIEW' tt UNION SELECT 'LOCAL TEMPORARY' tt ) t ORDER BY TABLE_TYPE SQL } else { $Sql = <<'SQL'; SELECT * FROM ( SELECT NULL TABLE_CAT , NULL TABLE_SCHEM , tbl_name TABLE_NAME , TABLE_TYPE , NULL REMARKS , sql sqlite_sql FROM ( SELECT tbl_name, upper(type) TABLE_TYPE, sql FROM sqlite_master WHERE type IN ( 'table','view') UNION ALL SELECT tbl_name, 'LOCAL TEMPORARY' TABLE_TYPE, sql FROM sqlite_temp_master WHERE type IN ( 'table','view') UNION ALL SELECT 'sqlite_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql UNION ALL SELECT 'sqlite_temp_master' tbl_name, 'SYSTEM TABLE' TABLE_TYPE, NULL sql ) ) SQL if ( defined $TblVal ) { push @Where, "TABLE_NAME LIKE '$TblVal'"; } if ( defined $TypVal ) { my $table_type_list; $TypVal =~ s/^\s+//; $TypVal =~ s/\s+$//; my @ttype_list = split (/\s*,\s*/, $TypVal); foreach my $table_type (@ttype_list) { if ($table_type !~ /^'.*'$/) { $table_type = "'" . $table_type . "'"; } $table_type_list = join(", ", @ttype_list); } push @Where, "TABLE_TYPE IN (\U$table_type_list)" if $table_type_list; } $Sql .= ' WHERE ' . join("\n AND ", @Where ) . "\n" if @Where; $Sql .= " ORDER BY TABLE_TYPE, TABLE_SCHEM, TABLE_NAME\n"; } my $sth = $dbh->prepare($Sql) or return undef; $sth->execute or return undef; $sth; } sub primary_key_info { my($dbh, $catalog, $schema, $table) = @_; my @pk_info; my $sth_tables = $dbh->table_info($catalog, $schema, $table, ''); # this is a hack but much simpler than using pragma index_list etc # also the pragma doesn't list 'INTEGER PRIMARK KEY' autoinc PKs! while ( my $row = $sth_tables->fetchrow_hashref ) { my $sql = $row->{sqlite_sql} or next; next unless $sql =~ /(.*?)\s*PRIMARY\s+KEY\s*(?:\(\s*(.*?)\s*\))?/si; my @pk = split /\s*,\s*/, $2 || ''; unless (@pk) { my $prefix = $1; $prefix =~ s/.*create\s+table\s+.*?\(//i; $prefix = (split /\s*,\s*/, $prefix)[-1]; @pk = (split /\s+/, $prefix)[0]; # take first word as name } #warn "GOT PK $row->{TABLE_NAME} (@pk)\n"; my $key_seq = 0; for my $pk_field (@pk) { push @pk_info, { TABLE_SCHEM => $row->{TABLE_SCHEM}, TABLE_NAME => $row->{TABLE_NAME}, COLUMN_NAME => $pk_field, KEY_SEQ => ++$key_seq, PK_NAME => 'PRIMARY KEY', }; } } my $sponge = DBI->connect("DBI:Sponge:", '','') or return $dbh->DBI::set_err($DBI::err, "DBI::Sponge: $DBI::errstr"); my @names = qw(TABLE_CAT TABLE_SCHEM TABLE_NAME COLUMN_NAME KEY_SEQ PK_NAME); my $sth = $sponge->prepare("column_info $table", { rows => [ map { [ @{$_}{@names} ] } @pk_info ], NUM_OF_FIELDS => scalar @names, NAME => \@names, }) or return $dbh->DBI::set_err($sponge->err(), $sponge->errstr()); return $sth; } sub type_info_all { my ($dbh) = @_; return; # XXX code just copied from DBD::Oracle, not yet thought about my $names = { TYPE_NAME => 0, DATA_TYPE => 1, COLUMN_SIZE => 2, LITERAL_PREFIX => 3, LITERAL_SUFFIX => 4, CREATE_PARAMS => 5, NULLABLE => 6, CASE_SENSITIVE => 7, SEARCHABLE => 8, UNSIGNED_ATTRIBUTE => 9, FIXED_PREC_SCALE =>10, AUTO_UNIQUE_VALUE =>11, LOCAL_TYPE_NAME =>12, MINIMUM_SCALE =>13, MAXIMUM_SCALE =>14, SQL_DATA_TYPE =>15, SQL_DATETIME_SUB=>16, NUM_PREC_RADIX =>17, }; my $ti = [ $names, [ 'CHAR', 1, 255, '\'', '\'', 'max length', 1, 1, 3, undef, '0', '0', undef, undef, undef, 1, undef, undef ], [ 'NUMBER', 3, 38, undef, undef, 'precision,scale', 1, '0', 3, '0', '0', '0', undef, '0', 38, 3, undef, 10 ], [ 'DOUBLE', 8, 15, undef, undef, undef, 1, '0', 3, '0', '0', '0', undef, undef, undef, 8, undef, 10 ], [ 'DATE', 9, 19, '\'', '\'', undef, 1, '0', 3, undef, '0', '0', undef, '0', '0', 11, undef, undef ], [ 'VARCHAR', 12, 1024*1024, '\'', '\'', 'max length', 1, 1, 3, undef, '0', '0', undef, undef, undef, 12, undef, undef ] ]; return $ti; } 1; __END__ =head1 NAME DBD::SQLite2 - Self Contained RDBMS in a DBI Driver (sqlite 2.x) =head1 SYNOPSIS use DBI; my $dbh = DBI->connect("dbi:SQLite2:dbname=dbfile","",""); =head1 DESCRIPTION SQLite is a public domain RDBMS database engine that you can find at http://www.sqlite.org/. Rather than ask you to install SQLite first, because SQLite is public domain, DBD::SQLite2 includes the entire thing in the distribution. So in order to get a fast transaction capable RDBMS working for your perl project you simply have to install this module, and B else. For real work please use the updated L driver with the up-to-date sqlite3 backend. SQLite2 supports the following features: =over 4 =item Implements a large subset of SQL92 See http://www.sqlite.org/lang.html for details. =item A complete DB in a single disk file Everything for your database is stored in a single disk file, making it easier to move things around than with L. =item Atomic commit and rollback Yes, DBD::SQLite2 is small and light, but it supports full transactions =item Extensible User-defined aggregate or regular functions can be registered with the SQL parser. =back There's lots more to it, so please refer to the docs on the SQLite web page, listed above, for SQL details. Also refer to L for details on how to use DBI itself. =head1 CONFORMANCE WITH DBI SPECIFICATION The API works like every DBI module does. Please see L for more details about core features. Currently many statement attributes are not implemented or are limited by the typeless nature of the SQLite2 database. =head1 DRIVER PRIVATE ATTRIBUTES =head2 Database Handle Attributes =over 4 =item sqlite_version Returns the version of the SQLite library which DBD::SQLite2 is using, i.e, "2.8.15". =item sqlite_encoding Returns either "UTF-8" or "iso8859" to indicate how the SQLite library was compiled. =item sqlite_handle_binary_nulls Set this attribute to 1 to transparently handle binary nulls in quoted and returned data. B This will cause all backslash characters (C<\>) to be doubled up in all columns regardless of whether or not they contain binary data or not. This may break your database if you use it from another application. This does not use the built in C and C functions, which may be considered a bug. =back =head1 DRIVER PRIVATE METHODS =head2 $dbh->func('last_insert_rowid') This method returns the last inserted rowid. If you specify an INTEGER PRIMARY KEY as the first column in your table, that is the column that is returned. Otherwise, it is the hidden ROWID column. See the sqlite docs for details. =head2 $dbh->func( $name, $argc, $func_ref, "create_function" ) This method will register a new function which will be useable in SQL query. The method's parameters are: =over =item $name The name of the function. This is the name of the function as it will be used from SQL. =item $argc The number of arguments taken by the function. If this number is -1, the function can take any number of arguments. =item $func_ref This should be a reference to the function's implementation. =back For example, here is how to define a now() function which returns the current number of seconds since the epoch: $dbh->func( 'now', 0, sub { return time }, 'create_function' ); After this, it could be use from SQL as: INSERT INTO mytable ( now() ); =head2 $dbh->func( $name, $argc, $pkg, 'create_aggregate' ) This method will register a new aggregate function which can then used from SQL. The method's parameters are: =over =item $name The name of the aggregate function, this is the name under which the function will be available from SQL. =item $argc This is an integer which tells the SQL parser how many arguments the function takes. If that number is -1, the function can take any number of arguments. =item $pkg This is the package which implements the aggregator interface. =back The aggregator interface consists of defining three methods: =over =item new() This method will be called once to create an object which should be used to aggregate the rows in a particular group. The step() and finalize() methods will be called upon the reference return by the method. =item step(@_) This method will be called once for each rows in the aggregate. =item finalize() This method will be called once all rows in the aggregate were processed and it should return the aggregate function's result. When there is no rows in the aggregate, finalize() will be called right after new(). =back Here is a simple aggregate function which returns the variance (example adapted from pysqlite): package variance; sub new { bless [], shift; } sub step { my ( $self, $value ) = @_; push @$self, $value; } sub finalize { my $self = $_[0]; my $n = @$self; # Variance is NULL unless there is more than one row return undef unless $n || $n == 1; my $mu = 0; foreach my $v ( @$self ) { $mu += $v; } $mu /= $n; my $sigma = 0; foreach my $v ( @$self ) { $sigma += ($x - $mu)**2; } $sigma = $sigma / ($n - 1); return $sigma; } $dbh->func( "variance", 1, 'variance', "create_aggregate" ); The aggregate function can then be used as: SELECT group_name, variance(score) FROM results GROUP BY group_name; =head1 NOTES To access the database from the command line, try using dbish which comes with the DBI module. Just type: dbish dbi:SQLite:foo.db On the command line to access the file F. Alternatively you can install SQLite from the link above without conflicting with DBD::SQLite2 and use the supplied C command line tool. =head1 PERFORMANCE SQLite is fast, very fast. I recently processed my 72MB log file with it, inserting the data (400,000+ rows) by using transactions and only committing every 1000 rows (otherwise the insertion is quite slow), and then performing queries on the data. Queries like count(*) and avg(bytes) took fractions of a second to return, but what surprised me most of all was: SELECT url, count(*) as count FROM access_log GROUP BY url ORDER BY count desc LIMIT 20 To discover the top 20 hit URLs on the site (http://axkit.org), and it returned within 2 seconds. I'm seriously considering switching my log analysis code to use this little speed demon! Oh yeah, and that was with no indexes on the table, on a 400MHz PIII. For best performance be sure to tune your hdparm settings if you are using linux. Also you might want to set: PRAGMA default_synchronous = OFF Which will prevent sqlite from doing fsync's when writing (which slows down non-transactional writes significantly) at the expense of some peace of mind. Also try playing with the cache_size pragma. =head1 BUGS Likely to be many, please use http://rt.cpan.org/ for reporting bugs. =head1 AUTHOR Matt Sergeant, matt@sergeant.org Perl extension functions contributed by Francis J. Lacoste and Wolfgang Sourdeau . Maintainance help by Reini Urban =head1 SEE ALSO L, L. =cut DBD-SQLite2-0.36/parse.h0000644000175000017500000001337112126353147014114 0ustar rurbanrurban#define TK_END_OF_FILE 1 #define TK_ILLEGAL 2 #define TK_SPACE 3 #define TK_UNCLOSED_STRING 4 #define TK_COMMENT 5 #define TK_FUNCTION 6 #define TK_COLUMN 7 #define TK_AGG_FUNCTION 8 #define TK_SEMI 9 #define TK_EXPLAIN 10 #define TK_BEGIN 11 #define TK_TRANSACTION 12 #define TK_COMMIT 13 #define TK_END 14 #define TK_ROLLBACK 15 #define TK_CREATE 16 #define TK_TABLE 17 #define TK_TEMP 18 #define TK_LP 19 #define TK_RP 20 #define TK_AS 21 #define TK_COMMA 22 #define TK_ID 23 #define TK_ABORT 24 #define TK_AFTER 25 #define TK_ASC 26 #define TK_ATTACH 27 #define TK_BEFORE 28 #define TK_CASCADE 29 #define TK_CLUSTER 30 #define TK_CONFLICT 31 #define TK_COPY 32 #define TK_DATABASE 33 #define TK_DEFERRED 34 #define TK_DELIMITERS 35 #define TK_DESC 36 #define TK_DETACH 37 #define TK_EACH 38 #define TK_FAIL 39 #define TK_FOR 40 #define TK_GLOB 41 #define TK_IGNORE 42 #define TK_IMMEDIATE 43 #define TK_INITIALLY 44 #define TK_INSTEAD 45 #define TK_LIKE 46 #define TK_MATCH 47 #define TK_KEY 48 #define TK_OF 49 #define TK_OFFSET 50 #define TK_PRAGMA 51 #define TK_RAISE 52 #define TK_REPLACE 53 #define TK_RESTRICT 54 #define TK_ROW 55 #define TK_STATEMENT 56 #define TK_TRIGGER 57 #define TK_VACUUM 58 #define TK_VIEW 59 #define TK_OR 60 #define TK_AND 61 #define TK_NOT 62 #define TK_EQ 63 #define TK_NE 64 #define TK_ISNULL 65 #define TK_NOTNULL 66 #define TK_IS 67 #define TK_BETWEEN 68 #define TK_IN 69 #define TK_GT 70 #define TK_GE 71 #define TK_LT 72 #define TK_LE 73 #define TK_BITAND 74 #define TK_BITOR 75 #define TK_LSHIFT 76 #define TK_RSHIFT 77 #define TK_PLUS 78 #define TK_MINUS 79 #define TK_STAR 80 #define TK_SLASH 81 #define TK_REM 82 #define TK_CONCAT 83 #define TK_UMINUS 84 #define TK_UPLUS 85 #define TK_BITNOT 86 #define TK_STRING 87 #define TK_JOIN_KW 88 #define TK_INTEGER 89 #define TK_CONSTRAINT 90 #define TK_DEFAULT 91 #define TK_FLOAT 92 #define TK_NULL 93 #define TK_PRIMARY 94 #define TK_UNIQUE 95 #define TK_CHECK 96 #define TK_REFERENCES 97 #define TK_COLLATE 98 #define TK_ON 99 #define TK_DELETE 100 #define TK_UPDATE 101 #define TK_INSERT 102 #define TK_SET 103 #define TK_DEFERRABLE 104 #define TK_FOREIGN 105 #define TK_DROP 106 #define TK_UNION 107 #define TK_ALL 108 #define TK_INTERSECT 109 #define TK_EXCEPT 110 #define TK_SELECT 111 #define TK_DISTINCT 112 #define TK_DOT 113 #define TK_FROM 114 #define TK_JOIN 115 #define TK_USING 116 #define TK_ORDER 117 #define TK_BY 118 #define TK_GROUP 119 #define TK_HAVING 120 #define TK_LIMIT 121 #define TK_WHERE 122 #define TK_INTO 123 #define TK_VALUES 124 #define TK_VARIABLE 125 #define TK_CASE 126 #define TK_WHEN 127 #define TK_THEN 128 #define TK_ELSE 129 #define TK_INDEX 130 DBD-SQLite2-0.36/SQLite2.xs0000644000175000017500000000214012126353147014420 0ustar rurbanrurban/* $Id: SQLite2.xs,v 1.2 2004/08/09 13:23:55 matt Exp $ */ #include "SQLiteXS.h" DBISTATE_DECLARE; MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2::db PROTOTYPES: DISABLE AV * list_tables(dbh) SV *dbh CODE: { RETVAL = newAV(); } OUTPUT: RETVAL int last_insert_rowid(dbh) SV *dbh CODE: { D_imp_dbh(dbh); RETVAL = sqlite_last_insert_rowid(imp_dbh->db); } OUTPUT: RETVAL void create_function(dbh, name, argc, func) SV *dbh char *name int argc SV *func CODE: { sqlite2_db_create_function( dbh, name, argc, func ); } void create_aggregate(dbh, name, argc, aggr) SV *dbh char *name int argc SV *aggr CODE: { sqlite2_db_create_aggregate( dbh, name, argc, aggr ); } int busy_timeout(dbh, timeout=0) SV *dbh int timeout CODE: RETVAL = sqlite2_busy_timeout( dbh, timeout ); OUTPUT: RETVAL MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2::st PROTOTYPES: DISABLE MODULE = DBD::SQLite2 PACKAGE = DBD::SQLite2 INCLUDE: SQLite2.xsi DBD-SQLite2-0.36/os.c0000644000175000017500000014463712130551267013426 0ustar rurbanrurban/* ** 2001 September 16 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code that is specific to particular operating ** systems. The purpose of this file is to provide a uniform abstraction ** on which the rest of SQLite can operate. */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #if OS_UNIX # include # include # include # ifndef O_LARGEFILE # define O_LARGEFILE 0 # endif # ifdef SQLITE_DISABLE_LFS # undef O_LARGEFILE # define O_LARGEFILE 0 # endif # ifndef O_NOFOLLOW # define O_NOFOLLOW 0 # endif # ifndef O_BINARY # define O_BINARY 0 # endif #endif #if OS_WIN # include #endif #if OS_MAC # include # include # include # include # include # include # include #endif /* ** The DJGPP compiler environment looks mostly like Unix, but it ** lacks the fcntl() system call. So redefine fcntl() to be something ** that always succeeds. This means that locking does not occur under ** DJGPP. But its DOS - what did you expect? */ #ifdef __DJGPP__ # define fcntl(A,B,C) 0 #endif /* ** Macros used to determine whether or not to use threads. The ** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for ** Posix threads and SQLITE_W32_THREADS is defined if we are ** synchronizing using Win32 threads. */ #if OS_UNIX && defined(THREADSAFE) && THREADSAFE # include # define SQLITE_UNIX_THREADS 1 #endif #if OS_WIN && defined(THREADSAFE) && THREADSAFE # define SQLITE_W32_THREADS 1 #endif #if OS_MAC && defined(THREADSAFE) && THREADSAFE # include # define SQLITE_MACOS_MULTITASKING 1 #endif /* ** Macros for performance tracing. Normally turned off */ #if 0 static int last_page = 0; __inline__ unsigned long long int hwtime(void){ unsigned long long int x; __asm__("rdtsc\n\t" "mov %%edx, %%ecx\n\t" :"=A" (x)); return x; } static unsigned long long int g_start; static unsigned int elapse; #define TIMER_START g_start=hwtime() #define TIMER_END elapse=hwtime()-g_start #define SEEK(X) last_page=(X) #define TRACE1(X) fprintf(stderr,X) #define TRACE2(X,Y) fprintf(stderr,X,Y) #define TRACE3(X,Y,Z) fprintf(stderr,X,Y,Z) #define TRACE4(X,Y,Z,A) fprintf(stderr,X,Y,Z,A) #define TRACE5(X,Y,Z,A,B) fprintf(stderr,X,Y,Z,A,B) #else #define TIMER_START #define TIMER_END #define SEEK(X) #define TRACE1(X) #define TRACE2(X,Y) #define TRACE3(X,Y,Z) #define TRACE4(X,Y,Z,A) #define TRACE5(X,Y,Z,A,B) #endif #if OS_UNIX /* ** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) ** section 6.5.2.2 lines 483 through 490 specify that when a process ** sets or clears a lock, that operation overrides any prior locks set ** by the same process. It does not explicitly say so, but this implies ** that it overrides locks set by the same process using a different ** file descriptor. Consider this test case: ** ** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); ** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); ** ** Suppose ./file1 and ./file2 are really the same file (because ** one is a hard or symbolic link to the other) then if you set ** an exclusive lock on fd1, then try to get an exclusive lock ** on fd2, it works. I would have expected the second lock to ** fail since there was already a lock on the file due to fd1. ** But not so. Since both locks came from the same process, the ** second overrides the first, even though they were on different ** file descriptors opened on different file names. ** ** Bummer. If you ask me, this is broken. Badly broken. It means ** that we cannot use POSIX locks to synchronize file access among ** competing threads of the same process. POSIX locks will work fine ** to synchronize access for threads in separate processes, but not ** threads within the same process. ** ** To work around the problem, SQLite has to manage file locks internally ** on its own. Whenever a new database is opened, we have to find the ** specific inode of the database file (the inode is determined by the ** st_dev and st_ino fields of the stat structure that fstat() fills in) ** and check for locks already existing on that inode. When locks are ** created or removed, we have to look at our own internal record of the ** locks to see if another thread has previously set a lock on that same ** inode. ** ** The OsFile structure for POSIX is no longer just an integer file ** descriptor. It is now a structure that holds the integer file ** descriptor and a pointer to a structure that describes the internal ** locks on the corresponding inode. There is one locking structure ** per inode, so if the same inode is opened twice, both OsFile structures ** point to the same locking structure. The locking structure keeps ** a reference count (so we will know when to delete it) and a "cnt" ** field that tells us its internal lock status. cnt==0 means the ** file is unlocked. cnt==-1 means the file has an exclusive lock. ** cnt>0 means there are cnt shared locks on the file. ** ** Any attempt to lock or unlock a file first checks the locking ** structure. The fcntl() system call is only invoked to set a ** POSIX lock if the internal lock structure transitions between ** a locked and an unlocked state. ** ** 2004-Jan-11: ** More recent discoveries about POSIX advisory locks. (The more ** I discover, the more I realize the a POSIX advisory locks are ** an abomination.) ** ** If you close a file descriptor that points to a file that has locks, ** all locks on that file that are owned by the current process are ** released. To work around this problem, each OsFile structure contains ** a pointer to an openCnt structure. There is one openCnt structure ** per open inode, which means that multiple OsFiles can point to a single ** openCnt. When an attempt is made to close an OsFile, if there are ** other OsFiles open on the same inode that are holding locks, the call ** to close() the file descriptor is deferred until all of the locks clear. ** The openCnt structure keeps a list of file descriptors that need to ** be closed and that list is walked (and cleared) when the last lock ** clears. ** ** First, under Linux threads, because each thread has a separate ** process ID, lock operations in one thread do not override locks ** to the same file in other threads. Linux threads behave like ** separate processes in this respect. But, if you close a file ** descriptor in linux threads, all locks are cleared, even locks ** on other threads and even though the other threads have different ** process IDs. Linux threads is inconsistent in this respect. ** (I'm beginning to think that linux threads is an abomination too.) ** The consequence of this all is that the hash table for the lockInfo ** structure has to include the process id as part of its key because ** locks in different threads are treated as distinct. But the ** openCnt structure should not include the process id in its ** key because close() clears lock on all threads, not just the current ** thread. Were it not for this goofiness in linux threads, we could ** combine the lockInfo and openCnt structures into a single structure. */ /* ** An instance of the following structure serves as the key used ** to locate a particular lockInfo structure given its inode. Note ** that we have to include the process ID as part of the key. On some ** threading implementations (ex: linux), each thread has a separate ** process ID. */ struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ pid_t pid; /* Process ID */ }; /* ** An instance of the following structure is allocated for each open ** inode on each thread with a different process ID. (Threads have ** different process IDs on linux, but not on most other unixes.) ** ** A single inode can have multiple file descriptors, so each OsFile ** structure contains a pointer to an instance of this object and this ** object keeps a count of the number of OsFiles pointing to it. */ struct lockInfo { struct lockKey key; /* The lookup key */ int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */ int nRef; /* Number of pointers to this structure */ }; /* ** An instance of the following structure serves as the key used ** to locate a particular openCnt structure given its inode. This ** is the same as the lockKey except that the process ID is omitted. */ struct openKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ }; /* ** An instance of the following structure is allocated for each open ** inode. This structure keeps track of the number of locks on that ** inode. If a close is attempted against an inode that is holding ** locks, the close is deferred until all locks clear by adding the ** file descriptor to be closed to the pending list. */ struct openCnt { struct openKey key; /* The lookup key */ int nRef; /* Number of pointers to this structure */ int nLock; /* Number of outstanding locks */ int nPending; /* Number of pending close() operations */ int *aPending; /* Malloced space holding fd's awaiting a close() */ }; /* ** These hash table maps inodes and process IDs into lockInfo and openCnt ** structures. Access to these hash tables must be protected by a mutex. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; static Hash openHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ pLock->nRef--; if( pLock->nRef==0 ){ sqliteHashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqliteFree(pLock); } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ pOpen->nRef--; if( pOpen->nRef==0 ){ sqliteHashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); sqliteFree(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that ** describes that file descriptor. Create a new ones if necessary. The ** return values might be unset if an error occurs. ** ** Return the number of errors. */ int findLockInfo( int fd, /* The file descriptor used in the key */ struct lockInfo **ppLock, /* Return the lockInfo structure here */ struct openCnt **ppOpen /* Return the openCnt structure here */ ){ int rc; struct lockKey key1; struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; key1.pid = getpid(); memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = (struct lockInfo*)sqliteHashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); if( pLock==0 ) return 1; pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pOld = sqliteHashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); sqliteFree(pLock); return 1; } }else{ pLock->nRef++; } *ppLock = pLock; pOpen = (struct openCnt*)sqliteHashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqliteMallocRaw( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); return 1; } pOpen->key = key2; pOpen->nRef = 1; pOpen->nLock = 0; pOpen->nPending = 0; pOpen->aPending = 0; pOld = sqliteHashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); if( pOld!=0 ){ assert( pOld==pOpen ); sqliteFree(pOpen); releaseLockInfo(pLock); return 1; } }else{ pOpen->nRef++; } *ppOpen = pOpen; return 0; } #endif /** POSIX advisory lock work-around **/ /* ** If we compile with the SQLITE_TEST macro set, then the following block ** of code will give us the ability to simulate a disk I/O error. This ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST int sqlite_io_error_pending = 0; #define SimulateIOError(A) \ if( sqlite_io_error_pending ) \ if( sqlite_io_error_pending-- == 1 ){ local_ioerr(); return A; } static void local_ioerr(){ sqlite_io_error_pending = 0; /* Really just a place to set a breakpoint */ } #else #define SimulateIOError(A) #endif /* ** When testing, keep a count of the number of open files. */ #ifdef SQLITE_TEST int sqlite_open_file_count = 0; #define OpenCounter(X) sqlite_open_file_count+=(X) #else #define OpenCounter(X) #endif /* ** Delete the named file */ int sqliteOsDelete(const char *zFilename){ #if OS_UNIX unlink(zFilename); #endif #if OS_WIN DeleteFile(zFilename); #endif #if OS_MAC unlink(zFilename); #endif return SQLITE_OK; } /* ** Return TRUE if the named file exists. */ int sqliteOsFileExists(const char *zFilename){ #if OS_UNIX return access(zFilename, 0)==0; #endif #if OS_WIN return GetFileAttributes(zFilename) != 0xffffffff; #endif #if OS_MAC return access(zFilename, 0)==0; #endif } #if 0 /* NOT USED */ /* ** Change the name of an existing file. */ int sqliteOsFileRename(const char *zOldName, const char *zNewName){ #if OS_UNIX if( link(zOldName, zNewName) ){ return SQLITE_ERROR; } unlink(zOldName); return SQLITE_OK; #endif #if OS_WIN if( !MoveFile(zOldName, zNewName) ){ return SQLITE_ERROR; } return SQLITE_OK; #endif #if OS_MAC /**** FIX ME ***/ return SQLITE_ERROR; #endif } #endif /* NOT USED */ /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, ** try to create it. ** ** On success, a handle for the open file is written to *id ** and *pReadonly is set to 0 if the file was opened for reading and ** writing or 1 if the file was opened read-only. The function returns ** SQLITE_OK. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ int sqliteOsOpenReadWrite( const char *zFilename, OsFile *id, int *pReadonly ){ #if OS_UNIX int rc; id->dirfd = -1; id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644); if( id->fd<0 ){ #ifdef EISDIR if( errno==EISDIR ){ return SQLITE_CANTOPEN; } #endif id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->fd<0 ){ return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } sqliteOsEnterMutex(); rc = findLockInfo(id->fd, &id->pLock, &id->pOpen); sqliteOsLeaveMutex(); if( rc ){ close(id->fd); return SQLITE_NOMEM; } id->locked = 0; TRACE3("OPEN %-3d %s\n", id->fd, zFilename); OpenCounter(+1); return SQLITE_OK; #endif #if OS_WIN HANDLE h = CreateFile(zFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ h = CreateFile(zFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } id->h = h; id->locked = 0; OpenCounter(+1); return SQLITE_OK; #endif #if OS_MAC FSSpec fsSpec; # ifdef _LARGE_FILE HFSUniStr255 dfName; FSRef fsRef; if( __path2fss(zFilename, &fsSpec) != noErr ){ if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) return SQLITE_CANTOPEN; } if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) return SQLITE_CANTOPEN; FSGetDataForkName(&dfName); if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, fsRdWrShPerm, &(id->refNum)) != noErr ){ if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, fsRdWrPerm, &(id->refNum)) != noErr ){ if (FSOpenFork(&fsRef, dfName.length, dfName.unicode, fsRdPerm, &(id->refNum)) != noErr ) return SQLITE_CANTOPEN; else *pReadonly = 1; } else *pReadonly = 0; } else *pReadonly = 0; # else __path2fss(zFilename, &fsSpec); if( !sqliteOsFileExists(zFilename) ){ if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) return SQLITE_CANTOPEN; } if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNum)) != noErr ){ if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ){ if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) return SQLITE_CANTOPEN; else *pReadonly = 1; } else *pReadonly = 0; } else *pReadonly = 0; # endif if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ id->refNumRF = -1; } id->locked = 0; id->delOnClose = 0; OpenCounter(+1); return SQLITE_OK; #endif } /* ** Attempt to open a new file for exclusive access by this process. ** The file will be opened for both reading and writing. To avoid ** a potential security problem, we do not allow the file to have ** previously existed. Nor do we allow the file to be a symbolic ** link. ** ** If delFlag is true, then make arrangements to automatically delete ** the file when it is closed. ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ #if OS_UNIX int rc; if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } id->dirfd = -1; id->fd = open(zFilename, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600); if( id->fd<0 ){ return SQLITE_CANTOPEN; } sqliteOsEnterMutex(); rc = findLockInfo(id->fd, &id->pLock, &id->pOpen); sqliteOsLeaveMutex(); if( rc ){ close(id->fd); unlink(zFilename); return SQLITE_NOMEM; } id->locked = 0; if( delFlag ){ unlink(zFilename); } TRACE3("OPEN-EX %-3d %s\n", id->fd, zFilename); OpenCounter(+1); return SQLITE_OK; #endif #if OS_WIN HANDLE h; int fileflags; if( delFlag ){ fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_DELETE_ON_CLOSE; }else{ fileflags = FILE_FLAG_RANDOM_ACCESS; } h = CreateFile(zFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } id->h = h; id->locked = 0; OpenCounter(+1); return SQLITE_OK; #endif #if OS_MAC FSSpec fsSpec; # ifdef _LARGE_FILE HFSUniStr255 dfName; FSRef fsRef; __path2fss(zFilename, &fsSpec); if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) return SQLITE_CANTOPEN; if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) return SQLITE_CANTOPEN; FSGetDataForkName(&dfName); if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, fsRdWrPerm, &(id->refNum)) != noErr ) return SQLITE_CANTOPEN; # else __path2fss(zFilename, &fsSpec); if( HCreate(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, 'SQLI', cDocumentFile) != noErr ) return SQLITE_CANTOPEN; if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrPerm, &(id->refNum)) != noErr ) return SQLITE_CANTOPEN; # endif id->refNumRF = -1; id->locked = 0; id->delOnClose = delFlag; if (delFlag) id->pathToDel = sqliteOsFullPathname(zFilename); OpenCounter(+1); return SQLITE_OK; #endif } /* ** Attempt to open a new file for read-only access. ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqliteOsOpenReadOnly(const char *zFilename, OsFile *id){ #if OS_UNIX int rc; id->dirfd = -1; id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); if( id->fd<0 ){ return SQLITE_CANTOPEN; } sqliteOsEnterMutex(); rc = findLockInfo(id->fd, &id->pLock, &id->pOpen); sqliteOsLeaveMutex(); if( rc ){ close(id->fd); return SQLITE_NOMEM; } id->locked = 0; TRACE3("OPEN-RO %-3d %s\n", id->fd, zFilename); OpenCounter(+1); return SQLITE_OK; #endif #if OS_WIN HANDLE h = CreateFile(zFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } id->h = h; id->locked = 0; OpenCounter(+1); return SQLITE_OK; #endif #if OS_MAC FSSpec fsSpec; # ifdef _LARGE_FILE HFSUniStr255 dfName; FSRef fsRef; if( __path2fss(zFilename, &fsSpec) != noErr ) return SQLITE_CANTOPEN; if( FSpMakeFSRef(&fsSpec, &fsRef) != noErr ) return SQLITE_CANTOPEN; FSGetDataForkName(&dfName); if( FSOpenFork(&fsRef, dfName.length, dfName.unicode, fsRdPerm, &(id->refNum)) != noErr ) return SQLITE_CANTOPEN; # else __path2fss(zFilename, &fsSpec); if( HOpenDF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdPerm, &(id->refNum)) != noErr ) return SQLITE_CANTOPEN; # endif if( HOpenRF(fsSpec.vRefNum, fsSpec.parID, fsSpec.name, fsRdWrShPerm, &(id->refNumRF)) != noErr){ id->refNumRF = -1; } id->locked = 0; id->delOnClose = 0; OpenCounter(+1); return SQLITE_OK; #endif } /* ** Attempt to open a file descriptor for the directory that contains a ** file. This file descriptor can be used to fsync() the directory ** in order to make sure the creation of a new file is actually written ** to disk. ** ** This routine is only meaningful for Unix. It is a no-op under ** windows since windows does not support hard links. ** ** On success, a handle for a previously open file is at *id is ** updated with the new directory file descriptor and SQLITE_OK is ** returned. ** ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id unchanged. */ int sqliteOsOpenDirectory( const char *zDirname, OsFile *id ){ #if OS_UNIX if( id->fd<0 ){ /* Do not open the directory if the corresponding file is not already ** open. */ return SQLITE_CANTOPEN; } assert( id->dirfd<0 ); id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644); if( id->dirfd<0 ){ return SQLITE_CANTOPEN; } TRACE3("OPENDIR %-3d %s\n", id->dirfd, zDirname); #endif return SQLITE_OK; } /* ** If the following global variable points to a string which is the ** name of a directory, then that directory will be used to store ** temporary files. */ const char *sqlite_temp_directory = 0; /* ** Create a temporary file name in zBuf. zBuf must be big enough to ** hold at least SQLITE_TEMPNAME_SIZE characters. */ int sqliteOsTempFileName(char *zBuf){ #if OS_UNIX static const char *azDirs[] = { 0, "/var/tmp", "/usr/tmp", "/tmp", ".", }; static unsigned char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; int i, j; struct stat buf; const char *zDir = "."; azDirs[0] = sqlite_temp_directory; for(i=0; i0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; zDir = zTempPath; }else{ zDir = sqlite_temp_directory; } for(;;){ sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zDir); j = strlen(zBuf); sqliteRandomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; if( !sqliteOsFileExists(zBuf) ) break; } #endif #if OS_MAC static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; int i, j; char *zDir; char zTempPath[SQLITE_TEMPNAME_SIZE]; char zdirName[32]; CInfoPBRec infoRec; Str31 dirName; memset(&infoRec, 0, sizeof(infoRec)); memset(zTempPath, 0, SQLITE_TEMPNAME_SIZE); if( sqlite_temp_directory!=0 ){ zDir = sqlite_temp_directory; }else if( FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &(infoRec.dirInfo.ioVRefNum), &(infoRec.dirInfo.ioDrParID)) == noErr ){ infoRec.dirInfo.ioNamePtr = dirName; do{ infoRec.dirInfo.ioFDirIndex = -1; infoRec.dirInfo.ioDrDirID = infoRec.dirInfo.ioDrParID; if( PBGetCatInfoSync(&infoRec) == noErr ){ CopyPascalStringToC(dirName, zdirName); i = strlen(zdirName); memmove(&(zTempPath[i+1]), zTempPath, strlen(zTempPath)); strcpy(zTempPath, zdirName); zTempPath[i] = ':'; }else{ *zTempPath = 0; break; } } while( infoRec.dirInfo.ioDrDirID != fsRtDirID ); zDir = zTempPath; } if( zDir[0]==0 ){ getcwd(zTempPath, SQLITE_TEMPNAME_SIZE-24); zDir = zTempPath; } for(;;){ sprintf(zBuf, "%s"TEMP_FILE_PREFIX, zDir); j = strlen(zBuf); sqliteRandomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; if( !sqliteOsFileExists(zBuf) ) break; } #endif return SQLITE_OK; } /* ** Close a file. */ int sqliteOsClose(OsFile *id){ #if OS_UNIX sqliteOsUnlock(id); if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqliteOsEnterMutex(); if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pOpen->aPending. It will be automatically closed when ** the last lock is cleared. */ int *aNew; struct openCnt *pOpen = id->pOpen; pOpen->nPending++; aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) ); if( aNew==0 ){ /* If a malloc fails, just leak the file descriptor */ }else{ pOpen->aPending = aNew; pOpen->aPending[pOpen->nPending-1] = id->fd; } }else{ /* There are no outstanding locks so we can close the file immediately */ close(id->fd); } releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); sqliteOsLeaveMutex(); TRACE2("CLOSE %-3d\n", id->fd); OpenCounter(-1); return SQLITE_OK; #endif #if OS_WIN CloseHandle(id->h); OpenCounter(-1); return SQLITE_OK; #endif #if OS_MAC if( id->refNumRF!=-1 ) FSClose(id->refNumRF); # ifdef _LARGE_FILE FSCloseFork(id->refNum); # else FSClose(id->refNum); # endif if( id->delOnClose ){ unlink(id->pathToDel); sqliteFree(id->pathToDel); } OpenCounter(-1); return SQLITE_OK; #endif } /* ** Read data from a file into a buffer. Return SQLITE_OK if all ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ int sqliteOsRead(OsFile *id, void *pBuf, int amt){ #if OS_UNIX int got; SimulateIOError(SQLITE_IOERR); TIMER_START; got = read(id->fd, pBuf, amt); TIMER_END; TRACE4("READ %-3d %7d %d\n", id->fd, last_page, elapse); SEEK(0); /* if( got<0 ) got = 0; */ if( got==amt ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } #endif #if OS_WIN DWORD got; SimulateIOError(SQLITE_IOERR); TRACE2("READ %d\n", last_page); if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ got = 0; } if( got==(DWORD)amt ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } #endif #if OS_MAC int got; SimulateIOError(SQLITE_IOERR); TRACE2("READ %d\n", last_page); # ifdef _LARGE_FILE FSReadFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&got); # else got = amt; FSRead(id->refNum, &got, pBuf); # endif if( got==amt ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } #endif } /* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){ #if OS_UNIX int wrote = 0; SimulateIOError(SQLITE_IOERR); TIMER_START; while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } TIMER_END; TRACE4("WRITE %-3d %7d %d\n", id->fd, last_page, elapse); SEEK(0); if( amt>0 ){ return SQLITE_FULL; } return SQLITE_OK; #endif #if OS_WIN int rc; DWORD wrote; SimulateIOError(SQLITE_IOERR); TRACE2("WRITE %d\n", last_page); while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } if( !rc || amt>(int)wrote ){ return SQLITE_FULL; } return SQLITE_OK; #endif #if OS_MAC OSErr oserr; int wrote = 0; SimulateIOError(SQLITE_IOERR); TRACE2("WRITE %d\n", last_page); while( amt>0 ){ # ifdef _LARGE_FILE oserr = FSWriteFork(id->refNum, fsAtMark, 0, (ByteCount)amt, pBuf, (ByteCount*)&wrote); # else wrote = amt; oserr = FSWrite(id->refNum, &wrote, pBuf); # endif if( wrote == 0 || oserr != noErr) break; amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } if( oserr != noErr || amt>wrote ){ return SQLITE_FULL; } return SQLITE_OK; #endif } /* ** Move the read/write pointer in a file. */ int sqliteOsSeek(OsFile *id, sql_off_t offset){ SEEK(offset/1024 + 1); #if OS_UNIX lseek(id->fd, offset, SEEK_SET); return SQLITE_OK; #endif #if OS_WIN { LONG upperBits = offset>>32; LONG lowerBits = offset & 0xffffffff; DWORD rc; rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); /* TRACE3("SEEK rc=0x%x upper=0x%x\n", rc, upperBits); */ } return SQLITE_OK; #endif #if OS_MAC { sql_off_t curSize; if( sqliteOsFileSize(id, &curSize) != SQLITE_OK ){ return SQLITE_IOERR; } if( offset >= curSize ){ if( sqliteOsTruncate(id, offset+1) != SQLITE_OK ){ return SQLITE_IOERR; } } # ifdef _LARGE_FILE if( FSSetForkPosition(id->refNum, fsFromStart, offset) != noErr ){ # else if( SetFPos(id->refNum, fsFromStart, offset) != noErr ){ # endif return SQLITE_IOERR; }else{ return SQLITE_OK; } } #endif } /* ** Make sure all writes to a particular file are committed to disk. ** ** Under Unix, also make sure that the directory entry for the file ** has been created by fsync-ing the directory that contains the file. ** If we do not do this and we encounter a power failure, the directory ** entry for the journal might not exist after we reboot. The next ** SQLite to access the file will not know that the journal exists (because ** the directory entry for the journal was never created) and the transaction ** will not roll back - possibly leading to database corruption. */ int sqliteOsSync(OsFile *id){ #if OS_UNIX SimulateIOError(SQLITE_IOERR); TRACE2("SYNC %-3d\n", id->fd); if( fsync(id->fd) ){ return SQLITE_IOERR; }else{ if( id->dirfd>=0 ){ TRACE2("DIRSYNC %-3d\n", id->dirfd); fsync(id->dirfd); close(id->dirfd); /* Only need to sync once, so close the directory */ id->dirfd = -1; /* when we are done. */ } return SQLITE_OK; } #endif #if OS_WIN if( FlushFileBuffers(id->h) ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } #endif #if OS_MAC # ifdef _LARGE_FILE if( FSFlushFork(id->refNum) != noErr ){ # else ParamBlockRec params; memset(¶ms, 0, sizeof(ParamBlockRec)); params.ioParam.ioRefNum = id->refNum; if( PBFlushFileSync(¶ms) != noErr ){ # endif return SQLITE_IOERR; }else{ return SQLITE_OK; } #endif } /* ** Truncate an open file to a specified size */ int sqliteOsTruncate(OsFile *id, sql_off_t nByte){ SimulateIOError(SQLITE_IOERR); #if OS_UNIX return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR; #endif #if OS_WIN { LONG upperBits = nByte>>32; SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); SetEndOfFile(id->h); } return SQLITE_OK; #endif #if OS_MAC # ifdef _LARGE_FILE if( FSSetForkSize(id->refNum, fsFromStart, nByte) != noErr){ # else if( SetEOF(id->refNum, nByte) != noErr ){ # endif return SQLITE_IOERR; }else{ return SQLITE_OK; } #endif } /* ** Determine the current size of a file in bytes */ int sqliteOsFileSize(OsFile *id, sql_off_t *pSize){ #if OS_UNIX struct stat buf; SimulateIOError(SQLITE_IOERR); if( fstat(id->fd, &buf)!=0 ){ return SQLITE_IOERR; } *pSize = buf.st_size; return SQLITE_OK; #endif #if OS_WIN DWORD upperBits, lowerBits; SimulateIOError(SQLITE_IOERR); lowerBits = GetFileSize(id->h, &upperBits); *pSize = (((sql_off_t)upperBits)<<32) + lowerBits; return SQLITE_OK; #endif #if OS_MAC # ifdef _LARGE_FILE if( FSGetForkSize(id->refNum, pSize) != noErr){ # else if( GetEOF(id->refNum, pSize) != noErr ){ # endif return SQLITE_IOERR; }else{ return SQLITE_OK; } #endif } #if OS_WIN /* ** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. ** Return false (zero) for Win95, Win98, or WinME. ** ** Here is an interesting observation: Win95, Win98, and WinME lack ** the LockFileEx() API. But we can still statically link against that ** API as long as we don't call it win running Win95/98/ME. A call to ** this routine is used to determine if the host is Win95/98/ME or ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. */ int isNT(void){ static int osType = 0; /* 0=unknown 1=win95 2=winNT */ if( osType==0 ){ OSVERSIONINFO sInfo; sInfo.dwOSVersionInfoSize = sizeof(sInfo); GetVersionEx(&sInfo); osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return osType==2; } #endif /* ** Windows file locking notes: [similar issues apply to MacOS] ** ** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because ** those functions are not available. So we use only LockFile() and ** UnlockFile(). ** ** LockFile() prevents not just writing but also reading by other processes. ** (This is a design error on the part of Windows, but there is nothing ** we can do about that.) So the region used for locking is at the ** end of the file where it is unlikely to ever interfere with an ** actual read attempt. ** ** A database read lock is obtained by locking a single randomly-chosen ** byte out of a specific range of bytes. The lock byte is obtained at ** random so two separate readers can probably access the file at the ** same time, unless they are unlucky and choose the same lock byte. ** A database write lock is obtained by locking all bytes in the range. ** There can only be one writer. ** ** A lock is obtained on the first byte of the lock range before acquiring ** either a read lock or a write lock. This prevents two processes from ** attempting to get a lock at a same time. The semantics of ** sqliteOsReadLock() require that if there is already a write lock, that ** lock is converted into a read lock atomically. The lock on the first ** byte allows us to drop the old write lock and get the read lock without ** another process jumping into the middle and messing us up. The same ** argument applies to sqliteOsWriteLock(). ** ** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, ** which means we can use reader/writer locks. When reader writer locks ** are used, the lock is placed on the same range of bytes that is used ** for probabilistic locking in Win95/98/ME. Hence, the locking scheme ** will support two or more Win95 readers or two or more WinNT readers. ** But a single Win95 reader will lock out all WinNT readers and a single ** WinNT reader will lock out all other Win95 readers. ** ** Note: On MacOS we use the resource fork for locking. ** ** The following #defines specify the range of bytes used for locking. ** N_LOCKBYTE is the number of bytes available for doing the locking. ** The first byte used to hold the lock while the lock is changing does ** not count toward this number. FIRST_LOCKBYTE is the address of ** the first byte in the range of bytes used for locking. */ #define N_LOCKBYTE 10239 #if OS_MAC # define FIRST_LOCKBYTE (0x000fffff - N_LOCKBYTE) #else # define FIRST_LOCKBYTE (0xffffffff - N_LOCKBYTE) #endif /* ** Change the status of the lock on the file "id" to be a readlock. ** If the file was write locked, then this reduces the lock to a read. ** If the file was read locked, then this acquires a new read lock. ** ** Return SQLITE_OK on success and SQLITE_BUSY on failure. If this ** library was compiled with large file support (LFS) but LFS is not ** available on the host, then an SQLITE_NOLFS is returned. */ int sqliteOsReadLock(OsFile *id){ #if OS_UNIX int rc; sqliteOsEnterMutex(); if( id->pLock->cnt>0 ){ if( !id->locked ){ id->pLock->cnt++; id->locked = 1; id->pOpen->nLock++; } rc = SQLITE_OK; }else if( id->locked || id->pLock->cnt==0 ){ struct flock lock; int s; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; s = fcntl(id->fd, F_SETLK, &lock); if( s!=0 ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ rc = SQLITE_OK; if( !id->locked ){ id->pOpen->nLock++; id->locked = 1; } id->pLock->cnt = 1; } }else{ rc = SQLITE_BUSY; } sqliteOsLeaveMutex(); return rc; #endif #if OS_WIN int rc; if( id->locked>0 ){ rc = SQLITE_OK; }else{ int lk; int res; int cnt = 100; sqliteRandomness(sizeof(lk), &lk); lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1; while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){ Sleep(1); } if( res ){ UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); if( isNT() ){ OVERLAPPED ovlp; ovlp.Offset = FIRST_LOCKBYTE+1; ovlp.OffsetHigh = 0; ovlp.hEvent = 0; res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, N_LOCKBYTE, 0, &ovlp); }else{ res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0); } UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0); } if( res ){ id->locked = lk; rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; } } return rc; #endif #if OS_MAC int rc; if( id->locked>0 || id->refNumRF == -1 ){ rc = SQLITE_OK; }else{ int lk; OSErr res; int cnt = 5; ParamBlockRec params; sqliteRandomness(sizeof(lk), &lk); lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1; memset(¶ms, 0, sizeof(params)); params.ioParam.ioRefNum = id->refNumRF; params.ioParam.ioPosMode = fsFromStart; params.ioParam.ioPosOffset = FIRST_LOCKBYTE; params.ioParam.ioReqCount = 1; while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ UInt32 finalTicks; Delay(1, &finalTicks); /* 1/60 sec */ } if( res == noErr ){ params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; params.ioParam.ioReqCount = N_LOCKBYTE; PBUnlockRangeSync(¶ms); params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk; params.ioParam.ioReqCount = 1; res = PBLockRangeSync(¶ms); params.ioParam.ioPosOffset = FIRST_LOCKBYTE; params.ioParam.ioReqCount = 1; PBUnlockRangeSync(¶ms); } if( res == noErr ){ id->locked = lk; rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; } } return rc; #endif } /* ** Change the lock status to be an exclusive or write lock. Return ** SQLITE_OK on success and SQLITE_BUSY on a failure. If this ** library was compiled with large file support (LFS) but LFS is not ** available on the host, then an SQLITE_NOLFS is returned. */ int sqliteOsWriteLock(OsFile *id){ #if OS_UNIX int rc; sqliteOsEnterMutex(); if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){ struct flock lock; int s; lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; s = fcntl(id->fd, F_SETLK, &lock); if( s!=0 ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ rc = SQLITE_OK; if( !id->locked ){ id->pOpen->nLock++; id->locked = 1; } id->pLock->cnt = -1; } }else{ rc = SQLITE_BUSY; } sqliteOsLeaveMutex(); return rc; #endif #if OS_WIN int rc; if( id->locked<0 ){ rc = SQLITE_OK; }else{ int res; int cnt = 100; while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){ Sleep(1); } if( res ){ if( id->locked>0 ){ if( isNT() ){ UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); }else{ res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0); } } if( res ){ res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); }else{ res = 0; } UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0); } if( res ){ id->locked = -1; rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; } } return rc; #endif #if OS_MAC int rc; if( id->locked<0 || id->refNumRF == -1 ){ rc = SQLITE_OK; }else{ OSErr res; int cnt = 5; ParamBlockRec params; memset(¶ms, 0, sizeof(params)); params.ioParam.ioRefNum = id->refNumRF; params.ioParam.ioPosMode = fsFromStart; params.ioParam.ioPosOffset = FIRST_LOCKBYTE; params.ioParam.ioReqCount = 1; while( cnt-->0 && (res = PBLockRangeSync(¶ms))!=noErr ){ UInt32 finalTicks; Delay(1, &finalTicks); /* 1/60 sec */ } if( res == noErr ){ params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked; params.ioParam.ioReqCount = 1; if( id->locked==0 || PBUnlockRangeSync(¶ms)==noErr ){ params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; params.ioParam.ioReqCount = N_LOCKBYTE; res = PBLockRangeSync(¶ms); }else{ res = afpRangeNotLocked; } params.ioParam.ioPosOffset = FIRST_LOCKBYTE; params.ioParam.ioReqCount = 1; PBUnlockRangeSync(¶ms); } if( res == noErr ){ id->locked = -1; rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; } } return rc; #endif } /* ** Unlock the given file descriptor. If the file descriptor was ** not previously locked, then this routine is a no-op. If this ** library was compiled with large file support (LFS) but LFS is not ** available on the host, then an SQLITE_NOLFS is returned. */ int sqliteOsUnlock(OsFile *id){ #if OS_UNIX int rc; if( !id->locked ) return SQLITE_OK; sqliteOsEnterMutex(); assert( id->pLock->cnt!=0 ); if( id->pLock->cnt>1 ){ id->pLock->cnt--; rc = SQLITE_OK; }else{ struct flock lock; int s; lock.l_type = F_UNLCK; lock.l_whence = SEEK_SET; lock.l_start = lock.l_len = 0L; s = fcntl(id->fd, F_SETLK, &lock); if( s!=0 ){ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; }else{ rc = SQLITE_OK; id->pLock->cnt = 0; } } if( rc==SQLITE_OK ){ /* Decrement the count of locks against this same file. When the ** count reaches zero, close any other file descriptors whose close ** was deferred because of outstanding locks. */ struct openCnt *pOpen = id->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 && pOpen->nPending>0 ){ int i; for(i=0; inPending; i++){ close(pOpen->aPending[i]); } sqliteFree(pOpen->aPending); pOpen->nPending = 0; pOpen->aPending = 0; } } sqliteOsLeaveMutex(); id->locked = 0; return rc; #endif #if OS_WIN int rc; if( id->locked==0 ){ rc = SQLITE_OK; }else if( isNT() || id->locked<0 ){ UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0); rc = SQLITE_OK; id->locked = 0; }else{ UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0); rc = SQLITE_OK; id->locked = 0; } return rc; #endif #if OS_MAC int rc; ParamBlockRec params; memset(¶ms, 0, sizeof(params)); params.ioParam.ioRefNum = id->refNumRF; params.ioParam.ioPosMode = fsFromStart; if( id->locked==0 || id->refNumRF == -1 ){ rc = SQLITE_OK; }else if( id->locked<0 ){ params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1; params.ioParam.ioReqCount = N_LOCKBYTE; PBUnlockRangeSync(¶ms); rc = SQLITE_OK; id->locked = 0; }else{ params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked; params.ioParam.ioReqCount = 1; PBUnlockRangeSync(¶ms); rc = SQLITE_OK; id->locked = 0; } return rc; #endif } /* ** Get information to seed the random number generator. The seed ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ int sqliteOsRandomSeed(char *zBuf){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the ** uninitialized space in zBuf - but valgrind errors tend to worry ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence.* This makes the ** tests repeatable. */ memset(zBuf, 0, 256); #if OS_UNIX && !defined(SQLITE_TEST) { int pid; time((time_t*)zBuf); pid = getpid(); memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); } #endif #if OS_WIN && !defined(SQLITE_TEST) GetSystemTime((LPSYSTEMTIME)zBuf); #endif #if OS_MAC { int pid; Microseconds((UnsignedWide*)zBuf); pid = getpid(); memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid)); } #endif return SQLITE_OK; } /* ** Sleep for a little while. Return the amount of time slept. */ int sqliteOsSleep(int ms){ #if OS_UNIX #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(ms*1000); return ms; #else sleep((ms+999)/1000); return 1000*((ms+999)/1000); #endif #endif #if OS_WIN Sleep(ms); return ms; #endif #if OS_MAC UInt32 finalTicks; UInt32 ticks = (((UInt32)ms+16)*3)/50; /* 1/60 sec per tick */ Delay(ticks, &finalTicks); return (int)((ticks*50)/3); #endif } /* ** Static variables used for thread synchronization */ static int inMutex = 0; #ifdef SQLITE_UNIX_THREADS static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif #ifdef SQLITE_W32_THREADS static CRITICAL_SECTION cs; #endif #ifdef SQLITE_MACOS_MULTITASKING static MPCriticalRegionID criticalRegion; #endif /* ** The following pair of routine implement mutual exclusion for ** multi-threaded processes. Only a single thread is allowed to ** executed code that is surrounded by EnterMutex() and LeaveMutex(). ** ** SQLite uses only a single Mutex. There is not much critical ** code and what little there is executes quickly and without blocking. */ void sqliteOsEnterMutex(){ #ifdef SQLITE_UNIX_THREADS pthread_mutex_lock(&mutex); #endif #ifdef SQLITE_W32_THREADS static int isInit = 0; while( !isInit ){ static long lock = 0; if( InterlockedIncrement(&lock)==1 ){ InitializeCriticalSection(&cs); isInit = 1; }else{ Sleep(1); } } EnterCriticalSection(&cs); #endif #ifdef SQLITE_MACOS_MULTITASKING static volatile int notInit = 1; if( notInit ){ if( notInit == 2 ) /* as close as you can get to thread safe init */ MPYield(); else{ notInit = 2; MPCreateCriticalRegion(&criticalRegion); notInit = 0; } } MPEnterCriticalRegion(criticalRegion, kDurationForever); #endif assert( !inMutex ); inMutex = 1; } void sqliteOsLeaveMutex(){ assert( inMutex ); inMutex = 0; #ifdef SQLITE_UNIX_THREADS pthread_mutex_unlock(&mutex); #endif #ifdef SQLITE_W32_THREADS LeaveCriticalSection(&cs); #endif #ifdef SQLITE_MACOS_MULTITASKING MPExitCriticalRegion(criticalRegion); #endif } /* ** Turn a relative pathname into a full pathname. Return a pointer ** to the full pathname stored in space obtained from sqliteMalloc(). ** The calling function is responsible for freeing this space once it ** is no longer needed. */ char *sqliteOsFullPathname(const char *zRelative){ #if OS_UNIX char *zFull = 0; if( zRelative[0]=='/' ){ sqliteSetString(&zFull, zRelative, (char*)0); }else{ char zBuf[5000]; sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative, (char*)0); } return zFull; #endif #if OS_WIN char *zNotUsed; char *zFull; int nByte; nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1; zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; GetFullPathName(zRelative, nByte, zFull, &zNotUsed); return zFull; #endif #if OS_MAC char *zFull = 0; if( zRelative[0]==':' ){ char zBuf[_MAX_PATH+1]; sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]), (char*)0); }else{ if( strchr(zRelative, ':') ){ sqliteSetString(&zFull, zRelative, (char*)0); }else{ char zBuf[_MAX_PATH+1]; sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0); } } return zFull; #endif } /* ** The following variable, if set to a non-zero value, becomes the result ** returned from sqliteOsCurrentTime(). This is used for testing. */ #ifdef SQLITE_TEST int sqlite_current_time = 0; #endif /* ** Find the current time (in Universal Coordinated Time). Write the ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ int sqliteOsCurrentTime(double *prNow){ #if OS_UNIX time_t t; time(&t); *prNow = t/86400.0 + 2440587.5; #endif #if OS_WIN FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ double now; GetSystemTimeAsFileTime( &ft ); now = ((double)ft.dwHighDateTime) * 4294967296.0; *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; #endif #ifdef SQLITE_TEST if( sqlite_current_time ){ *prNow = sqlite_current_time/86400.0 + 2440587.5; } #endif return 0; } DBD-SQLite2-0.36/util.c0000644000175000017500000007670412126353147013763 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ */ #include "sqliteInt.h" #include #include /* ** If malloc() ever fails, this global variable gets set to 1. ** This causes the library to abort and never again function. */ int sqlite_malloc_failed = 0; /* ** If MEMORY_DEBUG is defined, then use versions of malloc() and ** free() that track memory usage and check for buffer overruns. */ #ifdef MEMORY_DEBUG /* ** For keeping track of the number of mallocs and frees. This ** is used to check for memory leaks. */ int sqlite_nMalloc; /* Number of sqliteMalloc() calls */ int sqlite_nFree; /* Number of sqliteFree() calls */ int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */ #if MEMORY_DEBUG>1 static int memcnt = 0; #endif /* ** Number of 32-bit guard words */ #define N_GUARD 1 /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. */ void *sqliteMalloc_(int n, int bZero, char *zFile, int line){ void *p; int *pi; int i, k; if( sqlite_iMallocFail>=0 ){ sqlite_iMallocFail--; if( sqlite_iMallocFail==0 ){ sqlite_malloc_failed++; #if MEMORY_DEBUG>1 fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n", n, zFile,line); #endif sqlite_iMallocFail--; return 0; } } if( n==0 ) return 0; k = (n+sizeof(int)-1)/sizeof(int); pi = malloc( (N_GUARD*2+1+k)*sizeof(int)); if( pi==0 ){ sqlite_malloc_failed++; return 0; } sqlite_nMalloc++; for(i=0; i1 fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line); #endif return p; } /* ** Check to see if the given pointer was obtained from sqliteMalloc() ** and is able to hold at least N bytes. Raise an exception if this ** is not the case. ** ** This routine is used for testing purposes only. */ void sqliteCheckMemory(void *p, int N){ int *pi = p; int n, i, k; pi -= N_GUARD+1; for(i=0; i=0 && N1 fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line); #endif free(pi); } } /* ** Resize a prior allocation. If p==0, then this routine ** works just like sqliteMalloc(). If n==0, then this routine ** works just like sqliteFree(). */ void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){ int *oldPi, *pi, i, k, oldN, oldK; void *p; if( oldP==0 ){ return sqliteMalloc_(n,1,zFile,line); } if( n==0 ){ sqliteFree_(oldP,zFile,line); return 0; } oldPi = oldP; oldPi -= N_GUARD+1; if( oldPi[0]!=0xdead1122 ){ fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)oldP); return 0; } oldN = oldPi[N_GUARD]; oldK = (oldN+sizeof(int)-1)/sizeof(int); for(i=0; ioldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0, n-oldN); } memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int)); free(oldPi); #if MEMORY_DEBUG>1 fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n", ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line); #endif return p; } /* ** Make a duplicate of a string into memory obtained from malloc() ** Free the original string using sqliteFree(). ** ** This routine is called on all strings that are passed outside of ** the SQLite library. That way clients can free the string using free() ** rather than having to call sqliteFree(). */ void sqliteStrRealloc(char **pz){ char *zNew; if( pz==0 || *pz==0 ) return; zNew = malloc( strlen(*pz) + 1 ); if( zNew==0 ){ sqlite_malloc_failed++; sqliteFree(*pz); *pz = 0; } strcpy(zNew, *pz); sqliteFree(*pz); *pz = zNew; } /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqliteStrDup_(const char *z, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqliteMalloc_(strlen(z)+1, 0, zFile, line); if( zNew ) strcpy(zNew, z); return zNew; } char *sqliteStrNDup_(const char *z, int n, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqliteMalloc_(n+1, 0, zFile, line); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } #endif /* MEMORY_DEBUG */ /* ** The following versions of malloc() and free() are for use in a ** normal build. */ #if !defined(MEMORY_DEBUG) /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. See also sqliteMallocRaw(). */ void *sqliteMalloc(int n){ void *p; if( (p = malloc(n))==0 ){ if( n>0 ) sqlite_malloc_failed++; }else{ memset(p, 0, n); } return p; } /* ** Allocate new memory but do not set it to zero. Return NULL if ** no memory is available. See also sqliteMalloc(). */ void *sqliteMallocRaw(int n){ void *p; if( (p = malloc(n))==0 ){ if( n>0 ) sqlite_malloc_failed++; } return p; } /* ** Free memory previously obtained from sqliteMalloc() */ void sqliteFree(void *p){ if( p ){ free(p); } } /* ** Resize a prior allocation. If p==0, then this routine ** works just like sqliteMalloc(). If n==0, then this routine ** works just like sqliteFree(). */ void *sqliteRealloc(void *p, int n){ void *p2; if( p==0 ){ return sqliteMalloc(n); } if( n==0 ){ sqliteFree(p); return 0; } p2 = realloc(p, n); if( p2==0 ){ sqlite_malloc_failed++; } return p2; } /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqliteStrDup(const char *z){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(strlen(z)+1); if( zNew ) strcpy(zNew, z); return zNew; } char *sqliteStrNDup(const char *z, int n){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(n+1); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } #endif /* !defined(MEMORY_DEBUG) */ /* ** Create a string from the 2nd and subsequent arguments (up to the ** first NULL argument), store the string in memory obtained from ** sqliteMalloc() and make the pointer indicated by the 1st argument ** point to that string. The 1st argument must either be NULL or ** point to memory obtained from sqliteMalloc(). */ void sqliteSetString(char **pz, const char *zFirst, ...){ va_list ap; int nByte; const char *z; char *zResult; if( pz==0 ) return; nByte = strlen(zFirst) + 1; va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ nByte += strlen(z); } va_end(ap); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( nByte ); if( zResult==0 ){ return; } strcpy(zResult, zFirst); zResult += strlen(zResult); va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ strcpy(zResult, z); zResult += strlen(zResult); } va_end(ap); #ifdef MEMORY_DEBUG #if MEMORY_DEBUG>1 fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz); #endif #endif } /* ** Works like sqliteSetString, but each string is now followed by ** a length integer which specifies how much of the source string ** to copy (in bytes). -1 means use the whole string. The 1st ** argument must either be NULL or point to memory obtained from ** sqliteMalloc(). */ void sqliteSetNString(char **pz, ...){ va_list ap; int nByte; const char *z; char *zResult; int n; if( pz==0 ) return; nByte = 0; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ n = va_arg(ap, int); if( n<=0 ) n = strlen(z); nByte += n; } va_end(ap); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( nByte + 1 ); if( zResult==0 ) return; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ n = va_arg(ap, int); if( n<=0 ) n = strlen(z); strncpy(zResult, z, n); zResult += n; } *zResult = 0; #ifdef MEMORY_DEBUG #if MEMORY_DEBUG>1 fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz); #endif #endif va_end(ap); } /* ** Add an error message to pParse->zErrMsg and increment pParse->nErr. ** The following formatting characters are allowed: ** ** %s Insert a string ** %z A string that should be freed after use ** %d Insert an integer ** %T Insert a token ** %S Insert the first element of a SrcList */ void sqliteErrorMsg(Parse *pParse, const char *zFormat, ...){ va_list ap; pParse->nErr++; sqliteFree(pParse->zErrMsg); va_start(ap, zFormat); pParse->zErrMsg = sqliteVMPrintf(zFormat, ap); va_end(ap); } /* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the ** input does not begin with a quote character, then this routine ** is a no-op. ** ** 2002-Feb-14: This routine is extended to remove MS-Access style ** brackets from around identifers. For example: "[a-b-c]" becomes ** "a-b-c". */ void sqliteDequote(char *z){ int quote; int i, j; if( z==0 ) return; quote = z[0]; switch( quote ){ case '\'': break; case '"': break; case '[': quote = ']'; break; default: return; } for(i=1, j=0; z[i]; i++){ if( z[i]==quote ){ if( z[i+1]==quote ){ z[j++] = quote; i++; }else{ z[j++] = 0; break; } }else{ z[j++] = z[i]; } } } /* An array to map all upper-case characters into their corresponding ** lower-case character. */ static unsigned char UpperToLower[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107, 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, 252,253,254,255 }; /* ** This function computes a hash on the name of a keyword. ** Case is not significant. */ int sqliteHashNoCase(const char *z, int n){ int h = 0; if( n<=0 ) n = strlen(z); while( n > 0 ){ h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++]; n--; } return h & 0x7fffffff; } /* ** Some systems have stricmp(). Others have strcasecmp(). Because ** there is no consistency, we will define our own. */ int sqliteStrICmp(const char *zLeft, const char *zRight){ register unsigned char *a, *b; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } return UpperToLower[*a] - UpperToLower[*b]; } int sqliteStrNICmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; } /* ** Return TRUE if z is a pure numeric string. Return FALSE if the ** string contains any character which is not part of a number. ** ** Am empty string is considered non-numeric. */ int sqliteIsNumber(const char *z){ if( *z=='-' || *z=='+' ) z++; if( !isdigit(*z) ){ return 0; } z++; while( isdigit(*z) ){ z++; } if( *z=='.' ){ z++; if( !isdigit(*z) ) return 0; while( isdigit(*z) ){ z++; } } if( *z=='e' || *z=='E' ){ z++; if( *z=='+' || *z=='-' ) z++; if( !isdigit(*z) ) return 0; while( isdigit(*z) ){ z++; } } return *z==0; } /* ** The string z[] is an ascii representation of a real number. ** Convert this string to a double. ** ** This routine assumes that z[] really is a valid number. If it ** is not, the result is undefined. ** ** This routine is used instead of the library atof() function because ** the library atof() might want to use "," as the decimal point instead ** of "." depending on how locale is set. But that would cause problems ** for SQL. So this routine always uses "." regardless of locale. */ double sqliteAtoF(const char *z, const char **pzEnd){ int sign = 1; LONGDOUBLE_TYPE v1 = 0.0; if( *z=='-' ){ sign = -1; z++; }else if( *z=='+' ){ z++; } while( isdigit(*z) ){ v1 = v1*10.0 + (*z - '0'); z++; } if( *z=='.' ){ LONGDOUBLE_TYPE divisor = 1.0; z++; while( isdigit(*z) ){ v1 = v1*10.0 + (*z - '0'); divisor *= 10.0; z++; } v1 /= divisor; } if( *z=='e' || *z=='E' ){ int esign = 1; int eval = 0; LONGDOUBLE_TYPE scale = 1.0; z++; if( *z=='-' ){ esign = -1; z++; }else if( *z=='+' ){ z++; } while( isdigit(*z) ){ eval = eval*10 + *z - '0'; z++; } while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; } while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; } while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; } while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; } if( esign<0 ){ v1 /= scale; }else{ v1 *= scale; } } if( pzEnd ) *pzEnd = z; return sign<0 ? -v1 : v1; } /* ** The string zNum represents an integer. There might be some other ** information following the integer too, but that part is ignored. ** If the integer that the prefix of zNum represents will fit in a ** 32-bit signed integer, return TRUE. Otherwise return FALSE. ** ** This routine returns FALSE for the string -2147483648 even that ** that number will, in theory fit in a 32-bit integer. But positive ** 2147483648 will not fit in 32 bits. So it seems safer to return ** false. */ int sqliteFitsIn32Bits(const char *zNum){ int i, c; if( *zNum=='-' || *zNum=='+' ) zNum++; for(i=0; (c=zNum[i])>='0' && c<='9'; i++){} return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0); } /* This comparison routine is what we use for comparison operations ** between numeric values in an SQL expression. "Numeric" is a little ** bit misleading here. What we mean is that the strings have a ** type of "numeric" from the point of view of SQL. The strings ** do not necessarily contain numbers. They could contain text. ** ** If the input strings both look like actual numbers then they ** compare in numerical order. Numerical strings are always less ** than non-numeric strings so if one input string looks like a ** number and the other does not, then the one that looks like ** a number is the smaller. Non-numeric strings compare in ** lexigraphical order (the same order as strcmp()). */ int sqliteCompare(const char *atext, const char *btext){ int result; int isNumA, isNumB; if( atext==0 ){ return -1; }else if( btext==0 ){ return 1; } isNumA = sqliteIsNumber(atext); isNumB = sqliteIsNumber(btext); if( isNumA ){ if( !isNumB ){ result = -1; }else{ double rA, rB; rA = sqliteAtoF(atext, 0); rB = sqliteAtoF(btext, 0); if( rArB ){ result = +1; }else{ result = 0; } } }else if( isNumB ){ result = +1; }else { result = strcmp(atext, btext); } return result; } /* ** This routine is used for sorting. Each key is a list of one or more ** null-terminated elements. The list is terminated by two nulls in ** a row. For example, the following text is a key with three elements ** ** Aone\000Dtwo\000Athree\000\000 ** ** All elements begin with one of the characters "+-AD" and end with "\000" ** with zero or more text elements in between. Except, NULL elements ** consist of the special two-character sequence "N\000". ** ** Both arguments will have the same number of elements. This routine ** returns negative, zero, or positive if the first argument is less ** than, equal to, or greater than the first. (Result is a-b). ** ** Each element begins with one of the characters "+", "-", "A", "D". ** This character determines the sort order and collating sequence: ** ** + Sort numerically in ascending order ** - Sort numerically in descending order ** A Sort as strings in ascending order ** D Sort as strings in descending order. ** ** For the "+" and "-" sorting, pure numeric strings (strings for which the ** isNum() function above returns TRUE) always compare less than strings ** that are not pure numerics. Non-numeric strings compare in memcmp() ** order. This is the same sort order as the sqliteCompare() function ** above generates. ** ** The last point is a change from version 2.6.3 to version 2.7.0. In ** version 2.6.3 and earlier, substrings of digits compare in numerical ** and case was used only to break a tie. ** ** Elements that begin with 'A' or 'D' compare in memcmp() order regardless ** of whether or not they look like a number. ** ** Note that the sort order imposed by the rules above is the same ** from the ordering defined by the "<", "<=", ">", and ">=" operators ** of expressions and for indices. This was not the case for version ** 2.6.3 and earlier. */ int sqliteSortCompare(const char *a, const char *b){ int res = 0; int isNumA, isNumB; int dir = 0; while( res==0 && *a && *b ){ if( a[0]=='N' || b[0]=='N' ){ if( a[0]==b[0] ){ a += 2; b += 2; continue; } if( a[0]=='N' ){ dir = b[0]; res = -1; }else{ dir = a[0]; res = +1; } break; } assert( a[0]==b[0] ); if( (dir=a[0])=='A' || a[0]=='D' ){ res = strcmp(&a[1],&b[1]); if( res ) break; }else{ isNumA = sqliteIsNumber(&a[1]); isNumB = sqliteIsNumber(&b[1]); if( isNumA ){ double rA, rB; if( !isNumB ){ res = -1; break; } rA = sqliteAtoF(&a[1], 0); rB = sqliteAtoF(&b[1], 0); if( rArB ){ res = +1; break; } }else if( isNumB ){ res = +1; break; }else{ res = strcmp(&a[1],&b[1]); if( res ) break; } } a += strlen(&a[1]) + 2; b += strlen(&b[1]) + 2; } if( dir=='-' || dir=='D' ) res = -res; return res; } /* ** Some powers of 64. These constants are needed in the ** sqliteRealToSortable() routine below. */ #define _64e3 (64.0 * 64.0 * 64.0) #define _64e4 (64.0 * 64.0 * 64.0 * 64.0) #define _64e15 (_64e3 * _64e4 * _64e4 * _64e4) #define _64e16 (_64e4 * _64e4 * _64e4 * _64e4) #define _64e63 (_64e15 * _64e16 * _64e16 * _64e16) #define _64e64 (_64e16 * _64e16 * _64e16 * _64e16) /* ** The following procedure converts a double-precision floating point ** number into a string. The resulting string has the property that ** two such strings comparied using strcmp() or memcmp() will give the ** same results as a numeric comparison of the original floating point ** numbers. ** ** This routine is used to generate database keys from floating point ** numbers such that the keys sort in the same order as the original ** floating point numbers even though the keys are compared using ** memcmp(). ** ** The calling function should have allocated at least 14 characters ** of space for the buffer z[]. */ void sqliteRealToSortable(double r, char *z){ int neg; int exp; int cnt = 0; /* This array maps integers between 0 and 63 into base-64 digits. ** The digits must be chosen such at their ASCII codes are increasing. ** This means we can not use the traditional base-64 digit set. */ static const char zDigit[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "|~"; if( r<0.0 ){ neg = 1; r = -r; *z++ = '-'; } else { neg = 0; *z++ = '0'; } exp = 0; if( r==0.0 ){ exp = -1024; }else if( r<(0.5/64.0) ){ while( r < 0.5/_64e64 && exp > -961 ){ r *= _64e64; exp -= 64; } while( r < 0.5/_64e16 && exp > -1009 ){ r *= _64e16; exp -= 16; } while( r < 0.5/_64e4 && exp > -1021 ){ r *= _64e4; exp -= 4; } while( r < 0.5/64.0 && exp > -1024 ){ r *= 64.0; exp -= 1; } }else if( r>=0.5 ){ while( r >= 0.5*_64e63 && exp < 960 ){ r *= 1.0/_64e64; exp += 64; } while( r >= 0.5*_64e15 && exp < 1008 ){ r *= 1.0/_64e16; exp += 16; } while( r >= 0.5*_64e3 && exp < 1020 ){ r *= 1.0/_64e4; exp += 4; } while( r >= 0.5 && exp < 1023 ){ r *= 1.0/64.0; exp += 1; } } if( neg ){ exp = -exp; r = -r; } exp += 1024; r += 0.5; if( exp<0 ) return; if( exp>=2048 || r>=1.0 ){ strcpy(z, "~~~~~~~~~~~~"); return; } *z++ = zDigit[(exp>>6)&0x3f]; *z++ = zDigit[exp & 0x3f]; while( r>0.0 && cnt<10 ){ int digit; r *= 64.0; digit = (int)r; assert( digit>=0 && digit<64 ); *z++ = zDigit[digit & 0x3f]; r -= digit; cnt++; } *z = 0; } #ifdef SQLITE_UTF8 /* ** X is a pointer to the first byte of a UTF-8 character. Increment ** X so that it points to the next character. This only works right ** if X points to a well-formed UTF-8 string. */ #define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){} #define sqliteCharVal(X) sqlite_utf8_to_int(X) #else /* !defined(SQLITE_UTF8) */ /* ** For iso8859 encoding, the next character is just the next byte. */ #define sqliteNextChar(X) (++(X)); #define sqliteCharVal(X) ((int)*(X)) #endif /* defined(SQLITE_UTF8) */ #ifdef SQLITE_UTF8 /* ** Convert the UTF-8 character to which z points into a 31-bit ** UCS character. This only works right if z points to a well-formed ** UTF-8 string. */ static int sqlite_utf8_to_int(const unsigned char *z){ int c; static const int initVal[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 254, 255, }; c = initVal[*(z++)]; while( (0xc0&*z)==0x80 ){ c = (c<<6) | (0x3f&*(z++)); } return c; } #endif /* ** Compare two UTF-8 strings for equality where the first string can ** potentially be a "glob" expression. Return true (1) if they ** are the same and false (0) if they are different. ** ** Globbing rules: ** ** '*' Matches any sequence of zero or more characters. ** ** '?' Matches exactly one character. ** ** [...] Matches one character from the enclosed list of ** characters. ** ** [^...] Matches one character not in the enclosed list. ** ** With the [...] and [^...] matching, a ']' character can be included ** in the list by making it the first character after '[' or '^'. A ** range of characters can be specified using '-'. Example: ** "[a-z]" matches any single lower-case letter. To match a '-', make ** it the last character in the list. ** ** This routine is usually quick, but can be N**2 in the worst case. ** ** Hints: to match '*' or '?', put them in "[]". Like this: ** ** abc[*]xyz Matches "abc*xyz" only */ int sqliteGlobCompare(const unsigned char *zPattern, const unsigned char *zString){ register int c; int invert; int seen; int c2; while( (c = *zPattern)!=0 ){ switch( c ){ case '*': while( (c=zPattern[1]) == '*' || c == '?' ){ if( c=='?' ){ if( *zString==0 ) return 0; sqliteNextChar(zString); } zPattern++; } if( c==0 ) return 1; if( c=='[' ){ while( *zString && sqliteGlobCompare(&zPattern[1],zString)==0 ){ sqliteNextChar(zString); } return *zString!=0; }else{ while( (c2 = *zString)!=0 ){ while( c2 != 0 && c2 != c ){ c2 = *++zString; } if( c2==0 ) return 0; if( sqliteGlobCompare(&zPattern[1],zString) ) return 1; sqliteNextChar(zString); } return 0; } case '?': { if( *zString==0 ) return 0; sqliteNextChar(zString); zPattern++; break; } case '[': { int prior_c = 0; seen = 0; invert = 0; c = sqliteCharVal(zString); if( c==0 ) return 0; c2 = *++zPattern; if( c2=='^' ){ invert = 1; c2 = *++zPattern; } if( c2==']' ){ if( c==']' ) seen = 1; c2 = *++zPattern; } while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){ if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){ zPattern++; c2 = sqliteCharVal(zPattern); if( c>=prior_c && c<=c2 ) seen = 1; prior_c = 0; }else if( c==c2 ){ seen = 1; prior_c = c2; }else{ prior_c = c2; } sqliteNextChar(zPattern); } if( c2==0 || (seen ^ invert)==0 ) return 0; sqliteNextChar(zString); zPattern++; break; } default: { if( c != *zString ) return 0; zPattern++; zString++; break; } } } return *zString==0; } /* ** Compare two UTF-8 strings for equality using the "LIKE" operator of ** SQL. The '%' character matches any sequence of 0 or more ** characters and '_' matches any single character. Case is ** not significant. ** ** This routine is just an adaptation of the sqliteGlobCompare() ** routine above. */ int sqliteLikeCompare(const unsigned char *zPattern, const unsigned char *zString){ register int c; int c2; while( (c = UpperToLower[*zPattern])!=0 ){ switch( c ){ case '%': { while( (c=zPattern[1]) == '%' || c == '_' ){ if( c=='_' ){ if( *zString==0 ) return 0; sqliteNextChar(zString); } zPattern++; } if( c==0 ) return 1; c = UpperToLower[c]; while( (c2=UpperToLower[*zString])!=0 ){ while( c2 != 0 && c2 != c ){ c2 = UpperToLower[*++zString]; } if( c2==0 ) return 0; if( sqliteLikeCompare(&zPattern[1],zString) ) return 1; sqliteNextChar(zString); } return 0; } case '_': { if( *zString==0 ) return 0; sqliteNextChar(zString); zPattern++; break; } default: { if( c != UpperToLower[*zString] ) return 0; zPattern++; zString++; break; } } } return *zString==0; } /* ** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY. ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN ** when this routine is called. ** ** This routine is a attempt to detect if two threads use the ** same sqlite* pointer at the same time. There is a race ** condition so it is possible that the error is not detected. ** But usually the problem will be seen. The result will be an ** error which can be used to debug the application that is ** using SQLite incorrectly. ** ** Ticket #202: If db->magic is not a valid open value, take care not ** to modify the db structure at all. It could be that db is a stale ** pointer. In other words, it could be that there has been a prior ** call to sqlite_close(db) and db has been deallocated. And we do ** not want to write into deallocated memory. */ int sqliteSafetyOn(sqlite *db){ if( db->magic==SQLITE_MAGIC_OPEN ){ db->magic = SQLITE_MAGIC_BUSY; return 0; }else if( db->magic==SQLITE_MAGIC_BUSY || db->magic==SQLITE_MAGIC_ERROR || db->want_to_close ){ db->magic = SQLITE_MAGIC_ERROR; db->flags |= SQLITE_Interrupt; } return 1; } /* ** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN. ** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY ** when this routine is called. */ int sqliteSafetyOff(sqlite *db){ if( db->magic==SQLITE_MAGIC_BUSY ){ db->magic = SQLITE_MAGIC_OPEN; return 0; }else if( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ERROR || db->want_to_close ){ db->magic = SQLITE_MAGIC_ERROR; db->flags |= SQLITE_Interrupt; } return 1; } /* ** Check to make sure we are not currently executing an sqlite_exec(). ** If we are currently in an sqlite_exec(), return true and set ** sqlite.magic to SQLITE_MAGIC_ERROR. This will cause a complete ** shutdown of the database. ** ** This routine is used to try to detect when API routines are called ** at the wrong time or in the wrong sequence. */ int sqliteSafetyCheck(sqlite *db){ if( db->pVdbe!=0 ){ db->magic = SQLITE_MAGIC_ERROR; return 1; } return 0; } DBD-SQLite2-0.36/sqlite.h0000644000175000017500000011274612126353147014311 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus extern "C" { #endif /* ** The version of the SQLite library. */ #define SQLITE_VERSION "2.8.15" /* ** The version string is also compiled into the library so that a program ** can check to make sure that the lib*.a file and the *.h file are from ** the same version. */ extern const char sqlite_version[]; /* ** The SQLITE_UTF8 macro is defined if the library expects to see ** UTF-8 encoded data. The SQLITE_ISO8859 macro is defined if the ** iso8859 encoded should be used. */ #define SQLITE_UTF8 1 /* ** The following constant holds one of two strings, "UTF-8" or "iso8859", ** depending on which character encoding the SQLite library expects to ** see. The character encoding makes a difference for the LIKE and GLOB ** operators and for the LENGTH() and SUBSTR() functions. */ extern const char sqlite_encoding[]; /* ** Each open sqlite database is represented by an instance of the ** following opaque structure. */ typedef struct sqlite sqlite; /* ** A function to open a new sqlite database. ** ** If the database does not exist and mode indicates write ** permission, then a new database is created. If the database ** does not exist and mode does not indicate write permission, ** then the open fails, an error message generated (if errmsg!=0) ** and the function returns 0. ** ** If mode does not indicates user write permission, then the ** database is opened read-only. ** ** The Truth: As currently implemented, all databases are opened ** for writing all the time. Maybe someday we will provide the ** ability to open a database readonly. The mode parameters is ** provided in anticipation of that enhancement. */ sqlite *sqlite_open(const char *filename, int mode, char **errmsg); /* ** A function to close the database. ** ** Call this function with a pointer to a structure that was previously ** returned from sqlite_open() and the corresponding database will by closed. */ void sqlite_close(sqlite *); /* ** The type for a callback function. */ typedef int (*sqlite_callback)(void*,int,char**, char**); /* ** A function to executes one or more statements of SQL. ** ** If one or more of the SQL statements are queries, then ** the callback function specified by the 3rd parameter is ** invoked once for each row of the query result. This callback ** should normally return 0. If the callback returns a non-zero ** value then the query is aborted, all subsequent SQL statements ** are skipped and the sqlite_exec() function returns the SQLITE_ABORT. ** ** The 4th parameter is an arbitrary pointer that is passed ** to the callback function as its first parameter. ** ** The 2nd parameter to the callback function is the number of ** columns in the query result. The 3rd parameter to the callback ** is an array of strings holding the values for each column. ** The 4th parameter to the callback is an array of strings holding ** the names of each column. ** ** The callback function may be NULL, even for queries. A NULL ** callback is not an error. It just means that no callback ** will be invoked. ** ** If an error occurs while parsing or evaluating the SQL (but ** not while executing the callback) then an appropriate error ** message is written into memory obtained from malloc() and ** *errmsg is made to point to that message. The calling function ** is responsible for freeing the memory that holds the error ** message. Use sqlite_freemem() for this. If errmsg==NULL, ** then no error message is ever written. ** ** The return value is is SQLITE_OK if there are no errors and ** some other return code if there is an error. The particular ** return value depends on the type of error. ** ** If the query could not be executed because a database file is ** locked or busy, then this function returns SQLITE_BUSY. (This ** behavior can be modified somewhat using the sqlite_busy_handler() ** and sqlite_busy_timeout() functions below.) */ int sqlite_exec( sqlite*, /* An open database */ const char *sql, /* SQL to be executed */ sqlite_callback, /* Callback function */ void *, /* 1st argument to callback function */ char **errmsg /* Error msg written here */ ); /* ** Return values for sqlite_exec() and sqlite_step() */ #define SQLITE_OK 0 /* Successful result */ #define SQLITE_ERROR 1 /* SQL error or missing database */ #define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */ #define SQLITE_PERM 3 /* Access permission denied */ #define SQLITE_ABORT 4 /* Callback routine requested an abort */ #define SQLITE_BUSY 5 /* The database file is locked */ #define SQLITE_LOCKED 6 /* A table in the database is locked */ #define SQLITE_NOMEM 7 /* A malloc() failed */ #define SQLITE_READONLY 8 /* Attempt to write a readonly database */ #define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */ #define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ #define SQLITE_CORRUPT 11 /* The database disk image is malformed */ #define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */ #define SQLITE_FULL 13 /* Insertion failed because database is full */ #define SQLITE_CANTOPEN 14 /* Unable to open the database file */ #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ #define SQLITE_ROW 100 /* sqlite_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite_step() has finished executing */ /* ** Each entry in an SQLite table has a unique integer key. (The key is ** the value of the INTEGER PRIMARY KEY column if there is such a column, ** otherwise the key is generated at random. The unique key is always ** available as the ROWID, OID, or _ROWID_ column.) The following routine ** returns the integer key of the most recent insert in the database. ** ** This function is similar to the mysql_insert_id() function from MySQL. */ int sqlite_last_insert_rowid(sqlite*); /* ** This function returns the number of database rows that were changed ** (or inserted or deleted) by the most recent called sqlite_exec(). ** ** All changes are counted, even if they were later undone by a ** ROLLBACK or ABORT. Except, changes associated with creating and ** dropping tables are not counted. ** ** If a callback invokes sqlite_exec() recursively, then the changes ** in the inner, recursive call are counted together with the changes ** in the outer call. ** ** SQLite implements the command "DELETE FROM table" without a WHERE clause ** by dropping and recreating the table. (This is much faster than going ** through and deleting individual elements form the table.) Because of ** this optimization, the change count for "DELETE FROM table" will be ** zero regardless of the number of elements that were originally in the ** table. To get an accurate count of the number of rows deleted, use ** "DELETE FROM table WHERE 1" instead. */ int sqlite_changes(sqlite*); /* ** This function returns the number of database rows that were changed ** by the last INSERT, UPDATE, or DELETE statment executed by sqlite_exec(), ** or by the last VM to run to completion. The change count is not updated ** by SQL statements other than INSERT, UPDATE or DELETE. ** ** Changes are counted, even if they are later undone by a ROLLBACK or ** ABORT. Changes associated with trigger programs that execute as a ** result of the INSERT, UPDATE, or DELETE statement are not counted. ** ** If a callback invokes sqlite_exec() recursively, then the changes ** in the inner, recursive call are counted together with the changes ** in the outer call. ** ** SQLite implements the command "DELETE FROM table" without a WHERE clause ** by dropping and recreating the table. (This is much faster than going ** through and deleting individual elements form the table.) Because of ** this optimization, the change count for "DELETE FROM table" will be ** zero regardless of the number of elements that were originally in the ** table. To get an accurate count of the number of rows deleted, use ** "DELETE FROM table WHERE 1" instead. ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ int sqlite_last_statement_changes(sqlite*); /* If the parameter to this routine is one of the return value constants ** defined above, then this routine returns a constant text string which ** descripts (in English) the meaning of the return value. */ const char *sqlite_error_string(int); #define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */ /* This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically ** called in response to a user action such as pressing "Cancel" ** or Ctrl-C where the user wants a long query operation to halt ** immediately. */ void sqlite_interrupt(sqlite*); /* This function returns true if the given input string comprises ** one or more complete SQL statements. ** ** The algorithm is simple. If the last token other than spaces ** and comments is a semicolon, then return true. otherwise return ** false. */ int sqlite_complete(const char *sql); /* ** This routine identifies a callback function that is invoked ** whenever an attempt is made to open a database table that is ** currently locked by another process or thread. If the busy callback ** is NULL, then sqlite_exec() returns SQLITE_BUSY immediately if ** it finds a locked table. If the busy callback is not NULL, then ** sqlite_exec() invokes the callback with three arguments. The ** second argument is the name of the locked table and the third ** argument is the number of times the table has been busy. If the ** busy callback returns 0, then sqlite_exec() immediately returns ** SQLITE_BUSY. If the callback returns non-zero, then sqlite_exec() ** tries to open the table again and the cycle repeats. ** ** The default busy callback is NULL. ** ** Sqlite is re-entrant, so the busy handler may start a new query. ** (It is not clear why anyone would every want to do this, but it ** is allowed, in theory.) But the busy handler may not close the ** database. Closing the database from a busy handler will delete ** data structures out from under the executing query and will ** probably result in a coredump. */ void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*); /* ** This routine sets a busy handler that sleeps for a while when a ** table is locked. The handler will sleep multiple times until ** at least "ms" milleseconds of sleeping have been done. After ** "ms" milleseconds of sleeping, the handler returns 0 which ** causes sqlite_exec() to return SQLITE_BUSY. ** ** Calling this routine with an argument less than or equal to zero ** turns off all busy handlers. */ void sqlite_busy_timeout(sqlite*, int ms); /* ** This next routine is really just a wrapper around sqlite_exec(). ** Instead of invoking a user-supplied callback for each row of the ** result, this routine remembers each row of the result in memory ** obtained from malloc(), then returns all of the result after the ** query has finished. ** ** As an example, suppose the query result where this table: ** ** Name | Age ** ----------------------- ** Alice | 43 ** Bob | 28 ** Cindy | 21 ** ** If the 3rd argument were &azResult then after the function returns ** azResult will contain the following data: ** ** azResult[0] = "Name"; ** azResult[1] = "Age"; ** azResult[2] = "Alice"; ** azResult[3] = "43"; ** azResult[4] = "Bob"; ** azResult[5] = "28"; ** azResult[6] = "Cindy"; ** azResult[7] = "21"; ** ** Notice that there is an extra row of data containing the column ** headers. But the *nrow return value is still 3. *ncolumn is ** set to 2. In general, the number of values inserted into azResult ** will be ((*nrow) + 1)*(*ncolumn). ** ** After the calling function has finished using the result, it should ** pass the result data pointer to sqlite_free_table() in order to ** release the memory that was malloc-ed. Because of the way the ** malloc() happens, the calling function must not try to call ** malloc() directly. Only sqlite_free_table() is able to release ** the memory properly and safely. ** ** The return value of this routine is the same as from sqlite_exec(). */ int sqlite_get_table( sqlite*, /* An open database */ const char *sql, /* SQL to be executed */ char ***resultp, /* Result written to a char *[] that this points to */ int *nrow, /* Number of result rows written here */ int *ncolumn, /* Number of result columns written here */ char **errmsg /* Error msg written here */ ); /* ** Call this routine to free the memory that sqlite_get_table() allocated. */ void sqlite_free_table(char **result); /* ** The following routines are wrappers around sqlite_exec() and ** sqlite_get_table(). The only difference between the routines that ** follow and the originals is that the second argument to the ** routines that follow is really a printf()-style format ** string describing the SQL to be executed. Arguments to the format ** string appear at the end of the argument list. ** ** All of the usual printf formatting options apply. In addition, there ** is a "%q" option. %q works like %s in that it substitutes a null-terminated ** string from the argument list. But %q also doubles every '\'' character. ** %q is designed for use inside a string literal. By doubling each '\'' ** character it escapes that character and allows it to be inserted into ** the string. ** ** For example, so some string variable contains text as follows: ** ** char *zText = "It's a happy day!"; ** ** We can use this text in an SQL statement as follows: ** ** sqlite_exec_printf(db, "INSERT INTO table VALUES('%q')", ** callback1, 0, 0, zText); ** ** Because the %q format string is used, the '\'' character in zText ** is escaped and the SQL generated is as follows: ** ** INSERT INTO table1 VALUES('It''s a happy day!') ** ** This is correct. Had we used %s instead of %q, the generated SQL ** would have looked like this: ** ** INSERT INTO table1 VALUES('It's a happy day!'); ** ** This second example is an SQL syntax error. As a general rule you ** should always use %q instead of %s when inserting text into a string ** literal. */ int sqlite_exec_printf( sqlite*, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ sqlite_callback, /* Callback function */ void *, /* 1st argument to callback function */ char **errmsg, /* Error msg written here */ ... /* Arguments to the format string. */ ); int sqlite_exec_vprintf( sqlite*, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ sqlite_callback, /* Callback function */ void *, /* 1st argument to callback function */ char **errmsg, /* Error msg written here */ va_list ap /* Arguments to the format string. */ ); int sqlite_get_table_printf( sqlite*, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ char ***resultp, /* Result written to a char *[] that this points to */ int *nrow, /* Number of result rows written here */ int *ncolumn, /* Number of result columns written here */ char **errmsg, /* Error msg written here */ ... /* Arguments to the format string */ ); int sqlite_get_table_vprintf( sqlite*, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ char ***resultp, /* Result written to a char *[] that this points to */ int *nrow, /* Number of result rows written here */ int *ncolumn, /* Number of result columns written here */ char **errmsg, /* Error msg written here */ va_list ap /* Arguments to the format string */ ); char *sqlite_mprintf(const char*,...); char *sqlite_vmprintf(const char*, va_list); /* ** Windows systems should call this routine to free memory that ** is returned in the in the errmsg parameter of sqlite_open() when ** SQLite is a DLL. For some reason, it does not work to call free() ** directly. */ void sqlite_freemem(void *p); /* ** Windows systems need functions to call to return the sqlite_version ** and sqlite_encoding strings. */ const char *sqlite_libversion(void); const char *sqlite_libencoding(void); /* ** A pointer to the following structure is used to communicate with ** the implementations of user-defined functions. */ typedef struct sqlite_func sqlite_func; /* ** Use the following routines to create new user-defined functions. See ** the documentation for details. */ int sqlite_create_function( sqlite*, /* Database where the new function is registered */ const char *zName, /* Name of the new function */ int nArg, /* Number of arguments. -1 means any number */ void (*xFunc)(sqlite_func*,int,const char**), /* C code to implement */ void *pUserData /* Available via the sqlite_user_data() call */ ); int sqlite_create_aggregate( sqlite*, /* Database where the new function is registered */ const char *zName, /* Name of the function */ int nArg, /* Number of arguments */ void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */ void (*xFinalize)(sqlite_func*), /* Called once to get final result */ void *pUserData /* Available via the sqlite_user_data() call */ ); /* ** Use the following routine to define the datatype returned by a ** user-defined function. The second argument can be one of the ** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it ** can be an integer greater than or equal to zero. When the datatype ** parameter is non-negative, the type of the result will be the ** same as the datatype-th argument. If datatype==SQLITE_NUMERIC ** then the result is always numeric. If datatype==SQLITE_TEXT then ** the result is always text. If datatype==SQLITE_ARGS then the result ** is numeric if any argument is numeric and is text otherwise. */ int sqlite_function_type( sqlite *db, /* The database there the function is registered */ const char *zName, /* Name of the function */ int datatype /* The datatype for this function */ ); #define SQLITE_NUMERIC (-1) #define SQLITE_TEXT (-2) #define SQLITE_ARGS (-3) /* ** The user function implementations call one of the following four routines ** in order to return their results. The first parameter to each of these ** routines is a copy of the first argument to xFunc() or xFinialize(). ** The second parameter to these routines is the result to be returned. ** A NULL can be passed as the second parameter to sqlite_set_result_string() ** in order to return a NULL result. ** ** The 3rd argument to _string and _error is the number of characters to ** take from the string. If this argument is negative, then all characters ** up to and including the first '\000' are used. ** ** The sqlite_set_result_string() function allocates a buffer to hold the ** result and returns a pointer to this buffer. The calling routine ** (that is, the implmentation of a user function) can alter the content ** of this buffer if desired. */ char *sqlite_set_result_string(sqlite_func*,const char*,int); void sqlite_set_result_int(sqlite_func*,int); void sqlite_set_result_double(sqlite_func*,double); void sqlite_set_result_error(sqlite_func*,const char*,int); /* ** The pUserData parameter to the sqlite_create_function() and ** sqlite_create_aggregate() routines used to register user functions ** is available to the implementation of the function using this ** call. */ void *sqlite_user_data(sqlite_func*); /* ** Aggregate functions use the following routine to allocate ** a structure for storing their state. The first time this routine ** is called for a particular aggregate, a new structure of size nBytes ** is allocated, zeroed, and returned. On subsequent calls (for the ** same aggregate instance) the same buffer is returned. The implementation ** of the aggregate can use the returned buffer to accumulate data. ** ** The buffer allocated is freed automatically be SQLite. */ void *sqlite_aggregate_context(sqlite_func*, int nBytes); /* ** The next routine returns the number of calls to xStep for a particular ** aggregate function instance. The current call to xStep counts so this ** routine always returns at least 1. */ int sqlite_aggregate_count(sqlite_func*); /* ** This routine registers a callback with the SQLite library. The ** callback is invoked (at compile-time, not at run-time) for each ** attempt to access a column of a table in the database. The callback ** returns SQLITE_OK if access is allowed, SQLITE_DENY if the entire ** SQL statement should be aborted with an error and SQLITE_IGNORE ** if the column should be treated as a NULL value. */ int sqlite_set_authorizer( sqlite*, int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), void *pUserData ); /* ** The second parameter to the access authorization function above will ** be one of the values below. These values signify what kind of operation ** is to be authorized. The 3rd and 4th parameters to the authorization ** function will be parameters or NULL depending on which of the following ** codes is used as the second parameter. The 5th parameter is the name ** of the database ("main", "temp", etc.) if applicable. The 6th parameter ** is the name of the inner-most trigger or view that is responsible for ** the access attempt or NULL if this access attempt is directly from ** input SQL code. ** ** Arg-3 Arg-4 */ #define SQLITE_COPY 0 /* Table Name File Name */ #define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ #define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ #define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ #define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ #define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ #define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ #define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ #define SQLITE_CREATE_VIEW 8 /* View Name NULL */ #define SQLITE_DELETE 9 /* Table Name NULL */ #define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ #define SQLITE_DROP_TABLE 11 /* Table Name NULL */ #define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ #define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ #define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ #define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ #define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ #define SQLITE_DROP_VIEW 17 /* View Name NULL */ #define SQLITE_INSERT 18 /* Table Name NULL */ #define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ #define SQLITE_READ 20 /* Table Name Column Name */ #define SQLITE_SELECT 21 /* NULL NULL */ #define SQLITE_TRANSACTION 22 /* NULL NULL */ #define SQLITE_UPDATE 23 /* Table Name Column Name */ #define SQLITE_ATTACH 24 /* Filename NULL */ #define SQLITE_DETACH 25 /* Database Name NULL */ /* ** The return value of the authorization function should be one of the ** following constants: */ /* #define SQLITE_OK 0 // Allow access (This is actually defined above) */ #define SQLITE_DENY 1 /* Abort the SQL statement with an error */ #define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ /* ** Register a function that is called at every invocation of sqlite_exec() ** or sqlite_compile(). This function can be used (for example) to generate ** a log file of all SQL executed against a database. */ void *sqlite_trace(sqlite*, void(*xTrace)(void*,const char*), void*); /*** The Callback-Free API ** ** The following routines implement a new way to access SQLite that does not ** involve the use of callbacks. ** ** An sqlite_vm is an opaque object that represents a single SQL statement ** that is ready to be executed. */ typedef struct sqlite_vm sqlite_vm; /* ** To execute an SQLite query without the use of callbacks, you first have ** to compile the SQL using this routine. The 1st parameter "db" is a pointer ** to an sqlite object obtained from sqlite_open(). The 2nd parameter ** "zSql" is the text of the SQL to be compiled. The remaining parameters ** are all outputs. ** ** *pzTail is made to point to the first character past the end of the first ** SQL statement in zSql. This routine only compiles the first statement ** in zSql, so *pzTail is left pointing to what remains uncompiled. ** ** *ppVm is left pointing to a "virtual machine" that can be used to execute ** the compiled statement. Or if there is an error, *ppVm may be set to NULL. ** If the input text contained no SQL (if the input is and empty string or ** a comment) then *ppVm is set to NULL. ** ** If any errors are detected during compilation, an error message is written ** into space obtained from malloc() and *pzErrMsg is made to point to that ** error message. The calling routine is responsible for freeing the text ** of this message when it has finished with it. Use sqlite_freemem() to ** free the message. pzErrMsg may be NULL in which case no error message ** will be generated. ** ** On success, SQLITE_OK is returned. Otherwise and error code is returned. */ int sqlite_compile( sqlite *db, /* The open database */ const char *zSql, /* SQL statement to be compiled */ const char **pzTail, /* OUT: uncompiled tail of zSql */ sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */ char **pzErrmsg /* OUT: Error message. */ ); /* ** After an SQL statement has been compiled, it is handed to this routine ** to be executed. This routine executes the statement as far as it can ** go then returns. The return value will be one of SQLITE_DONE, ** SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, or SQLITE_MISUSE. ** ** SQLITE_DONE means that the execute of the SQL statement is complete ** an no errors have occurred. sqlite_step() should not be called again ** for the same virtual machine. *pN is set to the number of columns in ** the result set and *pazColName is set to an array of strings that ** describe the column names and datatypes. The name of the i-th column ** is (*pazColName)[i] and the datatype of the i-th column is ** (*pazColName)[i+*pN]. *pazValue is set to NULL. ** ** SQLITE_ERROR means that the virtual machine encountered a run-time ** error. sqlite_step() should not be called again for the same ** virtual machine. *pN is set to 0 and *pazColName and *pazValue are set ** to NULL. Use sqlite_finalize() to obtain the specific error code ** and the error message text for the error. ** ** SQLITE_BUSY means that an attempt to open the database failed because ** another thread or process is holding a lock. The calling routine ** can try again to open the database by calling sqlite_step() again. ** The return code will only be SQLITE_BUSY if no busy handler is registered ** using the sqlite_busy_handler() or sqlite_busy_timeout() routines. If ** a busy handler callback has been registered but returns 0, then this ** routine will return SQLITE_ERROR and sqltie_finalize() will return ** SQLITE_BUSY when it is called. ** ** SQLITE_ROW means that a single row of the result is now available. ** The data is contained in *pazValue. The value of the i-th column is ** (*azValue)[i]. *pN and *pazColName are set as described in SQLITE_DONE. ** Invoke sqlite_step() again to advance to the next row. ** ** SQLITE_MISUSE is returned if sqlite_step() is called incorrectly. ** For example, if you call sqlite_step() after the virtual machine ** has halted (after a prior call to sqlite_step() has returned SQLITE_DONE) ** or if you call sqlite_step() with an incorrectly initialized virtual ** machine or a virtual machine that has been deleted or that is associated ** with an sqlite structure that has been closed. */ int sqlite_step( sqlite_vm *pVm, /* The virtual machine to execute */ int *pN, /* OUT: Number of columns in result */ const char ***pazValue, /* OUT: Column data */ const char ***pazColName /* OUT: Column names and datatypes */ ); /* ** This routine is called to delete a virtual machine after it has finished ** executing. The return value is the result code. SQLITE_OK is returned ** if the statement executed successfully and some other value is returned if ** there was any kind of error. If an error occurred and pzErrMsg is not ** NULL, then an error message is written into memory obtained from malloc() ** and *pzErrMsg is made to point to that error message. The calling routine ** should use sqlite_freemem() to delete this message when it has finished ** with it. ** ** This routine can be called at any point during the execution of the ** virtual machine. If the virtual machine has not completed execution ** when this routine is called, that is like encountering an error or ** an interrupt. (See sqlite_interrupt().) Incomplete updates may be ** rolled back and transactions cancelled, depending on the circumstances, ** and the result code returned will be SQLITE_ABORT. */ int sqlite_finalize(sqlite_vm*, char **pzErrMsg); /* ** This routine deletes the virtual machine, writes any error message to ** *pzErrMsg and returns an SQLite return code in the same way as the ** sqlite_finalize() function. ** ** Additionally, if ppVm is not NULL, *ppVm is left pointing to a new virtual ** machine loaded with the compiled version of the original query ready for ** execution. ** ** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL. ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ int sqlite_reset(sqlite_vm*, char **pzErrMsg); /* ** If the SQL that was handed to sqlite_compile contains variables that ** are represeted in the SQL text by a question mark ('?'). This routine ** is used to assign values to those variables. ** ** The first parameter is a virtual machine obtained from sqlite_compile(). ** The 2nd "idx" parameter determines which variable in the SQL statement ** to bind the value to. The left most '?' is 1. The 3rd parameter is ** the value to assign to that variable. The 4th parameter is the number ** of bytes in the value, including the terminating \000 for strings. ** Finally, the 5th "copy" parameter is TRUE if SQLite should make its ** own private copy of this value, or false if the space that the 3rd ** parameter points to will be unchanging and can be used directly by ** SQLite. ** ** Unbound variables are treated as having a value of NULL. To explicitly ** set a variable to NULL, call this routine with the 3rd parameter as a ** NULL pointer. ** ** If the 4th "len" parameter is -1, then strlen() is used to find the ** length. ** ** This routine can only be called immediately after sqlite_compile() ** or sqlite_reset() and before any calls to sqlite_step(). ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ int sqlite_bind(sqlite_vm*, int idx, const char *value, int len, int copy); /* ** This routine configures a callback function - the progress callback - that ** is invoked periodically during long running calls to sqlite_exec(), ** sqlite_step() and sqlite_get_table(). An example use for this API is to keep ** a GUI updated during a large query. ** ** The progress callback is invoked once for every N virtual machine opcodes, ** where N is the second argument to this function. The progress callback ** itself is identified by the third argument to this function. The fourth ** argument to this function is a void pointer passed to the progress callback ** function each time it is invoked. ** ** If a call to sqlite_exec(), sqlite_step() or sqlite_get_table() results ** in less than N opcodes being executed, then the progress callback is not ** invoked. ** ** Calling this routine overwrites any previously installed progress callback. ** To remove the progress callback altogether, pass NULL as the third ** argument to this function. ** ** If the progress callback returns a result other than 0, then the current ** query is immediately terminated and any database changes rolled back. If the ** query was part of a larger transaction, then the transaction is not rolled ** back and remains active. The sqlite_exec() call returns SQLITE_ABORT. ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ void sqlite_progress_handler(sqlite*, int, int(*)(void*), void*); /* ** Register a callback function to be invoked whenever a new transaction ** is committed. The pArg argument is passed through to the callback. ** callback. If the callback function returns non-zero, then the commit ** is converted into a rollback. ** ** If another function was previously registered, its pArg value is returned. ** Otherwise NULL is returned. ** ** Registering a NULL function disables the callback. ** ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ void *sqlite_commit_hook(sqlite*, int(*)(void*), void*); /* ** Open an encrypted SQLite database. If pKey==0 or nKey==0, this routine ** is the same as sqlite_open(). ** ** The code to implement this API is not available in the public release ** of SQLite. */ sqlite *sqlite_open_encrypted( const char *zFilename, /* Name of the encrypted database */ const void *pKey, /* Pointer to the key */ int nKey, /* Number of bytes in the key */ int *pErrcode, /* Write error code here */ char **pzErrmsg /* Write error message here */ ); /* ** Change the key on an open database. If the current database is not ** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the ** database is decrypted. ** ** The code to implement this API is not available in the public release ** of SQLite. */ int sqlite_rekey( sqlite *db, /* Database to be rekeyed */ const void *pKey, int nKey /* The new key */ ); /* ** Encode a binary buffer "in" of size n bytes so that it contains ** no instances of characters '\'' or '\000'. The output is ** null-terminated and can be used as a string value in an INSERT ** or UPDATE statement. Use sqlite_decode_binary() to convert the ** string back into its original binary. ** ** The result is written into a preallocated output buffer "out". ** "out" must be able to hold at least 2 +(257*n)/254 bytes. ** In other words, the output will be expanded by as much as 3 ** bytes for every 254 bytes of input plus 2 bytes of fixed overhead. ** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.) ** ** The return value is the number of characters in the encoded ** string, excluding the "\000" terminator. ** ** If out==NULL then no output is generated but the routine still returns ** the number of characters that would have been generated if out had ** not been NULL. */ int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out); /* ** Decode the string "in" into binary data and write it into "out". ** This routine reverses the encoding created by sqlite_encode_binary(). ** The output will always be a few bytes less than the input. The number ** of bytes of output is returned. If the input is not a well-formed ** encoding, -1 is returned. ** ** The "in" and "out" parameters may point to the same buffer in order ** to decode a string in place. */ int sqlite_decode_binary(const unsigned char *in, unsigned char *out); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* _SQLITE_H_ */ DBD-SQLite2-0.36/copy.c0000644000175000017500000000737612126353147013757 0ustar rurbanrurban/* ** 2003 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the COPY command. ** ** $Id: copy.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include "sqliteInt.h" /* ** The COPY command is for compatibility with PostgreSQL and specificially ** for the ability to read the output of pg_dump. The format is as ** follows: ** ** COPY table FROM file [USING DELIMITERS string] ** ** "table" is an existing table name. We will read lines of code from ** file to fill this table with data. File might be "stdin". The optional ** delimiter string identifies the field separators. The default is a tab. */ void sqliteCopy( Parse *pParse, /* The parser context */ SrcList *pTableName, /* The name of the table into which we will insert */ Token *pFilename, /* The file from which to obtain information */ Token *pDelimiter, /* Use this as the field delimiter */ int onError /* What to do if a constraint fails */ ){ Table *pTab; int i; Vdbe *v; int addr, end; char *zFile = 0; const char *zDb; sqlite *db = pParse->db; if( sqlite_malloc_failed ) goto copy_cleanup; assert( pTableName->nSrc==1 ); pTab = sqliteSrcListLookup(pParse, pTableName); if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup; zFile = sqliteStrNDup(pFilename->z, pFilename->n); sqliteDequote(zFile); assert( pTab->iDbnDb ); zDb = db->aDb[pTab->iDb].zName; if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){ goto copy_cleanup; } v = sqliteGetVdbe(pParse); if( v ){ sqliteBeginWriteOperation(pParse, 1, pTab->iDb); addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n); sqliteVdbeDequoteP3(v, addr); sqliteOpenTableAndIndices(pParse, pTab, 0); if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */ } end = sqliteVdbeMakeLabel(v); addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end); if( pDelimiter ){ sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n); sqliteVdbeDequoteP3(v, addr); }else{ sqliteVdbeChangeP3(v, addr, "\t", 1); } if( pTab->iPKey>=0 ){ sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0); sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); }else{ sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); } for(i=0; inCol; i++){ if( i==pTab->iPKey ){ /* The integer primary key column is filled with NULL since its ** value is always pulled from the record number */ sqliteVdbeAddOp(v, OP_String, 0, 0); }else{ sqliteVdbeAddOp(v, OP_FileColumn, i, 0); } } sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0, 0, onError, addr); sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1); if( (db->flags & SQLITE_CountRows)!=0 ){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); /* Increment row count */ } sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeResolveLabel(v, end); sqliteVdbeAddOp(v, OP_Noop, 0, 0); sqliteEndWriteOperation(pParse); if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC); sqliteVdbeAddOp(v, OP_Callback, 1, 0); } } copy_cleanup: sqliteSrcListDelete(pTableName); sqliteFree(zFile); return; } DBD-SQLite2-0.36/pager.c0000644000175000017500000021732212130551337014071 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of the page cache subsystem or "pager". ** ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include #include /* ** Macros for troubleshooting. Normally turned off */ #if 0 static Pager *mainPager = 0; #define SET_PAGER(X) if( mainPager==0 ) mainPager = (X) #define CLR_PAGER(X) if( mainPager==(X) ) mainPager = 0 #define TRACE1(X) if( pPager==mainPager ) fprintf(stderr,X) #define TRACE2(X,Y) if( pPager==mainPager ) fprintf(stderr,X,Y) #define TRACE3(X,Y,Z) if( pPager==mainPager ) fprintf(stderr,X,Y,Z) #else #define SET_PAGER(X) #define CLR_PAGER(X) #define TRACE1(X) #define TRACE2(X,Y) #define TRACE3(X,Y,Z) #endif /* ** The page cache as a whole is always in one of the following ** states: ** ** SQLITE_UNLOCK The page cache is not currently reading or ** writing the database file. There is no ** data held in memory. This is the initial ** state. ** ** SQLITE_READLOCK The page cache is reading the database. ** Writing is not permitted. There can be ** multiple readers accessing the same database ** file at the same time. ** ** SQLITE_WRITELOCK The page cache is writing the database. ** Access is exclusive. No other processes or ** threads can be reading or writing while one ** process is writing. ** ** The page cache comes up in SQLITE_UNLOCK. The first time a ** sqlite_page_get() occurs, the state transitions to SQLITE_READLOCK. ** After all pages have been released using sqlite_page_unref(), ** the state transitions back to SQLITE_UNLOCK. The first time ** that sqlite_page_write() is called, the state transitions to ** SQLITE_WRITELOCK. (Note that sqlite_page_write() can only be ** called on an outstanding page which means that the pager must ** be in SQLITE_READLOCK before it transitions to SQLITE_WRITELOCK.) ** The sqlite_page_rollback() and sqlite_page_commit() functions ** transition the state from SQLITE_WRITELOCK back to SQLITE_READLOCK. */ #define SQLITE_UNLOCK 0 #define SQLITE_READLOCK 1 #define SQLITE_WRITELOCK 2 /* ** Each in-memory image of a page begins with the following header. ** This header is only visible to this pager module. The client ** code that calls pager sees only the data that follows the header. ** ** Client code should call sqlitepager_write() on a page prior to making ** any modifications to that page. The first time sqlitepager_write() ** is called, the original page contents are written into the rollback ** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once ** the journal page has made it onto the disk surface, PgHdr.needSync ** is cleared. The modified page cannot be written back into the original ** database file until the journal pages has been synced to disk and the ** PgHdr.needSync has been cleared. ** ** The PgHdr.dirty flag is set when sqlitepager_write() is called and ** is cleared again when the page content is written back to the original ** database file. */ typedef struct PgHdr PgHdr; struct PgHdr { Pager *pPager; /* The pager to which this page belongs */ Pgno pgno; /* The page number for this page */ PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ int nRef; /* Number of users of this page */ PgHdr *pNextFree, *pPrevFree; /* Freelist of pages where nRef==0 */ PgHdr *pNextAll, *pPrevAll; /* A list of all pages */ PgHdr *pNextCkpt, *pPrevCkpt; /* List of pages in the checkpoint journal */ u8 inJournal; /* TRUE if has been written to journal */ u8 inCkpt; /* TRUE if written to the checkpoint journal */ u8 dirty; /* TRUE if we need to write back changes */ u8 needSync; /* Sync journal before writing this page */ u8 alwaysRollback; /* Disable dont_rollback() for this page */ PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ /* SQLITE_PAGE_SIZE bytes of page data follow this header */ /* Pager.nExtra bytes of local data follow the page data */ }; /* ** A macro used for invoking the codec if there is one */ #ifdef SQLITE_HAS_CODEC # define CODEC(P,D,N,X) if( P->xCodec ){ P->xCodec(P->pCodecArg,D,N,X); } #else # define CODEC(P,D,N,X) #endif /* ** Convert a pointer to a PgHdr into a pointer to its data ** and back again. */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) #define PGHDR_TO_EXTRA(P) ((void*)&((char*)(&(P)[1]))[SQLITE_PAGE_SIZE]) /* ** How big to make the hash table used for locating in-memory pages ** by page number. */ #define N_PG_HASH 2048 /* ** Hash a page number */ #define pager_hash(PN) ((PN)&(N_PG_HASH-1)) /* ** A open page cache is an instance of the following structure. */ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ char *zDirectory; /* Directory hold database and journal files */ OsFile fd, jfd; /* File descriptors for database and journal */ OsFile cpfd; /* File descriptor for the checkpoint journal */ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ int ckptSize; /* Size of database (in pages) at ckpt_begin() */ sql_off_t ckptJSize; /* Size of journal at ckpt_begin() */ int nRec; /* Number of pages written to the journal */ u32 cksumInit; /* Quasi-random value added to every checksum */ int ckptNRec; /* Number of records in the checkpoint journal */ int nExtra; /* Add this many bytes to each in-memory page */ void (*xDestructor)(void*); /* Call this routine when freeing pages */ int nPage; /* Total number of in-memory pages */ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ int mxPage; /* Maximum number of pages to hold in cache */ int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ u8 journalOpen; /* True if journal file descriptors is valid */ u8 journalStarted; /* True if header of journal is synced */ u8 useJournal; /* Use a rollback journal on this file */ u8 ckptOpen; /* True if the checkpoint journal is open */ u8 ckptInUse; /* True we are in a checkpoint */ u8 ckptAutoopen; /* Open ckpt journal when main journal is opened*/ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */ u8 errMask; /* One of several kinds of errors */ u8 tempFile; /* zFilename is a temporary file */ u8 readOnly; /* True for a read-only database */ u8 needSync; /* True if an fsync() is needed on the journal */ u8 dirtyFile; /* True if database file has changed in any way */ u8 alwaysRollback; /* Disable dont_rollback() for all pages */ u8 *aInJournal; /* One bit for each page in the database file */ u8 *aInCkpt; /* One bit for each page in the database */ PgHdr *pFirst, *pLast; /* List of free pages */ PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ PgHdr *pAll; /* List of all pages */ PgHdr *pCkpt; /* List of pages in the checkpoint journal */ PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number of PgHdr */ }; /* ** These are bits that can be set in Pager.errMask. */ #define PAGER_ERR_FULL 0x01 /* a write() failed */ #define PAGER_ERR_MEM 0x02 /* malloc() failed */ #define PAGER_ERR_LOCK 0x04 /* error in the locking protocol */ #define PAGER_ERR_CORRUPT 0x08 /* database or journal corruption */ #define PAGER_ERR_DISK 0x10 /* general disk I/O error - bad hard drive? */ /* ** The journal file contains page records in the following ** format. ** ** Actually, this structure is the complete page record for pager ** formats less than 3. Beginning with format 3, this record is surrounded ** by two checksums. */ typedef struct PageRecord PageRecord; struct PageRecord { Pgno pgno; /* The page number */ char aData[SQLITE_PAGE_SIZE]; /* Original data for page pgno */ }; /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. ** ** There are three journal formats (so far). The 1st journal format writes ** 32-bit integers in the byte-order of the host machine. New ** formats writes integers as big-endian. All new journals use the ** new format, but we have to be able to read an older journal in order ** to rollback journals created by older versions of the library. ** ** The 3rd journal format (added for 2.8.0) adds additional sanity ** checking information to the journal. If the power fails while the ** journal is being written, semi-random garbage data might appear in ** the journal file after power is restored. If an attempt is then made ** to roll the journal back, the database could be corrupted. The additional ** sanity checking data is an attempt to discover the garbage in the ** journal and ignore it. ** ** The sanity checking information for the 3rd journal format consists ** of a 32-bit checksum on each page of data. The checksum covers both ** the page number and the SQLITE_PAGE_SIZE bytes of data for the page. ** This cksum is initialized to a 32-bit random value that appears in the ** journal file right after the header. The random initializer is important, ** because garbage data that appears at the end of a journal is likely ** data that was once in other files that have now been deleted. If the ** garbage data came from an obsolete journal file, the checksums might ** be correct. But by initializing the checksum to random value which ** is different for every journal, we minimize that risk. */ static const unsigned char aJournalMagic1[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd4, }; static const unsigned char aJournalMagic2[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd5, }; static const unsigned char aJournalMagic3[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd6, }; #define JOURNAL_FORMAT_1 1 #define JOURNAL_FORMAT_2 2 #define JOURNAL_FORMAT_3 3 /* ** The following integer determines what format to use when creating ** new primary journal files. By default we always use format 3. ** When testing, we can set this value to older journal formats in order to ** make sure that newer versions of the library are able to rollback older ** journal files. ** ** Note that checkpoint journals always use format 2 and omit the header. */ #ifdef SQLITE_TEST int journal_format = 3; #else # define journal_format 3 #endif /* ** The size of the header and of each page in the journal varies according ** to which journal format is being used. The following macros figure out ** the sizes based on format numbers. */ #define JOURNAL_HDR_SZ(X) \ (sizeof(aJournalMagic1) + sizeof(Pgno) + ((X)>=3)*2*sizeof(u32)) #define JOURNAL_PG_SZ(X) \ (SQLITE_PAGE_SIZE + sizeof(Pgno) + ((X)>=3)*sizeof(u32)) /* ** Enable reference count tracking here: */ #ifdef SQLITE_TEST int pager_refinfo_enable = 0; static void pager_refinfo(PgHdr *p){ static int cnt = 0; if( !pager_refinfo_enable ) return; printf( "REFCNT: %4d addr=0x%08x nRef=%d\n", p->pgno, (int)PGHDR_TO_DATA(p), p->nRef ); cnt++; /* Something to set a breakpoint on */ } # define REFINFO(X) pager_refinfo(X) #else # define REFINFO(X) #endif /* ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. ** ** If the journal format is 2 or 3, read a big-endian integer. If the ** journal format is 1, read an integer in the native byte-order of the ** host machine. */ static int read32bits(int format, OsFile *fd, u32 *pRes){ u32 res; int rc; rc = sqliteOsRead(fd, &res, sizeof(res)); if( rc==SQLITE_OK && format>JOURNAL_FORMAT_1 ){ unsigned char ac[4]; memcpy(ac, &res, 4); res = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; } *pRes = res; return rc; } /* ** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK ** on success or an error code is something goes wrong. ** ** If the journal format is 2 or 3, write the integer as 4 big-endian ** bytes. If the journal format is 1, write the integer in the native ** byte order. In normal operation, only formats 2 and 3 are used. ** Journal format 1 is only used for testing. */ static int write32bits(OsFile *fd, u32 val){ unsigned char ac[4]; if( journal_format<=1 ){ return sqliteOsWrite(fd, &val, 4); } ac[0] = (val>>24) & 0xff; ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; return sqliteOsWrite(fd, ac, 4); } /* ** Write a 32-bit integer into a page header right before the ** page data. This will overwrite the PgHdr.pDirty pointer. ** ** The integer is big-endian for formats 2 and 3 and native byte order ** for journal format 1. */ static void store32bits(u32 val, PgHdr *p, int offset){ unsigned char *ac; ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; if( journal_format<=1 ){ memcpy(ac, &val, 4); }else{ ac[0] = (val>>24) & 0xff; ac[1] = (val>>16) & 0xff; ac[2] = (val>>8) & 0xff; ac[3] = val & 0xff; } } /* ** Convert the bits in the pPager->errMask into an approprate ** return code. */ static int pager_errcode(Pager *pPager){ int rc = SQLITE_OK; if( pPager->errMask & PAGER_ERR_LOCK ) rc = SQLITE_PROTOCOL; if( pPager->errMask & PAGER_ERR_DISK ) rc = SQLITE_IOERR; if( pPager->errMask & PAGER_ERR_FULL ) rc = SQLITE_FULL; if( pPager->errMask & PAGER_ERR_MEM ) rc = SQLITE_NOMEM; if( pPager->errMask & PAGER_ERR_CORRUPT ) rc = SQLITE_CORRUPT; return rc; } /* ** Add or remove a page from the list of all pages that are in the ** checkpoint journal. ** ** The Pager keeps a separate list of pages that are currently in ** the checkpoint journal. This helps the sqlitepager_ckpt_commit() ** routine run MUCH faster for the common case where there are many ** pages in memory but only a few are in the checkpoint journal. */ static void page_add_to_ckpt_list(PgHdr *pPg){ Pager *pPager = pPg->pPager; if( pPg->inCkpt ) return; assert( pPg->pPrevCkpt==0 && pPg->pNextCkpt==0 ); pPg->pPrevCkpt = 0; if( pPager->pCkpt ){ pPager->pCkpt->pPrevCkpt = pPg; } pPg->pNextCkpt = pPager->pCkpt; pPager->pCkpt = pPg; pPg->inCkpt = 1; } static void page_remove_from_ckpt_list(PgHdr *pPg){ if( !pPg->inCkpt ) return; if( pPg->pPrevCkpt ){ assert( pPg->pPrevCkpt->pNextCkpt==pPg ); pPg->pPrevCkpt->pNextCkpt = pPg->pNextCkpt; }else{ assert( pPg->pPager->pCkpt==pPg ); pPg->pPager->pCkpt = pPg->pNextCkpt; } if( pPg->pNextCkpt ){ assert( pPg->pNextCkpt->pPrevCkpt==pPg ); pPg->pNextCkpt->pPrevCkpt = pPg->pPrevCkpt; } pPg->pNextCkpt = 0; pPg->pPrevCkpt = 0; pPg->inCkpt = 0; } /* ** Find a page in the hash table given its page number. Return ** a pointer to the page or NULL if not found. */ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ PgHdr *p = pPager->aHash[pager_hash(pgno)]; while( p && p->pgno!=pgno ){ p = p->pNextHash; } return p; } /* ** Unlock the database and clear the in-memory cache. This routine ** sets the state of the pager back to what it was when it was first ** opened. Any outstanding pages are invalidated and subsequent attempts ** to access those pages will likely result in a coredump. */ static void pager_reset(Pager *pPager){ PgHdr *pPg, *pNext; for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); } pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->pAll = 0; memset(pPager->aHash, 0, sizeof(pPager->aHash)); pPager->nPage = 0; if( pPager->state>=SQLITE_WRITELOCK ){ sqlitepager_rollback(pPager); } sqliteOsUnlock(&pPager->fd); pPager->state = SQLITE_UNLOCK; pPager->dbSize = -1; pPager->nRef = 0; assert( pPager->journalOpen==0 ); } /* ** When this routine is called, the pager has the journal file open and ** a write lock on the database. This routine releases the database ** write lock and acquires a read lock in its place. The journal file ** is deleted and closed. ** ** TODO: Consider keeping the journal file open for temporary databases. ** This might give a performance improvement on windows where opening ** a file is an expensive operation. */ static int pager_unwritelock(Pager *pPager){ int rc; PgHdr *pPg; if( pPager->stateckptOpen ){ sqliteOsClose(&pPager->cpfd); pPager->ckptOpen = 0; } if( pPager->journalOpen ){ sqliteOsClose(&pPager->jfd); pPager->journalOpen = 0; sqliteOsDelete(pPager->zJournal); sqliteFree( pPager->aInJournal ); pPager->aInJournal = 0; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ pPg->inJournal = 0; pPg->dirty = 0; pPg->needSync = 0; } }else{ assert( pPager->dirtyFile==0 || pPager->useJournal==0 ); } rc = sqliteOsReadLock(&pPager->fd); if( rc==SQLITE_OK ){ pPager->state = SQLITE_READLOCK; }else{ /* This can only happen if a process does a BEGIN, then forks and the ** child process does the COMMIT. Because of the semantics of unix ** file locking, the unlock will fail. */ pPager->state = SQLITE_UNLOCK; } return rc; } /* ** Compute and return a checksum for the page of data. ** ** This is not a real checksum. It is really just the sum of the ** random initial value and the page number. We considered do a checksum ** of the database, but that was found to be too slow. */ static u32 pager_cksum(Pager *pPager, Pgno pgno, const char *aData){ u32 cksum = pPager->cksumInit + pgno; return cksum; } /* ** Read a single page from the journal file opened on file descriptor ** jfd. Playback this one page. ** ** There are three different journal formats. The format parameter determines ** which format is used by the journal that is played back. */ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int format){ int rc; PgHdr *pPg; /* An existing page in the cache */ PageRecord pgRec; u32 cksum; rc = read32bits(format, jfd, &pgRec.pgno); if( rc!=SQLITE_OK ) return rc; rc = sqliteOsRead(jfd, &pgRec.aData, sizeof(pgRec.aData)); if( rc!=SQLITE_OK ) return rc; /* Sanity checking on the page. This is more important that I originally ** thought. If a power failure occurs while the journal is being written, ** it could cause invalid data to be written into the journal. We need to ** detect this invalid data (with high probability) and ignore it. */ if( pgRec.pgno==0 ){ return SQLITE_DONE; } if( pgRec.pgno>(unsigned)pPager->dbSize ){ return SQLITE_OK; } if( format>=JOURNAL_FORMAT_3 ){ rc = read32bits(format, jfd, &cksum); if( rc ) return rc; if( pager_cksum(pPager, pgRec.pgno, pgRec.aData)!=cksum ){ return SQLITE_DONE; } } /* Playback the page. Update the in-memory copy of the page ** at the same time, if there is one. */ pPg = pager_lookup(pPager, pgRec.pgno); TRACE2("PLAYBACK %d\n", pgRec.pgno); sqliteOsSeek(&pPager->fd, (pgRec.pgno-1)*(sql_off_t)SQLITE_PAGE_SIZE); rc = sqliteOsWrite(&pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE); if( pPg ){ /* No page should ever be rolled back that is in use, except for page ** 1 which is held in use in order to keep the lock on the database ** active. */ assert( pPg->nRef==0 || pPg->pgno==1 ); memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE); memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); pPg->dirty = 0; pPg->needSync = 0; CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); } return rc; } /* ** Playback the journal and thus restore the database file to ** the state it was in before we started making changes. ** ** The journal file format is as follows: ** ** * 8 byte prefix. One of the aJournalMagic123 vectors defined ** above. The format of the journal file is determined by which ** of the three prefix vectors is seen. ** * 4 byte big-endian integer which is the number of valid page records ** in the journal. If this value is 0xffffffff, then compute the ** number of page records from the journal size. This field appears ** in format 3 only. ** * 4 byte big-endian integer which is the initial value for the ** sanity checksum. This field appears in format 3 only. ** * 4 byte integer which is the number of pages to truncate the ** database to during a rollback. ** * Zero or more pages instances, each as follows: ** + 4 byte page number. ** + SQLITE_PAGE_SIZE bytes of data. ** + 4 byte checksum (format 3 only) ** ** When we speak of the journal header, we mean the first 4 bullets above. ** Each entry in the journal is an instance of the 5th bullet. Note that ** bullets 2 and 3 only appear in format-3 journals. ** ** Call the value from the second bullet "nRec". nRec is the number of ** valid page entries in the journal. In most cases, you can compute the ** value of nRec from the size of the journal file. But if a power ** failure occurred while the journal was being written, it could be the ** case that the size of the journal file had already been increased but ** the extra entries had not yet made it safely to disk. In such a case, ** the value of nRec computed from the file size would be too large. For ** that reason, we always use the nRec value in the header. ** ** If the nRec value is 0xffffffff it means that nRec should be computed ** from the file size. This value is used when the user selects the ** no-sync option for the journal. A power failure could lead to corruption ** in this case. But for things like temporary table (which will be ** deleted when the power is restored) we don't care. ** ** Journal formats 1 and 2 do not have an nRec value in the header so we ** have to compute nRec from the file size. This has risks (as described ** above) which is why all persistent tables have been changed to use ** format 3. ** ** If the file opened as the journal file is not a well-formed ** journal file then the database will likely already be ** corrupted, so the PAGER_ERR_CORRUPT bit is set in pPager->errMask ** and SQLITE_CORRUPT is returned. If it all works, then this routine ** returns SQLITE_OK. */ static int pager_playback(Pager *pPager, int useJournalSize){ sql_off_t szJ; /* Size of the journal file in bytes */ int nRec; /* Number of Records in the journal */ int i; /* Loop counter */ Pgno mxPg = 0; /* Size of the original file in pages */ int format; /* Format of the journal file. */ unsigned char aMagic[sizeof(aJournalMagic1)]; int rc; /* Figure out how many records are in the journal. Abort early if ** the journal is empty. */ assert( pPager->journalOpen ); sqliteOsSeek(&pPager->jfd, 0); rc = sqliteOsFileSize(&pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_playback; } /* If the journal file is too small to contain a complete header, ** it must mean that the process that created the journal was just ** beginning to write the journal file when it died. In that case, ** the database file should have still been completely unchanged. ** Nothing needs to be rolled back. We can safely ignore this journal. */ if( szJ < sizeof(aMagic)+sizeof(Pgno) ){ goto end_playback; } /* Read the beginning of the journal and truncate the ** database file back to its original size. */ rc = sqliteOsRead(&pPager->jfd, aMagic, sizeof(aMagic)); if( rc!=SQLITE_OK ){ rc = SQLITE_PROTOCOL; goto end_playback; } if( memcmp(aMagic, aJournalMagic3, sizeof(aMagic))==0 ){ format = JOURNAL_FORMAT_3; }else if( memcmp(aMagic, aJournalMagic2, sizeof(aMagic))==0 ){ format = JOURNAL_FORMAT_2; }else if( memcmp(aMagic, aJournalMagic1, sizeof(aMagic))==0 ){ format = JOURNAL_FORMAT_1; }else{ rc = SQLITE_PROTOCOL; goto end_playback; } if( format>=JOURNAL_FORMAT_3 ){ if( szJ < sizeof(aMagic) + 3*sizeof(u32) ){ /* Ignore the journal if it is too small to contain a complete ** header. We already did this test once above, but at the prior ** test, we did not know the journal format and so we had to assume ** the smallest possible header. Now we know the header is bigger ** than the minimum so we test again. */ goto end_playback; } rc = read32bits(format, &pPager->jfd, (u32*)&nRec); if( rc ) goto end_playback; rc = read32bits(format, &pPager->jfd, &pPager->cksumInit); if( rc ) goto end_playback; if( nRec==0xffffffff || useJournalSize ){ nRec = (szJ - JOURNAL_HDR_SZ(3))/JOURNAL_PG_SZ(3); } }else{ nRec = (szJ - JOURNAL_HDR_SZ(2))/JOURNAL_PG_SZ(2); assert( nRec*JOURNAL_PG_SZ(2)+JOURNAL_HDR_SZ(2)==szJ ); } rc = read32bits(format, &pPager->jfd, &mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg ); rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(sql_off_t)mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } pPager->dbSize = mxPg; /* Copy original pages out of the journal and back into the database file. */ for(i=0; ijfd, format); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; } break; } } /* Pages that have been written to the journal but never synced ** where not restored by the loop above. We have to restore those ** pages by reading them back from the original database. */ if( rc==SQLITE_OK ){ PgHdr *pPg; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ char zBuf[SQLITE_PAGE_SIZE]; if( !pPg->dirty ) continue; if( (int)pPg->pgno <= pPager->origDbSize ){ sqliteOsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(sql_off_t)(pPg->pgno-1)); rc = sqliteOsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE); TRACE2("REFETCH %d\n", pPg->pgno); CODEC(pPager, zBuf, pPg->pgno, 2); if( rc ) break; }else{ memset(zBuf, 0, SQLITE_PAGE_SIZE); } if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){ memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE); memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); } pPg->needSync = 0; pPg->dirty = 0; } } end_playback: if( rc!=SQLITE_OK ){ pager_unwritelock(pPager); pPager->errMask |= PAGER_ERR_CORRUPT; rc = SQLITE_CORRUPT; }else{ rc = pager_unwritelock(pPager); } return rc; } /* ** Playback the checkpoint journal. ** ** This is similar to playing back the transaction journal but with ** a few extra twists. ** ** (1) The number of pages in the database file at the start of ** the checkpoint is stored in pPager->ckptSize, not in the ** journal file itself. ** ** (2) In addition to playing back the checkpoint journal, also ** playback all pages of the transaction journal beginning ** at offset pPager->ckptJSize. */ static int pager_ckpt_playback(Pager *pPager){ sql_off_t szJ; /* Size of the full journal */ int nRec; /* Number of Records */ int i; /* Loop counter */ int rc; /* Truncate the database back to its original size. */ rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(sql_off_t)pPager->ckptSize); pPager->dbSize = pPager->ckptSize; /* Figure out how many records are in the checkpoint journal. */ assert( pPager->ckptInUse && pPager->journalOpen ); sqliteOsSeek(&pPager->cpfd, 0); nRec = pPager->ckptNRec; /* Copy original pages out of the checkpoint journal and back into the ** database file. Note that the checkpoint journal always uses format ** 2 instead of format 3 since it does not need to be concerned with ** power failures corrupting the journal and can thus omit the checksums. */ for(i=nRec-1; i>=0; i--){ rc = pager_playback_one_page(pPager, &pPager->cpfd, 2); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_ckpt_playback; } /* Figure out how many pages need to be copied out of the transaction ** journal. */ rc = sqliteOsSeek(&pPager->jfd, pPager->ckptJSize); if( rc!=SQLITE_OK ){ goto end_ckpt_playback; } rc = sqliteOsFileSize(&pPager->jfd, &szJ); if( rc!=SQLITE_OK ){ goto end_ckpt_playback; } nRec = (szJ - pPager->ckptJSize)/JOURNAL_PG_SZ(journal_format); for(i=nRec-1; i>=0; i--){ rc = pager_playback_one_page(pPager, &pPager->jfd, journal_format); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_DONE ); goto end_ckpt_playback; } } end_ckpt_playback: if( rc!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_CORRUPT; rc = SQLITE_CORRUPT; } return rc; } /* ** Change the maximum number of in-memory pages that are allowed. ** ** The maximum number is the absolute value of the mxPage parameter. ** If mxPage is negative, the noSync flag is also set. noSync bypasses ** calls to sqliteOsSync(). The pager runs much faster with noSync on, ** but if the operating system crashes or there is an abrupt power ** failure, the database file might be left in an inconsistent and ** unrepairable state. */ void sqlitepager_set_cachesize(Pager *pPager, int mxPage){ if( mxPage>=0 ){ pPager->noSync = pPager->tempFile; if( pPager->noSync==0 ) pPager->needSync = 0; }else{ pPager->noSync = 1; mxPage = -mxPage; } if( mxPage>10 ){ pPager->mxPage = mxPage; } } /* ** Adjust the robustness of the database to damage due to OS crashes ** or power failures by changing the number of syncs()s when writing ** the rollback journal. There are three levels: ** ** OFF sqliteOsSync() is never called. This is the default ** for temporary and transient files. ** ** NORMAL The journal is synced once before writes begin on the ** database. This is normally adequate protection, but ** it is theoretically possible, though very unlikely, ** that an inopertune power failure could leave the journal ** in a state which would cause damage to the database ** when it is rolled back. ** ** FULL The journal is synced twice before writes begin on the ** database (with some additional information - the nRec field ** of the journal header - being written in between the two ** syncs). If we assume that writing a ** single disk sector is atomic, then this mode provides ** assurance that the journal will not be corrupted to the ** point of causing damage to the database during rollback. ** ** Numeric values associated with these states are OFF==1, NORMAL=2, ** and FULL=3. */ void sqlitepager_set_safety_level(Pager *pPager, int level){ pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; if( pPager->noSync==0 ) pPager->needSync = 0; } /* ** Open a temporary file. Write the name of the file into zName ** (zName must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write ** the file descriptor into *fd. Return SQLITE_OK on success or some ** other error code if we fail. ** ** The OS will automatically delete the temporary file when it is ** closed. */ static int sqlitepager_opentemp(char *zFile, OsFile *fd){ int cnt = 8; int rc; do{ cnt--; sqliteOsTempFileName(zFile); rc = sqliteOsOpenExclusive(zFile, fd, 1); }while( cnt>0 && rc!=SQLITE_OK ); return rc; } /* ** Create a new page cache and put a pointer to the page cache in *ppPager. ** The file to be cached need not exist. The file is not locked until ** the first call to sqlitepager_get() and is only held open until the ** last page is released using sqlitepager_unref(). ** ** If zFilename is NULL then a randomly-named temporary file is created ** and used as the file to be cached. The file will be deleted ** automatically when it is closed. */ int sqlitepager_open( Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int mxPage, /* Max number of in-memory cache pages */ int nExtra, /* Extra bytes append to each in-memory page */ int useJournal /* TRUE to use a rollback journal on this file */ ){ Pager *pPager; char *zFullPathname; int nameLen; OsFile fd; int rc, i; int tempFile; int readOnly = 0; char zTemp[SQLITE_TEMPNAME_SIZE]; *ppPager = 0; if( sqlite_malloc_failed ){ return SQLITE_NOMEM; } if( zFilename && zFilename[0] ){ zFullPathname = sqliteOsFullPathname(zFilename); rc = sqliteOsOpenReadWrite(zFullPathname, &fd, &readOnly); tempFile = 0; }else{ rc = sqlitepager_opentemp(zTemp, &fd); zFilename = zTemp; zFullPathname = sqliteOsFullPathname(zFilename); tempFile = 1; } if( sqlite_malloc_failed ){ return SQLITE_NOMEM; } if( rc!=SQLITE_OK ){ sqliteFree(zFullPathname); return SQLITE_CANTOPEN; } nameLen = strlen(zFullPathname); pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); if( pPager==0 ){ sqliteOsClose(&fd); sqliteFree(zFullPathname); return SQLITE_NOMEM; } SET_PAGER(pPager); pPager->zFilename = (char*)&pPager[1]; pPager->zDirectory = &pPager->zFilename[nameLen+1]; pPager->zJournal = &pPager->zDirectory[nameLen+1]; strcpy(pPager->zFilename, zFullPathname); strcpy(pPager->zDirectory, zFullPathname); for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} if( i>0 ) pPager->zDirectory[i-1] = 0; strcpy(pPager->zJournal, zFullPathname); sqliteFree(zFullPathname); strcpy(&pPager->zJournal[nameLen], "-journal"); pPager->fd = fd; pPager->journalOpen = 0; pPager->useJournal = useJournal; pPager->ckptOpen = 0; pPager->ckptInUse = 0; pPager->nRef = 0; pPager->dbSize = -1; pPager->ckptSize = 0; pPager->ckptJSize = 0; pPager->nPage = 0; pPager->mxPage = mxPage>5 ? mxPage : 10; pPager->state = SQLITE_UNLOCK; pPager->errMask = 0; pPager->tempFile = tempFile; pPager->readOnly = readOnly; pPager->needSync = 0; pPager->noSync = pPager->tempFile || !useJournal; pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->nExtra = nExtra; memset(pPager->aHash, 0, sizeof(pPager->aHash)); *ppPager = pPager; return SQLITE_OK; } /* ** Set the destructor for this pager. If not NULL, the destructor is called ** when the reference count on each page reaches zero. The destructor can ** be used to clean up information in the extra segment appended to each page. ** ** The destructor is not called as a result sqlitepager_close(). ** Destructors are only called by sqlitepager_unref(). */ void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){ pPager->xDestructor = xDesc; } /* ** Return the total number of pages in the disk file associated with ** pPager. */ int sqlitepager_pagecount(Pager *pPager){ sql_off_t n; assert( pPager!=0 ); if( pPager->dbSize>=0 ){ return pPager->dbSize; } if( sqliteOsFileSize(&pPager->fd, &n)!=SQLITE_OK ){ pPager->errMask |= PAGER_ERR_DISK; return 0; } n /= SQLITE_PAGE_SIZE; if( pPager->state!=SQLITE_UNLOCK ){ pPager->dbSize = n; } return n; } /* ** Forward declaration */ static int syncJournal(Pager*); /* ** Truncate the file to the number of pages specified. */ int sqlitepager_truncate(Pager *pPager, Pgno nPage){ int rc; if( pPager->dbSize<0 ){ sqlitepager_pagecount(pPager); } if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( nPage>=(unsigned)pPager->dbSize ){ return SQLITE_OK; } syncJournal(pPager); rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(sql_off_t)nPage); if( rc==SQLITE_OK ){ pPager->dbSize = nPage; } return rc; } /* ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that ** transaction is rolled back. All outstanding pages are invalidated ** and their memory is freed. Any attempt to use a page associated ** with this page cache after this function returns will likely ** result in a coredump. */ int sqlitepager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case SQLITE_WRITELOCK: { sqlitepager_rollback(pPager); sqliteOsUnlock(&pPager->fd); assert( pPager->journalOpen==0 ); break; } case SQLITE_READLOCK: { sqliteOsUnlock(&pPager->fd); break; } default: { /* Do nothing */ break; } } for(pPg=pPager->pAll; pPg; pPg=pNext){ pNext = pPg->pNextAll; sqliteFree(pPg); } sqliteOsClose(&pPager->fd); assert( pPager->journalOpen==0 ); /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqliteOsDelete(pPager->zFilename); ** } */ CLR_PAGER(pPager); if( pPager->zFilename!=(char*)&pPager[1] ){ assert( 0 ); /* Cannot happen */ sqliteFree(pPager->zFilename); sqliteFree(pPager->zJournal); sqliteFree(pPager->zDirectory); } sqliteFree(pPager); return SQLITE_OK; } /* ** Return the page number for the given page data. */ Pgno sqlitepager_pagenumber(void *pData){ PgHdr *p = DATA_TO_PGHDR(pData); return p->pgno; } /* ** Increment the reference count for a page. If the page is ** currently on the freelist (the reference count is zero) then ** remove it from the freelist. */ #define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++) static void _page_ref(PgHdr *pPg){ if( pPg->nRef==0 ){ /* The page is currently on the freelist. Remove it. */ if( pPg==pPg->pPager->pFirstSynced ){ PgHdr *p = pPg->pNextFree; while( p && p->needSync ){ p = p->pNextFree; } pPg->pPager->pFirstSynced = p; } if( pPg->pPrevFree ){ pPg->pPrevFree->pNextFree = pPg->pNextFree; }else{ pPg->pPager->pFirst = pPg->pNextFree; } if( pPg->pNextFree ){ pPg->pNextFree->pPrevFree = pPg->pPrevFree; }else{ pPg->pPager->pLast = pPg->pPrevFree; } pPg->pPager->nRef++; } pPg->nRef++; REFINFO(pPg); } /* ** Increment the reference count for a page. The input pointer is ** a reference to the page data. */ int sqlitepager_ref(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); page_ref(pPg); return SQLITE_OK; } /* ** Sync the journal. In other words, make sure all the pages that have ** been written to the journal have actually reached the surface of the ** disk. It is not safe to modify the original database file until after ** the journal has been synced. If the original database is modified before ** the journal is synced and a power failure occurs, the unsynced journal ** data would be lost and we would be unable to completely rollback the ** database changes. Database corruption would occur. ** ** This routine also updates the nRec field in the header of the journal. ** (See comments on the pager_playback() routine for additional information.) ** If the sync mode is FULL, two syncs will occur. First the whole journal ** is synced, then the nRec field is updated, then a second sync occurs. ** ** For temporary databases, we do not care if we are able to rollback ** after a power failure, so sync occurs. ** ** This routine clears the needSync field of every page current held in ** memory. */ static int syncJournal(Pager *pPager){ PgHdr *pPg; int rc = SQLITE_OK; /* Sync the journal before modifying the main database ** (assuming there is a journal and it needs to be synced.) */ if( pPager->needSync ){ if( !pPager->tempFile ){ assert( pPager->journalOpen ); /* assert( !pPager->noSync ); // noSync might be set if synchronous ** was turned off after the transaction was started. Ticket #615 */ #ifndef NDEBUG { /* Make sure the pPager->nRec counter we are keeping agrees ** with the nRec computed from the size of the journal file. */ sql_off_t hdrSz, pgSz, jSz; hdrSz = JOURNAL_HDR_SZ(journal_format); pgSz = JOURNAL_PG_SZ(journal_format); rc = sqliteOsFileSize(&pPager->jfd, &jSz); if( rc!=0 ) return rc; assert( pPager->nRec*pgSz+hdrSz==jSz ); } #endif if( journal_format>=3 ){ /* Write the nRec value into the journal file header */ sql_off_t szJ; if( pPager->fullSync ){ TRACE1("SYNC\n"); rc = sqliteOsSync(&pPager->jfd); if( rc!=0 ) return rc; } sqliteOsSeek(&pPager->jfd, sizeof(aJournalMagic1)); rc = write32bits(&pPager->jfd, pPager->nRec); if( rc ) return rc; szJ = JOURNAL_HDR_SZ(journal_format) + pPager->nRec*JOURNAL_PG_SZ(journal_format); sqliteOsSeek(&pPager->jfd, szJ); } TRACE1("SYNC\n"); rc = sqliteOsSync(&pPager->jfd); if( rc!=0 ) return rc; pPager->journalStarted = 1; } pPager->needSync = 0; /* Erase the needSync flag from every page. */ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ pPg->needSync = 0; } pPager->pFirstSynced = pPager->pFirst; } #ifndef NDEBUG /* If the Pager.needSync flag is clear then the PgHdr.needSync ** flag must also be clear for all pages. Verify that this ** invariant is true. */ else{ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ assert( pPg->needSync==0 ); } assert( pPager->pFirstSynced==pPager->pFirst ); } #endif return rc; } /* ** Given a list of pages (connected by the PgHdr.pDirty pointer) write ** every one of those pages out to the database file and mark them all ** as clean. */ static int pager_write_pagelist(PgHdr *pList){ Pager *pPager; int rc; if( pList==0 ) return SQLITE_OK; pPager = pList->pPager; while( pList ){ assert( pList->dirty ); sqliteOsSeek(&pPager->fd, (pList->pgno-1)*(sql_off_t)SQLITE_PAGE_SIZE); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); TRACE2("STORE %d\n", pList->pgno); rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE); CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0); if( rc ) return rc; pList->dirty = 0; pList = pList->pDirty; } return SQLITE_OK; } /* ** Collect every dirty page into a dirty list and ** return a pointer to the head of that list. All pages are ** collected even if they are still in use. */ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ PgHdr *p, *pList; pList = 0; for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ){ p->pDirty = pList; pList = p; } } return pList; } /* ** Acquire a page. ** ** A read lock on the disk file is obtained when the first page is acquired. ** This read lock is dropped when the last page is released. ** ** A _get works for any page number greater than 0. If the database ** file is smaller than the requested page, then no actual disk ** read occurs and the memory image of the page is initialized to ** all zeros. The extra data appended to a page is always initialized ** to zeros the first time a page is loaded into memory. ** ** The acquisition might fail for several reasons. In all cases, ** an appropriate error code is returned and *ppPage is set to NULL. ** ** See also sqlitepager_lookup(). Both this routine and _lookup() attempt ** to find a page in the in-memory cache first. If the page is not already ** in memory, this routine goes to disk to read it in whereas _lookup() ** just returns 0. This routine acquires a read-lock the first time it ** has to go to disk, and could also playback an old journal if necessary. ** Since _lookup() never goes to disk, it never has to deal with locks ** or journal files. */ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ PgHdr *pPg; int rc; /* Make sure we have not hit any critical errors. */ assert( pPager!=0 ); assert( pgno!=0 ); *ppPage = 0; if( pPager->errMask & ~(PAGER_ERR_FULL) ){ return pager_errcode(pPager); } /* If this is the first page accessed, then get a read lock ** on the database file. */ if( pPager->nRef==0 ){ rc = sqliteOsReadLock(&pPager->fd); if( rc!=SQLITE_OK ){ return rc; } pPager->state = SQLITE_READLOCK; /* If a journal file exists, try to play it back. */ if( pPager->useJournal && sqliteOsFileExists(pPager->zJournal) ){ int rc; /* Get a write lock on the database */ rc = sqliteOsWriteLock(&pPager->fd); if( rc!=SQLITE_OK ){ if( sqliteOsUnlock(&pPager->fd)!=SQLITE_OK ){ /* This should never happen! */ rc = SQLITE_INTERNAL; } return rc; } pPager->state = SQLITE_WRITELOCK; /* Open the journal for reading only. Return SQLITE_BUSY if ** we are unable to open the journal file. ** ** The journal file does not need to be locked itself. The ** journal file is never open unless the main database file holds ** a write lock, so there is never any chance of two or more ** processes opening the journal at the same time. */ rc = sqliteOsOpenReadOnly(pPager->zJournal, &pPager->jfd); if( rc!=SQLITE_OK ){ rc = sqliteOsUnlock(&pPager->fd); assert( rc==SQLITE_OK ); return SQLITE_BUSY; } pPager->journalOpen = 1; pPager->journalStarted = 0; /* Playback and delete the journal. Drop the database write ** lock and reacquire the read lock. */ rc = pager_playback(pPager, 0); if( rc!=SQLITE_OK ){ return rc; } } pPg = 0; }else{ /* Search for page in cache */ pPg = pager_lookup(pPager, pgno); } if( pPg==0 ){ /* The requested page is not in the page cache. */ int h; pPager->nMiss++; if( pPager->nPagemxPage || pPager->pFirst==0 ){ /* Create a new page */ pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE + sizeof(u32) + pPager->nExtra ); if( pPg==0 ){ pager_unwritelock(pPager); pPager->errMask |= PAGER_ERR_MEM; return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); pPg->pPager = pPager; pPg->pNextAll = pPager->pAll; if( pPager->pAll ){ pPager->pAll->pPrevAll = pPg; } pPg->pPrevAll = 0; pPager->pAll = pPg; pPager->nPage++; }else{ /* Find a page to recycle. Try to locate a page that does not ** require us to do an fsync() on the journal. */ pPg = pPager->pFirstSynced; /* If we could not find a page that does not require an fsync() ** on the journal file then fsync the journal file. This is a ** very slow operation, so we work hard to avoid it. But sometimes ** it can't be helped. */ if( pPg==0 ){ int rc = syncJournal(pPager); if( rc!=0 ){ sqlitepager_rollback(pPager); return SQLITE_IOERR; } pPg = pPager->pFirst; } assert( pPg->nRef==0 ); /* Write the page to the database file if it is dirty. */ if( pPg->dirty ){ assert( pPg->needSync==0 ); pPg->pDirty = 0; rc = pager_write_pagelist( pPg ); if( rc!=SQLITE_OK ){ sqlitepager_rollback(pPager); return SQLITE_IOERR; } } assert( pPg->dirty==0 ); /* If the page we are recycling is marked as alwaysRollback, then ** set the global alwaysRollback flag, thus disabling the ** sqlite_dont_rollback() optimization for the rest of this transaction. ** It is necessary to do this because the page marked alwaysRollback ** might be reloaded at a later time but at that point we won't remember ** that is was marked alwaysRollback. This means that all pages must ** be marked as alwaysRollback from here on out. */ if( pPg->alwaysRollback ){ pPager->alwaysRollback = 1; } /* Unlink the old page from the free list and the hash table */ if( pPg==pPager->pFirstSynced ){ PgHdr *p = pPg->pNextFree; while( p && p->needSync ){ p = p->pNextFree; } pPager->pFirstSynced = p; } if( pPg->pPrevFree ){ pPg->pPrevFree->pNextFree = pPg->pNextFree; }else{ assert( pPager->pFirst==pPg ); pPager->pFirst = pPg->pNextFree; } if( pPg->pNextFree ){ pPg->pNextFree->pPrevFree = pPg->pPrevFree; }else{ assert( pPager->pLast==pPg ); pPager->pLast = pPg->pPrevFree; } pPg->pNextFree = pPg->pPrevFree = 0; if( pPg->pNextHash ){ pPg->pNextHash->pPrevHash = pPg->pPrevHash; } if( pPg->pPrevHash ){ pPg->pPrevHash->pNextHash = pPg->pNextHash; }else{ h = pager_hash(pPg->pgno); assert( pPager->aHash[h]==pPg ); pPager->aHash[h] = pPg->pNextHash; } pPg->pNextHash = pPg->pPrevHash = 0; pPager->nOvfl++; } pPg->pgno = pgno; if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ sqliteCheckMemory(pPager->aInJournal, pgno/8); assert( pPager->journalOpen ); pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; pPg->needSync = 0; }else{ pPg->inJournal = 0; pPg->needSync = 0; } if( pPager->aInCkpt && (int)pgno<=pPager->ckptSize && (pPager->aInCkpt[pgno/8] & (1<<(pgno&7)))!=0 ){ page_add_to_ckpt_list(pPg); }else{ page_remove_from_ckpt_list(pPg); } pPg->dirty = 0; pPg->nRef = 1; REFINFO(pPg); pPager->nRef++; h = pager_hash(pgno); pPg->pNextHash = pPager->aHash[h]; pPager->aHash[h] = pPg; if( pPg->pNextHash ){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } if( pPager->nExtra>0 ){ memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); } if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager); if( pPager->errMask!=0 ){ sqlitepager_unref(PGHDR_TO_DATA(pPg)); rc = pager_errcode(pPager); return rc; } if( pPager->dbSize<(int)pgno ){ memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); }else{ int rc; sqliteOsSeek(&pPager->fd, (pgno-1)*(sql_off_t)SQLITE_PAGE_SIZE); rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); TRACE2("FETCH %d\n", pPg->pgno); CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); if( rc!=SQLITE_OK ){ sql_off_t fileSize; if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK || fileSize>=pgno*SQLITE_PAGE_SIZE ){ sqlitepager_unref(PGHDR_TO_DATA(pPg)); return rc; }else{ memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); } } } }else{ /* The requested page is in the page cache. */ pPager->nHit++; page_ref(pPg); } *ppPage = PGHDR_TO_DATA(pPg); return SQLITE_OK; } /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, ** or 0 if the page is not in cache. ** ** See also sqlitepager_get(). The difference between this routine ** and sqlitepager_get() is that _get() will go to the disk and read ** in the page if the page is not already in cache. This routine ** returns NULL if the page is not in cache or if a disk I/O error ** has ever happened. */ void *sqlitepager_lookup(Pager *pPager, Pgno pgno){ PgHdr *pPg; assert( pPager!=0 ); assert( pgno!=0 ); if( pPager->errMask & ~(PAGER_ERR_FULL) ){ return 0; } /* if( pPager->nRef==0 ){ ** return 0; ** } */ pPg = pager_lookup(pPager, pgno); if( pPg==0 ) return 0; page_ref(pPg); return PGHDR_TO_DATA(pPg); } /* ** Release a page. ** ** If the number of references to the page drop to zero, then the ** page is added to the LRU list. When all references to all pages ** are released, a rollback occurs and the lock on the database is ** removed. */ int sqlitepager_unref(void *pData){ PgHdr *pPg; /* Decrement the reference count for this page */ pPg = DATA_TO_PGHDR(pData); assert( pPg->nRef>0 ); pPg->nRef--; REFINFO(pPg); /* When the number of references to a page reach 0, call the ** destructor and add the page to the freelist. */ if( pPg->nRef==0 ){ Pager *pPager; pPager = pPg->pPager; pPg->pNextFree = 0; pPg->pPrevFree = pPager->pLast; pPager->pLast = pPg; if( pPg->pPrevFree ){ pPg->pPrevFree->pNextFree = pPg; }else{ pPager->pFirst = pPg; } if( pPg->needSync==0 && pPager->pFirstSynced==0 ){ pPager->pFirstSynced = pPg; } if( pPager->xDestructor ){ pPager->xDestructor(pData); } /* When all pages reach the freelist, drop the read lock from ** the database file. */ pPager->nRef--; assert( pPager->nRef>=0 ); if( pPager->nRef==0 ){ pager_reset(pPager); } } return SQLITE_OK; } /* ** Create a journal file for pPager. There should already be a write ** lock on the database file when this routine is called. ** ** Return SQLITE_OK if everything. Return an error code and release the ** write lock if anything goes wrong. */ static int pager_open_journal(Pager *pPager){ int rc; assert( pPager->state==SQLITE_WRITELOCK ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); sqlitepager_pagecount(pPager); pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInJournal==0 ){ sqliteOsReadLock(&pPager->fd); pPager->state = SQLITE_READLOCK; return SQLITE_NOMEM; } rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile); if( rc!=SQLITE_OK ){ sqliteFree(pPager->aInJournal); pPager->aInJournal = 0; sqliteOsReadLock(&pPager->fd); pPager->state = SQLITE_READLOCK; return SQLITE_CANTOPEN; } sqliteOsOpenDirectory(pPager->zDirectory, &pPager->jfd); pPager->journalOpen = 1; pPager->journalStarted = 0; pPager->needSync = 0; pPager->alwaysRollback = 0; pPager->nRec = 0; if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } pPager->origDbSize = pPager->dbSize; if( journal_format==JOURNAL_FORMAT_3 ){ rc = sqliteOsWrite(&pPager->jfd, aJournalMagic3, sizeof(aJournalMagic3)); if( rc==SQLITE_OK ){ rc = write32bits(&pPager->jfd, pPager->noSync ? 0xffffffff : 0); } if( rc==SQLITE_OK ){ sqliteRandomness(sizeof(pPager->cksumInit), &pPager->cksumInit); rc = write32bits(&pPager->jfd, pPager->cksumInit); } }else if( journal_format==JOURNAL_FORMAT_2 ){ rc = sqliteOsWrite(&pPager->jfd, aJournalMagic2, sizeof(aJournalMagic2)); }else{ assert( journal_format==JOURNAL_FORMAT_1 ); rc = sqliteOsWrite(&pPager->jfd, aJournalMagic1, sizeof(aJournalMagic1)); } if( rc==SQLITE_OK ){ rc = write32bits(&pPager->jfd, pPager->dbSize); } if( pPager->ckptAutoopen && rc==SQLITE_OK ){ rc = sqlitepager_ckpt_begin(pPager); } if( rc!=SQLITE_OK ){ rc = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } } return rc; } /* ** Acquire a write-lock on the database. The lock is removed when ** the any of the following happen: ** ** * sqlitepager_commit() is called. ** * sqlitepager_rollback() is called. ** * sqlitepager_close() is called. ** * sqlitepager_unref() is called to on every outstanding page. ** ** The parameter to this routine is a pointer to any open page of the ** database file. Nothing changes about the page - it is used merely ** to acquire a pointer to the Pager structure and as proof that there ** is already a read-lock on the database. ** ** A journal file is opened if this is not a temporary file. For ** temporary files, the opening of the journal file is deferred until ** there is an actual need to write to the journal. ** ** If the database is already write-locked, this routine is a no-op. */ int sqlitepager_begin(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; assert( pPg->nRef>0 ); assert( pPager->state!=SQLITE_UNLOCK ); if( pPager->state==SQLITE_READLOCK ){ assert( pPager->aInJournal==0 ); rc = sqliteOsWriteLock(&pPager->fd); if( rc!=SQLITE_OK ){ return rc; } pPager->state = SQLITE_WRITELOCK; pPager->dirtyFile = 0; TRACE1("TRANSACTION\n"); if( pPager->useJournal && !pPager->tempFile ){ rc = pager_open_journal(pPager); } } return rc; } /* ** Mark a data page as writeable. The page is written into the journal ** if it is not there already. This routine must be called before making ** changes to a page. ** ** The first time this routine is called, the pager creates a new ** journal and acquires a write lock on the database. If the write ** lock could not be acquired, this routine returns SQLITE_BUSY. The ** calling routine must check for that return value and be careful not to ** change any page data until this routine returns SQLITE_OK. ** ** If the journal file could not be written because the disk is full, ** then this routine returns SQLITE_FULL and does an immediate rollback. ** All subsequent write attempts also return SQLITE_FULL until there ** is a call to sqlitepager_commit() or sqlitepager_rollback() to ** reset. */ int sqlitepager_write(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* Check for errors */ if( pPager->errMask ){ return pager_errcode(pPager); } if( pPager->readOnly ){ return SQLITE_PERM; } /* Mark the page as dirty. If the page has already been written ** to the journal then we can return right away. */ pPg->dirty = 1; if( pPg->inJournal && (pPg->inCkpt || pPager->ckptInUse==0) ){ pPager->dirtyFile = 1; return SQLITE_OK; } /* If we get this far, it means that the page needs to be ** written to the transaction journal or the ckeckpoint journal ** or both. ** ** First check to see that the transaction journal exists and ** create it if it does not. */ assert( pPager->state!=SQLITE_UNLOCK ); rc = sqlitepager_begin(pData); if( rc!=SQLITE_OK ){ return rc; } assert( pPager->state==SQLITE_WRITELOCK ); if( !pPager->journalOpen && pPager->useJournal ){ rc = pager_open_journal(pPager); if( rc!=SQLITE_OK ) return rc; } assert( pPager->journalOpen || !pPager->useJournal ); pPager->dirtyFile = 1; /* The transaction journal now exists and we have a write lock on the ** main database file. Write the current page to the transaction ** journal if it is not there already. */ if( !pPg->inJournal && pPager->useJournal ){ if( (int)pPg->pgno <= pPager->origDbSize ){ int szPg; u32 saved; if( journal_format>=JOURNAL_FORMAT_3 ){ u32 cksum = pager_cksum(pPager, pPg->pgno, pData); saved = *(u32*)PGHDR_TO_EXTRA(pPg); store32bits(cksum, pPg, SQLITE_PAGE_SIZE); szPg = SQLITE_PAGE_SIZE+8; }else{ szPg = SQLITE_PAGE_SIZE+4; } store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); rc = sqliteOsWrite(&pPager->jfd, &((char*)pData)[-4], szPg); TRACE3("JOURNAL %d %d\n", pPg->pgno, pPg->needSync); CODEC(pPager, pData, pPg->pgno, 0); if( journal_format>=JOURNAL_FORMAT_3 ){ *(u32*)PGHDR_TO_EXTRA(pPg) = saved; } if( rc!=SQLITE_OK ){ sqlitepager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->nRec++; assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->needSync = !pPager->noSync; pPg->inJournal = 1; if( pPager->ckptInUse ){ pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); page_add_to_ckpt_list(pPg); } }else{ pPg->needSync = !pPager->journalStarted && !pPager->noSync; TRACE3("APPEND %d %d\n", pPg->pgno, pPg->needSync); } if( pPg->needSync ){ pPager->needSync = 1; } } /* If the checkpoint journal is open and the page is not in it, ** then write the current page to the checkpoint journal. Note that ** the checkpoint journal always uses the simplier format 2 that lacks ** checksums. The header is also omitted from the checkpoint journal. */ if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); store32bits(pPg->pgno, pPg, -4); CODEC(pPager, pData, pPg->pgno, 7); rc = sqliteOsWrite(&pPager->cpfd, &((char*)pData)[-4], SQLITE_PAGE_SIZE+4); TRACE2("CKPT-JOURNAL %d\n", pPg->pgno); CODEC(pPager, pData, pPg->pgno, 0); if( rc!=SQLITE_OK ){ sqlitepager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; return rc; } pPager->ckptNRec++; assert( pPager->aInCkpt!=0 ); pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); page_add_to_ckpt_list(pPg); } /* Update the database size and return. */ if( pPager->dbSize<(int)pPg->pgno ){ pPager->dbSize = pPg->pgno; } return rc; } /* ** Return TRUE if the page given in the argument was previously passed ** to sqlitepager_write(). In other words, return TRUE if it is ok ** to change the content of the page. */ int sqlitepager_iswriteable(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); return pPg->dirty; } /* ** Replace the content of a single page with the information in the third ** argument. */ int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){ void *pPage; int rc; rc = sqlitepager_get(pPager, pgno, &pPage); if( rc==SQLITE_OK ){ rc = sqlitepager_write(pPage); if( rc==SQLITE_OK ){ memcpy(pPage, pData, SQLITE_PAGE_SIZE); } sqlitepager_unref(pPage); } return rc; } /* ** A call to this routine tells the pager that it is not necessary to ** write the information on page "pgno" back to the disk, even though ** that page might be marked as dirty. ** ** The overlying software layer calls this routine when all of the data ** on the given page is unused. The pager marks the page as clean so ** that it does not get written to disk. ** ** Tests show that this optimization, together with the ** sqlitepager_dont_rollback() below, more than double the speed ** of large INSERT operations and quadruple the speed of large DELETEs. ** ** When this routine is called, set the alwaysRollback flag to true. ** Subsequent calls to sqlitepager_dont_rollback() for the same page ** will thereafter be ignored. This is necessary to avoid a problem ** where a page with data is added to the freelist during one part of ** a transaction then removed from the freelist during a later part ** of the same transaction and reused for some other purpose. When it ** is first added to the freelist, this routine is called. When reused, ** the dont_rollback() routine is called. But because the page contains ** critical data, we still need to be sure it gets rolled back in spite ** of the dont_rollback() call. */ void sqlitepager_dont_write(Pager *pPager, Pgno pgno){ PgHdr *pPg; pPg = pager_lookup(pPager, pgno); pPg->alwaysRollback = 1; if( pPg && pPg->dirty ){ if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){ /* If this pages is the last page in the file and the file has grown ** during the current transaction, then do NOT mark the page as clean. ** When the database file grows, we must make sure that the last page ** gets written at least once so that the disk file will be the correct ** size. If you do not write this page and the size of the file ** on the disk ends up being too small, that can lead to database ** corruption during the next transaction. */ }else{ TRACE2("DONT_WRITE %d\n", pgno); pPg->dirty = 0; } } } /* ** A call to this routine tells the pager that if a rollback occurs, ** it is not necessary to restore the data on the given page. This ** means that the pager does not have to record the given page in the ** rollback journal. */ void sqlitepager_dont_rollback(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return; if( pPg->alwaysRollback || pPager->alwaysRollback ) return; if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->inJournal = 1; if( pPager->ckptInUse ){ pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); page_add_to_ckpt_list(pPg); } TRACE2("DONT_ROLLBACK %d\n", pPg->pgno); } if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); assert( pPager->aInCkpt!=0 ); pPager->aInCkpt[pPg->pgno/8] |= 1<<(pPg->pgno&7); page_add_to_ckpt_list(pPg); } } /* ** Commit all changes to the database and release the write lock. ** ** If the commit fails for any reason, a rollback attempt is made ** and an error code is returned. If the commit worked, SQLITE_OK ** is returned. */ int sqlitepager_commit(Pager *pPager){ int rc; PgHdr *pPg; if( pPager->errMask==PAGER_ERR_FULL ){ rc = sqlitepager_rollback(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } return rc; } if( pPager->errMask!=0 ){ rc = pager_errcode(pPager); return rc; } if( pPager->state!=SQLITE_WRITELOCK ){ return SQLITE_ERROR; } TRACE1("COMMIT\n"); if( pPager->dirtyFile==0 ){ /* Exit early (without doing the time-consuming sqliteOsSync() calls) ** if there have been no changes to the database file. */ assert( pPager->needSync==0 ); rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; } assert( pPager->journalOpen ); rc = syncJournal(pPager); if( rc!=SQLITE_OK ){ goto commit_abort; } pPg = pager_get_all_dirty_pages(pPager); if( pPg ){ rc = pager_write_pagelist(pPg); if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){ goto commit_abort; } } rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; /* Jump here if anything goes wrong during the commit process. */ commit_abort: rc = sqlitepager_rollback(pPager); if( rc==SQLITE_OK ){ rc = SQLITE_FULL; } return rc; } /* ** Rollback all changes. The database falls back to read-only mode. ** All in-memory cache pages revert to their original data contents. ** The journal is deleted. ** ** This routine cannot fail unless some other process is not following ** the correct locking protocol (SQLITE_PROTOCOL) or unless some other ** process is writing trash into the journal file (SQLITE_CORRUPT) or ** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error ** codes are returned for all these occasions. Otherwise, ** SQLITE_OK is returned. */ int sqlitepager_rollback(Pager *pPager){ int rc; TRACE1("ROLLBACK\n"); if( !pPager->dirtyFile || !pPager->journalOpen ){ rc = pager_unwritelock(pPager); pPager->dbSize = -1; return rc; } if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){ if( pPager->state>=SQLITE_WRITELOCK ){ pager_playback(pPager, 1); } return pager_errcode(pPager); } if( pPager->state!=SQLITE_WRITELOCK ){ return SQLITE_OK; } rc = pager_playback(pPager, 1); if( rc!=SQLITE_OK ){ rc = SQLITE_CORRUPT; pPager->errMask |= PAGER_ERR_CORRUPT; } pPager->dbSize = -1; return rc; } /* ** Return TRUE if the database file is opened read-only. Return FALSE ** if the database is (in theory) writable. */ int sqlitepager_isreadonly(Pager *pPager){ return pPager->readOnly; } /* ** This routine is used for testing and analysis only. */ int *sqlitepager_stats(Pager *pPager){ static int a[9]; a[0] = pPager->nRef; a[1] = pPager->nPage; a[2] = pPager->mxPage; a[3] = pPager->dbSize; a[4] = pPager->state; a[5] = pPager->errMask; a[6] = pPager->nHit; a[7] = pPager->nMiss; a[8] = pPager->nOvfl; return a; } /* ** Set the checkpoint. ** ** This routine should be called with the transaction journal already ** open. A new checkpoint journal is created that can be used to rollback ** changes of a single SQL command within a larger transaction. */ int sqlitepager_ckpt_begin(Pager *pPager){ int rc; char zTemp[SQLITE_TEMPNAME_SIZE]; if( !pPager->journalOpen ){ pPager->ckptAutoopen = 1; return SQLITE_OK; } assert( pPager->journalOpen ); assert( !pPager->ckptInUse ); pPager->aInCkpt = sqliteMalloc( pPager->dbSize/8 + 1 ); if( pPager->aInCkpt==0 ){ sqliteOsReadLock(&pPager->fd); return SQLITE_NOMEM; } #ifndef NDEBUG rc = sqliteOsFileSize(&pPager->jfd, &pPager->ckptJSize); if( rc ) goto ckpt_begin_failed; assert( pPager->ckptJSize == pPager->nRec*JOURNAL_PG_SZ(journal_format)+JOURNAL_HDR_SZ(journal_format) ); #endif pPager->ckptJSize = pPager->nRec*JOURNAL_PG_SZ(journal_format) + JOURNAL_HDR_SZ(journal_format); pPager->ckptSize = pPager->dbSize; if( !pPager->ckptOpen ){ rc = sqlitepager_opentemp(zTemp, &pPager->cpfd); if( rc ) goto ckpt_begin_failed; pPager->ckptOpen = 1; pPager->ckptNRec = 0; } pPager->ckptInUse = 1; return SQLITE_OK; ckpt_begin_failed: if( pPager->aInCkpt ){ sqliteFree(pPager->aInCkpt); pPager->aInCkpt = 0; } return rc; } /* ** Commit a checkpoint. */ int sqlitepager_ckpt_commit(Pager *pPager){ if( pPager->ckptInUse ){ PgHdr *pPg, *pNext; sqliteOsSeek(&pPager->cpfd, 0); /* sqliteOsTruncate(&pPager->cpfd, 0); */ pPager->ckptNRec = 0; pPager->ckptInUse = 0; sqliteFree( pPager->aInCkpt ); pPager->aInCkpt = 0; for(pPg=pPager->pCkpt; pPg; pPg=pNext){ pNext = pPg->pNextCkpt; assert( pPg->inCkpt ); pPg->inCkpt = 0; pPg->pPrevCkpt = pPg->pNextCkpt = 0; } pPager->pCkpt = 0; } pPager->ckptAutoopen = 0; return SQLITE_OK; } /* ** Rollback a checkpoint. */ int sqlitepager_ckpt_rollback(Pager *pPager){ int rc; if( pPager->ckptInUse ){ rc = pager_ckpt_playback(pPager); sqlitepager_ckpt_commit(pPager); }else{ rc = SQLITE_OK; } pPager->ckptAutoopen = 0; return rc; } /* ** Return the full pathname of the database file. */ const char *sqlitepager_filename(Pager *pPager){ return pPager->zFilename; } /* ** Set the codec for this pager */ void sqlitepager_set_codec( Pager *pPager, void (*xCodec)(void*,void*,Pgno,int), void *pCodecArg ){ pPager->xCodec = xCodec; pPager->pCodecArg = pCodecArg; } #ifdef SQLITE_TEST /* ** Print a listing of all referenced pages and their ref count. */ void sqlitepager_refdump(Pager *pPager){ PgHdr *pPg; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ if( pPg->nRef<=0 ) continue; printf("PAGE %3d addr=0x%08x nRef=%d\n", pPg->pgno, (int)PGHDR_TO_DATA(pPg), pPg->nRef); } } #endif DBD-SQLite2-0.36/SQLiteXS.h0000644000175000017500000000063412126353621014411 0ustar rurbanrurban #ifndef _SQLITEXS_H #define _SQLITEXS_H 1 /************************************************************************ DBI Specific Stuff - Added by Matt Sergeant ************************************************************************/ #define NEED_DBIXS_VERSION 93 #include #include "dbdimp.h" #include #include "sqlite.h" int sqlite2_busy_timeout( SV *dbh, int timeout ); #endif DBD-SQLite2-0.36/table.c0000644000175000017500000001243612126353147014065 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the sqlite_get_table() and sqlite_free_table() ** interface routines. These are just wrappers around the main ** interface routine of sqlite_exec(). ** ** These routines are in a separate files so that they will not be linked ** if they are not used. */ #include #include #include "sqliteInt.h" /* ** This structure is used to pass data from sqlite_get_table() through ** to the callback function is uses to build the result. */ typedef struct TabResult { char **azResult; char *zErrMsg; int nResult; int nAlloc; int nRow; int nColumn; long nData; int rc; } TabResult; /* ** This routine is called once for each row in the result table. Its job ** is to fill in the TabResult structure appropriately, allocating new ** memory as necessary. */ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ TabResult *p = (TabResult*)pArg; int need; int i; char *z; /* Make sure there is enough space in p->azResult to hold everything ** we need to remember from this invocation of the callback. */ if( p->nRow==0 && argv!=0 ){ need = nCol*2; }else{ need = nCol; } if( p->nData + need >= p->nAlloc ){ char **azNew; p->nAlloc = p->nAlloc*2 + need + 1; azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc ); if( azNew==0 ){ p->rc = SQLITE_NOMEM; return 1; } p->azResult = azNew; } /* If this is the first row, then generate an extra row containing ** the names of all columns. */ if( p->nRow==0 ){ p->nColumn = nCol; for(i=0; irc = SQLITE_NOMEM; return 1; } strcpy(z, colv[i]); } p->azResult[p->nData++] = z; } }else if( p->nColumn!=nCol ){ sqliteSetString(&p->zErrMsg, "sqlite_get_table() called with two or more incompatible queries", (char*)0); p->rc = SQLITE_ERROR; return 1; } /* Copy over the row data */ if( argv!=0 ){ for(i=0; irc = SQLITE_NOMEM; return 1; } strcpy(z, argv[i]); } p->azResult[p->nData++] = z; } p->nRow++; } return 0; } /* ** Query the database. But instead of invoking a callback for each row, ** malloc() for space to hold the result and return the entire results ** at the conclusion of the call. ** ** The result that is written to ***pazResult is held in memory obtained ** from malloc(). But the caller cannot free this memory directly. ** Instead, the entire table should be passed to sqlite_free_table() when ** the calling procedure is finished using it. */ int sqlite_get_table( sqlite *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ char ***pazResult, /* Write the result table here */ int *pnRow, /* Write the number of rows in the result here */ int *pnColumn, /* Write the number of columns of result here */ char **pzErrMsg /* Write error messages here */ ){ int rc; TabResult res; if( pazResult==0 ){ return SQLITE_ERROR; } *pazResult = 0; if( pnColumn ) *pnColumn = 0; if( pnRow ) *pnRow = 0; res.zErrMsg = 0; res.nResult = 0; res.nRow = 0; res.nColumn = 0; res.nData = 1; res.nAlloc = 20; res.rc = SQLITE_OK; res.azResult = malloc( sizeof(char*)*res.nAlloc ); if( res.azResult==0 ){ return SQLITE_NOMEM; } res.azResult[0] = 0; rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg); if( res.azResult ){ res.azResult[0] = (char*)res.nData; } if( rc==SQLITE_ABORT ){ sqlite_free_table(&res.azResult[1]); if( res.zErrMsg ){ if( pzErrMsg ){ free(*pzErrMsg); *pzErrMsg = res.zErrMsg; sqliteStrRealloc(pzErrMsg); }else{ sqliteFree(res.zErrMsg); } } return res.rc; } sqliteFree(res.zErrMsg); if( rc!=SQLITE_OK ){ sqlite_free_table(&res.azResult[1]); return rc; } if( res.nAlloc>res.nData ){ char **azNew; azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) ); if( azNew==0 ){ sqlite_free_table(&res.azResult[1]); return SQLITE_NOMEM; } res.nAlloc = res.nData+1; res.azResult = azNew; } *pazResult = &res.azResult[1]; if( pnColumn ) *pnColumn = res.nColumn; if( pnRow ) *pnRow = res.nRow; return rc; } /* ** This routine frees the space the sqlite_get_table() malloced. */ void sqlite_free_table( char **azResult /* Result returned from from sqlite_get_table() */ ){ if( azResult ){ int i, n; azResult--; if( azResult==0 ) return; n = (int)(long)azResult[0]; for(i=1; i= 16 ) return '0'; digit = (int)*val; d = digit; digit += '0'; *val = (*val - d)*10.0; return digit; } #endif #define etBUFSIZE 1000 /* Size of the output buffer */ /* ** The root program. All variations call this core. ** ** INPUTS: ** func This is a pointer to a function taking three arguments ** 1. A pointer to anything. Same as the "arg" parameter. ** 2. A pointer to the list of characters to be output ** (Note, this list is NOT null terminated.) ** 3. An integer number of characters to be output. ** (Note: This number might be zero.) ** ** arg This is the pointer to anything which will be passed as the ** first argument to "func". Use it for whatever you like. ** ** fmt This is the format string, as in the usual print. ** ** ap This is a pointer to a list of arguments. Same as in ** vfprint. ** ** OUTPUTS: ** The return value is the total number of characters sent to ** the function "func". Returns -1 on a error. ** ** Note that the order in which automatic variables are declared below ** seems to make a big difference in determining how fast this beast ** will run. */ static int vxprintf( void (*func)(void*,const char*,int), /* Consumer of text */ void *arg, /* First argument to the consumer */ int useExtended, /* Allow extended %-conversions */ const char *fmt, /* Format string */ va_list ap /* arguments */ ){ int c; /* Next character in the format string */ char *bufpt; /* Pointer to the conversion buffer */ int precision; /* Precision of the current field */ int length; /* Length of the field */ int idx; /* A general purpose loop counter */ int count; /* Total number of characters output */ int width; /* Width of the current field */ etByte flag_leftjustify; /* True if "-" flag is present */ etByte flag_plussign; /* True if "+" flag is present */ etByte flag_blanksign; /* True if " " flag is present */ etByte flag_alternateform; /* True if "#" flag is present */ etByte flag_zeropad; /* True if field width constant starts with zero */ etByte flag_long; /* True if "l" flag is present */ unsigned long longvalue; /* Value for integer types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */ et_info *infop; /* Pointer to the appropriate info structure */ char buf[etBUFSIZE]; /* Conversion buffer */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ etByte errorflag = 0; /* True if an error is encountered */ etByte xtype; /* Conversion paradigm */ char *zExtra; /* Extra memory used for etTCLESCAPE conversions */ static char spaces[] = " "; #define etSPACESIZE (sizeof(spaces)-1) #ifndef etNOFLOATINGPOINT int exp; /* exponent of real numbers */ double rounder; /* Used for rounding floating point values */ etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ etByte flag_exp; /* True to force display of the exponent */ int nsd; /* Number of significant digits returned */ #endif func(arg,"",0); count = length = 0; bufpt = 0; for(; (c=(*fmt))!=0; ++fmt){ if( c!='%' ){ int amt; bufpt = (char *)fmt; amt = 1; while( (c=(*++fmt))!='%' && c!=0 ) amt++; (*func)(arg,bufpt,amt); count += amt; if( c==0 ) break; } if( (c=(*++fmt))==0 ){ errorflag = 1; (*func)(arg,"%",1); count++; break; } /* Find out what flags are present */ flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_zeropad = 0; do{ switch( c ){ case '-': flag_leftjustify = 1; c = 0; break; case '+': flag_plussign = 1; c = 0; break; case ' ': flag_blanksign = 1; c = 0; break; case '#': flag_alternateform = 1; c = 0; break; case '0': flag_zeropad = 1; c = 0; break; default: break; } }while( c==0 && (c=(*++fmt))!=0 ); /* Get the field width */ width = 0; if( c=='*' ){ width = va_arg(ap,int); if( width<0 ){ flag_leftjustify = 1; width = -width; } c = *++fmt; }else{ while( c>='0' && c<='9' ){ width = width*10 + c - '0'; c = *++fmt; } } if( width > etBUFSIZE-10 ){ width = etBUFSIZE-10; } /* Get the precision */ if( c=='.' ){ precision = 0; c = *++fmt; if( c=='*' ){ precision = va_arg(ap,int); if( precision<0 ) precision = -precision; c = *++fmt; }else{ while( c>='0' && c<='9' ){ precision = precision*10 + c - '0'; c = *++fmt; } } /* Limit the precision to prevent overflowing buf[] during conversion */ if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40; }else{ precision = -1; } /* Get the conversion type modifier */ if( c=='l' ){ flag_long = 1; c = *++fmt; }else{ flag_long = 0; } /* Fetch the info entry for the field */ infop = 0; xtype = etERROR; for(idx=0; idxflags & FLAG_INTERN)==0 ){ xtype = infop->type; } break; } } zExtra = 0; /* ** At this point, variables are initialized as follows: ** ** flag_alternateform TRUE if a '#' is present. ** flag_plussign TRUE if a '+' is present. ** flag_leftjustify TRUE if a '-' is present or if the ** field width was negative. ** flag_zeropad TRUE if the width began with 0. ** flag_long TRUE if the letter 'l' (ell) prefixed ** the conversion character. ** flag_blanksign TRUE if a ' ' is present. ** width The specified field width. This is ** always non-negative. Zero is the default. ** precision The specified precision. The default ** is -1. ** xtype The class of the conversion. ** infop Pointer to the appropriate info struct. */ switch( xtype ){ case etRADIX: if( flag_long ) longvalue = va_arg(ap,long); else longvalue = va_arg(ap,int); #if 1 /* For the format %#x, the value zero is printed "0" not "0x0". ** I think this is stupid. */ if( longvalue==0 ) flag_alternateform = 0; #else /* More sensible: turn off the prefix for octal (to prevent "00"), ** but leave the prefix for hex. */ if( longvalue==0 && infop->base==8 ) flag_alternateform = 0; #endif if( infop->flags & FLAG_SIGNED ){ if( *(long*)&longvalue<0 ){ longvalue = -*(long*)&longvalue; prefix = '-'; }else if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; }else prefix = 0; if( flag_zeropad && precisioncharset; base = infop->base; do{ /* Convert to ascii */ *(--bufpt) = cset[longvalue%base]; longvalue = longvalue/base; }while( longvalue>0 ); } length = &buf[etBUFSIZE-1]-bufpt; for(idx=precision-length; idx>0; idx--){ *(--bufpt) = '0'; /* Zero pad */ } if( prefix ) *(--bufpt) = prefix; /* Add sign */ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ char *pre, x; pre = infop->prefix; if( *bufpt!=pre[0] ){ for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x; } } length = &buf[etBUFSIZE-1]-bufpt; break; case etFLOAT: case etEXP: case etGENERIC: realvalue = va_arg(ap,double); #ifndef etNOFLOATINGPOINT if( precision<0 ) precision = 6; /* Set default precision */ if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10; if( realvalue<0.0 ){ realvalue = -realvalue; prefix = '-'; }else{ if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; } if( infop->type==etGENERIC && precision>0 ) precision--; rounder = 0.0; #if 0 /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */ for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); #else /* It makes more sense to use 0.5 */ for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1); #endif if( infop->type==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; if( realvalue>0.0 ){ while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; } while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; } while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; } while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; } if( exp>350 || exp<-350 ){ bufpt = "NaN"; length = 3; break; } } bufpt = buf; /* ** If the field type is etGENERIC, then convert to either etEXP ** or etFLOAT, as appropriate. */ flag_exp = xtype==etEXP; if( xtype!=etFLOAT ){ realvalue += rounder; if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } } if( xtype==etGENERIC ){ flag_rtz = !flag_alternateform; if( exp<-4 || exp>precision ){ xtype = etEXP; }else{ precision = precision - exp; xtype = etFLOAT; } }else{ flag_rtz = 0; } /* ** The "exp+precision" test causes output to be of type etEXP if ** the precision is too large to fit in buf[]. */ nsd = 0; if( xtype==etFLOAT && exp+precision0 || flag_alternateform); if( prefix ) *(bufpt++) = prefix; /* Sign */ if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */ else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd); if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */ for(exp++; exp<0 && precision>0; precision--, exp++){ *(bufpt++) = '0'; } while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); *(bufpt--) = 0; /* Null terminate */ if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; } bufpt++; /* point to next free slot */ }else{ /* etEXP or etGENERIC */ flag_dp = (precision>0 || flag_alternateform); if( prefix ) *(bufpt++) = prefix; /* Sign */ *(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */ if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */ while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd); bufpt--; /* point to last digit */ if( flag_rtz && flag_dp ){ /* Remove tail zeros */ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; } bufpt++; /* point to next free slot */ if( exp || flag_exp ){ *(bufpt++) = infop->charset[0]; if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */ else { *(bufpt++) = '+'; } if( exp>=100 ){ *(bufpt++) = (exp/100)+'0'; /* 100's digit */ exp %= 100; } *(bufpt++) = exp/10+'0'; /* 10's digit */ *(bufpt++) = exp%10+'0'; /* 1's digit */ } } /* The converted number is in buf[] and zero terminated. Output it. ** Note that the number is in the usual order, not reversed as with ** integer conversions. */ length = bufpt-buf; bufpt = buf; /* Special case: Add leading zeros if the flag_zeropad flag is ** set and we are not left justified */ if( flag_zeropad && !flag_leftjustify && length < width){ int i; int nPad = width - length; for(i=width; i>=nPad; i--){ bufpt[i] = bufpt[i-nPad]; } i = prefix!=0; while( nPad-- ) bufpt[i++] = '0'; length = width; } #endif break; case etSIZE: *(va_arg(ap,int*)) = count; length = width = 0; break; case etPERCENT: buf[0] = '%'; bufpt = buf; length = 1; break; case etCHARLIT: case etCHARX: c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt); if( precision>=0 ){ for(idx=1; idx=0 && precisionetBUFSIZE ){ bufpt = zExtra = sqliteMalloc( n ); if( bufpt==0 ) return -1; }else{ bufpt = buf; } j = 0; if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; for(i=0; (c=arg[i])!=0; i++){ bufpt[j++] = c; if( c=='\'' ) bufpt[j++] = c; } if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\''; bufpt[j] = 0; length = j; if( precision>=0 && precisionz, pToken->n); length = width = 0; break; } case etSRCLIST: { SrcList *pSrc = va_arg(ap, SrcList*); int k = va_arg(ap, int); struct SrcList_item *pItem = &pSrc->a[k]; assert( k>=0 && knSrc ); if( pItem->zDatabase && pItem->zDatabase[0] ){ (*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase)); (*func)(arg, ".", 1); } (*func)(arg, pItem->zName, strlen(pItem->zName)); length = width = 0; break; } case etERROR: buf[0] = '%'; buf[1] = c; errorflag = 0; idx = 1+(c!=0); (*func)(arg,"%",idx); count += idx; if( c==0 ) fmt--; break; }/* End switch over the format type */ /* ** The text of the conversion is pointed to by "bufpt" and is ** "length" characters long. The field width is "width". Do ** the output. */ if( !flag_leftjustify ){ register int nspace; nspace = width-length; if( nspace>0 ){ count += nspace; while( nspace>=etSPACESIZE ){ (*func)(arg,spaces,etSPACESIZE); nspace -= etSPACESIZE; } if( nspace>0 ) (*func)(arg,spaces,nspace); } } if( length>0 ){ (*func)(arg,bufpt,length); count += length; } if( flag_leftjustify ){ register int nspace; nspace = width-length; if( nspace>0 ){ count += nspace; while( nspace>=etSPACESIZE ){ (*func)(arg,spaces,etSPACESIZE); nspace -= etSPACESIZE; } if( nspace>0 ) (*func)(arg,spaces,nspace); } } if( zExtra ){ sqliteFree(zExtra); } }/* End for loop over the format string */ return errorflag ? -1 : count; } /* End of function */ /* This structure is used to store state information about the ** write to memory that is currently in progress. */ struct sgMprintf { char *zBase; /* A base allocation */ char *zText; /* The string collected so far */ int nChar; /* Length of the string so far */ int nTotal; /* Output size if unconstrained */ int nAlloc; /* Amount of space allocated in zText */ void *(*xRealloc)(void*,int); /* Function used to realloc memory */ }; /* ** This function implements the callback from vxprintf. ** ** This routine add nNewChar characters of text in zNewText to ** the sgMprintf structure pointed to by "arg". */ static void mout(void *arg, const char *zNewText, int nNewChar){ struct sgMprintf *pM = (struct sgMprintf*)arg; pM->nTotal += nNewChar; if( pM->nChar + nNewChar + 1 > pM->nAlloc ){ if( pM->xRealloc==0 ){ nNewChar = pM->nAlloc - pM->nChar - 1; }else{ pM->nAlloc = pM->nChar + nNewChar*2 + 1; if( pM->zText==pM->zBase ){ pM->zText = pM->xRealloc(0, pM->nAlloc); if( pM->zText && pM->nChar ){ memcpy(pM->zText, pM->zBase, pM->nChar); } }else{ pM->zText = pM->xRealloc(pM->zText, pM->nAlloc); } } } if( pM->zText ){ if( nNewChar>0 ){ memcpy(&pM->zText[pM->nChar], zNewText, nNewChar); pM->nChar += nNewChar; } pM->zText[pM->nChar] = 0; } } /* ** This routine is a wrapper around xprintf() that invokes mout() as ** the consumer. */ static char *base_vprintf( void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */ int useInternal, /* Use internal %-conversions if true */ char *zInitBuf, /* Initially write here, before mallocing */ int nInitBuf, /* Size of zInitBuf[] */ const char *zFormat, /* format string */ va_list ap /* arguments */ ){ struct sgMprintf sM; sM.zBase = sM.zText = zInitBuf; sM.nChar = sM.nTotal = 0; sM.nAlloc = nInitBuf; sM.xRealloc = xRealloc; vxprintf(mout, &sM, useInternal, zFormat, ap); if( xRealloc ){ if( sM.zText==sM.zBase ){ sM.zText = xRealloc(0, sM.nChar+1); memcpy(sM.zText, sM.zBase, sM.nChar+1); }else if( sM.nAlloc>sM.nChar+10 ){ sM.zText = xRealloc(sM.zText, sM.nChar+1); } } return sM.zText; } /* ** Realloc that is a real function, not a macro. */ static void *printf_realloc(void *old, int size){ return sqliteRealloc(old,size); } /* ** Print into memory obtained from sqliteMalloc(). Use the internal ** %-conversion extensions. */ char *sqliteVMPrintf(const char *zFormat, va_list ap){ char zBase[1000]; return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); } /* ** Print into memory obtained from sqliteMalloc(). Use the internal ** %-conversion extensions. */ char *sqliteMPrintf(const char *zFormat, ...){ va_list ap; char *z; char zBase[1000]; va_start(ap, zFormat); z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap); va_end(ap); return z; } /* ** Print into memory obtained from malloc(). Do not use the internal ** %-conversion extensions. This routine is for use by external users. */ char *sqlite_mprintf(const char *zFormat, ...){ va_list ap; char *z; char zBuf[200]; va_start(ap,zFormat); z = base_vprintf((void*(*)(void*,int))realloc, 0, zBuf, sizeof(zBuf), zFormat, ap); va_end(ap); return z; } /* This is the varargs version of sqlite_mprintf. */ char *sqlite_vmprintf(const char *zFormat, va_list ap){ char zBuf[200]; return base_vprintf((void*(*)(void*,int))realloc, 0, zBuf, sizeof(zBuf), zFormat, ap); } /* ** sqlite_snprintf() works like snprintf() except that it ignores the ** current locale settings. This is important for SQLite because we ** are not able to use a "," as the decimal point in place of "." as ** specified by some locales. */ char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); z = base_vprintf(0, 0, zBuf, n, zFormat, ap); va_end(ap); return z; } /* ** The following four routines implement the varargs versions of the ** sqlite_exec() and sqlite_get_table() interfaces. See the sqlite.h ** header files for a more detailed description of how these interfaces ** work. ** ** These routines are all just simple wrappers. */ int sqlite_exec_printf( sqlite *db, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ sqlite_callback xCallback, /* Callback function */ void *pArg, /* 1st argument to callback function */ char **errmsg, /* Error msg written here */ ... /* Arguments to the format string. */ ){ va_list ap; int rc; va_start(ap, errmsg); rc = sqlite_exec_vprintf(db, sqlFormat, xCallback, pArg, errmsg, ap); va_end(ap); return rc; } int sqlite_exec_vprintf( sqlite *db, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ sqlite_callback xCallback, /* Callback function */ void *pArg, /* 1st argument to callback function */ char **errmsg, /* Error msg written here */ va_list ap /* Arguments to the format string. */ ){ char *zSql; int rc; zSql = sqlite_vmprintf(sqlFormat, ap); rc = sqlite_exec(db, zSql, xCallback, pArg, errmsg); free(zSql); return rc; } int sqlite_get_table_printf( sqlite *db, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ char ***resultp, /* Result written to a char *[] that this points to */ int *nrow, /* Number of result rows written here */ int *ncol, /* Number of result columns written here */ char **errmsg, /* Error msg written here */ ... /* Arguments to the format string */ ){ va_list ap; int rc; va_start(ap, errmsg); rc = sqlite_get_table_vprintf(db, sqlFormat, resultp, nrow, ncol, errmsg, ap); va_end(ap); return rc; } int sqlite_get_table_vprintf( sqlite *db, /* An open database */ const char *sqlFormat, /* printf-style format string for the SQL */ char ***resultp, /* Result written to a char *[] that this points to */ int *nrow, /* Number of result rows written here */ int *ncolumn, /* Number of result columns written here */ char **errmsg, /* Error msg written here */ va_list ap /* Arguments to the format string */ ){ char *zSql; int rc; zSql = sqlite_vmprintf(sqlFormat, ap); rc = sqlite_get_table(db, zSql, resultp, nrow, ncolumn, errmsg); free(zSql); return rc; } DBD-SQLite2-0.36/os.h0000644000175000017500000001361512130553602013415 0ustar rurbanrurban/* ** 2001 September 16 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This header file (together with is companion C source-code file ** "os.c") attempt to abstract the underlying operating system so that ** the SQLite library will work on both POSIX and windows systems. */ #ifndef _SQLITE_OS_H_ #define _SQLITE_OS_H_ /* ** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE ** to the compiler command line. */ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks ** large file support, or if the OS is windows, these should be no-ops. ** ** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch ** on the compiler command line. This is necessary if you are compiling ** on a recent machine (ex: RedHat 7.2) but you want your code to work ** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 ** without this option, LFS is enable. But LFS does not exist in the kernel ** in RedHat 6.0, so the code won't work. Hence, for maximum binary ** portability you should omit LFS. ** ** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. */ #ifndef SQLITE_DISABLE_LFS # define _LARGE_FILE 1 # ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif /* ** Temporary files are named starting with this prefix followed by 16 random ** alphanumeric characters, and no file extension. They are stored in the ** OS's standard temporary file directory, and are deleted prior to exit. ** If sqlite is being embedded in another program, you may wish to change the ** prefix to reflect your program's name, so that if your program exits ** prematurely, old temporary files can be easily identified. This can be done ** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line. */ #ifndef TEMP_FILE_PREFIX # define TEMP_FILE_PREFIX "sqlite_" #endif /* ** Figure out if we are dealing with Unix, Windows or MacOS. ** ** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix. ** The MacOS build is designed to use CodeWarrior (tested with v8) */ #ifndef OS_UNIX # ifndef OS_WIN # ifndef OS_MAC # if defined(__MACOS__) # define OS_MAC 1 # define OS_WIN 0 # define OS_UNIX 0 # elif defined(_WIN32) || defined(WIN32) || defined(__MINGW32__) || defined(__BORLANDC__) # define OS_MAC 0 # define OS_WIN 1 # define OS_UNIX 0 # else # define OS_MAC 0 # define OS_WIN 0 # define OS_UNIX 1 # endif # else # define OS_WIN 0 # define OS_UNIX 0 # endif # else # define OS_MAC 0 # define OS_UNIX 0 # endif #else # define OS_MAC 0 # ifndef OS_WIN # define OS_WIN 0 # endif #endif /* ** A handle for an open file is stored in an OsFile object. */ #if OS_UNIX # include # include # include # include typedef struct OsFile OsFile; struct OsFile { struct openCnt *pOpen; /* Info about all open fd's on this inode */ struct lockInfo *pLock; /* Info about locks on this inode */ int fd; /* The file descriptor */ int locked; /* True if this instance holds the lock */ int dirfd; /* File descriptor for the directory */ }; # define SQLITE_TEMPNAME_SIZE 200 # if defined(HAVE_USLEEP) && HAVE_USLEEP # define SQLITE_MIN_SLEEP_MS 1 # else # define SQLITE_MIN_SLEEP_MS 1000 # endif typedef off_t sql_off_t; #endif #if OS_WIN #include #include typedef struct OsFile OsFile; struct OsFile { HANDLE h; /* Handle for accessing the file */ int locked; /* 0: unlocked, <0: write lock, >0: read lock */ }; # if defined(_MSC_VER) || defined(__BORLANDC__) typedef __int64 sql_off_t; # else # if defined(__MINGW32__) /* always large file */ typedef long long sql_off_t; # else typedef off_t sql_off_t; /* this should not happen */ # endif # endif # define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) # define SQLITE_MIN_SLEEP_MS 1 #endif #if OS_MAC # include # include typedef struct OsFile OsFile; struct OsFile { SInt16 refNum; /* Data fork/file reference number */ SInt16 refNumRF; /* Resource fork reference number (for locking) */ int locked; /* 0: unlocked, <0: write lock, >0: read lock */ int delOnClose; /* True if file is to be deleted on close */ char *pathToDel; /* Name of file to delete on close */ }; # ifdef _LARGE_FILE typedef SInt64 sql_off_t; # else typedef SInt32 sql_off_t; # endif # define SQLITE_TEMPNAME_SIZE _MAX_PATH # define SQLITE_MIN_SLEEP_MS 17 #endif int sqliteOsDelete(const char*); int sqliteOsFileExists(const char*); int sqliteOsFileRename(const char*, const char*); int sqliteOsOpenReadWrite(const char*, OsFile*, int*); int sqliteOsOpenExclusive(const char*, OsFile*, int); int sqliteOsOpenReadOnly(const char*, OsFile*); int sqliteOsOpenDirectory(const char*, OsFile*); int sqliteOsTempFileName(char*); int sqliteOsClose(OsFile*); int sqliteOsRead(OsFile*, void*, int amt); int sqliteOsWrite(OsFile*, const void*, int amt); int sqliteOsSeek(OsFile*, sql_off_t offset); int sqliteOsSync(OsFile*); int sqliteOsTruncate(OsFile*, sql_off_t size); int sqliteOsFileSize(OsFile*, sql_off_t *pSize); int sqliteOsReadLock(OsFile*); int sqliteOsWriteLock(OsFile*); int sqliteOsUnlock(OsFile*); int sqliteOsRandomSeed(char*); int sqliteOsSleep(int ms); int sqliteOsCurrentTime(double*); void sqliteOsEnterMutex(void); void sqliteOsLeaveMutex(void); char *sqliteOsFullPathname(const char*); #endif /* _SQLITE_OS_H_ */ DBD-SQLite2-0.36/expr.c0000644000175000017500000014373412126353147013762 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include "sqliteInt.h" #include /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function ** is responsible for making sure the node eventually gets freed. */ Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ /* When malloc fails, we leak memory from pLeft and pRight */ return 0; } pNew->op = op; pNew->pLeft = pLeft; pNew->pRight = pRight; if( pToken ){ assert( pToken->dyn==0 ); pNew->token = *pToken; pNew->span = *pToken; }else{ assert( pNew->token.dyn==0 ); assert( pNew->token.z==0 ); assert( pNew->token.n==0 ); if( pLeft && pRight ){ sqliteExprSpan(pNew, &pLeft->span, &pRight->span); }else{ pNew->span = pNew->token; } } return pNew; } /* ** Set the Expr.span field of the given expression to span all ** text between the two given tokens. */ void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ assert( pRight!=0 ); assert( pLeft!=0 ); /* Note: pExpr might be NULL due to a prior malloc failure */ if( pExpr && pRight->z && pLeft->z ){ if( pLeft->dyn==0 && pRight->dyn==0 ){ pExpr->span.z = pLeft->z; pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z); }else{ pExpr->span.z = 0; } } } /* ** Construct a new expression node for a function with multiple ** arguments. */ Expr *sqliteExprFunction(ExprList *pList, Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ /* sqliteExprListDelete(pList); // Leak pList when malloc fails */ return 0; } pNew->op = TK_FUNCTION; pNew->pList = pList; if( pToken ){ assert( pToken->dyn==0 ); pNew->token = *pToken; }else{ pNew->token.z = 0; } pNew->span = pNew->token; return pNew; } /* ** Recursively delete an expression tree. */ void sqliteExprDelete(Expr *p){ if( p==0 ) return; if( p->span.dyn ) sqliteFree((char*)p->span.z); if( p->token.dyn ) sqliteFree((char*)p->token.z); sqliteExprDelete(p->pLeft); sqliteExprDelete(p->pRight); sqliteExprListDelete(p->pList); sqliteSelectDelete(p->pSelect); sqliteFree(p); } /* ** The following group of routines make deep copies of expressions, ** expression lists, ID lists, and select statements. The copies can ** be deleted (by being passed to their respective ...Delete() routines) ** without effecting the originals. ** ** The expression list, ID, and source lists return by sqliteExprListDup(), ** sqliteIdListDup(), and sqliteSrcListDup() can not be further expanded ** by subsequent calls to sqlite*ListAppend() routines. ** ** Any tables that the SrcList might point to are not duplicated. */ Expr *sqliteExprDup(Expr *p){ Expr *pNew; if( p==0 ) return 0; pNew = sqliteMallocRaw( sizeof(*p) ); if( pNew==0 ) return 0; memcpy(pNew, p, sizeof(*pNew)); if( p->token.z!=0 ){ pNew->token.z = sqliteStrDup(p->token.z); pNew->token.dyn = 1; }else{ assert( pNew->token.z==0 ); } pNew->span.z = 0; pNew->pLeft = sqliteExprDup(p->pLeft); pNew->pRight = sqliteExprDup(p->pRight); pNew->pList = sqliteExprListDup(p->pList); pNew->pSelect = sqliteSelectDup(p->pSelect); return pNew; } void sqliteTokenCopy(Token *pTo, Token *pFrom){ if( pTo->dyn ) sqliteFree((char*)pTo->z); if( pFrom->z ){ pTo->n = pFrom->n; pTo->z = sqliteStrNDup(pFrom->z, pFrom->n); pTo->dyn = 1; }else{ pTo->z = 0; } } ExprList *sqliteExprListDup(ExprList *p){ ExprList *pNew; struct ExprList_item *pItem; int i; if( p==0 ) return 0; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nExpr = pNew->nAlloc = p->nExpr; pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) ); if( pItem==0 ){ sqliteFree(pNew); return 0; } for(i=0; inExpr; i++, pItem++){ Expr *pNewExpr, *pOldExpr; pItem->pExpr = pNewExpr = sqliteExprDup(pOldExpr = p->a[i].pExpr); if( pOldExpr->span.z!=0 && pNewExpr ){ /* Always make a copy of the span for top-level expressions in the ** expression list. The logic in SELECT processing that determines ** the names of columns in the result set needs this information */ sqliteTokenCopy(&pNewExpr->span, &pOldExpr->span); } assert( pNewExpr==0 || pNewExpr->span.z!=0 || pOldExpr->span.z==0 || sqlite_malloc_failed ); pItem->zName = sqliteStrDup(p->a[i].zName); pItem->sortOrder = p->a[i].sortOrder; pItem->isAgg = p->a[i].isAgg; pItem->done = 0; } return pNew; } SrcList *sqliteSrcListDup(SrcList *p){ SrcList *pNew; int i; int nByte; if( p==0 ) return 0; nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); pNew = sqliteMallocRaw( nByte ); if( pNew==0 ) return 0; pNew->nSrc = pNew->nAlloc = p->nSrc; for(i=0; inSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->pTab = 0; pNewItem->pSelect = sqliteSelectDup(pOldItem->pSelect); pNewItem->pOn = sqliteExprDup(pOldItem->pOn); pNewItem->pUsing = sqliteIdListDup(pOldItem->pUsing); } return pNew; } IdList *sqliteIdListDup(IdList *p){ IdList *pNew; int i; if( p==0 ) return 0; pNew = sqliteMallocRaw( sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->nId = pNew->nAlloc = p->nId; pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ) return 0; for(i=0; inId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->idx = pOldItem->idx; } return pNew; } Select *sqliteSelectDup(Select *p){ Select *pNew; if( p==0 ) return 0; pNew = sqliteMallocRaw( sizeof(*p) ); if( pNew==0 ) return 0; pNew->isDistinct = p->isDistinct; pNew->pEList = sqliteExprListDup(p->pEList); pNew->pSrc = sqliteSrcListDup(p->pSrc); pNew->pWhere = sqliteExprDup(p->pWhere); pNew->pGroupBy = sqliteExprListDup(p->pGroupBy); pNew->pHaving = sqliteExprDup(p->pHaving); pNew->pOrderBy = sqliteExprListDup(p->pOrderBy); pNew->op = p->op; pNew->pPrior = sqliteSelectDup(p->pPrior); pNew->nLimit = p->nLimit; pNew->nOffset = p->nOffset; pNew->zSelect = 0; pNew->iLimit = -1; pNew->iOffset = -1; return pNew; } /* ** Add a new element to the end of an expression list. If pList is ** initially NULL, then create a new expression list. */ ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){ if( pList==0 ){ pList = sqliteMalloc( sizeof(ExprList) ); if( pList==0 ){ /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */ return 0; } assert( pList->nAlloc==0 ); } if( pList->nAlloc<=pList->nExpr ){ pList->nAlloc = pList->nAlloc*2 + 4; pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); if( pList->a==0 ){ /* sqliteExprDelete(pExpr); // Leak memory if malloc fails */ pList->nExpr = pList->nAlloc = 0; return pList; } } assert( pList->a!=0 ); if( pExpr || pName ){ struct ExprList_item *pItem = &pList->a[pList->nExpr++]; memset(pItem, 0, sizeof(*pItem)); pItem->pExpr = pExpr; if( pName ){ sqliteSetNString(&pItem->zName, pName->z, pName->n, 0); sqliteDequote(pItem->zName); } } return pList; } /* ** Delete an entire expression list. */ void sqliteExprListDelete(ExprList *pList){ int i; if( pList==0 ) return; assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); assert( pList->nExpr<=pList->nAlloc ); for(i=0; inExpr; i++){ sqliteExprDelete(pList->a[i].pExpr); sqliteFree(pList->a[i].zName); } sqliteFree(pList->a); sqliteFree(pList); } /* ** Walk an expression tree. Return 1 if the expression is constant ** and 0 if it involves variables. ** ** For the purposes of this function, a double-quoted string (ex: "abc") ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqliteExprIsConstant(Expr *p){ switch( p->op ){ case TK_ID: case TK_COLUMN: case TK_DOT: case TK_FUNCTION: return 0; case TK_NULL: case TK_STRING: case TK_INTEGER: case TK_FLOAT: case TK_VARIABLE: return 1; default: { if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0; if( p->pRight && !sqliteExprIsConstant(p->pRight) ) return 0; if( p->pList ){ int i; for(i=0; ipList->nExpr; i++){ if( !sqliteExprIsConstant(p->pList->a[i].pExpr) ) return 0; } } return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0); } } return 0; } /* ** If the given expression codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ int sqliteExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { if( sqliteFitsIn32Bits(p->token.z) ){ *pValue = atoi(p->token.z); return 1; } break; } case TK_STRING: { const char *z = p->token.z; int n = p->token.n; if( n>0 && z[0]=='-' ){ z++; n--; } while( n>0 && *z && isdigit(*z) ){ z++; n--; } if( n==0 && sqliteFitsIn32Bits(p->token.z) ){ *pValue = atoi(p->token.z); return 1; } break; } case TK_UPLUS: { return sqliteExprIsInteger(p->pLeft, pValue); } case TK_UMINUS: { int v; if( sqliteExprIsInteger(p->pLeft, &v) ){ *pValue = -v; return 1; } break; } default: break; } return 0; } /* ** Return TRUE if the given string is a row-id column name. */ int sqliteIsRowid(const char *z){ if( sqliteStrICmp(z, "_ROWID_")==0 ) return 1; if( sqliteStrICmp(z, "ROWID")==0 ) return 1; if( sqliteStrICmp(z, "OID")==0 ) return 1; return 0; } /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up ** that name in the set of source tables in pSrcList and make the pExpr ** expression node refer back to that source column. The following changes ** are made to pExpr: ** ** pExpr->iDb Set the index in db->aDb[] of the database holding ** the table. ** pExpr->iTable Set to the cursor number for the table obtained ** from pSrcList. ** pExpr->iColumn Set to the column number within the table. ** pExpr->dataType Set to the appropriate data type for the column. ** pExpr->op Set to TK_COLUMN. ** pExpr->pLeft Any expression this points to is deleted ** pExpr->pRight Any expression this points to is deleted. ** ** The pDbToken is the name of the database (the "X"). This value may be ** NULL meaning that name is of the form Y.Z or Z. Any available database ** can be used. The pTableToken is the name of the table (the "Y"). This ** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it ** means that the form of the name is Z and that columns from any table ** can be used. ** ** If the name cannot be resolved unambiguously, leave an error message ** in pParse and return non-zero. Return zero on success. */ static int lookupName( Parse *pParse, /* The parsing context */ Token *pDbToken, /* Name of the database containing table, or NULL */ Token *pTableToken, /* Name of table containing column, or NULL */ Token *pColumnToken, /* Name of the column. */ SrcList *pSrcList, /* List of tables used to resolve column names */ ExprList *pEList, /* List of expressions used to resolve "AS" */ Expr *pExpr /* Make this EXPR node point to the selected column */ ){ char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ char *zCol = 0; /* Name of the column. The "Z" */ int i, j; /* Loop counters */ int cnt = 0; /* Number of matching column names */ int cntTab = 0; /* Number of matching table names */ sqlite *db = pParse->db; /* The database */ assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ if( pDbToken && pDbToken->z ){ zDb = sqliteStrNDup(pDbToken->z, pDbToken->n); sqliteDequote(zDb); }else{ zDb = 0; } if( pTableToken && pTableToken->z ){ zTab = sqliteStrNDup(pTableToken->z, pTableToken->n); sqliteDequote(zTab); }else{ assert( zDb==0 ); zTab = 0; } zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n); sqliteDequote(zCol); if( sqlite_malloc_failed ){ return 1; /* Leak memory (zDb and zTab) if malloc fails */ } assert( zTab==0 || pEList==0 ); pExpr->iTable = -1; for(i=0; inSrc; i++){ struct SrcList_item *pItem = &pSrcList->a[i]; Table *pTab = pItem->pTab; Column *pCol; if( pTab==0 ) continue; assert( pTab->nCol>0 ); if( zTab ){ if( pItem->zAlias ){ char *zTabName = pItem->zAlias; if( sqliteStrICmp(zTabName, zTab)!=0 ) continue; }else{ char *zTabName = pTab->zName; if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue; if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){ continue; } } } if( 0==(cntTab++) ){ pExpr->iTable = pItem->iCursor; pExpr->iDb = pTab->iDb; } for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ if( sqliteStrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iTable = pItem->iCursor; pExpr->iDb = pTab->iDb; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK; break; } } } /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){ TriggerStack *pTriggerStack = pParse->trigStack; Table *pTab = 0; if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){ pExpr->iTable = pTriggerStack->newIdx; assert( pTriggerStack->pTab ); pTab = pTriggerStack->pTab; }else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){ pExpr->iTable = pTriggerStack->oldIdx; assert( pTriggerStack->pTab ); pTab = pTriggerStack->pTab; } if( pTab ){ int j; Column *pCol = pTab->aCol; pExpr->iDb = pTab->iDb; cntTab++; for(j=0; j < pTab->nCol; j++, pCol++) { if( sqliteStrICmp(pCol->zName, zCol)==0 ){ cnt++; pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK; break; } } } } /* ** Perhaps the name is a reference to the ROWID */ if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){ cnt = 1; pExpr->iColumn = -1; pExpr->dataType = SQLITE_SO_NUM; } /* ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z ** might refer to an result-set alias. This happens, for example, when ** we are resolving names in the WHERE clause of the following command: ** ** SELECT a+b AS x FROM table WHERE x<10; ** ** In cases like this, replace pExpr with a copy of the expression that ** forms the result set entry ("a+b" in the example) and return immediately. ** Note that the expression in the result set should have already been ** resolved by the time the WHERE clause is resolved. */ if( cnt==0 && pEList!=0 ){ for(j=0; jnExpr; j++){ char *zAs = pEList->a[j].zName; if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){ assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pExpr->op = TK_AS; pExpr->iColumn = j; pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr); sqliteFree(zCol); assert( zTab==0 && zDb==0 ); return 0; } } } /* ** If X and Y are NULL (in other words if only the column name Z is ** supplied) and the value of Z is enclosed in double-quotes, then ** Z is a string literal if it doesn't match any column names. In that ** case, we need to return right away and not make any changes to ** pExpr. */ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ sqliteFree(zCol); return 0; } /* ** cnt==0 means there was not match. cnt>1 means there were two or ** more matches. Either way, we have an error. */ if( cnt!=1 ){ char *z = 0; char *zErr; zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; if( zDb ){ sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0); }else if( zTab ){ sqliteSetString(&z, zTab, ".", zCol, 0); }else{ z = sqliteStrDup(zCol); } sqliteErrorMsg(pParse, zErr, z); sqliteFree(z); } /* Clean up and return */ sqliteFree(zDb); sqliteFree(zTab); sqliteFree(zCol); sqliteExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqliteExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; sqliteAuthRead(pParse, pExpr, pSrcList); return cnt!=1; } /* ** This routine walks an expression tree and resolves references to ** table columns. Nodes of the form ID.ID or ID resolve into an ** index to the table in the table list and a column offset. The ** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable ** value is changed to the index of the referenced table in pTabList ** plus the "base" value. The base value will ultimately become the ** VDBE cursor number for a cursor that is pointing into the referenced ** table. The Expr.iColumn value is changed to the index of the column ** of the referenced table. The Expr.iColumn value for the special ** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an ** alias for ROWID. ** ** We also check for instances of the IN operator. IN comes in two ** forms: ** ** expr IN (exprlist) ** and ** expr IN (SELECT ...) ** ** The first form is handled by creating a set holding the list ** of allowed values. The second form causes the SELECT to generate ** a temporary table. ** ** This routine also looks for scalar SELECTs that are part of an expression. ** If it finds any, it generates code to write the value of that select ** into a memory cell. ** ** Unknown columns or tables provoke an error. The function returns ** the number of errors seen and leaves an error message on pParse->zErrMsg. */ int sqliteExprResolveIds( Parse *pParse, /* The parser context */ SrcList *pSrcList, /* List of tables used to resolve column names */ ExprList *pEList, /* List of expressions used to resolve "AS" */ Expr *pExpr /* The expression to be analyzed. */ ){ int i; if( pExpr==0 || pSrcList==0 ) return 0; for(i=0; inSrc; i++){ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab ); } switch( pExpr->op ){ /* Double-quoted strings (ex: "abc") are used as identifiers if ** possible. Otherwise they remain as strings. Single-quoted ** strings (ex: 'abc') are always string literals. */ case TK_STRING: { if( pExpr->token.z[0]=='\'' ) break; /* Fall thru into the TK_ID case if this is a double-quoted string */ } /* A lone identifier is the name of a columnd. */ case TK_ID: { if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){ return 1; } break; } /* A table name and column name: ID.ID ** Or a database, table and column: ID.ID.ID */ case TK_DOT: { Token *pColumn; Token *pTable; Token *pDb; Expr *pRight; pRight = pExpr->pRight; if( pRight->op==TK_ID ){ pDb = 0; pTable = &pExpr->pLeft->token; pColumn = &pRight->token; }else{ assert( pRight->op==TK_DOT ); pDb = &pExpr->pLeft->token; pTable = &pRight->pLeft->token; pColumn = &pRight->pRight->token; } if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){ return 1; } break; } case TK_IN: { Vdbe *v = sqliteGetVdbe(pParse); if( v==0 ) return 1; if( sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){ return 1; } if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into a temporary ** table. The cursor number of the temporary table has already ** been put in iTable by sqliteExprResolveInSelect(). */ pExpr->iTable = pParse->nTab++; sqliteVdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 1); sqliteSelect(pParse, pExpr->pSelect, SRT_Set, pExpr->iTable, 0,0,0); }else if( pExpr->pList ){ /* Case 2: expr IN (exprlist) ** ** Create a set to put the exprlist values in. The Set id is stored ** in iTable. */ int i, iSet; for(i=0; ipList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; if( !sqliteExprIsConstant(pE2) ){ sqliteErrorMsg(pParse, "right-hand side of IN operator must be constant"); return 1; } if( sqliteExprCheck(pParse, pE2, 0, 0) ){ return 1; } } iSet = pExpr->iTable = pParse->nSet++; for(i=0; ipList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; switch( pE2->op ){ case TK_FLOAT: case TK_INTEGER: case TK_STRING: { int addr; assert( pE2->token.z ); addr = sqliteVdbeOp3(v, OP_SetInsert, iSet, 0, pE2->token.z, pE2->token.n); sqliteVdbeDequoteP3(v, addr); break; } default: { sqliteExprCode(pParse, pE2); sqliteVdbeAddOp(v, OP_SetInsert, iSet, 0); break; } } } } break; } case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ pExpr->iColumn = pParse->nMem++; if( sqliteSelect(pParse, pExpr->pSelect, SRT_Mem, pExpr->iColumn,0,0,0) ){ return 1; } break; } /* For all else, just recursively walk the tree */ default: { if( pExpr->pLeft && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){ return 1; } if( pExpr->pRight && sqliteExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){ return 1; } if( pExpr->pList ){ int i; ExprList *pList = pExpr->pList; for(i=0; inExpr; i++){ Expr *pArg = pList->a[i].pExpr; if( sqliteExprResolveIds(pParse, pSrcList, pEList, pArg) ){ return 1; } } } } } return 0; } /* ** pExpr is a node that defines a function of some kind. It might ** be a syntactic function like "count(x)" or it might be a function ** that implements an operator, like "a LIKE b". ** ** This routine makes *pzName point to the name of the function and ** *pnName hold the number of characters in the function name. */ static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){ switch( pExpr->op ){ case TK_FUNCTION: { *pzName = pExpr->token.z; *pnName = pExpr->token.n; break; } case TK_LIKE: { *pzName = "like"; *pnName = 4; break; } case TK_GLOB: { *pzName = "glob"; *pnName = 4; break; } default: { *pzName = "can't happen"; *pnName = 12; break; } } } /* ** Error check the functions in an expression. Make sure all ** function names are recognized and all functions have the correct ** number of arguments. Leave an error message in pParse->zErrMsg ** if anything is amiss. Return the number of errors. ** ** if pIsAgg is not null and this expression is an aggregate function ** (like count(*) or max(value)) then write a 1 into *pIsAgg. */ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ int nErr = 0; if( pExpr==0 ) return 0; switch( pExpr->op ){ case TK_GLOB: case TK_LIKE: case TK_FUNCTION: { int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ int i; int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; getFunctionName(pExpr, &zId, &nId); pDef = sqliteFindFunction(pParse->db, zId, nId, n, 0); if( pDef==0 ){ pDef = sqliteFindFunction(pParse->db, zId, nId, -1, 0); if( pDef==0 ){ no_such_func = 1; }else{ wrong_num_args = 1; } }else{ is_agg = pDef->xFunc==0; } if( is_agg && !allowAgg ){ sqliteErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId); nErr++; is_agg = 0; }else if( no_such_func ){ sqliteErrorMsg(pParse, "no such function: %.*s", nId, zId); nErr++; }else if( wrong_num_args ){ sqliteErrorMsg(pParse,"wrong number of arguments to function %.*s()", nId, zId); nErr++; } if( is_agg ){ pExpr->op = TK_AGG_FUNCTION; if( pIsAgg ) *pIsAgg = 1; } for(i=0; nErr==0 && ipList->a[i].pExpr, allowAgg && !is_agg, pIsAgg); } if( pDef==0 ){ /* Already reported an error */ }else if( pDef->dataType>=0 ){ if( pDef->dataTypedataType = sqliteExprType(pExpr->pList->a[pDef->dataType].pExpr); }else{ pExpr->dataType = SQLITE_SO_NUM; } }else if( pDef->dataType==SQLITE_ARGS ){ pDef->dataType = SQLITE_SO_TEXT; for(i=0; ipList->a[i].pExpr)==SQLITE_SO_NUM ){ pExpr->dataType = SQLITE_SO_NUM; break; } } }else if( pDef->dataType==SQLITE_NUMERIC ){ pExpr->dataType = SQLITE_SO_NUM; }else{ pExpr->dataType = SQLITE_SO_TEXT; } } default: { if( pExpr->pLeft ){ nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg); } if( nErr==0 && pExpr->pRight ){ nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg); } if( nErr==0 && pExpr->pList ){ int n = pExpr->pList->nExpr; int i; for(i=0; nErr==0 && ipList->a[i].pExpr; nErr = sqliteExprCheck(pParse, pE2, allowAgg, pIsAgg); } } break; } } return nErr; } /* ** Return either SQLITE_SO_NUM or SQLITE_SO_TEXT to indicate whether the ** given expression should sort as numeric values or as text. ** ** The sqliteExprResolveIds() and sqliteExprCheck() routines must have ** both been called on the expression before it is passed to this routine. */ int sqliteExprType(Expr *p){ if( p==0 ) return SQLITE_SO_NUM; while( p ) switch( p->op ){ case TK_PLUS: case TK_MINUS: case TK_STAR: case TK_SLASH: case TK_AND: case TK_OR: case TK_ISNULL: case TK_NOTNULL: case TK_NOT: case TK_UMINUS: case TK_UPLUS: case TK_BITAND: case TK_BITOR: case TK_BITNOT: case TK_LSHIFT: case TK_RSHIFT: case TK_REM: case TK_INTEGER: case TK_FLOAT: case TK_IN: case TK_BETWEEN: case TK_GLOB: case TK_LIKE: return SQLITE_SO_NUM; case TK_STRING: case TK_NULL: case TK_CONCAT: case TK_VARIABLE: return SQLITE_SO_TEXT; case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: if( sqliteExprType(p->pLeft)==SQLITE_SO_NUM ){ return SQLITE_SO_NUM; } p = p->pRight; break; case TK_AS: p = p->pLeft; break; case TK_COLUMN: case TK_FUNCTION: case TK_AGG_FUNCTION: return p->dataType; case TK_SELECT: assert( p->pSelect ); assert( p->pSelect->pEList ); assert( p->pSelect->pEList->nExpr>0 ); p = p->pSelect->pEList->a[0].pExpr; break; case TK_CASE: { if( p->pRight && sqliteExprType(p->pRight)==SQLITE_SO_NUM ){ return SQLITE_SO_NUM; } if( p->pList ){ int i; ExprList *pList = p->pList; for(i=1; inExpr; i+=2){ if( sqliteExprType(pList->a[i].pExpr)==SQLITE_SO_NUM ){ return SQLITE_SO_NUM; } } } return SQLITE_SO_TEXT; } default: assert( p->op==TK_ABORT ); /* Can't Happen */ break; } return SQLITE_SO_NUM; } /* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. */ void sqliteExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; int op; if( v==0 || pExpr==0 ) return; switch( pExpr->op ){ case TK_PLUS: op = OP_Add; break; case TK_MINUS: op = OP_Subtract; break; case TK_STAR: op = OP_Multiply; break; case TK_SLASH: op = OP_Divide; break; case TK_AND: op = OP_And; break; case TK_OR: op = OP_Or; break; case TK_LT: op = OP_Lt; break; case TK_LE: op = OP_Le; break; case TK_GT: op = OP_Gt; break; case TK_GE: op = OP_Ge; break; case TK_NE: op = OP_Ne; break; case TK_EQ: op = OP_Eq; break; case TK_ISNULL: op = OP_IsNull; break; case TK_NOTNULL: op = OP_NotNull; break; case TK_NOT: op = OP_Not; break; case TK_UMINUS: op = OP_Negative; break; case TK_BITAND: op = OP_BitAnd; break; case TK_BITOR: op = OP_BitOr; break; case TK_BITNOT: op = OP_BitNot; break; case TK_LSHIFT: op = OP_ShiftLeft; break; case TK_RSHIFT: op = OP_ShiftRight; break; case TK_REM: op = OP_Remainder; break; default: break; } switch( pExpr->op ){ case TK_COLUMN: { if( pParse->useAgg ){ sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); }else if( pExpr->iColumn>=0 ){ sqliteVdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); }else{ sqliteVdbeAddOp(v, OP_Recno, pExpr->iTable, 0); } break; } case TK_STRING: case TK_FLOAT: case TK_INTEGER: { if( pExpr->op==TK_INTEGER && sqliteFitsIn32Bits(pExpr->token.z) ){ sqliteVdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0); }else{ sqliteVdbeAddOp(v, OP_String, 0, 0); } assert( pExpr->token.z ); sqliteVdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n); sqliteVdbeDequoteP3(v, -1); break; } case TK_NULL: { sqliteVdbeAddOp(v, OP_String, 0, 0); break; } case TK_VARIABLE: { sqliteVdbeAddOp(v, OP_Variable, pExpr->iTable, 0); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ op += 6; /* Convert numeric opcodes to text opcodes */ } /* Fall through into the next case */ } case TK_AND: case TK_OR: case TK_PLUS: case TK_STAR: case TK_MINUS: case TK_REM: case TK_BITAND: case TK_BITOR: case TK_SLASH: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, 0, 0); break; } case TK_LSHIFT: case TK_RSHIFT: { sqliteExprCode(pParse, pExpr->pRight); sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 0, 0); break; } case TK_CONCAT: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, OP_Concat, 2, 0); break; } case TK_UMINUS: { assert( pExpr->pLeft ); if( pExpr->pLeft->op==TK_FLOAT || pExpr->pLeft->op==TK_INTEGER ){ Token *p = &pExpr->pLeft->token; char *z = sqliteMalloc( p->n + 2 ); sprintf(z, "-%.*s", p->n, p->z); if( pExpr->pLeft->op==TK_INTEGER && sqliteFitsIn32Bits(z) ){ sqliteVdbeAddOp(v, OP_Integer, atoi(z), 0); }else{ sqliteVdbeAddOp(v, OP_String, 0, 0); } sqliteVdbeChangeP3(v, -1, z, p->n+1); sqliteFree(z); break; } /* Fall through into TK_NOT */ } case TK_BITNOT: case TK_NOT: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 0, 0); break; } case TK_ISNULL: case TK_NOTNULL: { int dest; sqliteVdbeAddOp(v, OP_Integer, 1, 0); sqliteExprCode(pParse, pExpr->pLeft); dest = sqliteVdbeCurrentAddr(v) + 2; sqliteVdbeAddOp(v, op, 1, dest); sqliteVdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_AGG_FUNCTION: { sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); break; } case TK_GLOB: case TK_LIKE: case TK_FUNCTION: { ExprList *pList = pExpr->pList; int nExpr = pList ? pList->nExpr : 0; FuncDef *pDef; int nId; const char *zId; getFunctionName(pExpr, &zId, &nId); pDef = sqliteFindFunction(pParse->db, zId, nId, nExpr, 0); assert( pDef!=0 ); nExpr = sqliteExprCodeExprList(pParse, pList, pDef->includeTypes); sqliteVdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER); break; } case TK_SELECT: { sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); break; } case TK_IN: { int addr; sqliteVdbeAddOp(v, OP_Integer, 1, 0); sqliteExprCode(pParse, pExpr->pLeft); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_NotNull, -1, addr+4); sqliteVdbeAddOp(v, OP_Pop, 2, 0); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_Goto, 0, addr+6); if( pExpr->pSelect ){ sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, addr+6); }else{ sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, addr+6); } sqliteVdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_BETWEEN: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); sqliteVdbeAddOp(v, OP_Ge, 0, 0); sqliteVdbeAddOp(v, OP_Pull, 1, 0); sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); sqliteVdbeAddOp(v, OP_Le, 0, 0); sqliteVdbeAddOp(v, OP_And, 0, 0); break; } case TK_UPLUS: case TK_AS: { sqliteExprCode(pParse, pExpr->pLeft); break; } case TK_CASE: { int expr_end_label; int jumpInst; int addr; int nExpr; int i; assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); assert(pExpr->pList->nExpr > 0); nExpr = pExpr->pList->nExpr; expr_end_label = sqliteVdbeMakeLabel(v); if( pExpr->pLeft ){ sqliteExprCode(pParse, pExpr->pLeft); } for(i=0; ipList->a[i].pExpr); if( pExpr->pLeft ){ sqliteVdbeAddOp(v, OP_Dup, 1, 1); jumpInst = sqliteVdbeAddOp(v, OP_Ne, 1, 0); sqliteVdbeAddOp(v, OP_Pop, 1, 0); }else{ jumpInst = sqliteVdbeAddOp(v, OP_IfNot, 1, 0); } sqliteExprCode(pParse, pExpr->pList->a[i+1].pExpr); sqliteVdbeAddOp(v, OP_Goto, 0, expr_end_label); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeChangeP2(v, jumpInst, addr); } if( pExpr->pLeft ){ sqliteVdbeAddOp(v, OP_Pop, 1, 0); } if( pExpr->pRight ){ sqliteExprCode(pParse, pExpr->pRight); }else{ sqliteVdbeAddOp(v, OP_String, 0, 0); } sqliteVdbeResolveLabel(v, expr_end_label); break; } case TK_RAISE: { if( !pParse->trigStack ){ sqliteErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); pParse->nErr++; return; } if( pExpr->iColumn == OE_Rollback || pExpr->iColumn == OE_Abort || pExpr->iColumn == OE_Fail ){ sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, pExpr->token.z, pExpr->token.n); sqliteVdbeDequoteP3(v, -1); } else { assert( pExpr->iColumn == OE_Ignore ); sqliteVdbeOp3(v, OP_Goto, 0, pParse->trigStack->ignoreJump, "(IGNORE jump)", 0); } } break; } } /* ** Generate code that pushes the value of every element of the given ** expression list onto the stack. If the includeTypes flag is true, ** then also push a string that is the datatype of each element onto ** the stack after the value. ** ** Return the number of elements pushed onto the stack. */ int sqliteExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ int includeTypes /* TRUE to put datatypes on the stack too */ ){ struct ExprList_item *pItem; int i, n; Vdbe *v; if( pList==0 ) return 0; v = sqliteGetVdbe(pParse); n = pList->nExpr; for(pItem=pList->a, i=0; ipExpr); if( includeTypes ){ sqliteVdbeOp3(v, OP_String, 0, 0, sqliteExprType(pItem->pExpr)==SQLITE_SO_NUM ? "numeric" : "text", P3_STATIC); } } return includeTypes ? n*2 : n; } /* ** Generate code for a boolean expression such that a jump is made ** to the label "dest" if the expression is true but execution ** continues straight thru if the expression is false. ** ** If the expression evaluates to NULL (neither true nor false), then ** take the jump if the jumpIfNull flag is true. */ void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; switch( pExpr->op ){ case TK_LT: op = OP_Lt; break; case TK_LE: op = OP_Le; break; case TK_GT: op = OP_Gt; break; case TK_GE: op = OP_Ge; break; case TK_NE: op = OP_Ne; break; case TK_EQ: op = OP_Eq; break; case TK_ISNULL: op = OP_IsNull; break; case TK_NOTNULL: op = OP_NotNull; break; default: break; } switch( pExpr->op ){ case TK_AND: { int d2 = sqliteVdbeMakeLabel(v); sqliteExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); sqliteVdbeResolveLabel(v, d2); break; } case TK_OR: { sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); sqliteExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_NOT: { sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ op += 6; /* Convert numeric opcodes to text opcodes */ } sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 1, dest); break; } case TK_IN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); if( pExpr->pSelect ){ sqliteVdbeAddOp(v, OP_Found, pExpr->iTable, dest); }else{ sqliteVdbeAddOp(v, OP_SetFound, pExpr->iTable, dest); } break; } case TK_BETWEEN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); addr = sqliteVdbeAddOp(v, OP_Lt, !jumpIfNull, 0); sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); sqliteVdbeAddOp(v, OP_Le, jumpIfNull, dest); sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); sqliteVdbeAddOp(v, OP_Pop, 1, 0); break; } default: { sqliteExprCode(pParse, pExpr); sqliteVdbeAddOp(v, OP_If, jumpIfNull, dest); break; } } } /* ** Generate code for a boolean expression such that a jump is made ** to the label "dest" if the expression is false but execution ** continues straight thru if the expression is true. ** ** If the expression evaluates to NULL (neither true nor false) then ** jump if jumpIfNull is true or fall through if jumpIfNull is false. */ void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ Vdbe *v = pParse->pVdbe; int op = 0; if( v==0 || pExpr==0 ) return; switch( pExpr->op ){ case TK_LT: op = OP_Ge; break; case TK_LE: op = OP_Gt; break; case TK_GT: op = OP_Le; break; case TK_GE: op = OP_Lt; break; case TK_NE: op = OP_Eq; break; case TK_EQ: op = OP_Ne; break; case TK_ISNULL: op = OP_NotNull; break; case TK_NOTNULL: op = OP_IsNull; break; default: break; } switch( pExpr->op ){ case TK_AND: { sqliteExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); break; } case TK_OR: { int d2 = sqliteVdbeMakeLabel(v); sqliteExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull); sqliteExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); sqliteVdbeResolveLabel(v, d2); break; } case TK_NOT: { sqliteExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ /* Convert numeric comparison opcodes into text comparison opcodes. ** This step depends on the fact that the text comparision opcodes are ** always 6 greater than their corresponding numeric comparison ** opcodes. */ assert( OP_Eq+6 == OP_StrEq ); op += 6; } sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 1, dest); break; } case TK_IN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_NotNull, -1, addr+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, jumpIfNull ? dest : addr+4); if( pExpr->pSelect ){ sqliteVdbeAddOp(v, OP_NotFound, pExpr->iTable, dest); }else{ sqliteVdbeAddOp(v, OP_SetNotFound, pExpr->iTable, dest); } break; } case TK_BETWEEN: { int addr; sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, OP_Dup, 0, 0); sqliteExprCode(pParse, pExpr->pList->a[0].pExpr); addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_Ge, !jumpIfNull, addr+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, dest); sqliteExprCode(pParse, pExpr->pList->a[1].pExpr); sqliteVdbeAddOp(v, OP_Gt, jumpIfNull, dest); break; } default: { sqliteExprCode(pParse, pExpr); sqliteVdbeAddOp(v, OP_IfNot, jumpIfNull, dest); break; } } } /* ** Do a deep comparison of two expression trees. Return TRUE (non-zero) ** if they are identical and return FALSE if they differ in any way. */ int sqliteExprCompare(Expr *pA, Expr *pB){ int i; if( pA==0 ){ return pB==0; }else if( pB==0 ){ return 0; } if( pA->op!=pB->op ) return 0; if( !sqliteExprCompare(pA->pLeft, pB->pLeft) ) return 0; if( !sqliteExprCompare(pA->pRight, pB->pRight) ) return 0; if( pA->pList ){ if( pB->pList==0 ) return 0; if( pA->pList->nExpr!=pB->pList->nExpr ) return 0; for(i=0; ipList->nExpr; i++){ if( !sqliteExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){ return 0; } } }else if( pB->pList ){ return 0; } if( pA->pSelect || pB->pSelect ) return 0; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; if( pA->token.z ){ if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; if( sqliteStrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; } return 1; } /* ** Add a new element to the pParse->aAgg[] array and return its index. */ static int appendAggInfo(Parse *pParse){ if( (pParse->nAgg & 0x7)==0 ){ int amt = pParse->nAgg + 8; AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0])); if( aAgg==0 ){ return -1; } pParse->aAgg = aAgg; } memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0])); return pParse->nAgg++; } /* ** Analyze the given expression looking for aggregate functions and ** for variables that need to be added to the pParse->aAgg[] array. ** Make additional entries to the pParse->aAgg[] array as necessary. ** ** This routine should only be called after the expression has been ** analyzed by sqliteExprResolveIds() and sqliteExprCheck(). ** ** If errors are seen, leave an error message in zErrMsg and return ** the number of errors. */ int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){ int i; AggExpr *aAgg; int nErr = 0; if( pExpr==0 ) return 0; switch( pExpr->op ){ case TK_COLUMN: { aAgg = pParse->aAgg; for(i=0; inAgg; i++){ if( aAgg[i].isAgg ) continue; if( aAgg[i].pExpr->iTable==pExpr->iTable && aAgg[i].pExpr->iColumn==pExpr->iColumn ){ break; } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 0; pParse->aAgg[i].pExpr = pExpr; } pExpr->iAgg = i; break; } case TK_AGG_FUNCTION: { aAgg = pParse->aAgg; for(i=0; inAgg; i++){ if( !aAgg[i].isAgg ) continue; if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){ break; } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 1; pParse->aAgg[i].pExpr = pExpr; pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n, pExpr->pList ? pExpr->pList->nExpr : 0, 0); } pExpr->iAgg = i; break; } default: { if( pExpr->pLeft ){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft); } if( nErr==0 && pExpr->pRight ){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight); } if( nErr==0 && pExpr->pList ){ int n = pExpr->pList->nExpr; int i; for(i=0; nErr==0 && ipList->a[i].pExpr); } } break; } } return nErr; } /* ** Locate a user function given a name and a number of arguments. ** Return a pointer to the FuncDef structure that defines that ** function, or return NULL if the function does not exist. ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a ** no matching function previously existed. When createFlag is true ** and the nArg parameter is -1, then only a function that accepts ** any number of arguments will be returned. ** ** If createFlag is false and nArg is -1, then the first valid ** function found is returned. A function is valid if either xFunc ** or xStep is non-zero. */ FuncDef *sqliteFindFunction( sqlite *db, /* An open database */ const char *zName, /* Name of the function. Not null-terminated */ int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ int createFlag /* Create new entry if true and does not otherwise exist */ ){ FuncDef *pFirst, *p, *pMaybe; pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName); if( p && !createFlag && nArg<0 ){ while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; } return p; } pMaybe = 0; while( p && p->nArg!=nArg ){ if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p; p = p->pNext; } if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){ return 0; } if( p==0 && pMaybe ){ assert( createFlag==0 ); return pMaybe; } if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){ p->nArg = nArg; p->pNext = pFirst; p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC; sqliteHashInsert(&db->aFunc, zName, nName, (void*)p); } return p; } DBD-SQLite2-0.36/parse.c0000644000175000017500000043030312126353147014105 0ustar rurbanrurban/* Driver template for the LEMON parser generator. ** The author disclaims copyright to this source code. */ /* First off, code is include which follows the "include" declaration ** in the input file. */ #include #line 33 "parse.y" #include "sqliteInt.h" #include "parse.h" /* ** An instance of this structure holds information about the ** LIMIT clause of a SELECT statement. */ struct LimitVal { int limit; /* The LIMIT value. -1 if there is no limit */ int offset; /* The OFFSET. 0 if there is none */ }; /* ** An instance of the following structure describes the event of a ** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, ** TK_DELETE, or TK_INSTEAD. If the event is of the form ** ** UPDATE ON (a,b,c) ** ** Then the "b" IdList records the list "a,b,c". */ struct TrigEvent { int a; IdList * b; }; #line 34 "parse.c" /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ /* ** These constants (all generated automatically by the parser generator) ** specify the various kinds of tokens (terminals) that the parser ** understands. ** ** Each symbol here is a terminal symbol in the grammar. */ /* Make sure the INTERFACE macro is defined. */ #ifndef INTERFACE # define INTERFACE 1 #endif /* The next thing included is series of defines which control ** various aspects of the generated parser. ** YYCODETYPE is the data type used for storing terminal ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 terminals ** and nonterminals. "int" is used otherwise. ** YYNOCODE is a number of type YYCODETYPE which corresponds ** to no legal terminal or nonterminal number. This ** number is used to fill in empty slots of the hash ** table. ** YYFALLBACK If defined, this indicates that one or more tokens ** have fall-back values which should be used if the ** original value of the token will not parse. ** YYACTIONTYPE is the data type used for storing terminal ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 rules and ** states combined. "int" is used otherwise. ** sqliteParserTOKENTYPE is the data type used for minor tokens given ** directly to the parser from the tokenizer. ** YYMINORTYPE is the data type used for all minor tokens. ** This is typically a union of many types, one of ** which is sqliteParserTOKENTYPE. The entry in the union ** for base tokens is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. ** sqliteParserARG_SDECL A static variable declaration for the %extra_argument ** sqliteParserARG_PDECL A parameter declaration for the %extra_argument ** sqliteParserARG_STORE Code to store %extra_argument into yypParser ** sqliteParserARG_FETCH Code to extract %extra_argument from yypParser ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. */ /*  */ #define YYCODETYPE unsigned char #define YYNOCODE 221 #define YYACTIONTYPE unsigned short int #define sqliteParserTOKENTYPE Token typedef union { sqliteParserTOKENTYPE yy0; TriggerStep * yy19; struct LimitVal yy124; Select* yy179; Expr * yy182; Expr* yy242; struct TrigEvent yy290; Token yy298; SrcList* yy307; IdList* yy320; ExprList* yy322; int yy372; struct {int value; int mask;} yy407; int yy441; } YYMINORTYPE; #define YYSTACKDEPTH 100 #define sqliteParserARG_SDECL Parse *pParse; #define sqliteParserARG_PDECL ,Parse *pParse #define sqliteParserARG_FETCH Parse *pParse = yypParser->pParse #define sqliteParserARG_STORE yypParser->pParse = pParse #define YYNSTATE 563 #define YYNRULE 293 #define YYERRORSYMBOL 131 #define YYERRSYMDT yy441 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) /* Next are that tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an ** action integer. ** ** Suppose the action integer is N. Then the action is determined as ** follows ** ** 0 <= N < YYNSTATE Shift N. That is, push the lookahead ** token onto the stack and goto state N. ** ** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. ** ** N == YYNSTATE+YYNRULE A syntax error has occurred. ** ** N == YYNSTATE+YYNRULE+1 The parser accepts its input. ** ** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused ** slots in the yy_action[] table. ** ** The action table is constructed as a single large table named yy_action[]. ** Given state S and lookahead X, the action is computed as ** ** yy_action[ yy_shift_ofst[S] + X ] ** ** If the index value yy_shift_ofst[S]+X is out of range or if the value ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table ** and that yy_default[S] should be used instead. ** ** The formula above is for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of ** YY_SHIFT_USE_DFLT. ** ** The following are the tables generated in this section: ** ** yy_action[] A single table containing all actions. ** yy_lookahead[] A table containing the lookahead for each entry in ** yy_action. Used to detect hash collisions. ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ static YYACTIONTYPE yy_action[] = { /* 0 */ 264, 106, 262, 119, 123, 117, 121, 129, 131, 133, /* 10 */ 135, 144, 146, 148, 150, 152, 154, 844, 426, 174, /* 20 */ 143, 425, 2, 3, 839, 142, 129, 131, 133, 135, /* 30 */ 144, 146, 148, 150, 152, 154, 247, 837, 427, 115, /* 40 */ 104, 139, 127, 125, 156, 161, 157, 162, 166, 119, /* 50 */ 123, 117, 121, 129, 131, 133, 135, 144, 146, 148, /* 60 */ 150, 152, 154, 448, 361, 218, 263, 143, 363, 369, /* 70 */ 374, 137, 142, 144, 146, 148, 150, 152, 154, 377, /* 80 */ 857, 1, 562, 3, 396, 327, 115, 104, 139, 127, /* 90 */ 125, 156, 161, 157, 162, 166, 119, 123, 117, 121, /* 100 */ 129, 131, 133, 135, 144, 146, 148, 150, 152, 154, /* 110 */ 482, 454, 444, 106, 143, 169, 20, 171, 172, 142, /* 120 */ 310, 73, 4, 6, 402, 68, 398, 29, 248, 64, /* 130 */ 46, 174, 497, 115, 104, 139, 127, 125, 156, 161, /* 140 */ 157, 162, 166, 119, 123, 117, 121, 129, 131, 133, /* 150 */ 135, 144, 146, 148, 150, 152, 154, 69, 193, 65, /* 160 */ 101, 44, 54, 60, 62, 308, 331, 244, 175, 106, /* 170 */ 20, 357, 333, 173, 640, 70, 359, 219, 36, 37, /* 180 */ 21, 22, 510, 143, 181, 179, 303, 299, 142, 31, /* 190 */ 20, 392, 177, 66, 67, 111, 358, 390, 112, 105, /* 200 */ 69, 191, 115, 104, 139, 127, 125, 156, 161, 157, /* 210 */ 162, 166, 119, 123, 117, 121, 129, 131, 133, 135, /* 220 */ 144, 146, 148, 150, 152, 154, 388, 312, 73, 688, /* 230 */ 306, 113, 183, 387, 21, 22, 230, 361, 52, 106, /* 240 */ 20, 363, 369, 374, 361, 544, 542, 53, 363, 369, /* 250 */ 374, 143, 377, 591, 21, 22, 142, 212, 338, 377, /* 260 */ 169, 38, 171, 172, 356, 348, 535, 46, 534, 792, /* 270 */ 115, 104, 139, 127, 125, 156, 161, 157, 162, 166, /* 280 */ 119, 123, 117, 121, 129, 131, 133, 135, 144, 146, /* 290 */ 148, 150, 152, 154, 790, 41, 336, 298, 44, 54, /* 300 */ 60, 62, 308, 331, 21, 22, 197, 167, 20, 333, /* 310 */ 58, 20, 395, 340, 343, 201, 169, 809, 171, 172, /* 320 */ 59, 143, 337, 311, 339, 281, 142, 346, 347, 20, /* 330 */ 205, 20, 639, 195, 35, 536, 537, 538, 842, 45, /* 340 */ 115, 104, 139, 127, 125, 156, 161, 157, 162, 166, /* 350 */ 119, 123, 117, 121, 129, 131, 133, 135, 144, 146, /* 360 */ 148, 150, 152, 154, 300, 276, 148, 150, 152, 154, /* 370 */ 71, 106, 21, 22, 430, 21, 22, 20, 443, 791, /* 380 */ 441, 106, 40, 335, 169, 143, 171, 172, 330, 305, /* 390 */ 142, 84, 86, 21, 22, 21, 22, 10, 572, 174, /* 400 */ 254, 18, 83, 69, 115, 104, 139, 127, 125, 156, /* 410 */ 161, 157, 162, 166, 119, 123, 117, 121, 129, 131, /* 420 */ 133, 135, 144, 146, 148, 150, 152, 154, 467, 106, /* 430 */ 661, 275, 143, 720, 295, 301, 169, 142, 171, 172, /* 440 */ 539, 21, 22, 487, 449, 219, 459, 103, 232, 451, /* 450 */ 282, 115, 104, 139, 127, 125, 156, 161, 157, 162, /* 460 */ 166, 119, 123, 117, 121, 129, 131, 133, 135, 144, /* 470 */ 146, 148, 150, 152, 154, 69, 417, 419, 418, 143, /* 480 */ 95, 237, 312, 494, 142, 489, 47, 283, 259, 75, /* 490 */ 10, 68, 189, 284, 209, 64, 289, 49, 115, 104, /* 500 */ 139, 127, 125, 156, 161, 157, 162, 166, 119, 123, /* 510 */ 117, 121, 129, 131, 133, 135, 144, 146, 148, 150, /* 520 */ 152, 154, 196, 297, 193, 357, 429, 296, 169, 32, /* 530 */ 171, 172, 391, 37, 175, 169, 276, 171, 172, 313, /* 540 */ 316, 323, 325, 663, 106, 689, 245, 251, 143, 651, /* 550 */ 181, 179, 292, 142, 386, 583, 491, 690, 177, 66, /* 560 */ 67, 111, 184, 437, 112, 105, 213, 115, 164, 139, /* 570 */ 127, 125, 156, 161, 157, 162, 166, 119, 123, 117, /* 580 */ 121, 129, 131, 133, 135, 144, 146, 148, 150, 152, /* 590 */ 154, 315, 726, 20, 106, 143, 333, 113, 183, 563, /* 600 */ 142, 43, 278, 440, 170, 185, 330, 666, 560, 561, /* 610 */ 249, 259, 103, 253, 115, 104, 139, 127, 125, 156, /* 620 */ 161, 157, 162, 166, 119, 123, 117, 121, 129, 131, /* 630 */ 133, 135, 144, 146, 148, 150, 152, 154, 800, 10, /* 640 */ 252, 169, 143, 171, 172, 445, 97, 142, 560, 561, /* 650 */ 216, 221, 217, 169, 313, 171, 172, 21, 22, 42, /* 660 */ 159, 115, 227, 139, 127, 125, 156, 161, 157, 162, /* 670 */ 166, 119, 123, 117, 121, 129, 131, 133, 135, 144, /* 680 */ 146, 148, 150, 152, 154, 256, 73, 106, 816, 143, /* 690 */ 169, 158, 171, 172, 142, 234, 397, 217, 545, 475, /* 700 */ 273, 302, 274, 217, 266, 481, 315, 96, 653, 104, /* 710 */ 139, 127, 125, 156, 161, 157, 162, 166, 119, 123, /* 720 */ 117, 121, 129, 131, 133, 135, 144, 146, 148, 150, /* 730 */ 152, 154, 106, 349, 291, 262, 143, 262, 264, 74, /* 740 */ 262, 142, 533, 464, 320, 477, 319, 329, 341, 274, /* 750 */ 481, 342, 137, 415, 416, 321, 266, 139, 127, 125, /* 760 */ 156, 161, 157, 162, 166, 119, 123, 117, 121, 129, /* 770 */ 131, 133, 135, 144, 146, 148, 150, 152, 154, 7, /* 780 */ 322, 23, 25, 27, 394, 68, 267, 13, 393, 64, /* 790 */ 518, 251, 106, 836, 344, 548, 14, 345, 458, 263, /* 800 */ 520, 263, 106, 91, 263, 557, 266, 314, 168, 106, /* 810 */ 462, 15, 443, 69, 16, 231, 276, 106, 193, 531, /* 820 */ 174, 448, 276, 106, 276, 17, 529, 174, 175, 318, /* 830 */ 106, 89, 106, 69, 276, 114, 286, 69, 68, 399, /* 840 */ 69, 116, 64, 328, 181, 179, 106, 106, 118, 366, /* 850 */ 163, 272, 177, 66, 67, 111, 215, 253, 112, 105, /* 860 */ 276, 371, 467, 233, 120, 375, 219, 143, 498, 503, /* 870 */ 444, 193, 142, 219, 486, 720, 401, 73, 453, 73, /* 880 */ 420, 175, 278, 451, 252, 400, 106, 380, 278, 68, /* 890 */ 278, 113, 183, 64, 225, 229, 106, 181, 179, 106, /* 900 */ 278, 69, 106, 106, 122, 177, 66, 67, 111, 411, /* 910 */ 106, 112, 105, 106, 124, 106, 106, 126, 106, 224, /* 920 */ 128, 130, 193, 106, 106, 106, 278, 351, 132, 352, /* 930 */ 831, 134, 175, 136, 138, 422, 141, 106, 367, 376, /* 940 */ 274, 145, 147, 149, 113, 183, 793, 690, 181, 179, /* 950 */ 106, 424, 106, 106, 424, 151, 177, 66, 67, 111, /* 960 */ 106, 106, 112, 105, 106, 106, 808, 106, 153, 106, /* 970 */ 155, 165, 106, 106, 106, 106, 106, 464, 176, 178, /* 980 */ 852, 106, 180, 182, 106, 190, 293, 192, 245, 106, /* 990 */ 210, 214, 226, 228, 241, 113, 183, 106, 474, 246, /* 1000 */ 137, 690, 280, 372, 290, 274, 381, 412, 274, 106, /* 1010 */ 471, 221, 832, 421, 438, 466, 274, 472, 480, 422, /* 1020 */ 478, 73, 515, 69, 519, 255, 478, 479, 221, 690, /* 1030 */ 540, 527, 508, 541, 516, 85, 39, 403, 406, 257, /* 1040 */ 317, 404, 198, 407, 405, 221, 408, 69, 413, 5, /* 1050 */ 824, 221, 211, 409, 817, 410, 546, 582, 258, 414, /* 1060 */ 90, 547, 199, 260, 223, 829, 830, 261, 324, 200, /* 1070 */ 815, 72, 34, 526, 222, 186, 423, 326, 94, 57, /* 1080 */ 428, 56, 187, 188, 265, 202, 431, 554, 332, 88, /* 1090 */ 33, 432, 433, 434, 279, 268, 436, 556, 435, 51, /* 1100 */ 578, 30, 549, 270, 439, 798, 334, 269, 799, 203, /* 1110 */ 442, 577, 204, 271, 28, 550, 447, 812, 446, 98, /* 1120 */ 532, 450, 727, 728, 823, 452, 819, 576, 26, 81, /* 1130 */ 82, 445, 235, 838, 80, 457, 575, 463, 461, 455, /* 1140 */ 24, 456, 551, 93, 813, 460, 277, 840, 465, 528, /* 1150 */ 79, 206, 807, 468, 469, 593, 470, 55, 552, 473, /* 1160 */ 350, 820, 355, 850, 592, 476, 250, 19, 207, 553, /* 1170 */ 353, 354, 841, 285, 236, 814, 484, 555, 287, 483, /* 1180 */ 843, 208, 660, 485, 488, 389, 63, 490, 662, 360, /* 1190 */ 492, 288, 851, 100, 806, 849, 495, 493, 362, 496, /* 1200 */ 92, 499, 719, 364, 240, 238, 500, 365, 501, 502, /* 1210 */ 239, 294, 504, 505, 507, 506, 568, 61, 11, 722, /* 1220 */ 108, 368, 571, 511, 12, 517, 512, 9, 8, 559, /* 1230 */ 370, 514, 725, 509, 50, 558, 373, 78, 243, 217, /* 1240 */ 18, 242, 818, 521, 77, 513, 110, 543, 855, 109, /* 1250 */ 522, 154, 245, 524, 107, 379, 378, 160, 523, 87, /* 1260 */ 194, 385, 48, 304, 530, 383, 382, 140, 76, 811, /* 1270 */ 99, 384, 525, 220, 810, 515, 49, 102, 515, 307, /* 1280 */ 515, 515, 309, 515, 515, 667, 668, 669, }; static YYCODETYPE yy_lookahead[] = { /* 0 */ 21, 140, 23, 70, 71, 72, 73, 74, 75, 76, /* 10 */ 77, 78, 79, 80, 81, 82, 83, 9, 25, 158, /* 20 */ 41, 28, 134, 135, 14, 46, 74, 75, 76, 77, /* 30 */ 78, 79, 80, 81, 82, 83, 22, 11, 45, 60, /* 40 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, /* 50 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, /* 60 */ 81, 82, 83, 53, 90, 204, 87, 41, 94, 95, /* 70 */ 96, 200, 46, 78, 79, 80, 81, 82, 83, 105, /* 80 */ 132, 133, 134, 135, 17, 19, 60, 61, 62, 63, /* 90 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, /* 100 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, /* 110 */ 100, 101, 102, 140, 41, 107, 23, 109, 110, 46, /* 120 */ 159, 111, 136, 137, 57, 19, 59, 141, 114, 23, /* 130 */ 62, 158, 146, 60, 61, 62, 63, 64, 65, 66, /* 140 */ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* 150 */ 77, 78, 79, 80, 81, 82, 83, 171, 52, 19, /* 160 */ 23, 93, 94, 95, 96, 97, 98, 194, 62, 140, /* 170 */ 23, 140, 104, 20, 20, 146, 22, 204, 147, 148, /* 180 */ 87, 88, 196, 41, 78, 79, 80, 158, 46, 19, /* 190 */ 23, 21, 86, 87, 88, 89, 165, 166, 92, 93, /* 200 */ 171, 128, 60, 61, 62, 63, 64, 65, 66, 67, /* 210 */ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, /* 220 */ 78, 79, 80, 81, 82, 83, 161, 162, 111, 20, /* 230 */ 20, 125, 126, 168, 87, 88, 19, 90, 34, 140, /* 240 */ 23, 94, 95, 96, 90, 78, 79, 43, 94, 95, /* 250 */ 96, 41, 105, 113, 87, 88, 46, 158, 23, 105, /* 260 */ 107, 149, 109, 110, 152, 153, 99, 62, 140, 127, /* 270 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, /* 280 */ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 290 */ 80, 81, 82, 83, 14, 90, 91, 20, 93, 94, /* 300 */ 95, 96, 97, 98, 87, 88, 15, 19, 23, 104, /* 310 */ 26, 23, 143, 78, 79, 24, 107, 9, 109, 110, /* 320 */ 36, 41, 87, 160, 89, 19, 46, 92, 93, 23, /* 330 */ 39, 23, 20, 42, 22, 207, 208, 209, 9, 139, /* 340 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, /* 350 */ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 360 */ 80, 81, 82, 83, 20, 140, 80, 81, 82, 83, /* 370 */ 172, 140, 87, 88, 205, 87, 88, 23, 146, 14, /* 380 */ 211, 140, 155, 156, 107, 41, 109, 110, 161, 158, /* 390 */ 46, 78, 79, 87, 88, 87, 88, 99, 9, 158, /* 400 */ 115, 12, 89, 171, 60, 61, 62, 63, 64, 65, /* 410 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, /* 420 */ 76, 77, 78, 79, 80, 81, 82, 83, 196, 140, /* 430 */ 9, 206, 41, 9, 80, 194, 107, 46, 109, 110, /* 440 */ 210, 87, 88, 17, 212, 204, 22, 158, 20, 217, /* 450 */ 146, 60, 61, 62, 63, 64, 65, 66, 67, 68, /* 460 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, /* 470 */ 79, 80, 81, 82, 83, 171, 100, 101, 102, 41, /* 480 */ 191, 192, 162, 57, 46, 59, 93, 183, 184, 174, /* 490 */ 99, 19, 127, 189, 129, 23, 181, 104, 60, 61, /* 500 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, /* 510 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, /* 520 */ 82, 83, 20, 108, 52, 140, 18, 112, 107, 144, /* 530 */ 109, 110, 147, 148, 62, 107, 140, 109, 110, 47, /* 540 */ 100, 101, 102, 9, 140, 20, 122, 22, 41, 9, /* 550 */ 78, 79, 80, 46, 62, 9, 130, 19, 86, 87, /* 560 */ 88, 89, 158, 167, 92, 93, 128, 60, 61, 62, /* 570 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, /* 580 */ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, /* 590 */ 83, 99, 9, 23, 140, 41, 104, 125, 126, 0, /* 600 */ 46, 156, 206, 95, 108, 201, 161, 111, 9, 10, /* 610 */ 183, 184, 158, 88, 60, 61, 62, 63, 64, 65, /* 620 */ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, /* 630 */ 76, 77, 78, 79, 80, 81, 82, 83, 130, 99, /* 640 */ 115, 107, 41, 109, 110, 60, 192, 46, 9, 10, /* 650 */ 20, 113, 22, 107, 47, 109, 110, 87, 88, 140, /* 660 */ 62, 60, 61, 62, 63, 64, 65, 66, 67, 68, /* 670 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, /* 680 */ 79, 80, 81, 82, 83, 115, 111, 140, 9, 41, /* 690 */ 107, 93, 109, 110, 46, 20, 140, 22, 19, 124, /* 700 */ 20, 20, 22, 22, 152, 158, 99, 22, 123, 61, /* 710 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, /* 720 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, /* 730 */ 82, 83, 140, 19, 182, 23, 41, 23, 21, 173, /* 740 */ 23, 46, 63, 140, 91, 198, 93, 20, 89, 22, /* 750 */ 158, 92, 200, 55, 56, 29, 152, 62, 63, 64, /* 760 */ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, /* 770 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 11, /* 780 */ 54, 13, 14, 15, 16, 19, 182, 15, 146, 23, /* 790 */ 198, 22, 140, 11, 89, 27, 24, 92, 195, 87, /* 800 */ 32, 87, 140, 22, 87, 37, 152, 140, 146, 140, /* 810 */ 158, 39, 146, 171, 42, 146, 140, 140, 52, 51, /* 820 */ 158, 53, 140, 140, 140, 53, 58, 158, 62, 103, /* 830 */ 140, 50, 140, 171, 140, 158, 182, 171, 19, 140, /* 840 */ 171, 158, 23, 167, 78, 79, 140, 140, 158, 167, /* 850 */ 158, 167, 86, 87, 88, 89, 194, 88, 92, 93, /* 860 */ 140, 167, 196, 194, 158, 158, 204, 41, 100, 101, /* 870 */ 102, 52, 46, 204, 106, 9, 146, 111, 212, 111, /* 880 */ 49, 62, 206, 217, 115, 21, 140, 167, 206, 19, /* 890 */ 206, 125, 126, 23, 68, 69, 140, 78, 79, 140, /* 900 */ 206, 171, 140, 140, 158, 86, 87, 88, 89, 127, /* 910 */ 140, 92, 93, 140, 158, 140, 140, 158, 140, 93, /* 920 */ 158, 158, 52, 140, 140, 140, 206, 20, 158, 22, /* 930 */ 99, 158, 62, 158, 158, 22, 158, 140, 20, 139, /* 940 */ 22, 158, 158, 158, 125, 126, 127, 9, 78, 79, /* 950 */ 140, 140, 140, 140, 140, 158, 86, 87, 88, 89, /* 960 */ 140, 140, 92, 93, 140, 140, 9, 140, 158, 140, /* 970 */ 158, 158, 140, 140, 140, 140, 140, 140, 158, 158, /* 980 */ 9, 140, 158, 158, 140, 158, 140, 158, 122, 140, /* 990 */ 158, 158, 158, 158, 158, 125, 126, 140, 146, 158, /* 1000 */ 200, 103, 158, 20, 158, 22, 20, 158, 22, 140, /* 1010 */ 199, 113, 99, 199, 20, 158, 22, 20, 20, 22, /* 1020 */ 22, 111, 146, 171, 20, 140, 22, 158, 113, 114, /* 1030 */ 89, 35, 195, 92, 124, 89, 150, 140, 99, 140, /* 1040 */ 163, 213, 22, 140, 214, 113, 186, 171, 40, 9, /* 1050 */ 11, 113, 127, 215, 9, 216, 140, 9, 115, 38, /* 1060 */ 154, 20, 140, 140, 186, 99, 99, 186, 163, 20, /* 1070 */ 9, 171, 20, 116, 140, 202, 140, 163, 118, 139, /* 1080 */ 49, 157, 203, 14, 140, 22, 130, 116, 151, 154, /* 1090 */ 145, 140, 99, 140, 99, 187, 19, 33, 186, 44, /* 1100 */ 9, 142, 218, 116, 139, 9, 164, 188, 130, 140, /* 1110 */ 11, 9, 20, 19, 138, 152, 169, 9, 170, 193, /* 1120 */ 152, 14, 123, 123, 9, 9, 9, 9, 138, 180, /* 1130 */ 121, 60, 140, 14, 179, 103, 9, 176, 63, 169, /* 1140 */ 138, 140, 21, 117, 9, 140, 157, 9, 63, 87, /* 1150 */ 178, 22, 9, 123, 140, 113, 19, 48, 140, 197, /* 1160 */ 154, 9, 152, 9, 113, 19, 185, 140, 140, 219, /* 1170 */ 154, 20, 9, 20, 186, 9, 140, 152, 187, 114, /* 1180 */ 9, 20, 9, 176, 140, 166, 19, 140, 9, 166, /* 1190 */ 140, 188, 9, 98, 9, 9, 140, 186, 140, 186, /* 1200 */ 154, 114, 9, 48, 120, 193, 140, 19, 186, 176, /* 1210 */ 157, 113, 169, 140, 103, 186, 9, 139, 31, 9, /* 1220 */ 140, 139, 9, 123, 170, 19, 140, 139, 138, 140, /* 1230 */ 19, 197, 9, 176, 164, 218, 139, 177, 118, 22, /* 1240 */ 12, 119, 9, 169, 176, 186, 140, 210, 9, 113, /* 1250 */ 140, 83, 122, 114, 113, 19, 48, 93, 186, 89, /* 1260 */ 19, 160, 139, 20, 140, 140, 97, 200, 175, 9, /* 1270 */ 157, 159, 140, 140, 9, 220, 104, 151, 220, 139, /* 1280 */ 220, 220, 140, 220, 220, 111, 111, 111, }; #define YY_SHIFT_USE_DFLT (-68) static short yy_shift_ofst[] = { /* 0 */ 639, 599, -68, 768, 1040, -68, 1207, 1228, 540, 1213, /* 10 */ 1187, 772, -68, -68, -68, -68, -68, -68, 93, -68, /* 20 */ -68, -68, -68, 389, 1127, 389, 1118, 389, 1102, 170, /* 30 */ 1091, 93, 312, 1052, 1048, 147, -68, 712, -68, 205, /* 40 */ -68, 93, 68, -68, 298, -68, 393, 298, -68, 1055, /* 50 */ -68, 204, -68, -68, 1109, 284, 298, -68, -68, -68, /* 60 */ 298, -68, 1167, 870, 140, 106, 1051, 1042, 766, -68, /* 70 */ 277, 117, -68, 415, -68, 14, 1130, 1122, 1084, 1026, /* 80 */ 1009, -68, 313, -68, 946, -68, 1170, -68, 781, 313, /* 90 */ -68, 313, -68, 960, 870, 685, 870, 1095, 284, -68, /* 100 */ 137, -68, -68, 554, 870, -68, 1141, 93, 1136, 93, /* 110 */ -68, -68, -68, -68, 695, 870, 648, 870, -48, 870, /* 120 */ -48, 870, -48, 870, -48, 870, -67, 870, -67, 870, /* 130 */ -5, 870, -5, 870, -5, 870, -5, 870, -67, 826, /* 140 */ 870, -67, -68, -68, 870, 286, 870, 286, 870, 1168, /* 150 */ 870, 1168, 870, 1168, 870, -68, -68, 598, -68, 1164, /* 160 */ -68, -68, 870, 507, 870, -67, 288, 766, 153, 496, /* 170 */ 1174, 1175, 1176, -68, 554, 870, 695, 870, -68, 870, /* 180 */ -68, 870, -68, 819, 142, 925, 365, 1069, -68, 870, /* 190 */ 73, 870, 554, 1241, 291, 502, -68, 1020, 93, 1049, /* 200 */ -68, 1063, 93, 1092, -68, 1129, 93, 1161, -68, 870, /* 210 */ 280, 870, 438, 870, 554, 630, -68, 870, -68, -68, /* 220 */ 932, 93, -68, -68, -68, 870, 601, 870, 695, 217, /* 230 */ 766, 428, -68, 675, -68, 932, -68, 1095, 284, -68, /* 240 */ 870, 554, 1120, 870, 1217, 870, 554, -68, -68, 769, /* 250 */ -68, -68, -68, 285, -68, 570, -68, 943, -68, 306, /* 260 */ 932, 717, -68, -68, 93, -68, -68, 995, 987, -68, /* 270 */ 1094, 93, 680, -68, 93, -68, 284, -68, -68, 870, /* 280 */ 554, 117, 209, 525, 1153, 717, 995, 987, -68, 472, /* 290 */ -21, -68, -68, 1098, 354, -68, -68, -68, -68, 344, /* 300 */ -68, 681, -68, 1243, -68, 210, 298, -68, 93, 66, /* 310 */ -68, 607, -68, 93, -68, 440, 726, -68, 653, -68, /* 320 */ -68, -68, -68, 726, -68, 726, -68, 93, 727, -68, /* 330 */ -68, 137, -68, 1055, -68, -68, 235, -68, -68, -68, /* 340 */ 659, -68, -68, 705, -68, -68, -68, -68, 714, 313, /* 350 */ 907, -68, 313, 1151, -68, -68, -68, -68, 154, -26, /* 360 */ -68, 93, -68, 1155, 1188, 93, 918, 298, -68, 1211, /* 370 */ 93, 983, 298, -68, 870, 391, -68, 1208, 1236, 93, /* 380 */ 986, 1169, 93, 66, -68, 492, 1172, -68, -68, -68, /* 390 */ -68, -68, 117, 546, 508, 67, 93, -68, 93, 864, /* 400 */ 117, 421, 93, -7, 376, 939, 93, 932, 1008, 782, /* 410 */ 1039, 870, 26, 1021, 698, -68, -68, 966, 967, 831, /* 420 */ 93, 913, 93, -68, -68, -68, -68, 1031, -68, -68, /* 430 */ 956, 93, 993, 93, 538, 1077, 93, 994, 540, 1096, /* 440 */ 978, 1099, 10, 8, 585, 772, -68, 999, 1000, 1107, /* 450 */ 1115, 1116, 10, 1119, 1071, 93, 1032, 93, 424, 93, /* 460 */ 1075, 870, 554, 1138, 1085, 870, 554, 1030, 93, 1137, /* 470 */ 93, 997, -68, 575, 329, 1146, 870, 998, 870, 554, /* 480 */ 1163, 554, 1065, 93, 866, 1171, 426, 93, 1173, 93, /* 490 */ 1179, 93, 938, 1185, 93, 938, 1186, 534, 1087, 93, /* 500 */ 932, 866, 1193, 1071, 93, 898, 1111, 93, 424, 1210, /* 510 */ 1100, 93, 932, 1137, 910, 583, 1206, 870, 1004, 1223, /* 520 */ 1071, 93, 915, 1139, 93, 957, 996, 1062, 1143, 308, /* 530 */ 1265, 712, 679, 167, 1260, 1108, 1135, 1166, 941, 1045, /* 540 */ 1117, 1152, 941, 1233, -68, 93, 1041, 1061, 1064, 712, /* 550 */ 1121, 93, 971, 1154, 712, 1183, -68, 1064, 93, 1239, /* 560 */ -68, -68, -68, }; #define YY_REDUCE_USE_DFLT (-140) static short yy_reduce_ofst[] = { /* 0 */ -52, -112, -140, -14, -140, -140, -140, 1090, 1088, -140, /* 10 */ -140, 1054, -140, -140, -140, -140, -140, -140, 1027, -140, /* 20 */ -140, -140, -140, 1002, -140, 990, -140, 976, -140, 959, /* 30 */ -140, 385, 945, -140, -140, 31, -140, 112, 886, 227, /* 40 */ -140, 519, 445, -140, 200, -140, -140, 1123, -140, 1070, /* 50 */ -140, -140, -140, -140, -140, 924, 940, -140, -140, -140, /* 60 */ 1078, -140, -140, 231, -140, 241, -140, -140, 29, -140, /* 70 */ 198, 900, -140, 566, 315, 1093, 1068, 1060, 972, 955, /* 80 */ 949, -140, 935, -140, -140, -140, -140, -140, -140, 906, /* 90 */ -140, 1046, -140, -140, 289, -140, 454, 926, 1113, -140, /* 100 */ 1126, -140, -140, -129, 677, -140, -140, 1080, -140, 1106, /* 110 */ -140, -140, -140, -140, -129, 683, -129, 690, -129, 706, /* 120 */ -129, 746, -129, 756, -129, 759, -129, 762, -129, 763, /* 130 */ -129, 770, -129, 773, -129, 775, -129, 776, -129, 1067, /* 140 */ 778, -129, -140, -140, 783, -129, 784, -129, 785, -129, /* 150 */ 797, -129, 810, -129, 812, -129, -140, -140, -140, -140, /* 160 */ -140, -140, 692, -129, 813, -129, 1133, 662, 198, -140, /* 170 */ -140, -140, -140, -140, -129, 820, -129, 821, -129, 824, /* 180 */ -129, 825, -129, 404, -129, 873, 879, -140, -140, 827, /* 190 */ -129, 829, -129, -140, -140, -140, -140, -140, 922, -140, /* 200 */ -140, -140, 969, -140, -140, -140, 1028, -140, -140, 832, /* 210 */ -129, 99, -129, 833, -129, -140, -140, -139, -140, -140, /* 220 */ 878, 934, -140, -140, -140, 834, -129, 835, -129, 992, /* 230 */ 669, 198, -140, -140, -140, 988, -140, 1012, 1053, -140, /* 240 */ 836, -129, -140, -27, -140, 841, -129, -140, 427, 981, /* 250 */ -140, -140, -140, 885, -140, 899, -140, -140, -140, 923, /* 260 */ 881, 604, -140, -140, 944, -140, -140, 908, 919, -140, /* 270 */ -140, 684, -140, -140, 225, -140, 989, -140, -140, 844, /* 280 */ -129, 304, 198, 981, -140, 654, 991, 1003, -140, 846, /* 290 */ 552, -140, -140, -140, 1080, -140, -140, -140, -140, -129, /* 300 */ -140, -140, -140, -140, -140, -129, 1140, -140, 1142, -39, /* 310 */ 163, 320, -140, 667, -140, -140, 877, -140, -140, -140, /* 320 */ -140, -140, -140, 905, -140, 914, -140, 676, -140, -140, /* 330 */ -140, 937, -140, 942, -140, -140, -140, -140, -140, -140, /* 340 */ -140, -140, -140, -140, -140, -140, -140, -140, 1010, 1006, /* 350 */ -140, -140, 1016, -140, -140, -140, -140, -140, 1019, 1023, /* 360 */ -140, 1058, -140, -140, -140, 682, -140, 1082, -140, -140, /* 370 */ 694, -140, 1097, -140, 707, 800, -140, -140, -140, 720, /* 380 */ -140, -140, 1125, 1112, 1101, 65, -140, -140, -140, -140, /* 390 */ -140, -140, 642, 198, 169, -140, 556, -140, 699, -140, /* 400 */ 730, 198, 897, 828, 830, -140, 903, 860, 838, 839, /* 410 */ -140, 849, -129, -140, -140, -140, -140, -140, -140, -140, /* 420 */ 814, -140, 936, -140, -140, -140, -140, -140, -140, -140, /* 430 */ -140, 951, -140, 953, 912, -140, 396, -140, 965, -140, /* 440 */ -140, -140, 232, 198, 947, 948, -140, -140, -140, -140, /* 450 */ -140, -140, 666, -140, 970, 1001, -140, 603, 961, 1005, /* 460 */ -140, 652, -129, -140, -140, 857, -129, -140, 1014, 962, /* 470 */ 811, -140, -140, 852, 198, -140, 547, -140, 869, -129, /* 480 */ -140, -129, -140, 1036, 1007, -140, -140, 1044, -140, 1047, /* 490 */ -140, 1050, 1011, -140, 1056, 1013, -140, 198, -140, 1066, /* 500 */ 1022, 1033, -140, 1043, 1073, 1029, -140, 837, 1057, -140, /* 510 */ -140, 1086, 1059, 1034, 876, 198, -140, 592, -140, -140, /* 520 */ 1074, 1110, 1072, -140, 1132, -140, -140, -140, -140, 1124, /* 530 */ -140, 968, -140, 128, -140, -140, -140, -140, 230, -140, /* 540 */ -140, -140, 1037, -140, -140, 916, -140, -140, 884, 963, /* 550 */ -140, 1018, 950, -140, 1025, -140, -140, 1017, 1089, -140, /* 560 */ -140, -140, -140, }; static YYACTIONTYPE yy_default[] = { /* 0 */ 570, 570, 564, 856, 856, 566, 856, 572, 856, 856, /* 10 */ 856, 856, 652, 655, 656, 657, 658, 659, 573, 574, /* 20 */ 591, 592, 593, 856, 856, 856, 856, 856, 856, 856, /* 30 */ 856, 856, 856, 856, 856, 856, 584, 594, 604, 586, /* 40 */ 603, 856, 856, 605, 651, 616, 856, 651, 617, 636, /* 50 */ 634, 856, 637, 638, 856, 708, 651, 618, 706, 707, /* 60 */ 651, 619, 856, 856, 737, 797, 743, 738, 856, 664, /* 70 */ 856, 856, 665, 673, 675, 682, 720, 711, 713, 701, /* 80 */ 715, 670, 856, 600, 856, 601, 856, 602, 716, 856, /* 90 */ 717, 856, 718, 856, 856, 702, 856, 709, 708, 703, /* 100 */ 856, 588, 710, 705, 856, 736, 856, 856, 739, 856, /* 110 */ 740, 741, 742, 744, 747, 856, 748, 856, 749, 856, /* 120 */ 750, 856, 751, 856, 752, 856, 753, 856, 754, 856, /* 130 */ 755, 856, 756, 856, 757, 856, 758, 856, 759, 856, /* 140 */ 856, 760, 761, 762, 856, 763, 856, 764, 856, 765, /* 150 */ 856, 766, 856, 767, 856, 768, 769, 856, 770, 856, /* 160 */ 773, 771, 856, 856, 856, 779, 856, 797, 856, 856, /* 170 */ 856, 856, 856, 782, 796, 856, 774, 856, 775, 856, /* 180 */ 776, 856, 777, 856, 856, 856, 856, 856, 787, 856, /* 190 */ 856, 856, 788, 856, 856, 856, 845, 856, 856, 856, /* 200 */ 846, 856, 856, 856, 847, 856, 856, 856, 848, 856, /* 210 */ 856, 856, 856, 856, 789, 856, 781, 797, 794, 795, /* 220 */ 690, 856, 691, 785, 772, 856, 856, 856, 780, 856, /* 230 */ 797, 856, 784, 856, 783, 690, 786, 709, 708, 704, /* 240 */ 856, 714, 856, 797, 712, 856, 721, 674, 685, 683, /* 250 */ 684, 692, 693, 856, 694, 856, 695, 856, 696, 856, /* 260 */ 690, 681, 589, 590, 856, 679, 680, 698, 700, 686, /* 270 */ 856, 856, 856, 699, 856, 803, 708, 805, 804, 856, /* 280 */ 697, 685, 856, 856, 856, 681, 698, 700, 687, 856, /* 290 */ 681, 676, 677, 856, 856, 678, 671, 672, 778, 856, /* 300 */ 735, 856, 745, 856, 746, 856, 651, 620, 856, 801, /* 310 */ 624, 621, 625, 856, 626, 856, 856, 627, 856, 630, /* 320 */ 631, 632, 633, 856, 628, 856, 629, 856, 856, 802, /* 330 */ 622, 856, 623, 636, 635, 606, 856, 607, 608, 609, /* 340 */ 856, 610, 613, 856, 611, 614, 612, 615, 595, 856, /* 350 */ 856, 596, 856, 856, 597, 599, 598, 587, 856, 856, /* 360 */ 641, 856, 644, 856, 856, 856, 856, 651, 645, 856, /* 370 */ 856, 856, 651, 646, 856, 651, 647, 856, 856, 856, /* 380 */ 856, 856, 856, 801, 624, 649, 856, 648, 650, 642, /* 390 */ 643, 585, 856, 856, 581, 856, 856, 579, 856, 856, /* 400 */ 856, 856, 856, 828, 856, 856, 856, 690, 833, 856, /* 410 */ 856, 856, 856, 856, 856, 834, 835, 856, 856, 856, /* 420 */ 856, 856, 856, 733, 734, 825, 826, 856, 827, 580, /* 430 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, /* 440 */ 856, 856, 856, 856, 856, 856, 654, 856, 856, 856, /* 450 */ 856, 856, 856, 856, 653, 856, 856, 856, 856, 856, /* 460 */ 856, 856, 723, 856, 856, 856, 724, 856, 856, 731, /* 470 */ 856, 856, 732, 856, 856, 856, 856, 856, 856, 729, /* 480 */ 856, 730, 856, 856, 856, 856, 856, 856, 856, 856, /* 490 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, /* 500 */ 690, 856, 856, 653, 856, 856, 856, 856, 856, 856, /* 510 */ 856, 856, 690, 731, 856, 856, 856, 856, 856, 856, /* 520 */ 653, 856, 856, 856, 856, 856, 856, 856, 856, 856, /* 530 */ 856, 856, 856, 822, 856, 856, 856, 856, 856, 856, /* 540 */ 856, 856, 856, 856, 821, 856, 856, 856, 854, 856, /* 550 */ 856, 856, 856, 856, 856, 856, 853, 854, 856, 856, /* 560 */ 567, 569, 565, }; #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0])) /* The next table maps tokens into fallback tokens. If a construct ** like the following: ** ** %fallback ID X Y Z. ** ** appears in the grammer, then ID becomes a fallback token for X, Y, ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { 0, /* $ => nothing */ 0, /* END_OF_FILE => nothing */ 0, /* ILLEGAL => nothing */ 0, /* SPACE => nothing */ 0, /* UNCLOSED_STRING => nothing */ 0, /* COMMENT => nothing */ 0, /* FUNCTION => nothing */ 0, /* COLUMN => nothing */ 0, /* AGG_FUNCTION => nothing */ 0, /* SEMI => nothing */ 23, /* EXPLAIN => ID */ 23, /* BEGIN => ID */ 0, /* TRANSACTION => nothing */ 0, /* COMMIT => nothing */ 23, /* END => ID */ 0, /* ROLLBACK => nothing */ 0, /* CREATE => nothing */ 0, /* TABLE => nothing */ 23, /* TEMP => ID */ 0, /* LP => nothing */ 0, /* RP => nothing */ 0, /* AS => nothing */ 0, /* COMMA => nothing */ 0, /* ID => nothing */ 23, /* ABORT => ID */ 23, /* AFTER => ID */ 23, /* ASC => ID */ 23, /* ATTACH => ID */ 23, /* BEFORE => ID */ 23, /* CASCADE => ID */ 23, /* CLUSTER => ID */ 23, /* CONFLICT => ID */ 23, /* COPY => ID */ 23, /* DATABASE => ID */ 23, /* DEFERRED => ID */ 23, /* DELIMITERS => ID */ 23, /* DESC => ID */ 23, /* DETACH => ID */ 23, /* EACH => ID */ 23, /* FAIL => ID */ 23, /* FOR => ID */ 23, /* GLOB => ID */ 23, /* IGNORE => ID */ 23, /* IMMEDIATE => ID */ 23, /* INITIALLY => ID */ 23, /* INSTEAD => ID */ 23, /* LIKE => ID */ 23, /* MATCH => ID */ 23, /* KEY => ID */ 23, /* OF => ID */ 23, /* OFFSET => ID */ 23, /* PRAGMA => ID */ 23, /* RAISE => ID */ 23, /* REPLACE => ID */ 23, /* RESTRICT => ID */ 23, /* ROW => ID */ 23, /* STATEMENT => ID */ 23, /* TRIGGER => ID */ 23, /* VACUUM => ID */ 23, /* VIEW => ID */ 0, /* OR => nothing */ 0, /* AND => nothing */ 0, /* NOT => nothing */ 0, /* EQ => nothing */ 0, /* NE => nothing */ 0, /* ISNULL => nothing */ 0, /* NOTNULL => nothing */ 0, /* IS => nothing */ 0, /* BETWEEN => nothing */ 0, /* IN => nothing */ 0, /* GT => nothing */ 0, /* GE => nothing */ 0, /* LT => nothing */ 0, /* LE => nothing */ 0, /* BITAND => nothing */ 0, /* BITOR => nothing */ 0, /* LSHIFT => nothing */ 0, /* RSHIFT => nothing */ 0, /* PLUS => nothing */ 0, /* MINUS => nothing */ 0, /* STAR => nothing */ 0, /* SLASH => nothing */ 0, /* REM => nothing */ 0, /* CONCAT => nothing */ 0, /* UMINUS => nothing */ 0, /* UPLUS => nothing */ 0, /* BITNOT => nothing */ 0, /* STRING => nothing */ 0, /* JOIN_KW => nothing */ 0, /* INTEGER => nothing */ 0, /* CONSTRAINT => nothing */ 0, /* DEFAULT => nothing */ 0, /* FLOAT => nothing */ 0, /* NULL => nothing */ 0, /* PRIMARY => nothing */ 0, /* UNIQUE => nothing */ 0, /* CHECK => nothing */ 0, /* REFERENCES => nothing */ 0, /* COLLATE => nothing */ 0, /* ON => nothing */ 0, /* DELETE => nothing */ 0, /* UPDATE => nothing */ 0, /* INSERT => nothing */ 0, /* SET => nothing */ 0, /* DEFERRABLE => nothing */ 0, /* FOREIGN => nothing */ 0, /* DROP => nothing */ 0, /* UNION => nothing */ 0, /* ALL => nothing */ 0, /* INTERSECT => nothing */ 0, /* EXCEPT => nothing */ 0, /* SELECT => nothing */ 0, /* DISTINCT => nothing */ 0, /* DOT => nothing */ 0, /* FROM => nothing */ 0, /* JOIN => nothing */ 0, /* USING => nothing */ 0, /* ORDER => nothing */ 0, /* BY => nothing */ 0, /* GROUP => nothing */ 0, /* HAVING => nothing */ 0, /* LIMIT => nothing */ 0, /* WHERE => nothing */ 0, /* INTO => nothing */ 0, /* VALUES => nothing */ 0, /* VARIABLE => nothing */ 0, /* CASE => nothing */ 0, /* WHEN => nothing */ 0, /* THEN => nothing */ 0, /* ELSE => nothing */ 0, /* INDEX => nothing */ }; #endif /* YYFALLBACK */ /* The following structure represents a single element of the ** parser's stack. Information stored includes: ** ** + The state number for the parser at this level of the stack. ** ** + The value of the token stored at this level of the stack. ** (In other words, the "major" token.) ** ** + The semantic value stored at this level of the stack. This is ** the information used by the action routines in the grammar. ** It is sometimes called the "minor" token. */ struct yyStackEntry { int stateno; /* The state-number */ int major; /* The major token value. This is the code ** number for the token at this stack level */ YYMINORTYPE minor; /* The user-supplied minor token value. This ** is the value of the token */ }; typedef struct yyStackEntry yyStackEntry; /* The state of the parser is completely contained in an instance of ** the following structure */ struct yyParser { int yyidx; /* Index of top element in stack */ int yyerrcnt; /* Shifts left before out of the error */ sqliteParserARG_SDECL /* A place to hold %extra_argument */ yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ }; typedef struct yyParser yyParser; #ifndef NDEBUG #include static FILE *yyTraceFILE = 0; static char *yyTracePrompt = 0; #endif /* NDEBUG */ #ifndef NDEBUG /* ** Turn parser tracing on by giving a stream to which to write the trace ** and a prompt to preface each trace message. Tracing is turned off ** by making either argument NULL ** ** Inputs: **
    **
  • A FILE* to which trace output should be written. ** If NULL, then tracing is turned off. **
  • A prefix string written at the beginning of every ** line of trace output. If NULL, then tracing is ** turned off. **
** ** Outputs: ** None. */ void sqliteParserTrace(FILE *TraceFILE, char *zTracePrompt){ yyTraceFILE = TraceFILE; yyTracePrompt = zTracePrompt; if( yyTraceFILE==0 ) yyTracePrompt = 0; else if( yyTracePrompt==0 ) yyTraceFILE = 0; } #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *yyTokenName[] = { "$", "END_OF_FILE", "ILLEGAL", "SPACE", "UNCLOSED_STRING", "COMMENT", "FUNCTION", "COLUMN", "AGG_FUNCTION", "SEMI", "EXPLAIN", "BEGIN", "TRANSACTION", "COMMIT", "END", "ROLLBACK", "CREATE", "TABLE", "TEMP", "LP", "RP", "AS", "COMMA", "ID", "ABORT", "AFTER", "ASC", "ATTACH", "BEFORE", "CASCADE", "CLUSTER", "CONFLICT", "COPY", "DATABASE", "DEFERRED", "DELIMITERS", "DESC", "DETACH", "EACH", "FAIL", "FOR", "GLOB", "IGNORE", "IMMEDIATE", "INITIALLY", "INSTEAD", "LIKE", "MATCH", "KEY", "OF", "OFFSET", "PRAGMA", "RAISE", "REPLACE", "RESTRICT", "ROW", "STATEMENT", "TRIGGER", "VACUUM", "VIEW", "OR", "AND", "NOT", "EQ", "NE", "ISNULL", "NOTNULL", "IS", "BETWEEN", "IN", "GT", "GE", "LT", "LE", "BITAND", "BITOR", "LSHIFT", "RSHIFT", "PLUS", "MINUS", "STAR", "SLASH", "REM", "CONCAT", "UMINUS", "UPLUS", "BITNOT", "STRING", "JOIN_KW", "INTEGER", "CONSTRAINT", "DEFAULT", "FLOAT", "NULL", "PRIMARY", "UNIQUE", "CHECK", "REFERENCES", "COLLATE", "ON", "DELETE", "UPDATE", "INSERT", "SET", "DEFERRABLE", "FOREIGN", "DROP", "UNION", "ALL", "INTERSECT", "EXCEPT", "SELECT", "DISTINCT", "DOT", "FROM", "JOIN", "USING", "ORDER", "BY", "GROUP", "HAVING", "LIMIT", "WHERE", "INTO", "VALUES", "VARIABLE", "CASE", "WHEN", "THEN", "ELSE", "INDEX", "error", "input", "cmdlist", "ecmd", "explain", "cmdx", "cmd", "trans_opt", "onconf", "nm", "create_table", "create_table_args", "temp", "columnlist", "conslist_opt", "select", "column", "columnid", "type", "carglist", "id", "ids", "typename", "signed", "carg", "ccons", "sortorder", "expr", "idxlist_opt", "refargs", "defer_subclause", "refarg", "refact", "init_deferred_pred_opt", "conslist", "tcons", "idxlist", "defer_subclause_opt", "orconf", "resolvetype", "oneselect", "multiselect_op", "distinct", "selcollist", "from", "where_opt", "groupby_opt", "having_opt", "orderby_opt", "limit_opt", "sclp", "as", "seltablist", "stl_prefix", "joinop", "dbnm", "on_opt", "using_opt", "seltablist_paren", "joinop2", "sortlist", "sortitem", "collate", "exprlist", "setlist", "insert_cmd", "inscollist_opt", "itemlist", "inscollist", "likeop", "case_operand", "case_exprlist", "case_else", "expritem", "uniqueflag", "idxitem", "plus_num", "minus_num", "plus_opt", "number", "trigger_decl", "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause", "when_clause", "trigger_cmd", "database_kw_opt", "key_opt", }; #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. */ static const char *yyRuleName[] = { /* 0 */ "input ::= cmdlist", /* 1 */ "cmdlist ::= cmdlist ecmd", /* 2 */ "cmdlist ::= ecmd", /* 3 */ "ecmd ::= explain cmdx SEMI", /* 4 */ "ecmd ::= SEMI", /* 5 */ "cmdx ::= cmd", /* 6 */ "explain ::= EXPLAIN", /* 7 */ "explain ::=", /* 8 */ "cmd ::= BEGIN trans_opt onconf", /* 9 */ "trans_opt ::=", /* 10 */ "trans_opt ::= TRANSACTION", /* 11 */ "trans_opt ::= TRANSACTION nm", /* 12 */ "cmd ::= COMMIT trans_opt", /* 13 */ "cmd ::= END trans_opt", /* 14 */ "cmd ::= ROLLBACK trans_opt", /* 15 */ "cmd ::= create_table create_table_args", /* 16 */ "create_table ::= CREATE temp TABLE nm", /* 17 */ "temp ::= TEMP", /* 18 */ "temp ::=", /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP", /* 20 */ "create_table_args ::= AS select", /* 21 */ "columnlist ::= columnlist COMMA column", /* 22 */ "columnlist ::= column", /* 23 */ "column ::= columnid type carglist", /* 24 */ "columnid ::= nm", /* 25 */ "id ::= ID", /* 26 */ "ids ::= ID", /* 27 */ "ids ::= STRING", /* 28 */ "nm ::= ID", /* 29 */ "nm ::= STRING", /* 30 */ "nm ::= JOIN_KW", /* 31 */ "type ::=", /* 32 */ "type ::= typename", /* 33 */ "type ::= typename LP signed RP", /* 34 */ "type ::= typename LP signed COMMA signed RP", /* 35 */ "typename ::= ids", /* 36 */ "typename ::= typename ids", /* 37 */ "signed ::= INTEGER", /* 38 */ "signed ::= PLUS INTEGER", /* 39 */ "signed ::= MINUS INTEGER", /* 40 */ "carglist ::= carglist carg", /* 41 */ "carglist ::=", /* 42 */ "carg ::= CONSTRAINT nm ccons", /* 43 */ "carg ::= ccons", /* 44 */ "carg ::= DEFAULT STRING", /* 45 */ "carg ::= DEFAULT ID", /* 46 */ "carg ::= DEFAULT INTEGER", /* 47 */ "carg ::= DEFAULT PLUS INTEGER", /* 48 */ "carg ::= DEFAULT MINUS INTEGER", /* 49 */ "carg ::= DEFAULT FLOAT", /* 50 */ "carg ::= DEFAULT PLUS FLOAT", /* 51 */ "carg ::= DEFAULT MINUS FLOAT", /* 52 */ "carg ::= DEFAULT NULL", /* 53 */ "ccons ::= NULL onconf", /* 54 */ "ccons ::= NOT NULL onconf", /* 55 */ "ccons ::= PRIMARY KEY sortorder onconf", /* 56 */ "ccons ::= UNIQUE onconf", /* 57 */ "ccons ::= CHECK LP expr RP onconf", /* 58 */ "ccons ::= REFERENCES nm idxlist_opt refargs", /* 59 */ "ccons ::= defer_subclause", /* 60 */ "ccons ::= COLLATE id", /* 61 */ "refargs ::=", /* 62 */ "refargs ::= refargs refarg", /* 63 */ "refarg ::= MATCH nm", /* 64 */ "refarg ::= ON DELETE refact", /* 65 */ "refarg ::= ON UPDATE refact", /* 66 */ "refarg ::= ON INSERT refact", /* 67 */ "refact ::= SET NULL", /* 68 */ "refact ::= SET DEFAULT", /* 69 */ "refact ::= CASCADE", /* 70 */ "refact ::= RESTRICT", /* 71 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", /* 72 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", /* 73 */ "init_deferred_pred_opt ::=", /* 74 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", /* 75 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", /* 76 */ "conslist_opt ::=", /* 77 */ "conslist_opt ::= COMMA conslist", /* 78 */ "conslist ::= conslist COMMA tcons", /* 79 */ "conslist ::= conslist tcons", /* 80 */ "conslist ::= tcons", /* 81 */ "tcons ::= CONSTRAINT nm", /* 82 */ "tcons ::= PRIMARY KEY LP idxlist RP onconf", /* 83 */ "tcons ::= UNIQUE LP idxlist RP onconf", /* 84 */ "tcons ::= CHECK expr onconf", /* 85 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", /* 86 */ "defer_subclause_opt ::=", /* 87 */ "defer_subclause_opt ::= defer_subclause", /* 88 */ "onconf ::=", /* 89 */ "onconf ::= ON CONFLICT resolvetype", /* 90 */ "orconf ::=", /* 91 */ "orconf ::= OR resolvetype", /* 92 */ "resolvetype ::= ROLLBACK", /* 93 */ "resolvetype ::= ABORT", /* 94 */ "resolvetype ::= FAIL", /* 95 */ "resolvetype ::= IGNORE", /* 96 */ "resolvetype ::= REPLACE", /* 97 */ "cmd ::= DROP TABLE nm", /* 98 */ "cmd ::= CREATE temp VIEW nm AS select", /* 99 */ "cmd ::= DROP VIEW nm", /* 100 */ "cmd ::= select", /* 101 */ "select ::= oneselect", /* 102 */ "select ::= select multiselect_op oneselect", /* 103 */ "multiselect_op ::= UNION", /* 104 */ "multiselect_op ::= UNION ALL", /* 105 */ "multiselect_op ::= INTERSECT", /* 106 */ "multiselect_op ::= EXCEPT", /* 107 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", /* 108 */ "distinct ::= DISTINCT", /* 109 */ "distinct ::= ALL", /* 110 */ "distinct ::=", /* 111 */ "sclp ::= selcollist COMMA", /* 112 */ "sclp ::=", /* 113 */ "selcollist ::= sclp expr as", /* 114 */ "selcollist ::= sclp STAR", /* 115 */ "selcollist ::= sclp nm DOT STAR", /* 116 */ "as ::= AS nm", /* 117 */ "as ::= ids", /* 118 */ "as ::=", /* 119 */ "from ::=", /* 120 */ "from ::= FROM seltablist", /* 121 */ "stl_prefix ::= seltablist joinop", /* 122 */ "stl_prefix ::=", /* 123 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", /* 124 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", /* 125 */ "seltablist_paren ::= select", /* 126 */ "seltablist_paren ::= seltablist", /* 127 */ "dbnm ::=", /* 128 */ "dbnm ::= DOT nm", /* 129 */ "joinop ::= COMMA", /* 130 */ "joinop ::= JOIN", /* 131 */ "joinop ::= JOIN_KW JOIN", /* 132 */ "joinop ::= JOIN_KW nm JOIN", /* 133 */ "joinop ::= JOIN_KW nm nm JOIN", /* 134 */ "on_opt ::= ON expr", /* 135 */ "on_opt ::=", /* 136 */ "using_opt ::= USING LP idxlist RP", /* 137 */ "using_opt ::=", /* 138 */ "orderby_opt ::=", /* 139 */ "orderby_opt ::= ORDER BY sortlist", /* 140 */ "sortlist ::= sortlist COMMA sortitem collate sortorder", /* 141 */ "sortlist ::= sortitem collate sortorder", /* 142 */ "sortitem ::= expr", /* 143 */ "sortorder ::= ASC", /* 144 */ "sortorder ::= DESC", /* 145 */ "sortorder ::=", /* 146 */ "collate ::=", /* 147 */ "collate ::= COLLATE id", /* 148 */ "groupby_opt ::=", /* 149 */ "groupby_opt ::= GROUP BY exprlist", /* 150 */ "having_opt ::=", /* 151 */ "having_opt ::= HAVING expr", /* 152 */ "limit_opt ::=", /* 153 */ "limit_opt ::= LIMIT signed", /* 154 */ "limit_opt ::= LIMIT signed OFFSET signed", /* 155 */ "limit_opt ::= LIMIT signed COMMA signed", /* 156 */ "cmd ::= DELETE FROM nm dbnm where_opt", /* 157 */ "where_opt ::=", /* 158 */ "where_opt ::= WHERE expr", /* 159 */ "cmd ::= UPDATE orconf nm dbnm SET setlist where_opt", /* 160 */ "setlist ::= setlist COMMA nm EQ expr", /* 161 */ "setlist ::= nm EQ expr", /* 162 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt VALUES LP itemlist RP", /* 163 */ "cmd ::= insert_cmd INTO nm dbnm inscollist_opt select", /* 164 */ "insert_cmd ::= INSERT orconf", /* 165 */ "insert_cmd ::= REPLACE", /* 166 */ "itemlist ::= itemlist COMMA expr", /* 167 */ "itemlist ::= expr", /* 168 */ "inscollist_opt ::=", /* 169 */ "inscollist_opt ::= LP inscollist RP", /* 170 */ "inscollist ::= inscollist COMMA nm", /* 171 */ "inscollist ::= nm", /* 172 */ "expr ::= LP expr RP", /* 173 */ "expr ::= NULL", /* 174 */ "expr ::= ID", /* 175 */ "expr ::= JOIN_KW", /* 176 */ "expr ::= nm DOT nm", /* 177 */ "expr ::= nm DOT nm DOT nm", /* 178 */ "expr ::= INTEGER", /* 179 */ "expr ::= FLOAT", /* 180 */ "expr ::= STRING", /* 181 */ "expr ::= VARIABLE", /* 182 */ "expr ::= ID LP exprlist RP", /* 183 */ "expr ::= ID LP STAR RP", /* 184 */ "expr ::= expr AND expr", /* 185 */ "expr ::= expr OR expr", /* 186 */ "expr ::= expr LT expr", /* 187 */ "expr ::= expr GT expr", /* 188 */ "expr ::= expr LE expr", /* 189 */ "expr ::= expr GE expr", /* 190 */ "expr ::= expr NE expr", /* 191 */ "expr ::= expr EQ expr", /* 192 */ "expr ::= expr BITAND expr", /* 193 */ "expr ::= expr BITOR expr", /* 194 */ "expr ::= expr LSHIFT expr", /* 195 */ "expr ::= expr RSHIFT expr", /* 196 */ "expr ::= expr likeop expr", /* 197 */ "expr ::= expr NOT likeop expr", /* 198 */ "likeop ::= LIKE", /* 199 */ "likeop ::= GLOB", /* 200 */ "expr ::= expr PLUS expr", /* 201 */ "expr ::= expr MINUS expr", /* 202 */ "expr ::= expr STAR expr", /* 203 */ "expr ::= expr SLASH expr", /* 204 */ "expr ::= expr REM expr", /* 205 */ "expr ::= expr CONCAT expr", /* 206 */ "expr ::= expr ISNULL", /* 207 */ "expr ::= expr IS NULL", /* 208 */ "expr ::= expr NOTNULL", /* 209 */ "expr ::= expr NOT NULL", /* 210 */ "expr ::= expr IS NOT NULL", /* 211 */ "expr ::= NOT expr", /* 212 */ "expr ::= BITNOT expr", /* 213 */ "expr ::= MINUS expr", /* 214 */ "expr ::= PLUS expr", /* 215 */ "expr ::= LP select RP", /* 216 */ "expr ::= expr BETWEEN expr AND expr", /* 217 */ "expr ::= expr NOT BETWEEN expr AND expr", /* 218 */ "expr ::= expr IN LP exprlist RP", /* 219 */ "expr ::= expr IN LP select RP", /* 220 */ "expr ::= expr NOT IN LP exprlist RP", /* 221 */ "expr ::= expr NOT IN LP select RP", /* 222 */ "expr ::= expr IN nm dbnm", /* 223 */ "expr ::= expr NOT IN nm dbnm", /* 224 */ "expr ::= CASE case_operand case_exprlist case_else END", /* 225 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", /* 226 */ "case_exprlist ::= WHEN expr THEN expr", /* 227 */ "case_else ::= ELSE expr", /* 228 */ "case_else ::=", /* 229 */ "case_operand ::= expr", /* 230 */ "case_operand ::=", /* 231 */ "exprlist ::= exprlist COMMA expritem", /* 232 */ "exprlist ::= expritem", /* 233 */ "expritem ::= expr", /* 234 */ "expritem ::=", /* 235 */ "cmd ::= CREATE uniqueflag INDEX nm ON nm dbnm LP idxlist RP onconf", /* 236 */ "uniqueflag ::= UNIQUE", /* 237 */ "uniqueflag ::=", /* 238 */ "idxlist_opt ::=", /* 239 */ "idxlist_opt ::= LP idxlist RP", /* 240 */ "idxlist ::= idxlist COMMA idxitem", /* 241 */ "idxlist ::= idxitem", /* 242 */ "idxitem ::= nm sortorder", /* 243 */ "cmd ::= DROP INDEX nm dbnm", /* 244 */ "cmd ::= COPY orconf nm dbnm FROM nm USING DELIMITERS STRING", /* 245 */ "cmd ::= COPY orconf nm dbnm FROM nm", /* 246 */ "cmd ::= VACUUM", /* 247 */ "cmd ::= VACUUM nm", /* 248 */ "cmd ::= PRAGMA ids EQ nm", /* 249 */ "cmd ::= PRAGMA ids EQ ON", /* 250 */ "cmd ::= PRAGMA ids EQ plus_num", /* 251 */ "cmd ::= PRAGMA ids EQ minus_num", /* 252 */ "cmd ::= PRAGMA ids LP nm RP", /* 253 */ "cmd ::= PRAGMA ids", /* 254 */ "plus_num ::= plus_opt number", /* 255 */ "minus_num ::= MINUS number", /* 256 */ "number ::= INTEGER", /* 257 */ "number ::= FLOAT", /* 258 */ "plus_opt ::= PLUS", /* 259 */ "plus_opt ::=", /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", /* 261 */ "trigger_decl ::= temp TRIGGER nm trigger_time trigger_event ON nm dbnm foreach_clause when_clause", /* 262 */ "trigger_time ::= BEFORE", /* 263 */ "trigger_time ::= AFTER", /* 264 */ "trigger_time ::= INSTEAD OF", /* 265 */ "trigger_time ::=", /* 266 */ "trigger_event ::= DELETE", /* 267 */ "trigger_event ::= INSERT", /* 268 */ "trigger_event ::= UPDATE", /* 269 */ "trigger_event ::= UPDATE OF inscollist", /* 270 */ "foreach_clause ::=", /* 271 */ "foreach_clause ::= FOR EACH ROW", /* 272 */ "foreach_clause ::= FOR EACH STATEMENT", /* 273 */ "when_clause ::=", /* 274 */ "when_clause ::= WHEN expr", /* 275 */ "trigger_cmd_list ::= trigger_cmd SEMI trigger_cmd_list", /* 276 */ "trigger_cmd_list ::=", /* 277 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", /* 278 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", /* 279 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", /* 280 */ "trigger_cmd ::= DELETE FROM nm where_opt", /* 281 */ "trigger_cmd ::= select", /* 282 */ "expr ::= RAISE LP IGNORE RP", /* 283 */ "expr ::= RAISE LP ROLLBACK COMMA nm RP", /* 284 */ "expr ::= RAISE LP ABORT COMMA nm RP", /* 285 */ "expr ::= RAISE LP FAIL COMMA nm RP", /* 286 */ "cmd ::= DROP TRIGGER nm dbnm", /* 287 */ "cmd ::= ATTACH database_kw_opt ids AS nm key_opt", /* 288 */ "key_opt ::= USING ids", /* 289 */ "key_opt ::=", /* 290 */ "database_kw_opt ::= DATABASE", /* 291 */ "database_kw_opt ::=", /* 292 */ "cmd ::= DETACH database_kw_opt nm", }; #endif /* NDEBUG */ /* ** This function returns the symbolic name associated with a token ** value. */ const char *sqliteParserTokenName(int tokenType){ #ifndef NDEBUG if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){ return yyTokenName[tokenType]; }else{ return "Unknown"; } #else return ""; #endif } /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** ** Inputs: ** A pointer to the function used to allocate memory. ** ** Outputs: ** A pointer to a parser. This pointer is used in subsequent calls ** to sqliteParser and sqliteParserFree. */ void *sqliteParserAlloc(void *(*mallocProc)(size_t)){ yyParser *pParser; pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); if( pParser ){ pParser->yyidx = -1; } return pParser; } /* The following function deletes the value associated with a ** symbol. The symbol can be either a terminal or nonterminal. ** "yymajor" is the symbol code, and "yypminor" is a pointer to ** the value. */ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ case 146: #line 286 "parse.y" {sqliteSelectDelete((yypminor->yy179));} #line 1235 "parse.c" break; case 158: #line 533 "parse.y" {sqliteExprDelete((yypminor->yy242));} #line 1240 "parse.c" break; case 159: #line 746 "parse.y" {sqliteIdListDelete((yypminor->yy320));} #line 1245 "parse.c" break; case 167: #line 744 "parse.y" {sqliteIdListDelete((yypminor->yy320));} #line 1250 "parse.c" break; case 171: #line 288 "parse.y" {sqliteSelectDelete((yypminor->yy179));} #line 1255 "parse.c" break; case 174: #line 322 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1260 "parse.c" break; case 175: #line 353 "parse.y" {sqliteSrcListDelete((yypminor->yy307));} #line 1265 "parse.c" break; case 176: #line 483 "parse.y" {sqliteExprDelete((yypminor->yy242));} #line 1270 "parse.c" break; case 177: #line 459 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1275 "parse.c" break; case 178: #line 464 "parse.y" {sqliteExprDelete((yypminor->yy242));} #line 1280 "parse.c" break; case 179: #line 431 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1285 "parse.c" break; case 181: #line 324 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1290 "parse.c" break; case 183: #line 349 "parse.y" {sqliteSrcListDelete((yypminor->yy307));} #line 1295 "parse.c" break; case 184: #line 351 "parse.y" {sqliteSrcListDelete((yypminor->yy307));} #line 1300 "parse.c" break; case 187: #line 420 "parse.y" {sqliteExprDelete((yypminor->yy242));} #line 1305 "parse.c" break; case 188: #line 425 "parse.y" {sqliteIdListDelete((yypminor->yy320));} #line 1310 "parse.c" break; case 189: #line 400 "parse.y" {sqliteSelectDelete((yypminor->yy179));} #line 1315 "parse.c" break; case 191: #line 433 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1320 "parse.c" break; case 192: #line 435 "parse.y" {sqliteExprDelete((yypminor->yy242));} #line 1325 "parse.c" break; case 194: #line 719 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1330 "parse.c" break; case 195: #line 489 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1335 "parse.c" break; case 197: #line 520 "parse.y" {sqliteIdListDelete((yypminor->yy320));} #line 1340 "parse.c" break; case 198: #line 514 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1345 "parse.c" break; case 199: #line 522 "parse.y" {sqliteIdListDelete((yypminor->yy320));} #line 1350 "parse.c" break; case 202: #line 702 "parse.y" {sqliteExprListDelete((yypminor->yy322));} #line 1355 "parse.c" break; case 204: #line 721 "parse.y" {sqliteExprDelete((yypminor->yy242));} #line 1360 "parse.c" break; case 212: #line 828 "parse.y" {sqliteDeleteTriggerStep((yypminor->yy19));} #line 1365 "parse.c" break; case 214: #line 812 "parse.y" {sqliteIdListDelete((yypminor->yy290).b);} #line 1370 "parse.c" break; case 217: #line 836 "parse.y" {sqliteDeleteTriggerStep((yypminor->yy19));} #line 1375 "parse.c" break; default: break; /* If no destructor action specified: do nothing */ } } /* ** Pop the parser's stack once. ** ** If there is a destructor routine associated with the token which ** is popped from the stack, then call it. ** ** Return the major token number for the symbol popped. */ static int yy_pop_parser_stack(yyParser *pParser){ YYCODETYPE yymajor; yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; if( pParser->yyidx<0 ) return 0; #ifndef NDEBUG if( yyTraceFILE && pParser->yyidx>=0 ){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); } #endif yymajor = yytos->major; yy_destructor( yymajor, &yytos->minor); pParser->yyidx--; return yymajor; } /* ** Deallocate and destroy a parser. Destructors are all called for ** all stack elements before shutting the parser down. ** ** Inputs: **
    **
  • A pointer to the parser. This should be a pointer ** obtained from sqliteParserAlloc. **
  • A pointer to a function used to reclaim memory obtained ** from malloc. **
*/ void sqliteParserFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ yyParser *pParser = (yyParser*)p; if( pParser==0 ) return; while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); (*freeProc)((void*)pParser); } /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. ** ** If the look-ahead token is YYNOCODE, then check to see if the action is ** independent of the look-ahead. If it is, return the action, otherwise ** return YY_NO_ACTION. */ static int yy_find_shift_action( yyParser *pParser, /* The parser */ int iLookAhead /* The look-ahead token */ ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ i = yy_shift_ofst[stateno]; if( i==YY_SHIFT_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ return YY_NO_ACTION; } i += iLookAhead; if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK int iFallback; /* Fallback token */ if( iLookAhead %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } #endif return yy_find_shift_action(pParser, iFallback); } #endif return yy_default[stateno]; }else{ return yy_action[i]; } } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. ** ** If the look-ahead token is YYNOCODE, then check to see if the action is ** independent of the look-ahead. If it is, return the action, otherwise ** return YY_NO_ACTION. */ static int yy_find_reduce_action( yyParser *pParser, /* The parser */ int iLookAhead /* The look-ahead token */ ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; i = yy_reduce_ofst[stateno]; if( i==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; } if( iLookAhead==YYNOCODE ){ return YY_NO_ACTION; } i += iLookAhead; if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ return yy_default[stateno]; }else{ return yy_action[i]; } } /* ** Perform a shift action. */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ int yyNewState, /* The new state to shift in */ int yyMajor, /* The major token to shift in */ YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */ ){ yyStackEntry *yytos; yypParser->yyidx++; if( yypParser->yyidx>=YYSTACKDEPTH ){ sqliteParserARG_FETCH; yypParser->yyidx--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument var */ return; } yytos = &yypParser->yystack[yypParser->yyidx]; yytos->stateno = yyNewState; yytos->major = yyMajor; yytos->minor = *yypMinor; #ifndef NDEBUG if( yyTraceFILE && yypParser->yyidx>0 ){ int i; fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); for(i=1; i<=yypParser->yyidx; i++) fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); fprintf(yyTraceFILE,"\n"); } #endif } /* The following table contains information about every rule that ** is used during the reduce. */ static struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } yyRuleInfo[] = { { 132, 1 }, { 133, 2 }, { 133, 1 }, { 134, 3 }, { 134, 1 }, { 136, 1 }, { 135, 1 }, { 135, 0 }, { 137, 3 }, { 138, 0 }, { 138, 1 }, { 138, 2 }, { 137, 2 }, { 137, 2 }, { 137, 2 }, { 137, 2 }, { 141, 4 }, { 143, 1 }, { 143, 0 }, { 142, 4 }, { 142, 2 }, { 144, 3 }, { 144, 1 }, { 147, 3 }, { 148, 1 }, { 151, 1 }, { 152, 1 }, { 152, 1 }, { 140, 1 }, { 140, 1 }, { 140, 1 }, { 149, 0 }, { 149, 1 }, { 149, 4 }, { 149, 6 }, { 153, 1 }, { 153, 2 }, { 154, 1 }, { 154, 2 }, { 154, 2 }, { 150, 2 }, { 150, 0 }, { 155, 3 }, { 155, 1 }, { 155, 2 }, { 155, 2 }, { 155, 2 }, { 155, 3 }, { 155, 3 }, { 155, 2 }, { 155, 3 }, { 155, 3 }, { 155, 2 }, { 156, 2 }, { 156, 3 }, { 156, 4 }, { 156, 2 }, { 156, 5 }, { 156, 4 }, { 156, 1 }, { 156, 2 }, { 160, 0 }, { 160, 2 }, { 162, 2 }, { 162, 3 }, { 162, 3 }, { 162, 3 }, { 163, 2 }, { 163, 2 }, { 163, 1 }, { 163, 1 }, { 161, 3 }, { 161, 2 }, { 164, 0 }, { 164, 2 }, { 164, 2 }, { 145, 0 }, { 145, 2 }, { 165, 3 }, { 165, 2 }, { 165, 1 }, { 166, 2 }, { 166, 6 }, { 166, 5 }, { 166, 3 }, { 166, 10 }, { 168, 0 }, { 168, 1 }, { 139, 0 }, { 139, 3 }, { 169, 0 }, { 169, 2 }, { 170, 1 }, { 170, 1 }, { 170, 1 }, { 170, 1 }, { 170, 1 }, { 137, 3 }, { 137, 6 }, { 137, 3 }, { 137, 1 }, { 146, 1 }, { 146, 3 }, { 172, 1 }, { 172, 2 }, { 172, 1 }, { 172, 1 }, { 171, 9 }, { 173, 1 }, { 173, 1 }, { 173, 0 }, { 181, 2 }, { 181, 0 }, { 174, 3 }, { 174, 2 }, { 174, 4 }, { 182, 2 }, { 182, 1 }, { 182, 0 }, { 175, 0 }, { 175, 2 }, { 184, 2 }, { 184, 0 }, { 183, 6 }, { 183, 7 }, { 189, 1 }, { 189, 1 }, { 186, 0 }, { 186, 2 }, { 185, 1 }, { 185, 1 }, { 185, 2 }, { 185, 3 }, { 185, 4 }, { 187, 2 }, { 187, 0 }, { 188, 4 }, { 188, 0 }, { 179, 0 }, { 179, 3 }, { 191, 5 }, { 191, 3 }, { 192, 1 }, { 157, 1 }, { 157, 1 }, { 157, 0 }, { 193, 0 }, { 193, 2 }, { 177, 0 }, { 177, 3 }, { 178, 0 }, { 178, 2 }, { 180, 0 }, { 180, 2 }, { 180, 4 }, { 180, 4 }, { 137, 5 }, { 176, 0 }, { 176, 2 }, { 137, 7 }, { 195, 5 }, { 195, 3 }, { 137, 9 }, { 137, 6 }, { 196, 2 }, { 196, 1 }, { 198, 3 }, { 198, 1 }, { 197, 0 }, { 197, 3 }, { 199, 3 }, { 199, 1 }, { 158, 3 }, { 158, 1 }, { 158, 1 }, { 158, 1 }, { 158, 3 }, { 158, 5 }, { 158, 1 }, { 158, 1 }, { 158, 1 }, { 158, 1 }, { 158, 4 }, { 158, 4 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 4 }, { 200, 1 }, { 200, 1 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 3 }, { 158, 2 }, { 158, 3 }, { 158, 2 }, { 158, 3 }, { 158, 4 }, { 158, 2 }, { 158, 2 }, { 158, 2 }, { 158, 2 }, { 158, 3 }, { 158, 5 }, { 158, 6 }, { 158, 5 }, { 158, 5 }, { 158, 6 }, { 158, 6 }, { 158, 4 }, { 158, 5 }, { 158, 5 }, { 202, 5 }, { 202, 4 }, { 203, 2 }, { 203, 0 }, { 201, 1 }, { 201, 0 }, { 194, 3 }, { 194, 1 }, { 204, 1 }, { 204, 0 }, { 137, 11 }, { 205, 1 }, { 205, 0 }, { 159, 0 }, { 159, 3 }, { 167, 3 }, { 167, 1 }, { 206, 2 }, { 137, 4 }, { 137, 9 }, { 137, 6 }, { 137, 1 }, { 137, 2 }, { 137, 4 }, { 137, 4 }, { 137, 4 }, { 137, 4 }, { 137, 5 }, { 137, 2 }, { 207, 2 }, { 208, 2 }, { 210, 1 }, { 210, 1 }, { 209, 1 }, { 209, 0 }, { 137, 5 }, { 211, 10 }, { 213, 1 }, { 213, 1 }, { 213, 2 }, { 213, 0 }, { 214, 1 }, { 214, 1 }, { 214, 1 }, { 214, 3 }, { 215, 0 }, { 215, 3 }, { 215, 3 }, { 216, 0 }, { 216, 2 }, { 212, 3 }, { 212, 0 }, { 217, 6 }, { 217, 8 }, { 217, 5 }, { 217, 4 }, { 217, 1 }, { 158, 4 }, { 158, 6 }, { 158, 6 }, { 158, 6 }, { 137, 4 }, { 137, 6 }, { 219, 2 }, { 219, 0 }, { 218, 1 }, { 218, 0 }, { 137, 3 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ /* ** Perform a reduce action and the shift that must immediately ** follow the reduce. */ static void yy_reduce( yyParser *yypParser, /* The parser */ int yyruleno /* Number of the rule by which to reduce */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ sqliteParserARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 && yyruleno ** { ... } // User supplied code ** #line ** break; */ case 0: /* No destructor defined for cmdlist */ break; case 1: /* No destructor defined for cmdlist */ /* No destructor defined for ecmd */ break; case 2: /* No destructor defined for ecmd */ break; case 3: /* No destructor defined for explain */ /* No destructor defined for cmdx */ /* No destructor defined for SEMI */ break; case 4: /* No destructor defined for SEMI */ break; case 5: #line 72 "parse.y" { sqliteExec(pParse); } #line 1901 "parse.c" /* No destructor defined for cmd */ break; case 6: #line 73 "parse.y" { sqliteBeginParse(pParse, 1); } #line 1907 "parse.c" /* No destructor defined for EXPLAIN */ break; case 7: #line 74 "parse.y" { sqliteBeginParse(pParse, 0); } #line 1913 "parse.c" break; case 8: #line 79 "parse.y" {sqliteBeginTransaction(pParse,yymsp[0].minor.yy372);} #line 1918 "parse.c" /* No destructor defined for BEGIN */ /* No destructor defined for trans_opt */ break; case 9: break; case 10: /* No destructor defined for TRANSACTION */ break; case 11: /* No destructor defined for TRANSACTION */ /* No destructor defined for nm */ break; case 12: #line 83 "parse.y" {sqliteCommitTransaction(pParse);} #line 1934 "parse.c" /* No destructor defined for COMMIT */ /* No destructor defined for trans_opt */ break; case 13: #line 84 "parse.y" {sqliteCommitTransaction(pParse);} #line 1941 "parse.c" /* No destructor defined for END */ /* No destructor defined for trans_opt */ break; case 14: #line 85 "parse.y" {sqliteRollbackTransaction(pParse);} #line 1948 "parse.c" /* No destructor defined for ROLLBACK */ /* No destructor defined for trans_opt */ break; case 15: /* No destructor defined for create_table */ /* No destructor defined for create_table_args */ break; case 16: #line 90 "parse.y" { sqliteStartTable(pParse,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy298,yymsp[-2].minor.yy372,0); } #line 1961 "parse.c" /* No destructor defined for TABLE */ break; case 17: #line 94 "parse.y" {yygotominor.yy372 = 1;} #line 1967 "parse.c" /* No destructor defined for TEMP */ break; case 18: #line 95 "parse.y" {yygotominor.yy372 = 0;} #line 1973 "parse.c" break; case 19: #line 96 "parse.y" { sqliteEndTable(pParse,&yymsp[0].minor.yy0,0); } #line 1980 "parse.c" /* No destructor defined for LP */ /* No destructor defined for columnlist */ /* No destructor defined for conslist_opt */ break; case 20: #line 99 "parse.y" { sqliteEndTable(pParse,0,yymsp[0].minor.yy179); sqliteSelectDelete(yymsp[0].minor.yy179); } #line 1991 "parse.c" /* No destructor defined for AS */ break; case 21: /* No destructor defined for columnlist */ /* No destructor defined for COMMA */ /* No destructor defined for column */ break; case 22: /* No destructor defined for column */ break; case 23: /* No destructor defined for columnid */ /* No destructor defined for type */ /* No destructor defined for carglist */ break; case 24: #line 111 "parse.y" {sqliteAddColumn(pParse,&yymsp[0].minor.yy298);} #line 2010 "parse.c" break; case 25: #line 117 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 2015 "parse.c" break; case 26: #line 149 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 2020 "parse.c" break; case 27: #line 150 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 2025 "parse.c" break; case 28: #line 155 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 2030 "parse.c" break; case 29: #line 156 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 2035 "parse.c" break; case 30: #line 157 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 2040 "parse.c" break; case 31: break; case 32: #line 160 "parse.y" {sqliteAddColumnType(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298);} #line 2047 "parse.c" break; case 33: #line 161 "parse.y" {sqliteAddColumnType(pParse,&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0);} #line 2052 "parse.c" /* No destructor defined for LP */ /* No destructor defined for signed */ break; case 34: #line 163 "parse.y" {sqliteAddColumnType(pParse,&yymsp[-5].minor.yy298,&yymsp[0].minor.yy0);} #line 2059 "parse.c" /* No destructor defined for LP */ /* No destructor defined for signed */ /* No destructor defined for COMMA */ /* No destructor defined for signed */ break; case 35: #line 165 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy298;} #line 2068 "parse.c" break; case 36: #line 166 "parse.y" {yygotominor.yy298 = yymsp[-1].minor.yy298;} #line 2073 "parse.c" /* No destructor defined for ids */ break; case 37: #line 168 "parse.y" { yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); } #line 2079 "parse.c" break; case 38: #line 169 "parse.y" { yygotominor.yy372 = atoi(yymsp[0].minor.yy0.z); } #line 2084 "parse.c" /* No destructor defined for PLUS */ break; case 39: #line 170 "parse.y" { yygotominor.yy372 = -atoi(yymsp[0].minor.yy0.z); } #line 2090 "parse.c" /* No destructor defined for MINUS */ break; case 40: /* No destructor defined for carglist */ /* No destructor defined for carg */ break; case 41: break; case 42: /* No destructor defined for CONSTRAINT */ /* No destructor defined for nm */ /* No destructor defined for ccons */ break; case 43: /* No destructor defined for ccons */ break; case 44: #line 175 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} #line 2110 "parse.c" /* No destructor defined for DEFAULT */ break; case 45: #line 176 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} #line 2116 "parse.c" /* No destructor defined for DEFAULT */ break; case 46: #line 177 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} #line 2122 "parse.c" /* No destructor defined for DEFAULT */ break; case 47: #line 178 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} #line 2128 "parse.c" /* No destructor defined for DEFAULT */ /* No destructor defined for PLUS */ break; case 48: #line 179 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);} #line 2135 "parse.c" /* No destructor defined for DEFAULT */ /* No destructor defined for MINUS */ break; case 49: #line 180 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} #line 2142 "parse.c" /* No destructor defined for DEFAULT */ break; case 50: #line 181 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,0);} #line 2148 "parse.c" /* No destructor defined for DEFAULT */ /* No destructor defined for PLUS */ break; case 51: #line 182 "parse.y" {sqliteAddDefaultValue(pParse,&yymsp[0].minor.yy0,1);} #line 2155 "parse.c" /* No destructor defined for DEFAULT */ /* No destructor defined for MINUS */ break; case 52: /* No destructor defined for DEFAULT */ /* No destructor defined for NULL */ break; case 53: /* No destructor defined for NULL */ /* No destructor defined for onconf */ break; case 54: #line 189 "parse.y" {sqliteAddNotNull(pParse, yymsp[0].minor.yy372);} #line 2170 "parse.c" /* No destructor defined for NOT */ /* No destructor defined for NULL */ break; case 55: #line 190 "parse.y" {sqliteAddPrimaryKey(pParse,0,yymsp[0].minor.yy372);} #line 2177 "parse.c" /* No destructor defined for PRIMARY */ /* No destructor defined for KEY */ /* No destructor defined for sortorder */ break; case 56: #line 191 "parse.y" {sqliteCreateIndex(pParse,0,0,0,yymsp[0].minor.yy372,0,0);} #line 2185 "parse.c" /* No destructor defined for UNIQUE */ break; case 57: /* No destructor defined for CHECK */ /* No destructor defined for LP */ yy_destructor(158,&yymsp[-2].minor); /* No destructor defined for RP */ /* No destructor defined for onconf */ break; case 58: #line 194 "parse.y" {sqliteCreateForeignKey(pParse,0,&yymsp[-2].minor.yy298,yymsp[-1].minor.yy320,yymsp[0].minor.yy372);} #line 2198 "parse.c" /* No destructor defined for REFERENCES */ break; case 59: #line 195 "parse.y" {sqliteDeferForeignKey(pParse,yymsp[0].minor.yy372);} #line 2204 "parse.c" break; case 60: #line 196 "parse.y" { sqliteAddCollateType(pParse, sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n)); } #line 2211 "parse.c" /* No destructor defined for COLLATE */ break; case 61: #line 206 "parse.y" { yygotominor.yy372 = OE_Restrict * 0x010101; } #line 2217 "parse.c" break; case 62: #line 207 "parse.y" { yygotominor.yy372 = (yymsp[-1].minor.yy372 & yymsp[0].minor.yy407.mask) | yymsp[0].minor.yy407.value; } #line 2222 "parse.c" break; case 63: #line 209 "parse.y" { yygotominor.yy407.value = 0; yygotominor.yy407.mask = 0x000000; } #line 2227 "parse.c" /* No destructor defined for MATCH */ /* No destructor defined for nm */ break; case 64: #line 210 "parse.y" { yygotominor.yy407.value = yymsp[0].minor.yy372; yygotominor.yy407.mask = 0x0000ff; } #line 2234 "parse.c" /* No destructor defined for ON */ /* No destructor defined for DELETE */ break; case 65: #line 211 "parse.y" { yygotominor.yy407.value = yymsp[0].minor.yy372<<8; yygotominor.yy407.mask = 0x00ff00; } #line 2241 "parse.c" /* No destructor defined for ON */ /* No destructor defined for UPDATE */ break; case 66: #line 212 "parse.y" { yygotominor.yy407.value = yymsp[0].minor.yy372<<16; yygotominor.yy407.mask = 0xff0000; } #line 2248 "parse.c" /* No destructor defined for ON */ /* No destructor defined for INSERT */ break; case 67: #line 214 "parse.y" { yygotominor.yy372 = OE_SetNull; } #line 2255 "parse.c" /* No destructor defined for SET */ /* No destructor defined for NULL */ break; case 68: #line 215 "parse.y" { yygotominor.yy372 = OE_SetDflt; } #line 2262 "parse.c" /* No destructor defined for SET */ /* No destructor defined for DEFAULT */ break; case 69: #line 216 "parse.y" { yygotominor.yy372 = OE_Cascade; } #line 2269 "parse.c" /* No destructor defined for CASCADE */ break; case 70: #line 217 "parse.y" { yygotominor.yy372 = OE_Restrict; } #line 2275 "parse.c" /* No destructor defined for RESTRICT */ break; case 71: #line 219 "parse.y" {yygotominor.yy372 = yymsp[0].minor.yy372;} #line 2281 "parse.c" /* No destructor defined for NOT */ /* No destructor defined for DEFERRABLE */ break; case 72: #line 220 "parse.y" {yygotominor.yy372 = yymsp[0].minor.yy372;} #line 2288 "parse.c" /* No destructor defined for DEFERRABLE */ break; case 73: #line 222 "parse.y" {yygotominor.yy372 = 0;} #line 2294 "parse.c" break; case 74: #line 223 "parse.y" {yygotominor.yy372 = 1;} #line 2299 "parse.c" /* No destructor defined for INITIALLY */ /* No destructor defined for DEFERRED */ break; case 75: #line 224 "parse.y" {yygotominor.yy372 = 0;} #line 2306 "parse.c" /* No destructor defined for INITIALLY */ /* No destructor defined for IMMEDIATE */ break; case 76: break; case 77: /* No destructor defined for COMMA */ /* No destructor defined for conslist */ break; case 78: /* No destructor defined for conslist */ /* No destructor defined for COMMA */ /* No destructor defined for tcons */ break; case 79: /* No destructor defined for conslist */ /* No destructor defined for tcons */ break; case 80: /* No destructor defined for tcons */ break; case 81: /* No destructor defined for CONSTRAINT */ /* No destructor defined for nm */ break; case 82: #line 236 "parse.y" {sqliteAddPrimaryKey(pParse,yymsp[-2].minor.yy320,yymsp[0].minor.yy372);} #line 2335 "parse.c" /* No destructor defined for PRIMARY */ /* No destructor defined for KEY */ /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 83: #line 238 "parse.y" {sqliteCreateIndex(pParse,0,0,yymsp[-2].minor.yy320,yymsp[0].minor.yy372,0,0);} #line 2344 "parse.c" /* No destructor defined for UNIQUE */ /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 84: /* No destructor defined for CHECK */ yy_destructor(158,&yymsp[-1].minor); /* No destructor defined for onconf */ break; case 85: #line 241 "parse.y" { sqliteCreateForeignKey(pParse, yymsp[-6].minor.yy320, &yymsp[-3].minor.yy298, yymsp[-2].minor.yy320, yymsp[-1].minor.yy372); sqliteDeferForeignKey(pParse, yymsp[0].minor.yy372); } #line 2360 "parse.c" /* No destructor defined for FOREIGN */ /* No destructor defined for KEY */ /* No destructor defined for LP */ /* No destructor defined for RP */ /* No destructor defined for REFERENCES */ break; case 86: #line 246 "parse.y" {yygotominor.yy372 = 0;} #line 2370 "parse.c" break; case 87: #line 247 "parse.y" {yygotominor.yy372 = yymsp[0].minor.yy372;} #line 2375 "parse.c" break; case 88: #line 255 "parse.y" { yygotominor.yy372 = OE_Default; } #line 2380 "parse.c" break; case 89: #line 256 "parse.y" { yygotominor.yy372 = yymsp[0].minor.yy372; } #line 2385 "parse.c" /* No destructor defined for ON */ /* No destructor defined for CONFLICT */ break; case 90: #line 257 "parse.y" { yygotominor.yy372 = OE_Default; } #line 2392 "parse.c" break; case 91: #line 258 "parse.y" { yygotominor.yy372 = yymsp[0].minor.yy372; } #line 2397 "parse.c" /* No destructor defined for OR */ break; case 92: #line 259 "parse.y" { yygotominor.yy372 = OE_Rollback; } #line 2403 "parse.c" /* No destructor defined for ROLLBACK */ break; case 93: #line 260 "parse.y" { yygotominor.yy372 = OE_Abort; } #line 2409 "parse.c" /* No destructor defined for ABORT */ break; case 94: #line 261 "parse.y" { yygotominor.yy372 = OE_Fail; } #line 2415 "parse.c" /* No destructor defined for FAIL */ break; case 95: #line 262 "parse.y" { yygotominor.yy372 = OE_Ignore; } #line 2421 "parse.c" /* No destructor defined for IGNORE */ break; case 96: #line 263 "parse.y" { yygotominor.yy372 = OE_Replace; } #line 2427 "parse.c" /* No destructor defined for REPLACE */ break; case 97: #line 267 "parse.y" {sqliteDropTable(pParse,&yymsp[0].minor.yy298,0);} #line 2433 "parse.c" /* No destructor defined for DROP */ /* No destructor defined for TABLE */ break; case 98: #line 271 "parse.y" { sqliteCreateView(pParse, &yymsp[-5].minor.yy0, &yymsp[-2].minor.yy298, yymsp[0].minor.yy179, yymsp[-4].minor.yy372); } #line 2442 "parse.c" /* No destructor defined for VIEW */ /* No destructor defined for AS */ break; case 99: #line 274 "parse.y" { sqliteDropTable(pParse, &yymsp[0].minor.yy298, 1); } #line 2451 "parse.c" /* No destructor defined for DROP */ /* No destructor defined for VIEW */ break; case 100: #line 280 "parse.y" { sqliteSelect(pParse, yymsp[0].minor.yy179, SRT_Callback, 0, 0, 0, 0); sqliteSelectDelete(yymsp[0].minor.yy179); } #line 2461 "parse.c" break; case 101: #line 290 "parse.y" {yygotominor.yy179 = yymsp[0].minor.yy179;} #line 2466 "parse.c" break; case 102: #line 291 "parse.y" { if( yymsp[0].minor.yy179 ){ yymsp[0].minor.yy179->op = yymsp[-1].minor.yy372; yymsp[0].minor.yy179->pPrior = yymsp[-2].minor.yy179; } yygotominor.yy179 = yymsp[0].minor.yy179; } #line 2477 "parse.c" break; case 103: #line 299 "parse.y" {yygotominor.yy372 = TK_UNION;} #line 2482 "parse.c" /* No destructor defined for UNION */ break; case 104: #line 300 "parse.y" {yygotominor.yy372 = TK_ALL;} #line 2488 "parse.c" /* No destructor defined for UNION */ /* No destructor defined for ALL */ break; case 105: #line 301 "parse.y" {yygotominor.yy372 = TK_INTERSECT;} #line 2495 "parse.c" /* No destructor defined for INTERSECT */ break; case 106: #line 302 "parse.y" {yygotominor.yy372 = TK_EXCEPT;} #line 2501 "parse.c" /* No destructor defined for EXCEPT */ break; case 107: #line 304 "parse.y" { yygotominor.yy179 = sqliteSelectNew(yymsp[-6].minor.yy322,yymsp[-5].minor.yy307,yymsp[-4].minor.yy242,yymsp[-3].minor.yy322,yymsp[-2].minor.yy242,yymsp[-1].minor.yy322,yymsp[-7].minor.yy372,yymsp[0].minor.yy124.limit,yymsp[0].minor.yy124.offset); } #line 2509 "parse.c" /* No destructor defined for SELECT */ break; case 108: #line 312 "parse.y" {yygotominor.yy372 = 1;} #line 2515 "parse.c" /* No destructor defined for DISTINCT */ break; case 109: #line 313 "parse.y" {yygotominor.yy372 = 0;} #line 2521 "parse.c" /* No destructor defined for ALL */ break; case 110: #line 314 "parse.y" {yygotominor.yy372 = 0;} #line 2527 "parse.c" break; case 111: #line 325 "parse.y" {yygotominor.yy322 = yymsp[-1].minor.yy322;} #line 2532 "parse.c" /* No destructor defined for COMMA */ break; case 112: #line 326 "parse.y" {yygotominor.yy322 = 0;} #line 2538 "parse.c" break; case 113: #line 327 "parse.y" { yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[-1].minor.yy242,yymsp[0].minor.yy298.n?&yymsp[0].minor.yy298:0); } #line 2545 "parse.c" break; case 114: #line 330 "parse.y" { yygotominor.yy322 = sqliteExprListAppend(yymsp[-1].minor.yy322, sqliteExpr(TK_ALL, 0, 0, 0), 0); } #line 2552 "parse.c" /* No destructor defined for STAR */ break; case 115: #line 333 "parse.y" { Expr *pRight = sqliteExpr(TK_ALL, 0, 0, 0); Expr *pLeft = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298); yygotominor.yy322 = sqliteExprListAppend(yymsp[-3].minor.yy322, sqliteExpr(TK_DOT, pLeft, pRight, 0), 0); } #line 2562 "parse.c" /* No destructor defined for DOT */ /* No destructor defined for STAR */ break; case 116: #line 343 "parse.y" { yygotominor.yy298 = yymsp[0].minor.yy298; } #line 2569 "parse.c" /* No destructor defined for AS */ break; case 117: #line 344 "parse.y" { yygotominor.yy298 = yymsp[0].minor.yy298; } #line 2575 "parse.c" break; case 118: #line 345 "parse.y" { yygotominor.yy298.n = 0; } #line 2580 "parse.c" break; case 119: #line 357 "parse.y" {yygotominor.yy307 = sqliteMalloc(sizeof(*yygotominor.yy307));} #line 2585 "parse.c" break; case 120: #line 358 "parse.y" {yygotominor.yy307 = yymsp[0].minor.yy307;} #line 2590 "parse.c" /* No destructor defined for FROM */ break; case 121: #line 363 "parse.y" { yygotominor.yy307 = yymsp[-1].minor.yy307; if( yygotominor.yy307 && yygotominor.yy307->nSrc>0 ) yygotominor.yy307->a[yygotominor.yy307->nSrc-1].jointype = yymsp[0].minor.yy372; } #line 2599 "parse.c" break; case 122: #line 367 "parse.y" {yygotominor.yy307 = 0;} #line 2604 "parse.c" break; case 123: #line 368 "parse.y" { yygotominor.yy307 = sqliteSrcListAppend(yymsp[-5].minor.yy307,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298); if( yymsp[-2].minor.yy298.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy298); if( yymsp[-1].minor.yy242 ){ if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; } else { sqliteExprDelete(yymsp[-1].minor.yy242); } } if( yymsp[0].minor.yy320 ){ if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; } else { sqliteIdListDelete(yymsp[0].minor.yy320); } } } #line 2620 "parse.c" break; case 124: #line 381 "parse.y" { yygotominor.yy307 = sqliteSrcListAppend(yymsp[-6].minor.yy307,0,0); yygotominor.yy307->a[yygotominor.yy307->nSrc-1].pSelect = yymsp[-4].minor.yy179; if( yymsp[-2].minor.yy298.n ) sqliteSrcListAddAlias(yygotominor.yy307,&yymsp[-2].minor.yy298); if( yymsp[-1].minor.yy242 ){ if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pOn = yymsp[-1].minor.yy242; } else { sqliteExprDelete(yymsp[-1].minor.yy242); } } if( yymsp[0].minor.yy320 ){ if( yygotominor.yy307 && yygotominor.yy307->nSrc>1 ){ yygotominor.yy307->a[yygotominor.yy307->nSrc-2].pUsing = yymsp[0].minor.yy320; } else { sqliteIdListDelete(yymsp[0].minor.yy320); } } } #line 2637 "parse.c" /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 125: #line 401 "parse.y" {yygotominor.yy179 = yymsp[0].minor.yy179;} #line 2644 "parse.c" break; case 126: #line 402 "parse.y" { yygotominor.yy179 = sqliteSelectNew(0,yymsp[0].minor.yy307,0,0,0,0,0,-1,0); } #line 2651 "parse.c" break; case 127: #line 407 "parse.y" {yygotominor.yy298.z=0; yygotominor.yy298.n=0;} #line 2656 "parse.c" break; case 128: #line 408 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy298;} #line 2661 "parse.c" /* No destructor defined for DOT */ break; case 129: #line 412 "parse.y" { yygotominor.yy372 = JT_INNER; } #line 2667 "parse.c" /* No destructor defined for COMMA */ break; case 130: #line 413 "parse.y" { yygotominor.yy372 = JT_INNER; } #line 2673 "parse.c" /* No destructor defined for JOIN */ break; case 131: #line 414 "parse.y" { yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-1].minor.yy0,0,0); } #line 2679 "parse.c" /* No destructor defined for JOIN */ break; case 132: #line 415 "parse.y" { yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy298,0); } #line 2685 "parse.c" /* No destructor defined for JOIN */ break; case 133: #line 417 "parse.y" { yygotominor.yy372 = sqliteJoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298); } #line 2691 "parse.c" /* No destructor defined for JOIN */ break; case 134: #line 421 "parse.y" {yygotominor.yy242 = yymsp[0].minor.yy242;} #line 2697 "parse.c" /* No destructor defined for ON */ break; case 135: #line 422 "parse.y" {yygotominor.yy242 = 0;} #line 2703 "parse.c" break; case 136: #line 426 "parse.y" {yygotominor.yy320 = yymsp[-1].minor.yy320;} #line 2708 "parse.c" /* No destructor defined for USING */ /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 137: #line 427 "parse.y" {yygotominor.yy320 = 0;} #line 2716 "parse.c" break; case 138: #line 437 "parse.y" {yygotominor.yy322 = 0;} #line 2721 "parse.c" break; case 139: #line 438 "parse.y" {yygotominor.yy322 = yymsp[0].minor.yy322;} #line 2726 "parse.c" /* No destructor defined for ORDER */ /* No destructor defined for BY */ break; case 140: #line 439 "parse.y" { yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[-2].minor.yy242,0); if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372; } #line 2736 "parse.c" /* No destructor defined for COMMA */ break; case 141: #line 443 "parse.y" { yygotominor.yy322 = sqliteExprListAppend(0,yymsp[-2].minor.yy242,0); if( yygotominor.yy322 ) yygotominor.yy322->a[0].sortOrder = yymsp[-1].minor.yy372+yymsp[0].minor.yy372; } #line 2745 "parse.c" break; case 142: #line 447 "parse.y" {yygotominor.yy242 = yymsp[0].minor.yy242;} #line 2750 "parse.c" break; case 143: #line 452 "parse.y" {yygotominor.yy372 = SQLITE_SO_ASC;} #line 2755 "parse.c" /* No destructor defined for ASC */ break; case 144: #line 453 "parse.y" {yygotominor.yy372 = SQLITE_SO_DESC;} #line 2761 "parse.c" /* No destructor defined for DESC */ break; case 145: #line 454 "parse.y" {yygotominor.yy372 = SQLITE_SO_ASC;} #line 2767 "parse.c" break; case 146: #line 455 "parse.y" {yygotominor.yy372 = SQLITE_SO_UNK;} #line 2772 "parse.c" break; case 147: #line 456 "parse.y" {yygotominor.yy372 = sqliteCollateType(yymsp[0].minor.yy298.z, yymsp[0].minor.yy298.n);} #line 2777 "parse.c" /* No destructor defined for COLLATE */ break; case 148: #line 460 "parse.y" {yygotominor.yy322 = 0;} #line 2783 "parse.c" break; case 149: #line 461 "parse.y" {yygotominor.yy322 = yymsp[0].minor.yy322;} #line 2788 "parse.c" /* No destructor defined for GROUP */ /* No destructor defined for BY */ break; case 150: #line 465 "parse.y" {yygotominor.yy242 = 0;} #line 2795 "parse.c" break; case 151: #line 466 "parse.y" {yygotominor.yy242 = yymsp[0].minor.yy242;} #line 2800 "parse.c" /* No destructor defined for HAVING */ break; case 152: #line 469 "parse.y" {yygotominor.yy124.limit = -1; yygotominor.yy124.offset = 0;} #line 2806 "parse.c" break; case 153: #line 470 "parse.y" {yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = 0;} #line 2811 "parse.c" /* No destructor defined for LIMIT */ break; case 154: #line 472 "parse.y" {yygotominor.yy124.limit = yymsp[-2].minor.yy372; yygotominor.yy124.offset = yymsp[0].minor.yy372;} #line 2817 "parse.c" /* No destructor defined for LIMIT */ /* No destructor defined for OFFSET */ break; case 155: #line 474 "parse.y" {yygotominor.yy124.limit = yymsp[0].minor.yy372; yygotominor.yy124.offset = yymsp[-2].minor.yy372;} #line 2824 "parse.c" /* No destructor defined for LIMIT */ /* No destructor defined for COMMA */ break; case 156: #line 478 "parse.y" { sqliteDeleteFrom(pParse, sqliteSrcListAppend(0,&yymsp[-2].minor.yy298,&yymsp[-1].minor.yy298), yymsp[0].minor.yy242); } #line 2833 "parse.c" /* No destructor defined for DELETE */ /* No destructor defined for FROM */ break; case 157: #line 485 "parse.y" {yygotominor.yy242 = 0;} #line 2840 "parse.c" break; case 158: #line 486 "parse.y" {yygotominor.yy242 = yymsp[0].minor.yy242;} #line 2845 "parse.c" /* No destructor defined for WHERE */ break; case 159: #line 494 "parse.y" {sqliteUpdate(pParse,sqliteSrcListAppend(0,&yymsp[-4].minor.yy298,&yymsp[-3].minor.yy298),yymsp[-1].minor.yy322,yymsp[0].minor.yy242,yymsp[-5].minor.yy372);} #line 2851 "parse.c" /* No destructor defined for UPDATE */ /* No destructor defined for SET */ break; case 160: #line 497 "parse.y" {yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);} #line 2858 "parse.c" /* No destructor defined for COMMA */ /* No destructor defined for EQ */ break; case 161: #line 498 "parse.y" {yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,&yymsp[-2].minor.yy298);} #line 2865 "parse.c" /* No destructor defined for EQ */ break; case 162: #line 504 "parse.y" {sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298), yymsp[-1].minor.yy322, 0, yymsp[-4].minor.yy320, yymsp[-8].minor.yy372);} #line 2871 "parse.c" /* No destructor defined for INTO */ /* No destructor defined for VALUES */ /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 163: #line 506 "parse.y" {sqliteInsert(pParse, sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298), 0, yymsp[0].minor.yy179, yymsp[-1].minor.yy320, yymsp[-5].minor.yy372);} #line 2880 "parse.c" /* No destructor defined for INTO */ break; case 164: #line 509 "parse.y" {yygotominor.yy372 = yymsp[0].minor.yy372;} #line 2886 "parse.c" /* No destructor defined for INSERT */ break; case 165: #line 510 "parse.y" {yygotominor.yy372 = OE_Replace;} #line 2892 "parse.c" /* No destructor defined for REPLACE */ break; case 166: #line 516 "parse.y" {yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);} #line 2898 "parse.c" /* No destructor defined for COMMA */ break; case 167: #line 517 "parse.y" {yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);} #line 2904 "parse.c" break; case 168: #line 524 "parse.y" {yygotominor.yy320 = 0;} #line 2909 "parse.c" break; case 169: #line 525 "parse.y" {yygotominor.yy320 = yymsp[-1].minor.yy320;} #line 2914 "parse.c" /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 170: #line 526 "parse.y" {yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);} #line 2921 "parse.c" /* No destructor defined for COMMA */ break; case 171: #line 527 "parse.y" {yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);} #line 2927 "parse.c" break; case 172: #line 535 "parse.y" {yygotominor.yy242 = yymsp[-1].minor.yy242; sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } #line 2932 "parse.c" break; case 173: #line 536 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_NULL, 0, 0, &yymsp[0].minor.yy0);} #line 2937 "parse.c" break; case 174: #line 537 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} #line 2942 "parse.c" break; case 175: #line 538 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} #line 2947 "parse.c" break; case 176: #line 539 "parse.y" { Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298); Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy298); yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp2, 0); } #line 2956 "parse.c" /* No destructor defined for DOT */ break; case 177: #line 544 "parse.y" { Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &yymsp[-4].minor.yy298); Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &yymsp[-2].minor.yy298); Expr *temp3 = sqliteExpr(TK_ID, 0, 0, &yymsp[0].minor.yy298); Expr *temp4 = sqliteExpr(TK_DOT, temp2, temp3, 0); yygotominor.yy242 = sqliteExpr(TK_DOT, temp1, temp4, 0); } #line 2968 "parse.c" /* No destructor defined for DOT */ /* No destructor defined for DOT */ break; case 178: #line 551 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_INTEGER, 0, 0, &yymsp[0].minor.yy0);} #line 2975 "parse.c" break; case 179: #line 552 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_FLOAT, 0, 0, &yymsp[0].minor.yy0);} #line 2980 "parse.c" break; case 180: #line 553 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_STRING, 0, 0, &yymsp[0].minor.yy0);} #line 2985 "parse.c" break; case 181: #line 554 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_VARIABLE, 0, 0, &yymsp[0].minor.yy0); if( yygotominor.yy242 ) yygotominor.yy242->iTable = ++pParse->nVar; } #line 2993 "parse.c" break; case 182: #line 558 "parse.y" { yygotominor.yy242 = sqliteExprFunction(yymsp[-1].minor.yy322, &yymsp[-3].minor.yy0); sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } #line 3001 "parse.c" /* No destructor defined for LP */ break; case 183: #line 562 "parse.y" { yygotominor.yy242 = sqliteExprFunction(0, &yymsp[-3].minor.yy0); sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } #line 3010 "parse.c" /* No destructor defined for LP */ /* No destructor defined for STAR */ break; case 184: #line 566 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_AND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3017 "parse.c" /* No destructor defined for AND */ break; case 185: #line 567 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_OR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3023 "parse.c" /* No destructor defined for OR */ break; case 186: #line 568 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_LT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3029 "parse.c" /* No destructor defined for LT */ break; case 187: #line 569 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_GT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3035 "parse.c" /* No destructor defined for GT */ break; case 188: #line 570 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_LE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3041 "parse.c" /* No destructor defined for LE */ break; case 189: #line 571 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_GE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3047 "parse.c" /* No destructor defined for GE */ break; case 190: #line 572 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_NE, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3053 "parse.c" /* No destructor defined for NE */ break; case 191: #line 573 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_EQ, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3059 "parse.c" /* No destructor defined for EQ */ break; case 192: #line 574 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_BITAND, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3065 "parse.c" /* No destructor defined for BITAND */ break; case 193: #line 575 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_BITOR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3071 "parse.c" /* No destructor defined for BITOR */ break; case 194: #line 576 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_LSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3077 "parse.c" /* No destructor defined for LSHIFT */ break; case 195: #line 577 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_RSHIFT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3083 "parse.c" /* No destructor defined for RSHIFT */ break; case 196: #line 578 "parse.y" { ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0); pList = sqliteExprListAppend(pList, yymsp[-2].minor.yy242, 0); yygotominor.yy242 = sqliteExprFunction(pList, 0); if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372; sqliteExprSpan(yygotominor.yy242, &yymsp[-2].minor.yy242->span, &yymsp[0].minor.yy242->span); } #line 3095 "parse.c" break; case 197: #line 585 "parse.y" { ExprList *pList = sqliteExprListAppend(0, yymsp[0].minor.yy242, 0); pList = sqliteExprListAppend(pList, yymsp[-3].minor.yy242, 0); yygotominor.yy242 = sqliteExprFunction(pList, 0); if( yygotominor.yy242 ) yygotominor.yy242->op = yymsp[-1].minor.yy372; yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy242->span); } #line 3107 "parse.c" /* No destructor defined for NOT */ break; case 198: #line 594 "parse.y" {yygotominor.yy372 = TK_LIKE;} #line 3113 "parse.c" /* No destructor defined for LIKE */ break; case 199: #line 595 "parse.y" {yygotominor.yy372 = TK_GLOB;} #line 3119 "parse.c" /* No destructor defined for GLOB */ break; case 200: #line 596 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_PLUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3125 "parse.c" /* No destructor defined for PLUS */ break; case 201: #line 597 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_MINUS, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3131 "parse.c" /* No destructor defined for MINUS */ break; case 202: #line 598 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_STAR, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3137 "parse.c" /* No destructor defined for STAR */ break; case 203: #line 599 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_SLASH, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3143 "parse.c" /* No destructor defined for SLASH */ break; case 204: #line 600 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_REM, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3149 "parse.c" /* No destructor defined for REM */ break; case 205: #line 601 "parse.y" {yygotominor.yy242 = sqliteExpr(TK_CONCAT, yymsp[-2].minor.yy242, yymsp[0].minor.yy242, 0);} #line 3155 "parse.c" /* No destructor defined for CONCAT */ break; case 206: #line 602 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-1].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3164 "parse.c" break; case 207: #line 606 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_ISNULL, yymsp[-2].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3172 "parse.c" /* No destructor defined for IS */ break; case 208: #line 610 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-1].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3181 "parse.c" break; case 209: #line 614 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-2].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3189 "parse.c" /* No destructor defined for NOT */ break; case 210: #line 618 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_NOTNULL, yymsp[-3].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3198 "parse.c" /* No destructor defined for IS */ /* No destructor defined for NOT */ break; case 211: #line 622 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_NOT, yymsp[0].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); } #line 3208 "parse.c" break; case 212: #line 626 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_BITNOT, yymsp[0].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); } #line 3216 "parse.c" break; case 213: #line 630 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_UMINUS, yymsp[0].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); } #line 3224 "parse.c" break; case 214: #line 634 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_UPLUS, yymsp[0].minor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy242->span); } #line 3232 "parse.c" break; case 215: #line 638 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_SELECT, 0, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179; sqliteExprSpan(yygotominor.yy242,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } #line 3241 "parse.c" break; case 216: #line 643 "parse.y" { ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0); pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0); yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-4].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pList = pList; sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy242->span); } #line 3252 "parse.c" /* No destructor defined for BETWEEN */ /* No destructor defined for AND */ break; case 217: #line 650 "parse.y" { ExprList *pList = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0); pList = sqliteExprListAppend(pList, yymsp[0].minor.yy242, 0); yygotominor.yy242 = sqliteExpr(TK_BETWEEN, yymsp[-5].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pList = pList; yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy242->span); } #line 3266 "parse.c" /* No destructor defined for NOT */ /* No destructor defined for BETWEEN */ /* No destructor defined for AND */ break; case 218: #line 658 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322; sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3278 "parse.c" /* No destructor defined for IN */ /* No destructor defined for LP */ break; case 219: #line 663 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179; sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3289 "parse.c" /* No destructor defined for IN */ /* No destructor defined for LP */ break; case 220: #line 668 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-1].minor.yy322; yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3301 "parse.c" /* No destructor defined for NOT */ /* No destructor defined for IN */ /* No destructor defined for LP */ break; case 221: #line 674 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-5].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pSelect = yymsp[-1].minor.yy179; yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-5].minor.yy242->span,&yymsp[0].minor.yy0); } #line 3314 "parse.c" /* No destructor defined for NOT */ /* No destructor defined for IN */ /* No destructor defined for LP */ break; case 222: #line 680 "parse.y" { SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298); yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-3].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0); sqliteExprSpan(yygotominor.yy242,&yymsp[-3].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298); } #line 3327 "parse.c" /* No destructor defined for IN */ break; case 223: #line 686 "parse.y" { SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298); yygotominor.yy242 = sqliteExpr(TK_IN, yymsp[-4].minor.yy242, 0, 0); if( yygotominor.yy242 ) yygotominor.yy242->pSelect = sqliteSelectNew(0,pSrc,0,0,0,0,0,-1,0); yygotominor.yy242 = sqliteExpr(TK_NOT, yygotominor.yy242, 0, 0); sqliteExprSpan(yygotominor.yy242,&yymsp[-4].minor.yy242->span,yymsp[0].minor.yy298.z?&yymsp[0].minor.yy298:&yymsp[-1].minor.yy298); } #line 3339 "parse.c" /* No destructor defined for NOT */ /* No destructor defined for IN */ break; case 224: #line 696 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_CASE, yymsp[-3].minor.yy242, yymsp[-1].minor.yy242, 0); if( yygotominor.yy242 ) yygotominor.yy242->pList = yymsp[-2].minor.yy322; sqliteExprSpan(yygotominor.yy242, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); } #line 3350 "parse.c" break; case 225: #line 703 "parse.y" { yygotominor.yy322 = sqliteExprListAppend(yymsp[-4].minor.yy322, yymsp[-2].minor.yy242, 0); yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0); } #line 3358 "parse.c" /* No destructor defined for WHEN */ /* No destructor defined for THEN */ break; case 226: #line 707 "parse.y" { yygotominor.yy322 = sqliteExprListAppend(0, yymsp[-2].minor.yy242, 0); yygotominor.yy322 = sqliteExprListAppend(yygotominor.yy322, yymsp[0].minor.yy242, 0); } #line 3368 "parse.c" /* No destructor defined for WHEN */ /* No destructor defined for THEN */ break; case 227: #line 712 "parse.y" {yygotominor.yy242 = yymsp[0].minor.yy242;} #line 3375 "parse.c" /* No destructor defined for ELSE */ break; case 228: #line 713 "parse.y" {yygotominor.yy242 = 0;} #line 3381 "parse.c" break; case 229: #line 715 "parse.y" {yygotominor.yy242 = yymsp[0].minor.yy242;} #line 3386 "parse.c" break; case 230: #line 716 "parse.y" {yygotominor.yy242 = 0;} #line 3391 "parse.c" break; case 231: #line 724 "parse.y" {yygotominor.yy322 = sqliteExprListAppend(yymsp[-2].minor.yy322,yymsp[0].minor.yy242,0);} #line 3396 "parse.c" /* No destructor defined for COMMA */ break; case 232: #line 725 "parse.y" {yygotominor.yy322 = sqliteExprListAppend(0,yymsp[0].minor.yy242,0);} #line 3402 "parse.c" break; case 233: #line 726 "parse.y" {yygotominor.yy242 = yymsp[0].minor.yy242;} #line 3407 "parse.c" break; case 234: #line 727 "parse.y" {yygotominor.yy242 = 0;} #line 3412 "parse.c" break; case 235: #line 732 "parse.y" { SrcList *pSrc = sqliteSrcListAppend(0, &yymsp[-5].minor.yy298, &yymsp[-4].minor.yy298); if( yymsp[-9].minor.yy372!=OE_None ) yymsp[-9].minor.yy372 = yymsp[0].minor.yy372; if( yymsp[-9].minor.yy372==OE_Default) yymsp[-9].minor.yy372 = OE_Abort; sqliteCreateIndex(pParse, &yymsp[-7].minor.yy298, pSrc, yymsp[-2].minor.yy320, yymsp[-9].minor.yy372, &yymsp[-10].minor.yy0, &yymsp[-1].minor.yy0); } #line 3422 "parse.c" /* No destructor defined for INDEX */ /* No destructor defined for ON */ /* No destructor defined for LP */ break; case 236: #line 740 "parse.y" { yygotominor.yy372 = OE_Abort; } #line 3430 "parse.c" /* No destructor defined for UNIQUE */ break; case 237: #line 741 "parse.y" { yygotominor.yy372 = OE_None; } #line 3436 "parse.c" break; case 238: #line 749 "parse.y" {yygotominor.yy320 = 0;} #line 3441 "parse.c" break; case 239: #line 750 "parse.y" {yygotominor.yy320 = yymsp[-1].minor.yy320;} #line 3446 "parse.c" /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 240: #line 751 "parse.y" {yygotominor.yy320 = sqliteIdListAppend(yymsp[-2].minor.yy320,&yymsp[0].minor.yy298);} #line 3453 "parse.c" /* No destructor defined for COMMA */ break; case 241: #line 752 "parse.y" {yygotominor.yy320 = sqliteIdListAppend(0,&yymsp[0].minor.yy298);} #line 3459 "parse.c" break; case 242: #line 753 "parse.y" {yygotominor.yy298 = yymsp[-1].minor.yy298;} #line 3464 "parse.c" /* No destructor defined for sortorder */ break; case 243: #line 758 "parse.y" { sqliteDropIndex(pParse, sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298)); } #line 3472 "parse.c" /* No destructor defined for DROP */ /* No destructor defined for INDEX */ break; case 244: #line 766 "parse.y" {sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-6].minor.yy298,&yymsp[-5].minor.yy298),&yymsp[-3].minor.yy298,&yymsp[0].minor.yy0,yymsp[-7].minor.yy372);} #line 3479 "parse.c" /* No destructor defined for COPY */ /* No destructor defined for FROM */ /* No destructor defined for USING */ /* No destructor defined for DELIMITERS */ break; case 245: #line 768 "parse.y" {sqliteCopy(pParse,sqliteSrcListAppend(0,&yymsp[-3].minor.yy298,&yymsp[-2].minor.yy298),&yymsp[0].minor.yy298,0,yymsp[-4].minor.yy372);} #line 3488 "parse.c" /* No destructor defined for COPY */ /* No destructor defined for FROM */ break; case 246: #line 772 "parse.y" {sqliteVacuum(pParse,0);} #line 3495 "parse.c" /* No destructor defined for VACUUM */ break; case 247: #line 773 "parse.y" {sqliteVacuum(pParse,&yymsp[0].minor.yy298);} #line 3501 "parse.c" /* No destructor defined for VACUUM */ break; case 248: #line 777 "parse.y" {sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);} #line 3507 "parse.c" /* No destructor defined for PRAGMA */ /* No destructor defined for EQ */ break; case 249: #line 778 "parse.y" {sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy0,0);} #line 3514 "parse.c" /* No destructor defined for PRAGMA */ /* No destructor defined for EQ */ break; case 250: #line 779 "parse.y" {sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,0);} #line 3521 "parse.c" /* No destructor defined for PRAGMA */ /* No destructor defined for EQ */ break; case 251: #line 780 "parse.y" {sqlitePragma(pParse,&yymsp[-2].minor.yy298,&yymsp[0].minor.yy298,1);} #line 3528 "parse.c" /* No destructor defined for PRAGMA */ /* No destructor defined for EQ */ break; case 252: #line 781 "parse.y" {sqlitePragma(pParse,&yymsp[-3].minor.yy298,&yymsp[-1].minor.yy298,0);} #line 3535 "parse.c" /* No destructor defined for PRAGMA */ /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 253: #line 782 "parse.y" {sqlitePragma(pParse,&yymsp[0].minor.yy298,&yymsp[0].minor.yy298,0);} #line 3543 "parse.c" /* No destructor defined for PRAGMA */ break; case 254: #line 783 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy298;} #line 3549 "parse.c" /* No destructor defined for plus_opt */ break; case 255: #line 784 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy298;} #line 3555 "parse.c" /* No destructor defined for MINUS */ break; case 256: #line 785 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 3561 "parse.c" break; case 257: #line 786 "parse.y" {yygotominor.yy298 = yymsp[0].minor.yy0;} #line 3566 "parse.c" break; case 258: /* No destructor defined for PLUS */ break; case 259: break; case 260: #line 792 "parse.y" { Token all; all.z = yymsp[-4].minor.yy0.z; all.n = (yymsp[0].minor.yy0.z - yymsp[-4].minor.yy0.z) + yymsp[0].minor.yy0.n; sqliteFinishTrigger(pParse, yymsp[-1].minor.yy19, &all); } #line 3581 "parse.c" /* No destructor defined for trigger_decl */ /* No destructor defined for BEGIN */ break; case 261: #line 800 "parse.y" { SrcList *pTab = sqliteSrcListAppend(0, &yymsp[-3].minor.yy298, &yymsp[-2].minor.yy298); sqliteBeginTrigger(pParse, &yymsp[-7].minor.yy298, yymsp[-6].minor.yy372, yymsp[-5].minor.yy290.a, yymsp[-5].minor.yy290.b, pTab, yymsp[-1].minor.yy372, yymsp[0].minor.yy182, yymsp[-9].minor.yy372); } #line 3591 "parse.c" /* No destructor defined for TRIGGER */ /* No destructor defined for ON */ break; case 262: #line 806 "parse.y" { yygotominor.yy372 = TK_BEFORE; } #line 3598 "parse.c" /* No destructor defined for BEFORE */ break; case 263: #line 807 "parse.y" { yygotominor.yy372 = TK_AFTER; } #line 3604 "parse.c" /* No destructor defined for AFTER */ break; case 264: #line 808 "parse.y" { yygotominor.yy372 = TK_INSTEAD;} #line 3610 "parse.c" /* No destructor defined for INSTEAD */ /* No destructor defined for OF */ break; case 265: #line 809 "parse.y" { yygotominor.yy372 = TK_BEFORE; } #line 3617 "parse.c" break; case 266: #line 813 "parse.y" { yygotominor.yy290.a = TK_DELETE; yygotominor.yy290.b = 0; } #line 3622 "parse.c" /* No destructor defined for DELETE */ break; case 267: #line 814 "parse.y" { yygotominor.yy290.a = TK_INSERT; yygotominor.yy290.b = 0; } #line 3628 "parse.c" /* No destructor defined for INSERT */ break; case 268: #line 815 "parse.y" { yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = 0;} #line 3634 "parse.c" /* No destructor defined for UPDATE */ break; case 269: #line 816 "parse.y" {yygotominor.yy290.a = TK_UPDATE; yygotominor.yy290.b = yymsp[0].minor.yy320; } #line 3640 "parse.c" /* No destructor defined for UPDATE */ /* No destructor defined for OF */ break; case 270: #line 819 "parse.y" { yygotominor.yy372 = TK_ROW; } #line 3647 "parse.c" break; case 271: #line 820 "parse.y" { yygotominor.yy372 = TK_ROW; } #line 3652 "parse.c" /* No destructor defined for FOR */ /* No destructor defined for EACH */ /* No destructor defined for ROW */ break; case 272: #line 821 "parse.y" { yygotominor.yy372 = TK_STATEMENT; } #line 3660 "parse.c" /* No destructor defined for FOR */ /* No destructor defined for EACH */ /* No destructor defined for STATEMENT */ break; case 273: #line 824 "parse.y" { yygotominor.yy182 = 0; } #line 3668 "parse.c" break; case 274: #line 825 "parse.y" { yygotominor.yy182 = yymsp[0].minor.yy242; } #line 3673 "parse.c" /* No destructor defined for WHEN */ break; case 275: #line 829 "parse.y" { yymsp[-2].minor.yy19->pNext = yymsp[0].minor.yy19; yygotominor.yy19 = yymsp[-2].minor.yy19; } #line 3682 "parse.c" /* No destructor defined for SEMI */ break; case 276: #line 833 "parse.y" { yygotominor.yy19 = 0; } #line 3688 "parse.c" break; case 277: #line 839 "parse.y" { yygotominor.yy19 = sqliteTriggerUpdateStep(&yymsp[-3].minor.yy298, yymsp[-1].minor.yy322, yymsp[0].minor.yy242, yymsp[-4].minor.yy372); } #line 3693 "parse.c" /* No destructor defined for UPDATE */ /* No destructor defined for SET */ break; case 278: #line 844 "parse.y" {yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-5].minor.yy298, yymsp[-4].minor.yy320, yymsp[-1].minor.yy322, 0, yymsp[-7].minor.yy372);} #line 3700 "parse.c" /* No destructor defined for INTO */ /* No destructor defined for VALUES */ /* No destructor defined for LP */ /* No destructor defined for RP */ break; case 279: #line 847 "parse.y" {yygotominor.yy19 = sqliteTriggerInsertStep(&yymsp[-2].minor.yy298, yymsp[-1].minor.yy320, 0, yymsp[0].minor.yy179, yymsp[-4].minor.yy372);} #line 3709 "parse.c" /* No destructor defined for INTO */ break; case 280: #line 851 "parse.y" {yygotominor.yy19 = sqliteTriggerDeleteStep(&yymsp[-1].minor.yy298, yymsp[0].minor.yy242);} #line 3715 "parse.c" /* No destructor defined for DELETE */ /* No destructor defined for FROM */ break; case 281: #line 854 "parse.y" {yygotominor.yy19 = sqliteTriggerSelectStep(yymsp[0].minor.yy179); } #line 3722 "parse.c" break; case 282: #line 857 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, 0); yygotominor.yy242->iColumn = OE_Ignore; sqliteExprSpan(yygotominor.yy242, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); } #line 3731 "parse.c" /* No destructor defined for LP */ /* No destructor defined for IGNORE */ break; case 283: #line 862 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298); yygotominor.yy242->iColumn = OE_Rollback; sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); } #line 3742 "parse.c" /* No destructor defined for LP */ /* No destructor defined for ROLLBACK */ /* No destructor defined for COMMA */ break; case 284: #line 867 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298); yygotominor.yy242->iColumn = OE_Abort; sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); } #line 3754 "parse.c" /* No destructor defined for LP */ /* No destructor defined for ABORT */ /* No destructor defined for COMMA */ break; case 285: #line 872 "parse.y" { yygotominor.yy242 = sqliteExpr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy298); yygotominor.yy242->iColumn = OE_Fail; sqliteExprSpan(yygotominor.yy242, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); } #line 3766 "parse.c" /* No destructor defined for LP */ /* No destructor defined for FAIL */ /* No destructor defined for COMMA */ break; case 286: #line 879 "parse.y" { sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&yymsp[-1].minor.yy298,&yymsp[0].minor.yy298)); } #line 3776 "parse.c" /* No destructor defined for DROP */ /* No destructor defined for TRIGGER */ break; case 287: #line 884 "parse.y" { sqliteAttach(pParse, &yymsp[-3].minor.yy298, &yymsp[-1].minor.yy298, &yymsp[0].minor.yy298); } #line 3785 "parse.c" /* No destructor defined for ATTACH */ /* No destructor defined for database_kw_opt */ /* No destructor defined for AS */ break; case 288: #line 888 "parse.y" { yygotominor.yy298 = yymsp[0].minor.yy298; } #line 3793 "parse.c" /* No destructor defined for USING */ break; case 289: #line 889 "parse.y" { yygotominor.yy298.z = 0; yygotominor.yy298.n = 0; } #line 3799 "parse.c" break; case 290: /* No destructor defined for DATABASE */ break; case 291: break; case 292: #line 895 "parse.y" { sqliteDetach(pParse, &yymsp[0].minor.yy298); } #line 3811 "parse.c" /* No destructor defined for DETACH */ /* No destructor defined for database_kw_opt */ break; }; yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; yyact = yy_find_reduce_action(yypParser,yygoto); if( yyact < YYNSTATE ){ yy_shift(yypParser,yyact,yygoto,&yygotominor); }else if( yyact == YYNSTATE + YYNRULE + 1 ){ yy_accept(yypParser); } } /* ** The following code executes when the parse fails */ static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ sqliteParserARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); } #endif while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* ** The following code executes when a syntax error first occurs. */ static void yy_syntax_error( yyParser *yypParser, /* The parser */ int yymajor, /* The major type of the error token */ YYMINORTYPE yyminor /* The minor type of the error token */ ){ sqliteParserARG_FETCH; #define TOKEN (yyminor.yy0) #line 23 "parse.y" if( pParse->zErrMsg==0 ){ if( TOKEN.z[0] ){ sqliteErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); }else{ sqliteErrorMsg(pParse, "incomplete SQL statement"); } } #line 3865 "parse.c" sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* ** The following is executed when the parser accepts */ static void yy_accept( yyParser *yypParser /* The parser */ ){ sqliteParserARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); } #endif while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser accepts */ sqliteParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* The main parser program. ** The first argument is a pointer to a structure obtained from ** "sqliteParserAlloc" which describes the current state of the parser. ** The second argument is the major token number. The third is ** the minor token. The fourth optional argument is whatever the ** user wants (and specified in the grammar) and is available for ** use by the action routines. ** ** Inputs: **
    **
  • A pointer to the parser (an opaque structure.) **
  • The major token number. **
  • The minor token number. **
  • An option argument of a grammar-specified type. **
** ** Outputs: ** None. */ void sqliteParser( void *yyp, /* The parser */ int yymajor, /* The major token code number */ sqliteParserTOKENTYPE yyminor /* The value for the token */ sqliteParserARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; int yyact; /* The parser action. */ int yyendofinput; /* True if we are at the end of input */ int yyerrorhit = 0; /* True if yymajor has invoked an error */ yyParser *yypParser; /* The parser */ /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; if( yypParser->yyidx<0 ){ if( yymajor==0 ) return; yypParser->yyidx = 0; yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; } yyminorunion.yy0 = yyminor; yyendofinput = (yymajor==0); sqliteParserARG_STORE; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); } #endif do{ yyact = yy_find_shift_action(yypParser,yymajor); if( yyactyyerrcnt--; if( yyendofinput && yypParser->yyidx>=0 ){ yymajor = 0; }else{ yymajor = YYNOCODE; } }else if( yyact < YYNSTATE + YYNRULE ){ yy_reduce(yypParser,yyact-YYNSTATE); }else if( yyact == YY_ERROR_ACTION ){ int yymx; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); } #endif #ifdef YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** ** * Call the %syntax_error function. ** ** * Begin popping the stack until we enter a state where ** it is legal to shift the error symbol, then shift ** the error symbol. ** ** * Set the error count to three. ** ** * Begin accepting and shifting new tokens. No new error ** processing will occur until three tokens have been ** shifted successfully. ** */ if( yypParser->yyerrcnt<0 ){ yy_syntax_error(yypParser,yymajor,yyminorunion); } yymx = yypParser->yystack[yypParser->yyidx].major; if( yymx==YYERRORSYMBOL || yyerrorhit ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sDiscard input token %s\n", yyTracePrompt,yyTokenName[yymajor]); } #endif yy_destructor(yymajor,&yyminorunion); yymajor = YYNOCODE; }else{ while( yypParser->yyidx >= 0 && yymx != YYERRORSYMBOL && (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE ){ yy_pop_parser_stack(yypParser); } if( yypParser->yyidx < 0 || yymajor==0 ){ yy_destructor(yymajor,&yyminorunion); yy_parse_failed(yypParser); yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ YYMINORTYPE u2; u2.YYERRSYMDT = 0; yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); } } yypParser->yyerrcnt = 3; yyerrorhit = 1; #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** ** * Report an error message, and throw away the input token. ** ** * If the input token is $, then fail the parse. ** ** As before, subsequent error messages are suppressed until ** three input tokens have been successfully shifted. */ if( yypParser->yyerrcnt<=0 ){ yy_syntax_error(yypParser,yymajor,yyminorunion); } yypParser->yyerrcnt = 3; yy_destructor(yymajor,&yyminorunion); if( yyendofinput ){ yy_parse_failed(yypParser); } yymajor = YYNOCODE; #endif }else{ yy_accept(yypParser); yymajor = YYNOCODE; } }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); return; } DBD-SQLite2-0.36/README0000644000175000017500000000264512126353147013513 0ustar rurbanrurbanDBD::SQLite2 ============ SQLite is a small fast embedded SQL database engine. DBD::SQLite2 embeds that database engine into a DBD driver, so if you want a relational database for your project, but don't want to install a large RDBMS system like MySQL or PostgreSQL, then DBD::SQLite2 may be just what you need. Note: DBD::SQLite2 is the old version of DBD::SQLite, and embeds version 2.x.x of the sqlite library. The current version of DBD::SQLite embeds version 3 (or possibly later if I forget to update this file). This release is designed to allow you to have both versions installed on the same system. SQLite supports quite a lot of features, such as transactions (atomic commit and rollback), indexes, DBA-free operation, a large subset of SQL92 supported, and more. Installation requires a compiler. The engine is very fast, but for updates/inserts/dml it does perform a global lock on the entire database. This, obviously, might not be good for multiple user systems. So beware. The database also appears to be significantly faster if your transactions are coarse. One performance benchmark I did was inserting 100_000 rows into the database - with AutoCommit on it was doing about 50 rows per second. When I turned AutoCommit off it went up to 1000 rows per second. This module is distributed under the same terms as Perl itself, and is copyright Matt Sergeant, 2002. The underlying SQLite database engine is copyright free. DBD-SQLite2-0.36/date.c0000644000175000017500000005134012126353147013710 0ustar rurbanrurban/* ** 2003 October 31 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: date.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ ** ** NOTES: ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. ** ** 1970-01-01 00:00:00 is JD 2440587.5 ** 2000-01-01 00:00:00 is JD 2451544.5 ** ** This implemention requires years to be expressed as a 4-digit number ** which means that only dates between 0000-01-01 and 9999-12-31 can ** be represented, even though julian day numbers allow a much wider ** range of dates. ** ** The Gregorian calendar system is used for all dates and times, ** even those that predate the Gregorian calendar. Historians usually ** use the Julian calendar for dates prior to 1582-10-15 and for some ** dates afterwards, depending on locale. Beware of this difference. ** ** The conversion algorithms are implemented based on descriptions ** in the following text: ** ** Jean Meeus ** Astronomical Algorithms, 2nd Edition, 1998 ** ISBM 0-943396-61-1 ** Willmann-Bell, Inc ** Richmond, Virginia (USA) */ #include "os.h" #include "sqliteInt.h" #include #include #include #include #ifndef SQLITE_OMIT_DATETIME_FUNCS /* ** A structure for holding a single date and time. */ typedef struct DateTime DateTime; struct DateTime { double rJD; /* The julian day number */ int Y, M, D; /* Year, month, and day */ int h, m; /* Hour and minutes */ int tz; /* Timezone offset in minutes */ double s; /* Seconds */ char validYMD; /* True if Y,M,D are valid */ char validHMS; /* True if h,m,s are valid */ char validJD; /* True if rJD is valid */ char validTZ; /* True if tz is valid */ }; /* ** Convert zDate into one or more integers. Additional arguments ** come in groups of 5 as follows: ** ** N number of digits in the integer ** min minimum allowed value of the integer ** max maximum allowed value of the integer ** nextC first character after the integer ** pVal where to write the integers value. ** ** Conversions continue until one with nextC==0 is encountered. ** The function returns the number of successful conversions. */ static int getDigits(const char *zDate, ...){ va_list ap; int val; int N; int min; int max; int nextC; int *pVal; int cnt = 0; va_start(ap, zDate); do{ N = va_arg(ap, int); min = va_arg(ap, int); max = va_arg(ap, int); nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*zDate) ){ return cnt; } val = val*10 + *zDate - '0'; zDate++; } if( valmax || (nextC!=0 && nextC!=*zDate) ){ return cnt; } *pVal = val; zDate++; cnt++; }while( nextC ); return cnt; } /* ** Read text from z[] and convert into a floating point number. Return ** the number of digits converted. */ static int getValue(const char *z, double *pR){ const char *zEnd; *pR = sqliteAtoF(z, &zEnd); return zEnd - z; } /* ** Parse a timezone extension on the end of a date-time. ** The extension is of the form: ** ** (+/-)HH:MM ** ** If the parse is successful, write the number of minutes ** of change in *pnMin and return 0. If a parser error occurs, ** return 0. ** ** A missing specifier is not considered an error. */ static int parseTimezone(const char *zDate, DateTime *p){ int sgn = 0; int nHr, nMn; while( isspace(*zDate) ){ zDate++; } p->tz = 0; if( *zDate=='-' ){ sgn = -1; }else if( *zDate=='+' ){ sgn = +1; }else{ return *zDate!=0; } zDate++; if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){ return 1; } zDate += 5; p->tz = sgn*(nMn + nHr*60); while( isspace(*zDate) ){ zDate++; } return *zDate!=0; } /* ** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. ** The HH, MM, and SS must each be exactly 2 digits. The ** fractional seconds FFFF can be one or more digits. ** ** Return 1 if there is a parsing error and 0 on success. */ static int parseHhMmSs(const char *zDate, DateTime *p){ int h, m, s; double ms = 0.0; if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){ return 1; } zDate += 5; if( *zDate==':' ){ zDate++; if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){ return 1; } zDate += 2; if( *zDate=='.' && isdigit(zDate[1]) ){ double rScale = 1.0; zDate++; while( isdigit(*zDate) ){ ms = ms*10.0 + *zDate - '0'; rScale *= 10.0; zDate++; } ms /= rScale; } }else{ s = 0; } p->validJD = 0; p->validHMS = 1; p->h = h; p->m = m; p->s = s + ms; if( parseTimezone(zDate, p) ) return 1; p->validTZ = p->tz!=0; return 0; } /* ** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume ** that the YYYY-MM-DD is according to the Gregorian calendar. ** ** Reference: Meeus page 61 */ static void computeJD(DateTime *p){ int Y, M, D, A, B, X1, X2; if( p->validJD ) return; if( p->validYMD ){ Y = p->Y; M = p->M; D = p->D; }else{ Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ M = 1; D = 1; } if( M<=2 ){ Y--; M += 12; } A = Y/100; B = 2 - A + (A/4); X1 = 365.25*(Y+4716); X2 = 30.6001*(M+1); p->rJD = X1 + X2 + D + B - 1524.5; p->validJD = 1; p->validYMD = 0; if( p->validHMS ){ p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; if( p->validTZ ){ p->rJD += p->tz*60/86400.0; p->validHMS = 0; p->validTZ = 0; } } } /* ** Parse dates of the form ** ** YYYY-MM-DD HH:MM:SS.FFF ** YYYY-MM-DD HH:MM:SS ** YYYY-MM-DD HH:MM ** YYYY-MM-DD ** ** Write the result into the DateTime structure and return 0 ** on success and 1 if the input string is not a well-formed ** date. */ static int parseYyyyMmDd(const char *zDate, DateTime *p){ int Y, M, D, neg; if( zDate[0]=='-' ){ zDate++; neg = 1; }else{ neg = 0; } if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ return 1; } zDate += 10; while( isspace(*zDate) ){ zDate++; } if( parseHhMmSs(zDate, p)==0 ){ /* We got the time */ }else if( *zDate==0 ){ p->validHMS = 0; }else{ return 1; } p->validJD = 0; p->validYMD = 1; p->Y = neg ? -Y : Y; p->M = M; p->D = D; if( p->validTZ ){ computeJD(p); } return 0; } /* ** Attempt to parse the given string into a Julian Day Number. Return ** the number of errors. ** ** The following are acceptable forms for the input string: ** ** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM ** DDDD.DD ** now ** ** In the first form, the +/-HH:MM is always optional. The fractional ** seconds extension (the ".FFF") is optional. The seconds portion ** (":SS.FFF") is option. The year and date can be omitted as long ** as there is a time string. The time string can be omitted as long ** as there is a year and date. */ static int parseDateOrTime(const char *zDate, DateTime *p){ memset(p, 0, sizeof(*p)); if( parseYyyyMmDd(zDate,p)==0 ){ return 0; }else if( parseHhMmSs(zDate, p)==0 ){ return 0; }else if( sqliteStrICmp(zDate,"now")==0){ double r; if( sqliteOsCurrentTime(&r)==0 ){ p->rJD = r; p->validJD = 1; return 0; } return 1; }else if( sqliteIsNumber(zDate) ){ p->rJD = sqliteAtoF(zDate, 0); p->validJD = 1; return 0; } return 1; } /* ** Compute the Year, Month, and Day from the julian day number. */ static void computeYMD(DateTime *p){ int Z, A, B, C, D, E, X1; if( p->validYMD ) return; if( !p->validJD ){ p->Y = 2000; p->M = 1; p->D = 1; }else{ Z = p->rJD + 0.5; A = (Z - 1867216.25)/36524.25; A = Z + 1 + A - (A/4); B = A + 1524; C = (B - 122.1)/365.25; D = 365.25*C; E = (B-D)/30.6001; X1 = 30.6001*E; p->D = B - D - X1; p->M = E<14 ? E-1 : E-13; p->Y = p->M>2 ? C - 4716 : C - 4715; } p->validYMD = 1; } /* ** Compute the Hour, Minute, and Seconds from the julian day number. */ static void computeHMS(DateTime *p){ int Z, s; if( p->validHMS ) return; Z = p->rJD + 0.5; s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5; p->s = 0.001*s; s = p->s; p->s -= s; p->h = s/3600; s -= p->h*3600; p->m = s/60; p->s += s - p->m*60; p->validHMS = 1; } /* ** Compute both YMD and HMS */ static void computeYMD_HMS(DateTime *p){ computeYMD(p); computeHMS(p); } /* ** Clear the YMD and HMS and the TZ */ static void clearYMD_HMS_TZ(DateTime *p){ p->validYMD = 0; p->validHMS = 0; p->validTZ = 0; } /* ** Compute the difference (in days) between localtime and UTC (a.k.a. GMT) ** for the time value p where p is in UTC. */ static double localtimeOffset(DateTime *p){ DateTime x, y; time_t t; struct tm *pTm; x = *p; computeYMD_HMS(&x); if( x.Y<1971 || x.Y>=2038 ){ x.Y = 2000; x.M = 1; x.D = 1; x.h = 0; x.m = 0; x.s = 0.0; } else { int s = x.s + 0.5; x.s = s; } x.tz = 0; x.validJD = 0; computeJD(&x); t = (x.rJD-2440587.5)*86400.0 + 0.5; sqliteOsEnterMutex(); pTm = localtime(&t); y.Y = pTm->tm_year + 1900; y.M = pTm->tm_mon + 1; y.D = pTm->tm_mday; y.h = pTm->tm_hour; y.m = pTm->tm_min; y.s = pTm->tm_sec; sqliteOsLeaveMutex(); y.validYMD = 1; y.validHMS = 1; y.validJD = 0; y.validTZ = 0; computeJD(&y); return y.rJD - x.rJD; } /* ** Process a modifier to a date-time stamp. The modifiers are ** as follows: ** ** NNN days ** NNN hours ** NNN minutes ** NNN.NNNN seconds ** NNN months ** NNN years ** start of month ** start of year ** start of week ** start of day ** weekday N ** unixepoch ** localtime ** utc ** ** Return 0 on success and 1 if there is any kind of error. */ static int parseModifier(const char *zMod, DateTime *p){ int rc = 1; int n; double r; char *z, zBuf[30]; z = zBuf; for(n=0; nrJD += localtimeOffset(p); clearYMD_HMS_TZ(p); rc = 0; } break; } case 'u': { /* ** unixepoch ** ** Treat the current value of p->rJD as the number of ** seconds since 1970. Convert to a real julian day number. */ if( strcmp(z, "unixepoch")==0 && p->validJD ){ p->rJD = p->rJD/86400.0 + 2440587.5; clearYMD_HMS_TZ(p); rc = 0; }else if( strcmp(z, "utc")==0 ){ double c1; computeJD(p); c1 = localtimeOffset(p); p->rJD -= c1; clearYMD_HMS_TZ(p); p->rJD += c1 - localtimeOffset(p); rc = 0; } break; } case 'w': { /* ** weekday N ** ** Move the date to the same time on the next occurrance of ** weekday N where 0==Sunday, 1==Monday, and so forth. If the ** date is already on the appropriate weekday, this is a no-op. */ if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0 && (n=r)==r && n>=0 && r<7 ){ int Z; computeYMD_HMS(p); p->validTZ = 0; p->validJD = 0; computeJD(p); Z = p->rJD + 1.5; Z %= 7; if( Z>n ) Z -= 7; p->rJD += n - Z; clearYMD_HMS_TZ(p); rc = 0; } break; } case 's': { /* ** start of TTTTT ** ** Move the date backwards to the beginning of the current day, ** or month or year. */ if( strncmp(z, "start of ", 9)!=0 ) break; z += 9; computeYMD(p); p->validHMS = 1; p->h = p->m = 0; p->s = 0.0; p->validTZ = 0; p->validJD = 0; if( strcmp(z,"month")==0 ){ p->D = 1; rc = 0; }else if( strcmp(z,"year")==0 ){ computeYMD(p); p->M = 1; p->D = 1; rc = 0; }else if( strcmp(z,"day")==0 ){ rc = 0; } break; } case '+': case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { n = getValue(z, &r); if( n<=0 ) break; if( z[n]==':' ){ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the ** specified number of hours, minutes, seconds, and fractional seconds ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be ** omitted. */ const char *z2 = z; DateTime tx; int day; if( !isdigit(*z2) ) z2++; memset(&tx, 0, sizeof(tx)); if( parseHhMmSs(z2, &tx) ) break; computeJD(&tx); tx.rJD -= 0.5; day = (int)tx.rJD; tx.rJD -= day; if( z[0]=='-' ) tx.rJD = -tx.rJD; computeJD(p); clearYMD_HMS_TZ(p); p->rJD += tx.rJD; rc = 0; break; } z += n; while( isspace(z[0]) ) z++; n = strlen(z); if( n>10 || n<3 ) break; if( z[n-1]=='s' ){ z[n-1] = 0; n--; } computeJD(p); rc = 0; if( n==3 && strcmp(z,"day")==0 ){ p->rJD += r; }else if( n==4 && strcmp(z,"hour")==0 ){ p->rJD += r/24.0; }else if( n==6 && strcmp(z,"minute")==0 ){ p->rJD += r/(24.0*60.0); }else if( n==6 && strcmp(z,"second")==0 ){ p->rJD += r/(24.0*60.0*60.0); }else if( n==5 && strcmp(z,"month")==0 ){ int x, y; computeYMD_HMS(p); p->M += r; x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; p->Y += x; p->M -= x*12; p->validJD = 0; computeJD(p); y = r; if( y!=r ){ p->rJD += (r - y)*30.0; } }else if( n==4 && strcmp(z,"year")==0 ){ computeYMD_HMS(p); p->Y += r; p->validJD = 0; computeJD(p); }else{ rc = 1; } clearYMD_HMS_TZ(p); break; } default: { break; } } return rc; } /* ** Process time function arguments. argv[0] is a date-time stamp. ** argv[1] and following are modifiers. Parse them all and write ** the resulting time into the DateTime structure p. Return 0 ** on success and 1 if there are any errors. */ static int isDate(int argc, const char **argv, DateTime *p){ int i; if( argc==0 ) return 1; if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1; for(i=1; i /* Forward declarations */ static BtOps sqliteBtreeOps; static BtCursorOps sqliteBtreeCursorOps; /* ** Macros used for byteswapping. B is a pointer to the Btree ** structure. This is needed to access the Btree.needSwab boolean ** in order to tell if byte swapping is needed or not. ** X is an unsigned integer. SWAB16 byte swaps a 16-bit integer. ** SWAB32 byteswaps a 32-bit integer. */ #define SWAB16(B,X) ((B)->needSwab? swab16((u16)X) : ((u16)X)) #define SWAB32(B,X) ((B)->needSwab? swab32(X) : (X)) #define SWAB_ADD(B,X,A) \ if((B)->needSwab){ X=swab32(swab32(X)+A); }else{ X += (A); } /* ** The following global variable - available only if SQLITE_TEST is ** defined - is used to determine whether new databases are created in ** native byte order or in non-native byte order. Non-native byte order ** databases are created for testing purposes only. Under normal operation, ** only native byte-order databases should be created, but we should be ** able to read or write existing databases regardless of the byteorder. */ #ifdef SQLITE_TEST int btree_native_byte_order = 1; #else # define btree_native_byte_order 1 #endif /* ** Forward declarations of structures used only in this file. */ typedef struct PageOne PageOne; typedef struct MemPage MemPage; typedef struct PageHdr PageHdr; typedef struct Cell Cell; typedef struct CellHdr CellHdr; typedef struct FreeBlk FreeBlk; typedef struct OverflowPage OverflowPage; typedef struct FreelistInfo FreelistInfo; /* ** All structures on a database page are aligned to 4-byte boundries. ** This routine rounds up a number of bytes to the next multiple of 4. ** ** This might need to change for computer architectures that require ** and 8-byte alignment boundry for structures. */ #define ROUNDUP(X) ((X+3) & ~3) /* ** This is a magic string that appears at the beginning of every ** SQLite database in order to identify the file as a real database. */ static const char zMagicHeader[] = "** This file contains an SQLite 2.1 database **"; #define MAGIC_SIZE (sizeof(zMagicHeader)) /* ** This is a magic integer also used to test the integrity of the database ** file. This integer is used in addition to the string above so that ** if the file is written on a little-endian architecture and read ** on a big-endian architectures (or vice versa) we can detect the ** problem. ** ** The number used was obtained at random and has no special ** significance other than the fact that it represents a different ** integer on little-endian and big-endian machines. */ #define MAGIC 0xdae37528 /* ** The first page of the database file contains a magic header string ** to identify the file as an SQLite database file. It also contains ** a pointer to the first free page of the file. Page 2 contains the ** root of the principle BTree. The file might contain other BTrees ** rooted on pages above 2. ** ** The first page also contains SQLITE_N_BTREE_META integers that ** can be used by higher-level routines. ** ** Remember that pages are numbered beginning with 1. (See pager.c ** for additional information.) Page 0 does not exist and a page ** number of 0 is used to mean "no such page". */ struct PageOne { char zMagic[MAGIC_SIZE]; /* String that identifies the file as a database */ int iMagic; /* Integer to verify correct byte order */ Pgno freeList; /* First free page in a list of all free pages */ int nFree; /* Number of pages on the free list */ int aMeta[SQLITE_N_BTREE_META-1]; /* User defined integers */ }; /* ** Each database page has a header that is an instance of this ** structure. ** ** PageHdr.firstFree is 0 if there is no free space on this page. ** Otherwise, PageHdr.firstFree is the index in MemPage.u.aDisk[] of a ** FreeBlk structure that describes the first block of free space. ** All free space is defined by a linked list of FreeBlk structures. ** ** Data is stored in a linked list of Cell structures. PageHdr.firstCell ** is the index into MemPage.u.aDisk[] of the first cell on the page. The ** Cells are kept in sorted order. ** ** A Cell contains all information about a database entry and a pointer ** to a child page that contains other entries less than itself. In ** other words, the i-th Cell contains both Ptr(i) and Key(i). The ** right-most pointer of the page is contained in PageHdr.rightChild. */ struct PageHdr { Pgno rightChild; /* Child page that comes after all cells on this page */ u16 firstCell; /* Index in MemPage.u.aDisk[] of the first cell */ u16 firstFree; /* Index in MemPage.u.aDisk[] of the first free block */ }; /* ** Entries on a page of the database are called "Cells". Each Cell ** has a header and data. This structure defines the header. The ** key and data (collectively the "payload") follow this header on ** the database page. ** ** A definition of the complete Cell structure is given below. The ** header for the cell must be defined first in order to do some ** of the sizing #defines that follow. */ struct CellHdr { Pgno leftChild; /* Child page that comes before this cell */ u16 nKey; /* Number of bytes in the key */ u16 iNext; /* Index in MemPage.u.aDisk[] of next cell in sorted order */ u8 nKeyHi; /* Upper 8 bits of key size for keys larger than 64K bytes */ u8 nDataHi; /* Upper 8 bits of data size when the size is more than 64K */ u16 nData; /* Number of bytes of data */ }; /* ** The key and data size are split into a lower 16-bit segment and an ** upper 8-bit segment in order to pack them together into a smaller ** space. The following macros reassembly a key or data size back ** into an integer. */ #define NKEY(b,h) (SWAB16(b,h.nKey) + h.nKeyHi*65536) #define NDATA(b,h) (SWAB16(b,h.nData) + h.nDataHi*65536) /* ** The minimum size of a complete Cell. The Cell must contain a header ** and at least 4 bytes of payload. */ #define MIN_CELL_SIZE (sizeof(CellHdr)+4) /* ** The maximum number of database entries that can be held in a single ** page of the database. */ #define MX_CELL ((SQLITE_USABLE_SIZE-sizeof(PageHdr))/MIN_CELL_SIZE) /* ** The amount of usable space on a single page of the BTree. This is the ** page size minus the overhead of the page header. */ #define USABLE_SPACE (SQLITE_USABLE_SIZE - sizeof(PageHdr)) /* ** The maximum amount of payload (in bytes) that can be stored locally for ** a database entry. If the entry contains more data than this, the ** extra goes onto overflow pages. ** ** This number is chosen so that at least 4 cells will fit on every page. */ #define MX_LOCAL_PAYLOAD ((USABLE_SPACE/4-(sizeof(CellHdr)+sizeof(Pgno)))&~3) /* ** Data on a database page is stored as a linked list of Cell structures. ** Both the key and the data are stored in aPayload[]. The key always comes ** first. The aPayload[] field grows as necessary to hold the key and data, ** up to a maximum of MX_LOCAL_PAYLOAD bytes. If the size of the key and ** data combined exceeds MX_LOCAL_PAYLOAD bytes, then Cell.ovfl is the ** page number of the first overflow page. ** ** Though this structure is fixed in size, the Cell on the database ** page varies in size. Every cell has a CellHdr and at least 4 bytes ** of payload space. Additional payload bytes (up to the maximum of ** MX_LOCAL_PAYLOAD) and the Cell.ovfl value are allocated only as ** needed. */ struct Cell { CellHdr h; /* The cell header */ char aPayload[MX_LOCAL_PAYLOAD]; /* Key and data */ Pgno ovfl; /* The first overflow page */ }; /* ** Free space on a page is remembered using a linked list of the FreeBlk ** structures. Space on a database page is allocated in increments of ** at least 4 bytes and is always aligned to a 4-byte boundry. The ** linked list of FreeBlks is always kept in order by address. */ struct FreeBlk { u16 iSize; /* Number of bytes in this block of free space */ u16 iNext; /* Index in MemPage.u.aDisk[] of the next free block */ }; /* ** The number of bytes of payload that will fit on a single overflow page. */ #define OVERFLOW_SIZE (SQLITE_USABLE_SIZE-sizeof(Pgno)) /* ** When the key and data for a single entry in the BTree will not fit in ** the MX_LOCAL_PAYLOAD bytes of space available on the database page, ** then all extra bytes are written to a linked list of overflow pages. ** Each overflow page is an instance of the following structure. ** ** Unused pages in the database are also represented by instances of ** the OverflowPage structure. The PageOne.freeList field is the ** page number of the first page in a linked list of unused database ** pages. */ struct OverflowPage { Pgno iNext; char aPayload[OVERFLOW_SIZE]; }; /* ** The PageOne.freeList field points to a linked list of overflow pages ** hold information about free pages. The aPayload section of each ** overflow page contains an instance of the following structure. The ** aFree[] array holds the page number of nFree unused pages in the disk ** file. */ struct FreelistInfo { int nFree; Pgno aFree[(OVERFLOW_SIZE-sizeof(int))/sizeof(Pgno)]; }; /* ** For every page in the database file, an instance of the following structure ** is stored in memory. The u.aDisk[] array contains the raw bits read from ** the disk. The rest is auxiliary information held in memory only. The ** auxiliary info is only valid for regular database pages - it is not ** used for overflow pages and pages on the freelist. ** ** Of particular interest in the auxiliary info is the apCell[] entry. Each ** apCell[] entry is a pointer to a Cell structure in u.aDisk[]. The cells are ** put in this array so that they can be accessed in constant time, rather ** than in linear time which would be needed if we had to walk the linked ** list on every access. ** ** Note that apCell[] contains enough space to hold up to two more Cells ** than can possibly fit on one page. In the steady state, every apCell[] ** points to memory inside u.aDisk[]. But in the middle of an insert ** operation, some apCell[] entries may temporarily point to data space ** outside of u.aDisk[]. This is a transient situation that is quickly ** resolved. But while it is happening, it is possible for a database ** page to hold as many as two more cells than it might otherwise hold. ** The extra two entries in apCell[] are an allowance for this situation. ** ** The pParent field points back to the parent page. This allows us to ** walk up the BTree from any leaf to the root. Care must be taken to ** unref() the parent page pointer when this page is no longer referenced. ** The pageDestructor() routine handles that chore. */ struct MemPage { union u_page_data { char aDisk[SQLITE_PAGE_SIZE]; /* Page data stored on disk */ PageHdr hdr; /* Overlay page header */ } u; u8 isInit; /* True if auxiliary data is initialized */ u8 idxShift; /* True if apCell[] indices have changed */ u8 isOverfull; /* Some apCell[] points outside u.aDisk[] */ MemPage *pParent; /* The parent of this page. NULL for root */ int idxParent; /* Index in pParent->apCell[] of this node */ int nFree; /* Number of free bytes in u.aDisk[] */ int nCell; /* Number of entries on this page */ Cell *apCell[MX_CELL+2]; /* All data entires in sorted order */ }; /* ** The in-memory image of a disk page has the auxiliary information appended ** to the end. EXTRA_SIZE is the number of bytes of space needed to hold ** that extra information. */ #define EXTRA_SIZE (sizeof(MemPage)-sizeof(union u_page_data)) /* ** Everything we need to know about an open database */ struct Btree { BtOps *pOps; /* Function table */ Pager *pPager; /* The page cache */ BtCursor *pCursor; /* A list of all open cursors */ PageOne *page1; /* First page of the database */ u8 inTrans; /* True if a transaction is in progress */ u8 inCkpt; /* True if there is a checkpoint on the transaction */ u8 readOnly; /* True if the underlying file is readonly */ u8 needSwab; /* Need to byte-swapping */ }; typedef Btree Bt; /* ** A cursor is a pointer to a particular entry in the BTree. ** The entry is identified by its MemPage and the index in ** MemPage.apCell[] of the entry. */ struct BtCursor { BtCursorOps *pOps; /* Function table */ Btree *pBt; /* The Btree to which this cursor belongs */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ BtCursor *pShared; /* Loop of cursors with the same root page */ Pgno pgnoRoot; /* The root page of this tree */ MemPage *pPage; /* Page that contains the entry */ int idx; /* Index of the entry in pPage->apCell[] */ u8 wrFlag; /* True if writable */ u8 eSkip; /* Determines if next step operation is a no-op */ u8 iMatch; /* compare result from last sqliteBtreeMoveto() */ }; /* ** Legal values for BtCursor.eSkip. */ #define SKIP_NONE 0 /* Always step the cursor */ #define SKIP_NEXT 1 /* The next sqliteBtreeNext() is a no-op */ #define SKIP_PREV 2 /* The next sqliteBtreePrevious() is a no-op */ #define SKIP_INVALID 3 /* Calls to Next() and Previous() are invalid */ /* Forward declarations */ static int fileBtreeCloseCursor(BtCursor *pCur); /* ** Routines for byte swapping. */ u16 swab16(u16 x){ return ((x & 0xff)<<8) | ((x>>8)&0xff); } u32 swab32(u32 x){ return ((x & 0xff)<<24) | ((x & 0xff00)<<8) | ((x>>8) & 0xff00) | ((x>>24)&0xff); } /* ** Compute the total number of bytes that a Cell needs on the main ** database page. The number returned includes the Cell header, ** local payload storage, and the pointer to overflow pages (if ** applicable). Additional space allocated on overflow pages ** is NOT included in the value returned from this routine. */ static int cellSize(Btree *pBt, Cell *pCell){ int n = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h); if( n>MX_LOCAL_PAYLOAD ){ n = MX_LOCAL_PAYLOAD + sizeof(Pgno); }else{ n = ROUNDUP(n); } n += sizeof(CellHdr); return n; } /* ** Defragment the page given. All Cells are moved to the ** beginning of the page and all free space is collected ** into one big FreeBlk at the end of the page. */ static void defragmentPage(Btree *pBt, MemPage *pPage){ int pc, i, n; FreeBlk *pFBlk; char newPage[SQLITE_USABLE_SIZE]; assert( sqlitepager_iswriteable(pPage) ); assert( pPage->isInit ); pc = sizeof(PageHdr); pPage->u.hdr.firstCell = SWAB16(pBt, pc); memcpy(newPage, pPage->u.aDisk, pc); for(i=0; inCell; i++){ Cell *pCell = pPage->apCell[i]; /* This routine should never be called on an overfull page. The ** following asserts verify that constraint. */ assert( Addr(pCell) > Addr(pPage) ); assert( Addr(pCell) < Addr(pPage) + SQLITE_USABLE_SIZE ); n = cellSize(pBt, pCell); pCell->h.iNext = SWAB16(pBt, pc + n); memcpy(&newPage[pc], pCell, n); pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc]; pc += n; } assert( pPage->nFree==SQLITE_USABLE_SIZE-pc ); memcpy(pPage->u.aDisk, newPage, pc); if( pPage->nCell>0 ){ pPage->apCell[pPage->nCell-1]->h.iNext = 0; } pFBlk = (FreeBlk*)&pPage->u.aDisk[pc]; pFBlk->iSize = SWAB16(pBt, SQLITE_USABLE_SIZE - pc); pFBlk->iNext = 0; pPage->u.hdr.firstFree = SWAB16(pBt, pc); memset(&pFBlk[1], 0, SQLITE_USABLE_SIZE - pc - sizeof(FreeBlk)); } /* ** Allocate nByte bytes of space on a page. nByte must be a ** multiple of 4. ** ** Return the index into pPage->u.aDisk[] of the first byte of ** the new allocation. Or return 0 if there is not enough free ** space on the page to satisfy the allocation request. ** ** If the page contains nBytes of free space but does not contain ** nBytes of contiguous free space, then this routine automatically ** calls defragementPage() to consolidate all free space before ** allocating the new chunk. */ static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){ FreeBlk *p; u16 *pIdx; int start; int iSize; #ifndef NDEBUG int cnt = 0; #endif assert( sqlitepager_iswriteable(pPage) ); assert( nByte==ROUNDUP(nByte) ); assert( pPage->isInit ); if( pPage->nFreeisOverfull ) return 0; pIdx = &pPage->u.hdr.firstFree; p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)]; while( (iSize = SWAB16(pBt, p->iSize))iNext==0 ){ defragmentPage(pBt, pPage); pIdx = &pPage->u.hdr.firstFree; }else{ pIdx = &p->iNext; } p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)]; } if( iSize==nByte ){ start = SWAB16(pBt, *pIdx); *pIdx = p->iNext; }else{ FreeBlk *pNew; start = SWAB16(pBt, *pIdx); pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte]; pNew->iNext = p->iNext; pNew->iSize = SWAB16(pBt, iSize - nByte); *pIdx = SWAB16(pBt, start + nByte); } pPage->nFree -= nByte; return start; } /* ** Return a section of the MemPage.u.aDisk[] to the freelist. ** The first byte of the new free block is pPage->u.aDisk[start] ** and the size of the block is "size" bytes. Size must be ** a multiple of 4. ** ** Most of the effort here is involved in coalesing adjacent ** free blocks into a single big free block. */ static void freeSpace(Btree *pBt, MemPage *pPage, int start, int size){ int end = start + size; u16 *pIdx, idx; FreeBlk *pFBlk; FreeBlk *pNew; FreeBlk *pNext; int iSize; assert( sqlitepager_iswriteable(pPage) ); assert( size == ROUNDUP(size) ); assert( start == ROUNDUP(start) ); assert( pPage->isInit ); pIdx = &pPage->u.hdr.firstFree; idx = SWAB16(pBt, *pIdx); while( idx!=0 && idxu.aDisk[idx]; iSize = SWAB16(pBt, pFBlk->iSize); if( idx + iSize == start ){ pFBlk->iSize = SWAB16(pBt, iSize + size); if( idx + iSize + size == SWAB16(pBt, pFBlk->iNext) ){ pNext = (FreeBlk*)&pPage->u.aDisk[idx + iSize + size]; if( pBt->needSwab ){ pFBlk->iSize = swab16((u16)swab16(pNext->iSize)+iSize+size); }else{ pFBlk->iSize += pNext->iSize; } pFBlk->iNext = pNext->iNext; } pPage->nFree += size; return; } pIdx = &pFBlk->iNext; idx = SWAB16(pBt, *pIdx); } pNew = (FreeBlk*)&pPage->u.aDisk[start]; if( idx != end ){ pNew->iSize = SWAB16(pBt, size); pNew->iNext = SWAB16(pBt, idx); }else{ pNext = (FreeBlk*)&pPage->u.aDisk[idx]; pNew->iSize = SWAB16(pBt, size + SWAB16(pBt, pNext->iSize)); pNew->iNext = pNext->iNext; } *pIdx = SWAB16(pBt, start); pPage->nFree += size; } /* ** Initialize the auxiliary information for a disk block. ** ** The pParent parameter must be a pointer to the MemPage which ** is the parent of the page being initialized. The root of the ** BTree (usually page 2) has no parent and so for that page, ** pParent==NULL. ** ** Return SQLITE_OK on success. If we see that the page does ** not contain a well-formed database page, then return ** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not ** guarantee that the page is well-formed. It only shows that ** we failed to detect any corruption. */ static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){ int idx; /* An index into pPage->u.aDisk[] */ Cell *pCell; /* A pointer to a Cell in pPage->u.aDisk[] */ FreeBlk *pFBlk; /* A pointer to a free block in pPage->u.aDisk[] */ int sz; /* The size of a Cell in bytes */ int freeSpace; /* Amount of free space on the page */ if( pPage->pParent ){ assert( pPage->pParent==pParent ); return SQLITE_OK; } if( pParent ){ pPage->pParent = pParent; sqlitepager_ref(pParent); } if( pPage->isInit ) return SQLITE_OK; pPage->isInit = 1; pPage->nCell = 0; freeSpace = USABLE_SPACE; idx = SWAB16(pBt, pPage->u.hdr.firstCell); while( idx!=0 ){ if( idx>SQLITE_USABLE_SIZE-MIN_CELL_SIZE ) goto page_format_error; if( idxu.aDisk[idx]; sz = cellSize(pBt, pCell); if( idx+sz > SQLITE_USABLE_SIZE ) goto page_format_error; freeSpace -= sz; pPage->apCell[pPage->nCell++] = pCell; idx = SWAB16(pBt, pCell->h.iNext); } pPage->nFree = 0; idx = SWAB16(pBt, pPage->u.hdr.firstFree); while( idx!=0 ){ int iNext; if( idx>SQLITE_USABLE_SIZE-sizeof(FreeBlk) ) goto page_format_error; if( idxu.aDisk[idx]; pPage->nFree += SWAB16(pBt, pFBlk->iSize); iNext = SWAB16(pBt, pFBlk->iNext); if( iNext>0 && iNext <= idx ) goto page_format_error; idx = iNext; } if( pPage->nCell==0 && pPage->nFree==0 ){ /* As a special case, an uninitialized root page appears to be ** an empty database */ return SQLITE_OK; } if( pPage->nFree!=freeSpace ) goto page_format_error; return SQLITE_OK; page_format_error: return SQLITE_CORRUPT; } /* ** Set up a raw page so that it looks like a database page holding ** no entries. */ static void zeroPage(Btree *pBt, MemPage *pPage){ PageHdr *pHdr; FreeBlk *pFBlk; assert( sqlitepager_iswriteable(pPage) ); memset(pPage, 0, SQLITE_USABLE_SIZE); pHdr = &pPage->u.hdr; pHdr->firstCell = 0; pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr)); pFBlk = (FreeBlk*)&pHdr[1]; pFBlk->iNext = 0; pPage->nFree = SQLITE_USABLE_SIZE - sizeof(*pHdr); pFBlk->iSize = SWAB16(pBt, pPage->nFree); pPage->nCell = 0; pPage->isOverfull = 0; } /* ** This routine is called when the reference count for a page ** reaches zero. We need to unref the pParent pointer when that ** happens. */ static void pageDestructor(void *pData){ MemPage *pPage = (MemPage*)pData; if( pPage->pParent ){ MemPage *pParent = pPage->pParent; pPage->pParent = 0; sqlitepager_unref(pParent); } } /* ** Open a new database. ** ** Actually, this routine just sets up the internal data structures ** for accessing the database. We do not open the database file ** until the first page is loaded. ** ** zFilename is the name of the database file. If zFilename is NULL ** a new database with a random name is created. This randomly named ** database file will be deleted when sqliteBtreeClose() is called. */ int sqliteBtreeOpen( const char *zFilename, /* Name of the file containing the BTree database */ int omitJournal, /* if TRUE then do not journal this file */ int nCache, /* How many pages in the page cache */ Btree **ppBtree /* Pointer to new Btree object written here */ ){ Btree *pBt; int rc; /* ** The following asserts make sure that structures used by the btree are ** the right size. This is to guard against size changes that result ** when compiling on a different architecture. */ assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); assert( sizeof(PageHdr)==8 ); assert( sizeof(CellHdr)==12 ); assert( sizeof(FreeBlk)==4 ); assert( sizeof(OverflowPage)==SQLITE_USABLE_SIZE ); assert( sizeof(FreelistInfo)==OVERFLOW_SIZE ); assert( sizeof(ptr)==sizeof(char*) ); assert( sizeof(uptr)==sizeof(ptr) ); pBt = sqliteMalloc( sizeof(*pBt) ); if( pBt==0 ){ *ppBtree = 0; return SQLITE_NOMEM; } if( nCache<10 ) nCache = 10; rc = sqlitepager_open(&pBt->pPager, zFilename, nCache, EXTRA_SIZE, !omitJournal); if( rc!=SQLITE_OK ){ if( pBt->pPager ) sqlitepager_close(pBt->pPager); sqliteFree(pBt); *ppBtree = 0; return rc; } sqlitepager_set_destructor(pBt->pPager, pageDestructor); pBt->pCursor = 0; pBt->page1 = 0; pBt->readOnly = sqlitepager_isreadonly(pBt->pPager); pBt->pOps = &sqliteBtreeOps; *ppBtree = pBt; return SQLITE_OK; } /* ** Close an open database and invalidate all cursors. */ static int fileBtreeClose(Btree *pBt){ while( pBt->pCursor ){ fileBtreeCloseCursor(pBt->pCursor); } sqlitepager_close(pBt->pPager); sqliteFree(pBt); return SQLITE_OK; } /* ** Change the limit on the number of pages allowed in the cache. ** ** The maximum number of cache pages is set to the absolute ** value of mxPage. If mxPage is negative, the pager will ** operate asynchronously - it will not stop to do fsync()s ** to insure data is written to the disk surface before ** continuing. Transactions still work if synchronous is off, ** and the database cannot be corrupted if this program ** crashes. But if the operating system crashes or there is ** an abrupt power failure when synchronous is off, the database ** could be left in an inconsistent and unrecoverable state. ** Synchronous is on by default so database corruption is not ** normally a worry. */ static int fileBtreeSetCacheSize(Btree *pBt, int mxPage){ sqlitepager_set_cachesize(pBt->pPager, mxPage); return SQLITE_OK; } /* ** Change the way data is synced to disk in order to increase or decrease ** how well the database resists damage due to OS crashes and power ** failures. Level 1 is the same as asynchronous (no syncs() occur and ** there is a high probability of damage) Level 2 is the default. There ** is a very low but non-zero probability of damage. Level 3 reduces the ** probability of damage to near zero but with a write performance reduction. */ static int fileBtreeSetSafetyLevel(Btree *pBt, int level){ sqlitepager_set_safety_level(pBt->pPager, level); return SQLITE_OK; } /* ** Get a reference to page1 of the database file. This will ** also acquire a readlock on that file. ** ** SQLITE_OK is returned on success. If the file is not a ** well-formed database file, then SQLITE_CORRUPT is returned. ** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM ** is returned if we run out of memory. SQLITE_PROTOCOL is returned ** if there is a locking protocol violation. */ static int lockBtree(Btree *pBt){ int rc; if( pBt->page1 ) return SQLITE_OK; rc = sqlitepager_get(pBt->pPager, 1, (void**)&pBt->page1); if( rc!=SQLITE_OK ) return rc; /* Do some checking to help insure the file we opened really is ** a valid database file. */ if( sqlitepager_pagecount(pBt->pPager)>0 ){ PageOne *pP1 = pBt->page1; if( strcmp(pP1->zMagic,zMagicHeader)!=0 || (pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){ rc = SQLITE_NOTADB; goto page1_init_failed; } pBt->needSwab = pP1->iMagic!=MAGIC; } return rc; page1_init_failed: sqlitepager_unref(pBt->page1); pBt->page1 = 0; return rc; } /* ** If there are no outstanding cursors and we are not in the middle ** of a transaction but there is a read lock on the database, then ** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock. ** ** If there are any outstanding cursors, this routine is a no-op. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(Btree *pBt){ if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){ sqlitepager_unref(pBt->page1); pBt->page1 = 0; pBt->inTrans = 0; pBt->inCkpt = 0; } } /* ** Create a new database by initializing the first two pages of the ** file. */ static int newDatabase(Btree *pBt){ MemPage *pRoot; PageOne *pP1; int rc; if( sqlitepager_pagecount(pBt->pPager)>1 ) return SQLITE_OK; pP1 = pBt->page1; rc = sqlitepager_write(pBt->page1); if( rc ) return rc; rc = sqlitepager_get(pBt->pPager, 2, (void**)&pRoot); if( rc ) return rc; rc = sqlitepager_write(pRoot); if( rc ){ sqlitepager_unref(pRoot); return rc; } strcpy(pP1->zMagic, zMagicHeader); if( btree_native_byte_order ){ pP1->iMagic = MAGIC; pBt->needSwab = 0; }else{ pP1->iMagic = swab32(MAGIC); pBt->needSwab = 1; } zeroPage(pBt, pRoot); sqlitepager_unref(pRoot); return SQLITE_OK; } /* ** Attempt to start a new transaction. ** ** A transaction must be started before attempting any changes ** to the database. None of the following routines will work ** unless a transaction is started first: ** ** sqliteBtreeCreateTable() ** sqliteBtreeCreateIndex() ** sqliteBtreeClearTable() ** sqliteBtreeDropTable() ** sqliteBtreeInsert() ** sqliteBtreeDelete() ** sqliteBtreeUpdateMeta() */ static int fileBtreeBeginTrans(Btree *pBt){ int rc; if( pBt->inTrans ) return SQLITE_ERROR; if( pBt->readOnly ) return SQLITE_READONLY; if( pBt->page1==0 ){ rc = lockBtree(pBt); if( rc!=SQLITE_OK ){ return rc; } } rc = sqlitepager_begin(pBt->page1); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); } if( rc==SQLITE_OK ){ pBt->inTrans = 1; pBt->inCkpt = 0; }else{ unlockBtreeIfUnused(pBt); } return rc; } /* ** Commit the transaction currently in progress. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ static int fileBtreeCommit(Btree *pBt){ int rc; rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager); pBt->inTrans = 0; pBt->inCkpt = 0; unlockBtreeIfUnused(pBt); return rc; } /* ** Rollback the transaction in progress. All cursors will be ** invalided by this operation. Any attempt to use a cursor ** that was open at the beginning of this operation will result ** in an error. ** ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ static int fileBtreeRollback(Btree *pBt){ int rc; BtCursor *pCur; if( pBt->inTrans==0 ) return SQLITE_OK; pBt->inTrans = 0; pBt->inCkpt = 0; rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager); for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->pPage && pCur->pPage->isInit==0 ){ sqlitepager_unref(pCur->pPage); pCur->pPage = 0; } } unlockBtreeIfUnused(pBt); return rc; } /* ** Set the checkpoint for the current transaction. The checkpoint serves ** as a sub-transaction that can be rolled back independently of the ** main transaction. You must start a transaction before starting a ** checkpoint. The checkpoint is ended automatically if the transaction ** commits or rolls back. ** ** Only one checkpoint may be active at a time. It is an error to try ** to start a new checkpoint if another checkpoint is already active. */ static int fileBtreeBeginCkpt(Btree *pBt){ int rc; if( !pBt->inTrans || pBt->inCkpt ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager); pBt->inCkpt = 1; return rc; } /* ** Commit a checkpoint to transaction currently in progress. If no ** checkpoint is active, this is a no-op. */ static int fileBtreeCommitCkpt(Btree *pBt){ int rc; if( pBt->inCkpt && !pBt->readOnly ){ rc = sqlitepager_ckpt_commit(pBt->pPager); }else{ rc = SQLITE_OK; } pBt->inCkpt = 0; return rc; } /* ** Rollback the checkpoint to the current transaction. If there ** is no active checkpoint or transaction, this routine is a no-op. ** ** All cursors will be invalided by this operation. Any attempt ** to use a cursor that was open at the beginning of this operation ** will result in an error. */ static int fileBtreeRollbackCkpt(Btree *pBt){ int rc; BtCursor *pCur; if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK; rc = sqlitepager_ckpt_rollback(pBt->pPager); for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->pPage && pCur->pPage->isInit==0 ){ sqlitepager_unref(pCur->pPage); pCur->pPage = 0; } } pBt->inCkpt = 0; return rc; } /* ** Create a new cursor for the BTree whose root is on the page ** iTable. The act of acquiring a cursor gets a read lock on ** the database file. ** ** If wrFlag==0, then the cursor can only be used for reading. ** If wrFlag==1, then the cursor can be used for reading or for ** writing if other conditions for writing are also met. These ** are the conditions that must be met in order for writing to ** be allowed: ** ** 1: The cursor must have been opened with wrFlag==1 ** ** 2: No other cursors may be open with wrFlag==0 on the same table ** ** 3: The database must be writable (not on read-only media) ** ** 4: There must be an active transaction. ** ** Condition 2 warrants further discussion. If any cursor is opened ** on a table with wrFlag==0, that prevents all other cursors from ** writing to that table. This is a kind of "read-lock". When a cursor ** is opened with wrFlag==0 it is guaranteed that the table will not ** change as long as the cursor is open. This allows the cursor to ** do a sequential scan of the table without having to worry about ** entries being inserted or deleted during the scan. Cursors should ** be opened with wrFlag==0 only if this read-lock property is needed. ** That is to say, cursors should be opened with wrFlag==0 only if they ** intend to use the sqliteBtreeNext() system call. All other cursors ** should be opened with wrFlag==1 even if they never really intend ** to write. ** ** No checking is done to make sure that page iTable really is the ** root page of a b-tree. If it is not, then the cursor acquired ** will not work correctly. */ static int fileBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){ int rc; BtCursor *pCur, *pRing; if( pBt->readOnly && wrFlag ){ *ppCur = 0; return SQLITE_READONLY; } if( pBt->page1==0 ){ rc = lockBtree(pBt); if( rc!=SQLITE_OK ){ *ppCur = 0; return rc; } } pCur = sqliteMalloc( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; goto create_cursor_exception; } pCur->pgnoRoot = (Pgno)iTable; rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pCur->pPage); if( rc!=SQLITE_OK ){ goto create_cursor_exception; } rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0); if( rc!=SQLITE_OK ){ goto create_cursor_exception; } pCur->pOps = &sqliteBtreeCursorOps; pCur->pBt = pBt; pCur->wrFlag = wrFlag; pCur->idx = 0; pCur->eSkip = SKIP_INVALID; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pCur->pPrev = 0; pRing = pBt->pCursor; while( pRing && pRing->pgnoRoot!=pCur->pgnoRoot ){ pRing = pRing->pNext; } if( pRing ){ pCur->pShared = pRing->pShared; pRing->pShared = pCur; }else{ pCur->pShared = pCur; } pBt->pCursor = pCur; *ppCur = pCur; return SQLITE_OK; create_cursor_exception: *ppCur = 0; if( pCur ){ if( pCur->pPage ) sqlitepager_unref(pCur->pPage); sqliteFree(pCur); } unlockBtreeIfUnused(pBt); return rc; } /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ static int fileBtreeCloseCursor(BtCursor *pCur){ Btree *pBt = pCur->pBt; if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ pBt->pCursor = pCur->pNext; } if( pCur->pNext ){ pCur->pNext->pPrev = pCur->pPrev; } if( pCur->pPage ){ sqlitepager_unref(pCur->pPage); } if( pCur->pShared!=pCur ){ BtCursor *pRing = pCur->pShared; while( pRing->pShared!=pCur ){ pRing = pRing->pShared; } pRing->pShared = pCur->pShared; } unlockBtreeIfUnused(pBt); sqliteFree(pCur); return SQLITE_OK; } /* ** Make a temporary cursor by filling in the fields of pTempCur. ** The temporary cursor is not on the cursor list for the Btree. */ static void getTempCursor(BtCursor *pCur, BtCursor *pTempCur){ memcpy(pTempCur, pCur, sizeof(*pCur)); pTempCur->pNext = 0; pTempCur->pPrev = 0; if( pTempCur->pPage ){ sqlitepager_ref(pTempCur->pPage); } } /* ** Delete a temporary cursor such as was made by the CreateTemporaryCursor() ** function above. */ static void releaseTempCursor(BtCursor *pCur){ if( pCur->pPage ){ sqlitepager_unref(pCur->pPage); } } /* ** Set *pSize to the number of bytes of key in the entry the ** cursor currently points to. Always return SQLITE_OK. ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ static int fileBtreeKeySize(BtCursor *pCur, int *pSize){ Cell *pCell; MemPage *pPage; pPage = pCur->pPage; assert( pPage!=0 ); if( pCur->idx >= pPage->nCell ){ *pSize = 0; }else{ pCell = pPage->apCell[pCur->idx]; *pSize = NKEY(pCur->pBt, pCell->h); } return SQLITE_OK; } /* ** Read payload information from the entry that the pCur cursor is ** pointing to. Begin reading the payload at "offset" and read ** a total of "amt" bytes. Put the result in zBuf. ** ** This routine does not make a distinction between key and data. ** It just reads bytes from the payload area. */ static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){ char *aPayload; Pgno nextPage; int rc; Btree *pBt = pCur->pBt; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->idx>=0 && pCur->idxpPage->nCell ); aPayload = pCur->pPage->apCell[pCur->idx]->aPayload; if( offsetMX_LOCAL_PAYLOAD ){ a = MX_LOCAL_PAYLOAD - offset; } memcpy(zBuf, &aPayload[offset], a); if( a==amt ){ return SQLITE_OK; } offset = 0; zBuf += a; amt -= a; }else{ offset -= MX_LOCAL_PAYLOAD; } if( amt>0 ){ nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl); } while( amt>0 && nextPage ){ OverflowPage *pOvfl; rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl); if( rc!=0 ){ return rc; } nextPage = SWAB32(pBt, pOvfl->iNext); if( offset OVERFLOW_SIZE ){ a = OVERFLOW_SIZE - offset; } memcpy(zBuf, &pOvfl->aPayload[offset], a); offset = 0; amt -= a; zBuf += a; }else{ offset -= OVERFLOW_SIZE; } sqlitepager_unref(pOvfl); } if( amt>0 ){ return SQLITE_CORRUPT; } return SQLITE_OK; } /* ** Read part of the key associated with cursor pCur. A maximum ** of "amt" bytes will be transfered into zBuf[]. The transfer ** begins at "offset". The number of bytes actually read is ** returned. ** ** Change: It used to be that the amount returned will be smaller ** than the amount requested if there are not enough bytes in the key ** to satisfy the request. But now, it must be the case that there ** is enough data available to satisfy the request. If not, an exception ** is raised. The change was made in an effort to boost performance ** by eliminating unneeded tests. */ static int fileBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){ MemPage *pPage; assert( amt>=0 ); assert( offset>=0 ); assert( pCur->pPage!=0 ); pPage = pCur->pPage; if( pCur->idx >= pPage->nCell ){ return 0; } assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) ); getPayload(pCur, offset, amt, zBuf); return amt; } /* ** Set *pSize to the number of bytes of data in the entry the ** cursor currently points to. Always return SQLITE_OK. ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ static int fileBtreeDataSize(BtCursor *pCur, int *pSize){ Cell *pCell; MemPage *pPage; pPage = pCur->pPage; assert( pPage!=0 ); if( pCur->idx >= pPage->nCell ){ *pSize = 0; }else{ pCell = pPage->apCell[pCur->idx]; *pSize = NDATA(pCur->pBt, pCell->h); } return SQLITE_OK; } /* ** Read part of the data associated with cursor pCur. A maximum ** of "amt" bytes will be transfered into zBuf[]. The transfer ** begins at "offset". The number of bytes actually read is ** returned. The amount returned will be smaller than the ** amount requested if there are not enough bytes in the data ** to satisfy the request. */ static int fileBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){ Cell *pCell; MemPage *pPage; assert( amt>=0 ); assert( offset>=0 ); assert( pCur->pPage!=0 ); pPage = pCur->pPage; if( pCur->idx >= pPage->nCell ){ return 0; } pCell = pPage->apCell[pCur->idx]; assert( amt+offset <= NDATA(pCur->pBt, pCell->h) ); getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf); return amt; } /* ** Compare an external key against the key on the entry that pCur points to. ** ** The external key is pKey and is nKey bytes long. The last nIgnore bytes ** of the key associated with pCur are ignored, as if they do not exist. ** (The normal case is for nIgnore to be zero in which case the entire ** internal key is used in the comparison.) ** ** The comparison result is written to *pRes as follows: ** ** *pRes<0 This means pCur0 This means pCur>pKey ** ** When one key is an exact prefix of the other, the shorter key is ** considered less than the longer one. In order to be equal the ** keys must be exactly the same length. (The length of the pCur key ** is the actual key length minus nIgnore bytes.) */ static int fileBtreeKeyCompare( BtCursor *pCur, /* Pointer to entry to compare against */ const void *pKey, /* Key to compare against entry that pCur points to */ int nKey, /* Number of bytes in pKey */ int nIgnore, /* Ignore this many bytes at the end of pCur */ int *pResult /* Write the result here */ ){ Pgno nextPage; int n, c, rc, nLocal; Cell *pCell; Btree *pBt = pCur->pBt; const char *zKey = (const char*)pKey; assert( pCur->pPage ); assert( pCur->idx>=0 && pCur->idxpPage->nCell ); pCell = pCur->pPage->apCell[pCur->idx]; nLocal = NKEY(pBt, pCell->h) - nIgnore; if( nLocal<0 ) nLocal = 0; n = nKeyMX_LOCAL_PAYLOAD ){ n = MX_LOCAL_PAYLOAD; } c = memcmp(pCell->aPayload, zKey, n); if( c!=0 ){ *pResult = c; return SQLITE_OK; } zKey += n; nKey -= n; nLocal -= n; nextPage = SWAB32(pBt, pCell->ovfl); while( nKey>0 && nLocal>0 ){ OverflowPage *pOvfl; if( nextPage==0 ){ return SQLITE_CORRUPT; } rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl); if( rc ){ return rc; } nextPage = SWAB32(pBt, pOvfl->iNext); n = nKeyOVERFLOW_SIZE ){ n = OVERFLOW_SIZE; } c = memcmp(pOvfl->aPayload, zKey, n); sqlitepager_unref(pOvfl); if( c!=0 ){ *pResult = c; return SQLITE_OK; } nKey -= n; nLocal -= n; zKey += n; } if( c==0 ){ c = nLocal - nKey; } *pResult = c; return SQLITE_OK; } /* ** Move the cursor down to a new child page. The newPgno argument is the ** page number of the child page in the byte order of the disk image. */ static int moveToChild(BtCursor *pCur, int newPgno){ int rc; MemPage *pNewPage; Btree *pBt = pCur->pBt; newPgno = SWAB32(pBt, newPgno); rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage); if( rc ) return rc; rc = initPage(pBt, pNewPage, newPgno, pCur->pPage); if( rc ) return rc; assert( pCur->idx>=pCur->pPage->nCell || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) ); assert( pCur->idxpPage->nCell || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) ); pNewPage->idxParent = pCur->idx; pCur->pPage->idxShift = 0; sqlitepager_unref(pCur->pPage); pCur->pPage = pNewPage; pCur->idx = 0; if( pNewPage->nCell<1 ){ return SQLITE_CORRUPT; } return SQLITE_OK; } /* ** Move the cursor up to the parent page. ** ** pCur->idx is set to the cell index that contains the pointer ** to the page we are coming from. If we are coming from the ** right-most child page then pCur->idx is set to one more than ** the largest cell index. */ static void moveToParent(BtCursor *pCur){ Pgno oldPgno; MemPage *pParent; MemPage *pPage; int idxParent; pPage = pCur->pPage; assert( pPage!=0 ); pParent = pPage->pParent; assert( pParent!=0 ); idxParent = pPage->idxParent; sqlitepager_ref(pParent); sqlitepager_unref(pPage); pCur->pPage = pParent; assert( pParent->idxShift==0 ); if( pParent->idxShift==0 ){ pCur->idx = idxParent; #ifndef NDEBUG /* Verify that pCur->idx is the correct index to point back to the child ** page we just came from */ oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage)); if( pCur->idxnCell ){ assert( pParent->apCell[idxParent]->h.leftChild==oldPgno ); }else{ assert( pParent->u.hdr.rightChild==oldPgno ); } #endif }else{ /* The MemPage.idxShift flag indicates that cell indices might have ** changed since idxParent was set and hence idxParent might be out ** of date. So recompute the parent cell index by scanning all cells ** and locating the one that points to the child we just came from. */ int i; pCur->idx = pParent->nCell; oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage)); for(i=0; inCell; i++){ if( pParent->apCell[i]->h.leftChild==oldPgno ){ pCur->idx = i; break; } } } } /* ** Move the cursor to the root page */ static int moveToRoot(BtCursor *pCur){ MemPage *pNew; int rc; Btree *pBt = pCur->pBt; rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew); if( rc ) return rc; rc = initPage(pBt, pNew, pCur->pgnoRoot, 0); if( rc ) return rc; sqlitepager_unref(pCur->pPage); pCur->pPage = pNew; pCur->idx = 0; return SQLITE_OK; } /* ** Move the cursor down to the left-most leaf entry beneath the ** entry to which it is currently pointing. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc; while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){ rc = moveToChild(pCur, pgno); if( rc ) return rc; } return SQLITE_OK; } /* ** Move the cursor down to the right-most leaf entry beneath the ** page to which it is currently pointing. Notice the difference ** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() ** finds the left-most entry beneath the *entry* whereas moveToRightmost() ** finds the right-most entry beneath the *page*. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc; while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){ pCur->idx = pCur->pPage->nCell; rc = moveToChild(pCur, pgno); if( rc ) return rc; } pCur->idx = pCur->pPage->nCell - 1; return SQLITE_OK; } /* Move the cursor to the first entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ static int fileBtreeFirst(BtCursor *pCur, int *pRes){ int rc; if( pCur->pPage==0 ) return SQLITE_ABORT; rc = moveToRoot(pCur); if( rc ) return rc; if( pCur->pPage->nCell==0 ){ *pRes = 1; return SQLITE_OK; } *pRes = 0; rc = moveToLeftmost(pCur); pCur->eSkip = SKIP_NONE; return rc; } /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ static int fileBtreeLast(BtCursor *pCur, int *pRes){ int rc; if( pCur->pPage==0 ) return SQLITE_ABORT; rc = moveToRoot(pCur); if( rc ) return rc; assert( pCur->pPage->isInit ); if( pCur->pPage->nCell==0 ){ *pRes = 1; return SQLITE_OK; } *pRes = 0; rc = moveToRightmost(pCur); pCur->eSkip = SKIP_NONE; return rc; } /* Move the cursor so that it points to an entry near pKey. ** Return a success code. ** ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it ** were present. The cursor might point to an entry that comes ** before or after the key. ** ** The result of comparing the key with the entry to which the ** cursor is left pointing is stored in pCur->iMatch. The same ** value is also written to *pRes if pRes!=NULL. The meaning of ** this value is as follows: ** ** *pRes<0 The cursor is left pointing at an entry that ** is smaller than pKey or if the table is empty ** and the cursor is therefore left point to nothing. ** ** *pRes==0 The cursor is left pointing at an entry that ** exactly matches pKey. ** ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pKey. */ static int fileBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){ int rc; if( pCur->pPage==0 ) return SQLITE_ABORT; pCur->eSkip = SKIP_NONE; rc = moveToRoot(pCur); if( rc ) return rc; for(;;){ int lwr, upr; Pgno chldPg; MemPage *pPage = pCur->pPage; int c = -1; /* pRes return if table is empty must be -1 */ lwr = 0; upr = pPage->nCell-1; while( lwr<=upr ){ pCur->idx = (lwr+upr)/2; rc = fileBtreeKeyCompare(pCur, pKey, nKey, 0, &c); if( rc ) return rc; if( c==0 ){ pCur->iMatch = c; if( pRes ) *pRes = 0; return SQLITE_OK; } if( c<0 ){ lwr = pCur->idx+1; }else{ upr = pCur->idx-1; } } assert( lwr==upr+1 ); assert( pPage->isInit ); if( lwr>=pPage->nCell ){ chldPg = pPage->u.hdr.rightChild; }else{ chldPg = pPage->apCell[lwr]->h.leftChild; } if( chldPg==0 ){ pCur->iMatch = c; if( pRes ) *pRes = c; return SQLITE_OK; } pCur->idx = lwr; rc = moveToChild(pCur, chldPg); if( rc ) return rc; } /* NOT REACHED */ } /* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. */ static int fileBtreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage = pCur->pPage; assert( pRes!=0 ); if( pPage==0 ){ *pRes = 1; return SQLITE_ABORT; } assert( pPage->isInit ); assert( pCur->eSkip!=SKIP_INVALID ); if( pPage->nCell==0 ){ *pRes = 1; return SQLITE_OK; } assert( pCur->idxnCell ); if( pCur->eSkip==SKIP_NEXT ){ pCur->eSkip = SKIP_NONE; *pRes = 0; return SQLITE_OK; } pCur->eSkip = SKIP_NONE; pCur->idx++; if( pCur->idx>=pPage->nCell ){ if( pPage->u.hdr.rightChild ){ rc = moveToChild(pCur, pPage->u.hdr.rightChild); if( rc ) return rc; rc = moveToLeftmost(pCur); *pRes = 0; return rc; } do{ if( pPage->pParent==0 ){ *pRes = 1; return SQLITE_OK; } moveToParent(pCur); pPage = pCur->pPage; }while( pCur->idx>=pPage->nCell ); *pRes = 0; return SQLITE_OK; } *pRes = 0; if( pPage->u.hdr.rightChild==0 ){ return SQLITE_OK; } rc = moveToLeftmost(pCur); return rc; } /* ** Step the cursor to the back to the previous entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1. */ static int fileBtreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; pPage = pCur->pPage; if( pPage==0 ){ *pRes = 1; return SQLITE_ABORT; } assert( pPage->isInit ); assert( pCur->eSkip!=SKIP_INVALID ); if( pPage->nCell==0 ){ *pRes = 1; return SQLITE_OK; } if( pCur->eSkip==SKIP_PREV ){ pCur->eSkip = SKIP_NONE; *pRes = 0; return SQLITE_OK; } pCur->eSkip = SKIP_NONE; assert( pCur->idx>=0 ); if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){ rc = moveToChild(pCur, pgno); if( rc ) return rc; rc = moveToRightmost(pCur); }else{ while( pCur->idx==0 ){ if( pPage->pParent==0 ){ if( pRes ) *pRes = 1; return SQLITE_OK; } moveToParent(pCur); pPage = pCur->pPage; } pCur->idx--; rc = SQLITE_OK; } *pRes = 0; return rc; } /* ** Allocate a new page from the database file. ** ** The new page is marked as dirty. (In other words, sqlitepager_write() ** has already been called on the new page.) The new page has also ** been referenced and the calling routine is responsible for calling ** sqlitepager_unref() on the new page when it is done. ** ** SQLITE_OK is returned on success. Any other return value indicates ** an error. *ppPage and *pPgno are undefined in the event of an error. ** Do not invoke sqlitepager_unref() on *ppPage if an error is returned. ** ** If the "nearby" parameter is not 0, then a (feeble) effort is made to ** locate a page close to the page number "nearby". This can be used in an ** attempt to keep related pages close to each other in the database file, ** which in turn can make database access faster. */ static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){ PageOne *pPage1 = pBt->page1; int rc; if( pPage1->freeList ){ OverflowPage *pOvfl; FreelistInfo *pInfo; rc = sqlitepager_write(pPage1); if( rc ) return rc; SWAB_ADD(pBt, pPage1->nFree, -1); rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList), (void**)&pOvfl); if( rc ) return rc; rc = sqlitepager_write(pOvfl); if( rc ){ sqlitepager_unref(pOvfl); return rc; } pInfo = (FreelistInfo*)pOvfl->aPayload; if( pInfo->nFree==0 ){ *pPgno = SWAB32(pBt, pPage1->freeList); pPage1->freeList = pOvfl->iNext; *ppPage = (MemPage*)pOvfl; }else{ int closest, n; n = SWAB32(pBt, pInfo->nFree); if( n>1 && nearby>0 ){ int i, dist; closest = 0; dist = SWAB32(pBt, pInfo->aFree[0]) - nearby; if( dist<0 ) dist = -dist; for(i=1; iaFree[i]) - nearby; if( d2<0 ) d2 = -d2; if( d2nFree, -1); *pPgno = SWAB32(pBt, pInfo->aFree[closest]); pInfo->aFree[closest] = pInfo->aFree[n-1]; rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage); sqlitepager_unref(pOvfl); if( rc==SQLITE_OK ){ sqlitepager_dont_rollback(*ppPage); rc = sqlitepager_write(*ppPage); } } }else{ *pPgno = sqlitepager_pagecount(pBt->pPager) + 1; rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage); if( rc ) return rc; rc = sqlitepager_write(*ppPage); } return rc; } /* ** Add a page of the database file to the freelist. Either pgno or ** pPage but not both may be 0. ** ** sqlitepager_unref() is NOT called for pPage. */ static int freePage(Btree *pBt, void *pPage, Pgno pgno){ PageOne *pPage1 = pBt->page1; OverflowPage *pOvfl = (OverflowPage*)pPage; int rc; int needUnref = 0; MemPage *pMemPage; if( pgno==0 ){ assert( pOvfl!=0 ); pgno = sqlitepager_pagenumber(pOvfl); } assert( pgno>2 ); assert( sqlitepager_pagenumber(pOvfl)==pgno ); pMemPage = (MemPage*)pPage; pMemPage->isInit = 0; if( pMemPage->pParent ){ sqlitepager_unref(pMemPage->pParent); pMemPage->pParent = 0; } rc = sqlitepager_write(pPage1); if( rc ){ return rc; } SWAB_ADD(pBt, pPage1->nFree, 1); if( pPage1->nFree!=0 && pPage1->freeList!=0 ){ OverflowPage *pFreeIdx; rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList), (void**)&pFreeIdx); if( rc==SQLITE_OK ){ FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload; int n = SWAB32(pBt, pInfo->nFree); if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){ rc = sqlitepager_write(pFreeIdx); if( rc==SQLITE_OK ){ pInfo->aFree[n] = SWAB32(pBt, pgno); SWAB_ADD(pBt, pInfo->nFree, 1); sqlitepager_unref(pFreeIdx); sqlitepager_dont_write(pBt->pPager, pgno); return rc; } } sqlitepager_unref(pFreeIdx); } } if( pOvfl==0 ){ assert( pgno>0 ); rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pOvfl); if( rc ) return rc; needUnref = 1; } rc = sqlitepager_write(pOvfl); if( rc ){ if( needUnref ) sqlitepager_unref(pOvfl); return rc; } pOvfl->iNext = pPage1->freeList; pPage1->freeList = SWAB32(pBt, pgno); memset(pOvfl->aPayload, 0, OVERFLOW_SIZE); if( needUnref ) rc = sqlitepager_unref(pOvfl); return rc; } /* ** Erase all the data out of a cell. This involves returning overflow ** pages back the freelist. */ static int clearCell(Btree *pBt, Cell *pCell){ Pager *pPager = pBt->pPager; OverflowPage *pOvfl; Pgno ovfl, nextOvfl; int rc; if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){ return SQLITE_OK; } ovfl = SWAB32(pBt, pCell->ovfl); pCell->ovfl = 0; while( ovfl ){ rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl); if( rc ) return rc; nextOvfl = SWAB32(pBt, pOvfl->iNext); rc = freePage(pBt, pOvfl, ovfl); if( rc ) return rc; sqlitepager_unref(pOvfl); ovfl = nextOvfl; } return SQLITE_OK; } /* ** Create a new cell from key and data. Overflow pages are allocated as ** necessary and linked to this cell. */ static int fillInCell( Btree *pBt, /* The whole Btree. Needed to allocate pages */ Cell *pCell, /* Populate this Cell structure */ const void *pKey, int nKey, /* The key */ const void *pData,int nData /* The data */ ){ OverflowPage *pOvfl, *pPrior; Pgno *pNext; int spaceLeft; int n, rc; int nPayload; const char *pPayload; char *pSpace; Pgno nearby = 0; pCell->h.leftChild = 0; pCell->h.nKey = SWAB16(pBt, nKey & 0xffff); pCell->h.nKeyHi = nKey >> 16; pCell->h.nData = SWAB16(pBt, nData & 0xffff); pCell->h.nDataHi = nData >> 16; pCell->h.iNext = 0; pNext = &pCell->ovfl; pSpace = pCell->aPayload; spaceLeft = MX_LOCAL_PAYLOAD; pPayload = pKey; pKey = 0; nPayload = nKey; pPrior = 0; while( nPayload>0 ){ if( spaceLeft==0 ){ rc = allocatePage(pBt, (MemPage**)&pOvfl, pNext, nearby); if( rc ){ *pNext = 0; }else{ nearby = *pNext; } if( pPrior ) sqlitepager_unref(pPrior); if( rc ){ clearCell(pBt, pCell); return rc; } if( pBt->needSwab ) *pNext = swab32(*pNext); pPrior = pOvfl; spaceLeft = OVERFLOW_SIZE; pSpace = pOvfl->aPayload; pNext = &pOvfl->iNext; } n = nPayload; if( n>spaceLeft ) n = spaceLeft; memcpy(pSpace, pPayload, n); nPayload -= n; if( nPayload==0 && pData ){ pPayload = pData; nPayload = nData; pData = 0; }else{ pPayload += n; } spaceLeft -= n; pSpace += n; } *pNext = 0; if( pPrior ){ sqlitepager_unref(pPrior); } return SQLITE_OK; } /* ** Change the MemPage.pParent pointer on the page whose number is ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){ MemPage *pThis; if( pgno==0 ) return; assert( pPager!=0 ); pThis = sqlitepager_lookup(pPager, pgno); if( pThis && pThis->isInit ){ if( pThis->pParent!=pNewParent ){ if( pThis->pParent ) sqlitepager_unref(pThis->pParent); pThis->pParent = pNewParent; if( pNewParent ) sqlitepager_ref(pNewParent); } pThis->idxParent = idx; sqlitepager_unref(pThis); } } /* ** Reparent all children of the given page to be the given page. ** In other words, for every child of pPage, invoke reparentPage() ** to make sure that each child knows that pPage is its parent. ** ** This routine gets called after you memcpy() one page into ** another. */ static void reparentChildPages(Btree *pBt, MemPage *pPage){ int i; Pager *pPager = pBt->pPager; for(i=0; inCell; i++){ reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i); } reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i); pPage->idxShift = 0; } /* ** Remove the i-th cell from pPage. This routine effects pPage only. ** The cell content is not freed or deallocated. It is assumed that ** the cell content has been copied someplace else. This routine just ** removes the reference to the cell from pPage. ** ** "sz" must be the number of bytes in the cell. ** ** Do not bother maintaining the integrity of the linked list of Cells. ** Only the pPage->apCell[] array is important. The relinkCellList() ** routine will be called soon after this routine in order to rebuild ** the linked list. */ static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){ int j; assert( idx>=0 && idxnCell ); assert( sz==cellSize(pBt, pPage->apCell[idx]) ); assert( sqlitepager_iswriteable(pPage) ); freeSpace(pBt, pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz); for(j=idx; jnCell-1; j++){ pPage->apCell[j] = pPage->apCell[j+1]; } pPage->nCell--; pPage->idxShift = 1; } /* ** Insert a new cell on pPage at cell index "i". pCell points to the ** content of the cell. ** ** If the cell content will fit on the page, then put it there. If it ** will not fit, then just make pPage->apCell[i] point to the content ** and set pPage->isOverfull. ** ** Do not bother maintaining the integrity of the linked list of Cells. ** Only the pPage->apCell[] array is important. The relinkCellList() ** routine will be called soon after this routine in order to rebuild ** the linked list. */ static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){ int idx, j; assert( i>=0 && i<=pPage->nCell ); assert( sz==cellSize(pBt, pCell) ); assert( sqlitepager_iswriteable(pPage) ); idx = allocateSpace(pBt, pPage, sz); for(j=pPage->nCell; j>i; j--){ pPage->apCell[j] = pPage->apCell[j-1]; } pPage->nCell++; if( idx<=0 ){ pPage->isOverfull = 1; pPage->apCell[i] = pCell; }else{ memcpy(&pPage->u.aDisk[idx], pCell, sz); pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx]; } pPage->idxShift = 1; } /* ** Rebuild the linked list of cells on a page so that the cells ** occur in the order specified by the pPage->apCell[] array. ** Invoke this routine once to repair damage after one or more ** invocations of either insertCell() or dropCell(). */ static void relinkCellList(Btree *pBt, MemPage *pPage){ int i; u16 *pIdx; assert( sqlitepager_iswriteable(pPage) ); pIdx = &pPage->u.hdr.firstCell; for(i=0; inCell; i++){ int idx = Addr(pPage->apCell[i]) - Addr(pPage); assert( idx>0 && idxapCell[i]->h.iNext; } *pIdx = 0; } /* ** Make a copy of the contents of pFrom into pTo. The pFrom->apCell[] ** pointers that point into pFrom->u.aDisk[] must be adjusted to point ** into pTo->u.aDisk[] instead. But some pFrom->apCell[] entries might ** not point to pFrom->u.aDisk[]. Those are unchanged. */ static void copyPage(MemPage *pTo, MemPage *pFrom){ uptr from, to; int i; memcpy(pTo->u.aDisk, pFrom->u.aDisk, SQLITE_USABLE_SIZE); pTo->pParent = 0; pTo->isInit = 1; pTo->nCell = pFrom->nCell; pTo->nFree = pFrom->nFree; pTo->isOverfull = pFrom->isOverfull; to = Addr(pTo); from = Addr(pFrom); for(i=0; inCell; i++){ uptr x = Addr(pFrom->apCell[i]); if( x>from && xapCell[i]) = x + to - from; }else{ pTo->apCell[i] = pFrom->apCell[i]; } } } /* ** The following parameters determine how many adjacent pages get involved ** in a balancing operation. NN is the number of neighbors on either side ** of the page that participate in the balancing operation. NB is the ** total number of pages that participate, including the target page and ** NN neighbors on either side. ** ** The minimum value of NN is 1 (of course). Increasing NN above 1 ** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance ** in exchange for a larger degradation in INSERT and UPDATE performance. ** The value of NN appears to give the best results overall. */ #define NN 1 /* Number of neighbors on either side of pPage */ #define NB (NN*2+1) /* Total pages involved in the balance */ /* ** This routine redistributes Cells on pPage and up to two siblings ** of pPage so that all pages have about the same amount of free space. ** Usually one sibling on either side of pPage is used in the balancing, ** though both siblings might come from one side if pPage is the first ** or last child of its parent. If pPage has fewer than two siblings ** (something which can only happen if pPage is the root page or a ** child of root) then all available siblings participate in the balancing. ** ** The number of siblings of pPage might be increased or decreased by ** one in an effort to keep pages between 66% and 100% full. The root page ** is special and is allowed to be less than 66% full. If pPage is ** the root page, then the depth of the tree might be increased ** or decreased by one, as necessary, to keep the root page from being ** overfull or empty. ** ** This routine calls relinkCellList() on its input page regardless of ** whether or not it does any real balancing. Client routines will typically ** invoke insertCell() or dropCell() before calling this routine, so we ** need to call relinkCellList() to clean up the mess that those other ** routines left behind. ** ** pCur is left pointing to the same cell as when this routine was called ** even if that cell gets moved to a different page. pCur may be NULL. ** Set the pCur parameter to NULL if you do not care about keeping track ** of a cell as that will save this routine the work of keeping track of it. ** ** Note that when this routine is called, some of the Cells on pPage ** might not actually be stored in pPage->u.aDisk[]. This can happen ** if the page is overfull. Part of the job of this routine is to ** make sure all Cells for pPage once again fit in pPage->u.aDisk[]. ** ** In the course of balancing the siblings of pPage, the parent of pPage ** might become overfull or underfull. If that happens, then this routine ** is called recursively on the parent. ** ** If this routine fails for any reason, it might leave the database ** in a corrupted state. So if this routine fails, the database should ** be rolled back. */ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){ MemPage *pParent; /* The parent of pPage */ int nCell; /* Number of cells in apCell[] */ int nOld; /* Number of pages in apOld[] */ int nNew; /* Number of pages in apNew[] */ int nDiv; /* Number of cells in apDiv[] */ int i, j, k; /* Loop counters */ int idx; /* Index of pPage in pParent->apCell[] */ int nxDiv; /* Next divider slot in pParent->apCell[] */ int rc; /* The return code */ int iCur; /* apCell[iCur] is the cell of the cursor */ MemPage *pOldCurPage; /* The cursor originally points to this page */ int subtotal; /* Subtotal of bytes in cells on one page */ MemPage *extraUnref = 0; /* A page that needs to be unref-ed */ MemPage *apOld[NB]; /* pPage and up to two siblings */ Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */ MemPage *apNew[NB+1]; /* pPage and up to NB siblings after balancing */ Pgno pgnoNew[NB+1]; /* Page numbers for each page in apNew[] */ int idxDiv[NB]; /* Indices of divider cells in pParent */ Cell *apDiv[NB]; /* Divider cells in pParent */ Cell aTemp[NB]; /* Temporary holding area for apDiv[] */ int cntNew[NB+1]; /* Index in apCell[] of cell after i-th page */ int szNew[NB+1]; /* Combined size of cells place on i-th page */ MemPage aOld[NB]; /* Temporary copies of pPage and its siblings */ Cell *apCell[(MX_CELL+2)*NB]; /* All cells from pages being balanced */ int szCell[(MX_CELL+2)*NB]; /* Local size of all cells */ /* ** Return without doing any work if pPage is neither overfull nor ** underfull. */ assert( sqlitepager_iswriteable(pPage) ); if( !pPage->isOverfull && pPage->nFreenCell>=2){ relinkCellList(pBt, pPage); return SQLITE_OK; } /* ** Find the parent of the page to be balanceed. ** If there is no parent, it means this page is the root page and ** special rules apply. */ pParent = pPage->pParent; if( pParent==0 ){ Pgno pgnoChild; MemPage *pChild; assert( pPage->isInit ); if( pPage->nCell==0 ){ if( pPage->u.hdr.rightChild ){ /* ** The root page is empty. Copy the one child page ** into the root page and return. This reduces the depth ** of the BTree by one. */ pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild); rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild); if( rc ) return rc; memcpy(pPage, pChild, SQLITE_USABLE_SIZE); pPage->isInit = 0; rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0); assert( rc==SQLITE_OK ); reparentChildPages(pBt, pPage); if( pCur && pCur->pPage==pChild ){ sqlitepager_unref(pChild); pCur->pPage = pPage; sqlitepager_ref(pPage); } freePage(pBt, pChild, pgnoChild); sqlitepager_unref(pChild); }else{ relinkCellList(pBt, pPage); } return SQLITE_OK; } if( !pPage->isOverfull ){ /* It is OK for the root page to be less than half full. */ relinkCellList(pBt, pPage); return SQLITE_OK; } /* ** If we get to here, it means the root page is overfull. ** When this happens, Create a new child page and copy the ** contents of the root into the child. Then make the root ** page an empty page with rightChild pointing to the new ** child. Then fall thru to the code below which will cause ** the overfull child page to be split. */ rc = sqlitepager_write(pPage); if( rc ) return rc; rc = allocatePage(pBt, &pChild, &pgnoChild, sqlitepager_pagenumber(pPage)); if( rc ) return rc; assert( sqlitepager_iswriteable(pChild) ); copyPage(pChild, pPage); pChild->pParent = pPage; pChild->idxParent = 0; sqlitepager_ref(pPage); pChild->isOverfull = 1; if( pCur && pCur->pPage==pPage ){ sqlitepager_unref(pPage); pCur->pPage = pChild; }else{ extraUnref = pChild; } zeroPage(pBt, pPage); pPage->u.hdr.rightChild = SWAB32(pBt, pgnoChild); pParent = pPage; pPage = pChild; } rc = sqlitepager_write(pParent); if( rc ) return rc; assert( pParent->isInit ); /* ** Find the Cell in the parent page whose h.leftChild points back ** to pPage. The "idx" variable is the index of that cell. If pPage ** is the rightmost child of pParent then set idx to pParent->nCell */ if( pParent->idxShift ){ Pgno pgno, swabPgno; pgno = sqlitepager_pagenumber(pPage); swabPgno = SWAB32(pBt, pgno); for(idx=0; idxnCell; idx++){ if( pParent->apCell[idx]->h.leftChild==swabPgno ){ break; } } assert( idxnCell || pParent->u.hdr.rightChild==swabPgno ); }else{ idx = pPage->idxParent; } /* ** Initialize variables so that it will be safe to jump ** directly to balance_cleanup at any moment. */ nOld = nNew = 0; sqlitepager_ref(pParent); /* ** Find sibling pages to pPage and the Cells in pParent that divide ** the siblings. An attempt is made to find NN siblings on either ** side of pPage. More siblings are taken from one side, however, if ** pPage there are fewer than NN siblings on the other side. If pParent ** has NB or fewer children then all children of pParent are taken. */ nxDiv = idx - NN; if( nxDiv + NB > pParent->nCell ){ nxDiv = pParent->nCell - NB + 1; } if( nxDiv<0 ){ nxDiv = 0; } nDiv = 0; for(i=0, k=nxDiv; inCell ){ idxDiv[i] = k; apDiv[i] = pParent->apCell[k]; nDiv++; pgnoOld[i] = SWAB32(pBt, apDiv[i]->h.leftChild); }else if( k==pParent->nCell ){ pgnoOld[i] = SWAB32(pBt, pParent->u.hdr.rightChild); }else{ break; } rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]); if( rc ) goto balance_cleanup; rc = initPage(pBt, apOld[i], pgnoOld[i], pParent); if( rc ) goto balance_cleanup; apOld[i]->idxParent = k; nOld++; } /* ** Set iCur to be the index in apCell[] of the cell that the cursor ** is pointing to. We will need this later on in order to keep the ** cursor pointing at the same cell. If pCur points to a page that ** has no involvement with this rebalancing, then set iCur to a large ** number so that the iCur==j tests always fail in the main cell ** distribution loop below. */ if( pCur ){ iCur = 0; for(i=0; ipPage==apOld[i] ){ iCur += pCur->idx; break; } iCur += apOld[i]->nCell; if( ipPage==pParent && pCur->idx==idxDiv[i] ){ break; } iCur++; } pOldCurPage = pCur->pPage; } /* ** Make copies of the content of pPage and its siblings into aOld[]. ** The rest of this function will use data from the copies rather ** that the original pages since the original pages will be in the ** process of being overwritten. */ for(i=0; inCell; j++){ apCell[nCell] = pOld->apCell[j]; szCell[nCell] = cellSize(pBt, apCell[nCell]); nCell++; } if( ih.leftChild)==pgnoOld[i] ); apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild; nCell++; } } /* ** Figure out the number of pages needed to hold all nCell cells. ** Store this number in "k". Also compute szNew[] which is the total ** size of all cells on the i-th page and cntNew[] which is the index ** in apCell[] of the cell that divides path i from path i+1. ** cntNew[k] should equal nCell. ** ** This little patch of code is critical for keeping the tree ** balanced. */ for(subtotal=k=i=0; i USABLE_SPACE ){ szNew[k] = subtotal - szCell[i]; cntNew[k] = i; subtotal = 0; k++; } } szNew[k] = subtotal; cntNew[k] = nCell; k++; for(i=k-1; i>0; i--){ while( szNew[i]0 ); szNew[i] += szCell[cntNew[i-1]]; szNew[i-1] -= szCell[cntNew[i-1]-1]; } } assert( cntNew[0]>0 ); /* ** Allocate k new pages. Reuse old pages where possible. */ for(i=0; iisInit = 1; } /* Free any old pages that were not reused as new pages. */ while( ii ){ int t; MemPage *pT; t = pgnoNew[i]; pT = apNew[i]; pgnoNew[i] = pgnoNew[minI]; apNew[i] = apNew[minI]; pgnoNew[minI] = t; apNew[minI] = pT; } } /* ** Evenly distribute the data in apCell[] across the new pages. ** Insert divider cells into pParent as necessary. */ j = 0; for(i=0; inFree>=szCell[j] ); if( pCur && iCur==j ){ pCur->pPage = pNew; pCur->idx = pNew->nCell; } insertCell(pBt, pNew, pNew->nCell, apCell[j], szCell[j]); j++; } assert( pNew->nCell>0 ); assert( !pNew->isOverfull ); relinkCellList(pBt, pNew); if( iu.hdr.rightChild = apCell[j]->h.leftChild; apCell[j]->h.leftChild = SWAB32(pBt, pgnoNew[i]); if( pCur && iCur==j ){ pCur->pPage = pParent; pCur->idx = nxDiv; } insertCell(pBt, pParent, nxDiv, apCell[j], szCell[j]); j++; nxDiv++; } } assert( j==nCell ); apNew[nNew-1]->u.hdr.rightChild = aOld[nOld-1].u.hdr.rightChild; if( nxDiv==pParent->nCell ){ pParent->u.hdr.rightChild = SWAB32(pBt, pgnoNew[nNew-1]); }else{ pParent->apCell[nxDiv]->h.leftChild = SWAB32(pBt, pgnoNew[nNew-1]); } if( pCur ){ if( j<=iCur && pCur->pPage==pParent && pCur->idx>idxDiv[nOld-1] ){ assert( pCur->pPage==pOldCurPage ); pCur->idx += nNew - nOld; }else{ assert( pOldCurPage!=0 ); sqlitepager_ref(pCur->pPage); sqlitepager_unref(pOldCurPage); } } /* ** Reparent children of all cells. */ for(i=0; ipPage==0 ){ pCur->pPage = pParent; pCur->idx = 0; }else{ sqlitepager_unref(pParent); } return rc; } /* ** This routine checks all cursors that point to the same table ** as pCur points to. If any of those cursors were opened with ** wrFlag==0 then this routine returns SQLITE_LOCKED. If all ** cursors point to the same table were opened with wrFlag==1 ** then this routine returns SQLITE_OK. ** ** In addition to checking for read-locks (where a read-lock ** means a cursor opened with wrFlag==0) this routine also moves ** all cursors other than pCur so that they are pointing to the ** first Cell on root page. This is necessary because an insert ** or delete might change the number of cells on a page or delete ** a page entirely and we do not want to leave any cursors ** pointing to non-existant pages or cells. */ static int checkReadLocks(BtCursor *pCur){ BtCursor *p; assert( pCur->wrFlag ); for(p=pCur->pShared; p!=pCur; p=p->pShared){ assert( p ); assert( p->pgnoRoot==pCur->pgnoRoot ); if( p->wrFlag==0 ) return SQLITE_LOCKED; if( sqlitepager_pagenumber(p->pPage)!=p->pgnoRoot ){ moveToRoot(p); } } return SQLITE_OK; } /* ** Insert a new record into the BTree. The key is given by (pKey,nKey) ** and the data is given by (pData,nData). The cursor is used only to ** define what database the record should be inserted into. The cursor ** is left pointing at the new record. */ static int fileBtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ const void *pKey, int nKey, /* The key of the new record */ const void *pData, int nData /* The data of the new record */ ){ Cell newCell; int rc; int loc; int szNew; MemPage *pPage; Btree *pBt = pCur->pBt; if( pCur->pPage==0 ){ return SQLITE_ABORT; /* A rollback destroyed this cursor */ } if( !pBt->inTrans || nKey+nData==0 ){ /* Must start a transaction before doing an insert */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( !pBt->readOnly ); if( !pCur->wrFlag ){ return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } rc = fileBtreeMoveto(pCur, pKey, nKey, &loc); if( rc ) return rc; pPage = pCur->pPage; assert( pPage->isInit ); rc = sqlitepager_write(pPage); if( rc ) return rc; rc = fillInCell(pBt, &newCell, pKey, nKey, pData, nData); if( rc ) return rc; szNew = cellSize(pBt, &newCell); if( loc==0 ){ newCell.h.leftChild = pPage->apCell[pCur->idx]->h.leftChild; rc = clearCell(pBt, pPage->apCell[pCur->idx]); if( rc ) return rc; dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pPage->apCell[pCur->idx])); }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */ pCur->idx++; }else{ assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */ } insertCell(pBt, pPage, pCur->idx, &newCell, szNew); rc = balance(pCur->pBt, pPage, pCur); /* sqliteBtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ /* fflush(stdout); */ pCur->eSkip = SKIP_INVALID; return rc; } /* ** Delete the entry that the cursor is pointing to. ** ** The cursor is left pointing at either the next or the previous ** entry. If the cursor is left pointing to the next entry, then ** the pCur->eSkip flag is set to SKIP_NEXT which forces the next call to ** sqliteBtreeNext() to be a no-op. That way, you can always call ** sqliteBtreeNext() after a delete and the cursor will be left ** pointing to the first entry after the deleted entry. Similarly, ** pCur->eSkip is set to SKIP_PREV is the cursor is left pointing to ** the entry prior to the deleted entry so that a subsequent call to ** sqliteBtreePrevious() will always leave the cursor pointing at the ** entry immediately before the one that was deleted. */ static int fileBtreeDelete(BtCursor *pCur){ MemPage *pPage = pCur->pPage; Cell *pCell; int rc; Pgno pgnoChild; Btree *pBt = pCur->pBt; assert( pPage->isInit ); if( pCur->pPage==0 ){ return SQLITE_ABORT; /* A rollback destroyed this cursor */ } if( !pBt->inTrans ){ /* Must start a transaction before doing a delete */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } assert( !pBt->readOnly ); if( pCur->idx >= pPage->nCell ){ return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ return SQLITE_PERM; /* Did not open this cursor for writing */ } if( checkReadLocks(pCur) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } rc = sqlitepager_write(pPage); if( rc ) return rc; pCell = pPage->apCell[pCur->idx]; pgnoChild = SWAB32(pBt, pCell->h.leftChild); clearCell(pBt, pCell); if( pgnoChild ){ /* ** The entry we are about to delete is not a leaf so if we do not ** do something we will leave a hole on an internal page. ** We have to fill the hole by moving in a cell from a leaf. The ** next Cell after the one to be deleted is guaranteed to exist and ** to be a leaf so we can use it. */ BtCursor leafCur; Cell *pNext; int szNext; int notUsed; getTempCursor(pCur, &leafCur); rc = fileBtreeNext(&leafCur, ¬Used); if( rc!=SQLITE_OK ){ if( rc!=SQLITE_NOMEM ) rc = SQLITE_CORRUPT; return rc; } rc = sqlitepager_write(leafCur.pPage); if( rc ) return rc; dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell)); pNext = leafCur.pPage->apCell[leafCur.idx]; szNext = cellSize(pBt, pNext); pNext->h.leftChild = SWAB32(pBt, pgnoChild); insertCell(pBt, pPage, pCur->idx, pNext, szNext); rc = balance(pBt, pPage, pCur); if( rc ) return rc; pCur->eSkip = SKIP_NEXT; dropCell(pBt, leafCur.pPage, leafCur.idx, szNext); rc = balance(pBt, leafCur.pPage, pCur); releaseTempCursor(&leafCur); }else{ dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell)); if( pCur->idx>=pPage->nCell ){ pCur->idx = pPage->nCell-1; if( pCur->idx<0 ){ pCur->idx = 0; pCur->eSkip = SKIP_NEXT; }else{ pCur->eSkip = SKIP_PREV; } }else{ pCur->eSkip = SKIP_NEXT; } rc = balance(pBt, pPage, pCur); } return rc; } /* ** Create a new BTree table. Write into *piTable the page ** number for the root page of the new table. ** ** In the current implementation, BTree tables and BTree indices are the ** the same. In the future, we may change this so that BTree tables ** are restricted to having a 4-byte integer key and arbitrary data and ** BTree indices are restricted to having an arbitrary key and no data. ** But for now, this routine also serves to create indices. */ static int fileBtreeCreateTable(Btree *pBt, int *piTable){ MemPage *pRoot; Pgno pgnoRoot; int rc; if( !pBt->inTrans ){ /* Must start a transaction first */ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } if( pBt->readOnly ){ return SQLITE_READONLY; } rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0); if( rc ) return rc; assert( sqlitepager_iswriteable(pRoot) ); zeroPage(pBt, pRoot); sqlitepager_unref(pRoot); *piTable = (int)pgnoRoot; return SQLITE_OK; } /* ** Erase the given database page and all its children. Return ** the page to the freelist. */ static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){ MemPage *pPage; int rc; Cell *pCell; int idx; rc = sqlitepager_get(pBt->pPager, pgno, (void**)&pPage); if( rc ) return rc; rc = sqlitepager_write(pPage); if( rc ) return rc; rc = initPage(pBt, pPage, pgno, 0); if( rc ) return rc; idx = SWAB16(pBt, pPage->u.hdr.firstCell); while( idx>0 ){ pCell = (Cell*)&pPage->u.aDisk[idx]; idx = SWAB16(pBt, pCell->h.iNext); if( pCell->h.leftChild ){ rc = clearDatabasePage(pBt, SWAB32(pBt, pCell->h.leftChild), 1); if( rc ) return rc; } rc = clearCell(pBt, pCell); if( rc ) return rc; } if( pPage->u.hdr.rightChild ){ rc = clearDatabasePage(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1); if( rc ) return rc; } if( freePageFlag ){ rc = freePage(pBt, pPage, pgno); }else{ zeroPage(pBt, pPage); } sqlitepager_unref(pPage); return rc; } /* ** Delete all information from a single table in the database. */ static int fileBtreeClearTable(Btree *pBt, int iTable){ int rc; BtCursor *pCur; if( !pBt->inTrans ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->pgnoRoot==(Pgno)iTable ){ if( pCur->wrFlag==0 ) return SQLITE_LOCKED; moveToRoot(pCur); } } rc = clearDatabasePage(pBt, (Pgno)iTable, 0); if( rc ){ fileBtreeRollback(pBt); } return rc; } /* ** Erase all information in a table and add the root of the table to ** the freelist. Except, the root of the principle table (the one on ** page 2) is never added to the freelist. */ static int fileBtreeDropTable(Btree *pBt, int iTable){ int rc; MemPage *pPage; BtCursor *pCur; if( !pBt->inTrans ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( pCur->pgnoRoot==(Pgno)iTable ){ return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */ } } rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage); if( rc ) return rc; rc = fileBtreeClearTable(pBt, iTable); if( rc ) return rc; if( iTable>2 ){ rc = freePage(pBt, pPage, iTable); }else{ zeroPage(pBt, pPage); } sqlitepager_unref(pPage); return rc; } #if 0 /* UNTESTED */ /* ** Copy all cell data from one database file into another. ** pages back the freelist. */ static int copyCell(Btree *pBtFrom, BTree *pBtTo, Cell *pCell){ Pager *pFromPager = pBtFrom->pPager; OverflowPage *pOvfl; Pgno ovfl, nextOvfl; Pgno *pPrev; int rc = SQLITE_OK; MemPage *pNew, *pPrevPg; Pgno new; if( NKEY(pBtTo, pCell->h) + NDATA(pBtTo, pCell->h) <= MX_LOCAL_PAYLOAD ){ return SQLITE_OK; } pPrev = &pCell->ovfl; pPrevPg = 0; ovfl = SWAB32(pBtTo, pCell->ovfl); while( ovfl && rc==SQLITE_OK ){ rc = sqlitepager_get(pFromPager, ovfl, (void**)&pOvfl); if( rc ) return rc; nextOvfl = SWAB32(pBtFrom, pOvfl->iNext); rc = allocatePage(pBtTo, &pNew, &new, 0); if( rc==SQLITE_OK ){ rc = sqlitepager_write(pNew); if( rc==SQLITE_OK ){ memcpy(pNew, pOvfl, SQLITE_USABLE_SIZE); *pPrev = SWAB32(pBtTo, new); if( pPrevPg ){ sqlitepager_unref(pPrevPg); } pPrev = &pOvfl->iNext; pPrevPg = pNew; } } sqlitepager_unref(pOvfl); ovfl = nextOvfl; } if( pPrevPg ){ sqlitepager_unref(pPrevPg); } return rc; } #endif #if 0 /* UNTESTED */ /* ** Copy a page of data from one database over to another. */ static int copyDatabasePage( Btree *pBtFrom, Pgno pgnoFrom, Btree *pBtTo, Pgno *pTo ){ MemPage *pPageFrom, *pPage; Pgno to; int rc; Cell *pCell; int idx; rc = sqlitepager_get(pBtFrom->pPager, pgno, (void**)&pPageFrom); if( rc ) return rc; rc = allocatePage(pBt, &pPage, pTo, 0); if( rc==SQLITE_OK ){ rc = sqlitepager_write(pPage); } if( rc==SQLITE_OK ){ memcpy(pPage, pPageFrom, SQLITE_USABLE_SIZE); idx = SWAB16(pBt, pPage->u.hdr.firstCell); while( idx>0 ){ pCell = (Cell*)&pPage->u.aDisk[idx]; idx = SWAB16(pBt, pCell->h.iNext); if( pCell->h.leftChild ){ Pgno newChld; rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pCell->h.leftChild), pBtTo, &newChld); if( rc ) return rc; pCell->h.leftChild = SWAB32(pBtFrom, newChld); } rc = copyCell(pBtFrom, pBtTo, pCell); if( rc ) return rc; } if( pPage->u.hdr.rightChild ){ Pgno newChld; rc = copyDatabasePage(pBtFrom, SWAB32(pBtFrom, pPage->u.hdr.rightChild), pBtTo, &newChld); if( rc ) return rc; pPage->u.hdr.rightChild = SWAB32(pBtTo, newChild); } } sqlitepager_unref(pPage); return rc; } #endif /* ** Read the meta-information out of a database file. */ static int fileBtreeGetMeta(Btree *pBt, int *aMeta){ PageOne *pP1; int rc; int i; rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1); if( rc ) return rc; aMeta[0] = SWAB32(pBt, pP1->nFree); for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){ aMeta[i+1] = SWAB32(pBt, pP1->aMeta[i]); } sqlitepager_unref(pP1); return SQLITE_OK; } /* ** Write meta-information back into the database. */ static int fileBtreeUpdateMeta(Btree *pBt, int *aMeta){ PageOne *pP1; int rc, i; if( !pBt->inTrans ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } pP1 = pBt->page1; rc = sqlitepager_write(pP1); if( rc ) return rc; for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){ pP1->aMeta[i] = SWAB32(pBt, aMeta[i+1]); } return SQLITE_OK; } /****************************************************************************** ** The complete implementation of the BTree subsystem is above this line. ** All the code the follows is for testing and troubleshooting the BTree ** subsystem. None of the code that follows is used during normal operation. ******************************************************************************/ /* ** Print a disassembly of the given page on standard output. This routine ** is used for debugging and testing only. */ #ifdef SQLITE_TEST static int fileBtreePageDump(Btree *pBt, int pgno, int recursive){ int rc; MemPage *pPage; int i, j; int nFree; u16 idx; char range[20]; unsigned char payload[20]; rc = sqlitepager_get(pBt->pPager, (Pgno)pgno, (void**)&pPage); if( rc ){ return rc; } if( recursive ) printf("PAGE %d:\n", pgno); i = 0; idx = SWAB16(pBt, pPage->u.hdr.firstCell); while( idx>0 && idx<=SQLITE_USABLE_SIZE-MIN_CELL_SIZE ){ Cell *pCell = (Cell*)&pPage->u.aDisk[idx]; int sz = cellSize(pBt, pCell); sprintf(range,"%d..%d", idx, idx+sz-1); sz = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h); if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1; memcpy(payload, pCell->aPayload, sz); for(j=0; j0x7f ) payload[j] = '.'; } payload[sz] = 0; printf( "cell %2d: i=%-10s chld=%-4d nk=%-4d nd=%-4d payload=%s\n", i, range, (int)pCell->h.leftChild, NKEY(pBt, pCell->h), NDATA(pBt, pCell->h), payload ); if( pPage->isInit && pPage->apCell[i]!=pCell ){ printf("**** apCell[%d] does not match on prior entry ****\n", i); } i++; idx = SWAB16(pBt, pCell->h.iNext); } if( idx!=0 ){ printf("ERROR: next cell index out of range: %d\n", idx); } printf("right_child: %d\n", SWAB32(pBt, pPage->u.hdr.rightChild)); nFree = 0; i = 0; idx = SWAB16(pBt, pPage->u.hdr.firstFree); while( idx>0 && idxu.aDisk[idx]; sprintf(range,"%d..%d", idx, idx+p->iSize-1); nFree += SWAB16(pBt, p->iSize); printf("freeblock %2d: i=%-10s size=%-4d total=%d\n", i, range, SWAB16(pBt, p->iSize), nFree); idx = SWAB16(pBt, p->iNext); i++; } if( idx!=0 ){ printf("ERROR: next freeblock index out of range: %d\n", idx); } if( recursive && pPage->u.hdr.rightChild!=0 ){ idx = SWAB16(pBt, pPage->u.hdr.firstCell); while( idx>0 && idxu.aDisk[idx]; fileBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1); idx = SWAB16(pBt, pCell->h.iNext); } fileBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1); } sqlitepager_unref(pPage); return SQLITE_OK; } #endif #ifdef SQLITE_TEST /* ** Fill aResult[] with information about the entry and page that the ** cursor is pointing to. ** ** aResult[0] = The page number ** aResult[1] = The entry number ** aResult[2] = Total number of entries on this page ** aResult[3] = Size of this entry ** aResult[4] = Number of free bytes on this page ** aResult[5] = Number of free blocks on the page ** aResult[6] = Page number of the left child of this entry ** aResult[7] = Page number of the right child for the whole page ** ** This routine is used for testing and debugging only. */ static int fileBtreeCursorDump(BtCursor *pCur, int *aResult){ int cnt, idx; MemPage *pPage = pCur->pPage; Btree *pBt = pCur->pBt; aResult[0] = sqlitepager_pagenumber(pPage); aResult[1] = pCur->idx; aResult[2] = pPage->nCell; if( pCur->idx>=0 && pCur->idxnCell ){ aResult[3] = cellSize(pBt, pPage->apCell[pCur->idx]); aResult[6] = SWAB32(pBt, pPage->apCell[pCur->idx]->h.leftChild); }else{ aResult[3] = 0; aResult[6] = 0; } aResult[4] = pPage->nFree; cnt = 0; idx = SWAB16(pBt, pPage->u.hdr.firstFree); while( idx>0 && idxu.aDisk[idx])->iNext); } aResult[5] = cnt; aResult[7] = SWAB32(pBt, pPage->u.hdr.rightChild); return SQLITE_OK; } #endif /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ static Pager *fileBtreePager(Btree *pBt){ return pBt->pPager; } /* ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { Btree *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ int nPage; /* Number of pages in the database */ int *anRef; /* Number of times each page is referenced */ char *zErrMsg; /* An error message. NULL of no errors seen. */ }; /* ** Append a message to the error message string. */ static void checkAppendMsg(IntegrityCk *pCheck, char *zMsg1, char *zMsg2){ if( pCheck->zErrMsg ){ char *zOld = pCheck->zErrMsg; pCheck->zErrMsg = 0; sqliteSetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0); sqliteFree(zOld); }else{ sqliteSetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0); } } /* ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 ore more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ if( iPage==0 ) return 1; if( iPage>pCheck->nPage || iPage<0 ){ char zBuf[100]; sprintf(zBuf, "invalid page number %d", iPage); checkAppendMsg(pCheck, zContext, zBuf); return 1; } if( pCheck->anRef[iPage]==1 ){ char zBuf[100]; sprintf(zBuf, "2nd reference to page %d", iPage); checkAppendMsg(pCheck, zContext, zBuf); return 1; } return (pCheck->anRef[iPage]++)>1; } /* ** Check the integrity of the freelist or of an overflow page list. ** Verify that the number of pages on the list is N. */ static void checkList( IntegrityCk *pCheck, /* Integrity checking context */ int isFreeList, /* True for a freelist. False for overflow page list */ int iPage, /* Page number for first page in the list */ int N, /* Expected number of pages in the list */ char *zContext /* Context for error messages */ ){ int i; char zMsg[100]; while( N-- > 0 ){ OverflowPage *pOvfl; if( iPage<1 ){ sprintf(zMsg, "%d pages missing from overflow list", N+1); checkAppendMsg(pCheck, zContext, zMsg); break; } if( checkRef(pCheck, iPage, zContext) ) break; if( sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pOvfl) ){ sprintf(zMsg, "failed to get page %d", iPage); checkAppendMsg(pCheck, zContext, zMsg); break; } if( isFreeList ){ FreelistInfo *pInfo = (FreelistInfo*)pOvfl->aPayload; int n = SWAB32(pCheck->pBt, pInfo->nFree); for(i=0; ipBt, pInfo->aFree[i]), zContext); } N -= n; } iPage = SWAB32(pCheck->pBt, pOvfl->iNext); sqlitepager_unref(pOvfl); } } /* ** Return negative if zKey1zKey2. */ static int keyCompare( const char *zKey1, int nKey1, const char *zKey2, int nKey2 ){ int min = nKey1>nKey2 ? nKey2 : nKey1; int c = memcmp(zKey1, zKey2, min); if( c==0 ){ c = nKey1 - nKey2; } return c; } /* ** Do various sanity checks on a single page of a tree. Return ** the tree depth. Root pages return 0. Parents of root pages ** return 1, and so forth. ** ** These checks are done: ** ** 1. Make sure that cells and freeblocks do not overlap ** but combine to completely cover the page. ** 2. Make sure cell keys are in order. ** 3. Make sure no key is less than or equal to zLowerBound. ** 4. Make sure no key is greater than or equal to zUpperBound. ** 5. Check the integrity of overflow pages. ** 6. Recursively call checkTreePage on all children. ** 7. Verify that the depth of all children is the same. ** 8. Make sure this page is at least 33% full or else it is ** the root of the tree. */ static int checkTreePage( IntegrityCk *pCheck, /* Context for the sanity check */ int iPage, /* Page number of the page to check */ MemPage *pParent, /* Parent page */ char *zParentContext, /* Parent context */ char *zLowerBound, /* All keys should be greater than this, if not NULL */ int nLower, /* Number of characters in zLowerBound */ char *zUpperBound, /* All keys should be less than this, if not NULL */ int nUpper /* Number of characters in zUpperBound */ ){ MemPage *pPage; int i, rc, depth, d2, pgno; char *zKey1, *zKey2; int nKey1, nKey2; BtCursor cur; Btree *pBt; char zMsg[100]; char zContext[100]; char hit[SQLITE_USABLE_SIZE]; /* Check that the page exists */ cur.pBt = pBt = pCheck->pBt; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage, zParentContext) ) return 0; sprintf(zContext, "On tree page %d: ", iPage); if( (rc = sqlitepager_get(pCheck->pPager, (Pgno)iPage, (void**)&pPage))!=0 ){ sprintf(zMsg, "unable to get the page. error code=%d", rc); checkAppendMsg(pCheck, zContext, zMsg); return 0; } if( (rc = initPage(pBt, pPage, (Pgno)iPage, pParent))!=0 ){ sprintf(zMsg, "initPage() returns error code %d", rc); checkAppendMsg(pCheck, zContext, zMsg); sqlitepager_unref(pPage); return 0; } /* Check out all the cells. */ depth = 0; if( zLowerBound ){ zKey1 = sqliteMalloc( nLower+1 ); memcpy(zKey1, zLowerBound, nLower); zKey1[nLower] = 0; }else{ zKey1 = 0; } nKey1 = nLower; cur.pPage = pPage; for(i=0; inCell; i++){ Cell *pCell = pPage->apCell[i]; int sz; /* Check payload overflow pages */ nKey2 = NKEY(pBt, pCell->h); sz = nKey2 + NDATA(pBt, pCell->h); sprintf(zContext, "On page %d cell %d: ", iPage, i); if( sz>MX_LOCAL_PAYLOAD ){ int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE; checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext); } /* Check that keys are in the right order */ cur.idx = i; zKey2 = sqliteMallocRaw( nKey2+1 ); getPayload(&cur, 0, nKey2, zKey2); if( zKey1 && keyCompare(zKey1, nKey1, zKey2, nKey2)>=0 ){ checkAppendMsg(pCheck, zContext, "Key is out of order"); } /* Check sanity of left child page. */ pgno = SWAB32(pBt, pCell->h.leftChild); d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zKey2,nKey2); if( i>0 && d2!=depth ){ checkAppendMsg(pCheck, zContext, "Child page depth differs"); } depth = d2; sqliteFree(zKey1); zKey1 = zKey2; nKey1 = nKey2; } pgno = SWAB32(pBt, pPage->u.hdr.rightChild); sprintf(zContext, "On page %d at right child: ", iPage); checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zUpperBound,nUpper); sqliteFree(zKey1); /* Check for complete coverage of the page */ memset(hit, 0, sizeof(hit)); memset(hit, 1, sizeof(PageHdr)); for(i=SWAB16(pBt, pPage->u.hdr.firstCell); i>0 && iu.aDisk[i]; int j; for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++; i = SWAB16(pBt, pCell->h.iNext); } for(i=SWAB16(pBt,pPage->u.hdr.firstFree); i>0 && iu.aDisk[i]; int j; for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++; i = SWAB16(pBt,pFBlk->iNext); } for(i=0; i1 ){ sprintf(zMsg, "Multiple uses for byte %d of page %d", i, iPage); checkAppendMsg(pCheck, zMsg, 0); break; } } /* Check that free space is kept to a minimum */ #if 0 if( pParent && pParent->nCell>2 && pPage->nFree>3*SQLITE_USABLE_SIZE/4 ){ sprintf(zMsg, "free space (%d) greater than max (%d)", pPage->nFree, SQLITE_USABLE_SIZE/3); checkAppendMsg(pCheck, zContext, zMsg); } #endif sqlitepager_unref(pPage); return depth; } /* ** This routine does a complete check of the given BTree file. aRoot[] is ** an array of pages numbers were each page number is the root page of ** a table. nRoot is the number of entries in aRoot. ** ** If everything checks out, this routine returns NULL. If something is ** amiss, an error message is written into memory obtained from malloc() ** and a pointer to that error message is returned. The calling function ** is responsible for freeing the error message when it is done. */ char *fileBtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ int i; int nRef; IntegrityCk sCheck; nRef = *sqlitepager_stats(pBt->pPager); if( lockBtree(pBt)!=SQLITE_OK ){ return sqliteStrDup("Unable to acquire a read lock on the database"); } sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = sqlitepager_pagecount(sCheck.pPager); if( sCheck.nPage==0 ){ unlockBtreeIfUnused(pBt); return 0; } sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); sCheck.anRef[1] = 1; for(i=2; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } sCheck.zErrMsg = 0; /* Check the integrity of the freelist */ checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList), SWAB32(pBt, pBt->page1->nFree), "Main freelist: "); /* Check all the tables. */ for(i=0; ipPager) ){ char zBuf[100]; sprintf(zBuf, "Outstanding page count goes from %d to %d during this analysis", nRef, *sqlitepager_stats(pBt->pPager) ); checkAppendMsg(&sCheck, zBuf, 0); } /* Clean up and report errors. */ sqliteFree(sCheck.anRef); return sCheck.zErrMsg; } /* ** Return the full pathname of the underlying database file. */ static const char *fileBtreeGetFilename(Btree *pBt){ assert( pBt->pPager!=0 ); return sqlitepager_filename(pBt->pPager); } /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** ** The size of file pBtFrom may be reduced by this operation. ** If anything goes wrong, the transaction on pBtFrom is rolled back. */ static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ int rc = SQLITE_OK; Pgno i, nPage, nToPage; if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR; if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR; if( pBtTo->pCursor ) return SQLITE_BUSY; memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_USABLE_SIZE); rc = sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1); nToPage = sqlitepager_pagecount(pBtTo->pPager); nPage = sqlitepager_pagecount(pBtFrom->pPager); for(i=2; rc==SQLITE_OK && i<=nPage; i++){ void *pPage; rc = sqlitepager_get(pBtFrom->pPager, i, &pPage); if( rc ) break; rc = sqlitepager_overwrite(pBtTo->pPager, i, pPage); if( rc ) break; sqlitepager_unref(pPage); } for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ void *pPage; rc = sqlitepager_get(pBtTo->pPager, i, &pPage); if( rc ) break; rc = sqlitepager_write(pPage); sqlitepager_unref(pPage); sqlitepager_dont_write(pBtTo->pPager, i); } if( !rc && nPagepPager, nPage); } if( rc ){ fileBtreeRollback(pBtTo); } return rc; } /* ** The following tables contain pointers to all of the interface ** routines for this implementation of the B*Tree backend. To ** substitute a different implemention of the backend, one has merely ** to provide pointers to alternative functions in similar tables. */ static BtOps sqliteBtreeOps = { fileBtreeClose, fileBtreeSetCacheSize, fileBtreeSetSafetyLevel, fileBtreeBeginTrans, fileBtreeCommit, fileBtreeRollback, fileBtreeBeginCkpt, fileBtreeCommitCkpt, fileBtreeRollbackCkpt, fileBtreeCreateTable, fileBtreeCreateTable, /* Really sqliteBtreeCreateIndex() */ fileBtreeDropTable, fileBtreeClearTable, fileBtreeCursor, fileBtreeGetMeta, fileBtreeUpdateMeta, fileBtreeIntegrityCheck, fileBtreeGetFilename, fileBtreeCopyFile, fileBtreePager, #ifdef SQLITE_TEST fileBtreePageDump, #endif }; static BtCursorOps sqliteBtreeCursorOps = { fileBtreeMoveto, fileBtreeDelete, fileBtreeInsert, fileBtreeFirst, fileBtreeLast, fileBtreeNext, fileBtreePrevious, fileBtreeKeySize, fileBtreeKey, fileBtreeKeyCompare, fileBtreeDataSize, fileBtreeData, fileBtreeCloseCursor, #ifdef SQLITE_TEST fileBtreeCursorDump, #endif }; DBD-SQLite2-0.36/delete.c0000644000175000017500000003164212126353147014240 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** ** $Id: delete.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. */ Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){ Table *pTab = 0; int i; for(i=0; inSrc; i++){ const char *zTab = pSrc->a[i].zName; const char *zDb = pSrc->a[i].zDatabase; pTab = sqliteLocateTable(pParse, zTab, zDb); pSrc->a[i].pTab = pTab; } return pTab; } /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is ** writable return 0; */ int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){ if( pTab->readOnly ){ sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } if( !viewOk && pTab->pSelect ){ sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName); return 1; } return 0; } /* ** Process a DELETE FROM statement. */ void sqliteDeleteFrom( Parse *pParse, /* The parser context */ SrcList *pTabList, /* The table from which we should delete things */ Expr *pWhere /* The WHERE clause. May be null */ ){ Vdbe *v; /* The virtual database engine */ Table *pTab; /* The table from which records will be deleted */ const char *zDb; /* Name of database holding pTab */ int end, addr; /* A couple addresses of generated code */ int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Index *pIdx; /* For looping over indices of the table */ int iCur; /* VDBE Cursor number for pTab */ sqlite *db; /* Main database structure */ int isView; /* True if attempting to delete from a view */ AuthContext sContext; /* Authorization context */ int row_triggers_exist = 0; /* True if any triggers exist */ int before_triggers; /* True if there are BEFORE triggers */ int after_triggers; /* True if there are AFTER triggers */ int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ sContext.pParse = 0; if( pParse->nErr || sqlite_malloc_failed ){ pTabList = 0; goto delete_from_cleanup; } db = pParse->db; assert( pTabList->nSrc==1 ); /* Locate the table which we want to delete. This table has to be ** put in an SrcList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect ** an SrcList* parameter instead of just a Table* parameter. */ pTab = sqliteSrcListLookup(pParse, pTabList); if( pTab==0 ) goto delete_from_cleanup; before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_DELETE, TK_BEFORE, TK_ROW, 0); after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, TK_DELETE, TK_AFTER, TK_ROW, 0); row_triggers_exist = before_triggers || after_triggers; isView = pTab->pSelect!=0; if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){ goto delete_from_cleanup; } assert( pTab->iDbnDb ); zDb = db->aDb[pTab->iDb].zName; if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ goto delete_from_cleanup; } /* If pTab is really a view, make sure it has been initialized. */ if( isView && sqliteViewGetColumnNames(pParse, pTab) ){ goto delete_from_cleanup; } /* Allocate a cursor used to store the old.* data for a trigger. */ if( row_triggers_exist ){ oldIdx = pParse->nTab++; } /* Resolve the column names in all the expressions. */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; if( pWhere ){ if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){ goto delete_from_cleanup; } if( sqliteExprCheck(pParse, pWhere, 0, 0) ){ goto delete_from_cleanup; } } /* Start the view context */ if( isView ){ sqliteAuthContextPush(pParse, &sContext, pTab->zName); } /* Begin generating code. */ v = sqliteGetVdbe(pParse); if( v==0 ){ goto delete_from_cleanup; } sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView = sqliteSelectDup(pTab->pSelect); sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0); sqliteSelectDelete(pView); } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); } /* Special case: A DELETE without a WHERE clause deletes everything. ** It is easier just to erase the whole table. Note, however, that ** this means that the row change count will be incorrect. */ if( pWhere==0 && !row_triggers_exist ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqliteVdbeMakeLabel(v); int addr; if( !isView ){ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); } sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2); addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0); sqliteVdbeAddOp(v, OP_Next, iCur, addr); sqliteVdbeResolveLabel(v, endOfLoop); sqliteVdbeAddOp(v, OP_Close, iCur, 0); } if( !isView ){ sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb); } } } /* The usual case: There is a WHERE clause so we have to scan through ** the table and pick which records to delete. */ else{ /* Begin the database scan */ pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0); if( pWInfo==0 ) goto delete_from_cleanup; /* Remember the key of every item to be deleted. */ sqliteVdbeAddOp(v, OP_ListWrite, 0, 0); if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } /* End the database scan loop. */ sqliteWhereEnd(pWInfo); /* Open the pseudo-table used to store OLD if there are triggers. */ if( row_triggers_exist ){ sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); } /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete ** because deleting an item can change the scan order. */ sqliteVdbeAddOp(v, OP_ListRewind, 0, 0); end = sqliteVdbeMakeLabel(v); /* This is the beginning of the delete loop when there are ** row triggers. */ if( row_triggers_exist ){ addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); sqliteVdbeAddOp(v, OP_Dup, 0, 0); if( !isView ){ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); } sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0); sqliteVdbeAddOp(v, OP_Recno, iCur, 0); sqliteVdbeAddOp(v, OP_RowData, iCur, 0); sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0); if( !isView ){ sqliteVdbeAddOp(v, OP_Close, iCur, 0); } sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, addr); } if( !isView ){ /* Open cursors for the table we are deleting from and all its ** indices. If there are row triggers, this happens inside the ** OP_ListRead loop because the cursor have to all be closed ** before the trigger fires. If there are no row triggers, the ** cursors are opened only once on the outside the loop. */ pParse->nTab = iCur + 1; sqliteOpenTableAndIndices(pParse, pTab, iCur); /* This is the beginning of the delete loop when there are no ** row triggers */ if( !row_triggers_exist ){ addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); } /* Delete the row */ sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0); } /* If there are row triggers, close all cursors then invoke ** the AFTER triggers */ if( row_triggers_exist ){ if( !isView ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqliteVdbeAddOp(v, OP_Close, iCur, 0); } sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, addr); } /* End of the delete loop */ sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeResolveLabel(v, end); sqliteVdbeAddOp(v, OP_ListReset, 0, 0); /* Close the cursors after the loop if there are no row triggers */ if( !row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqliteVdbeAddOp(v, OP_Close, iCur, 0); pParse->nTab = iCur; } } sqliteVdbeAddOp(v, OP_SetCounts, 0, 0); sqliteEndWriteOperation(pParse); /* ** Return the number of rows that were deleted. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_ColumnName, 0, 1); sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC); sqliteVdbeAddOp(v, OP_Callback, 1, 0); } delete_from_cleanup: sqliteAuthContextPop(&sContext); sqliteSrcListDelete(pTabList); sqliteExprDelete(pWhere); return; } /* ** This routine generates VDBE code that causes a single row of a ** single table to be deleted. ** ** The VDBE must be in a particular state when this routine is called. ** These are the requirements: ** ** 1. A read/write cursor pointing to pTab, the table containing the row ** to be deleted, must be opened as cursor number "base". ** ** 2. Read/write cursors for all indices of pTab must be open as ** cursor number base+i for the i-th index. ** ** 3. The record number of the row to be deleted must be on the top ** of the stack. ** ** This routine pops the top of the stack to remove the record number ** and then generates code to remove both the table record and all index ** entries that point to that record. */ void sqliteGenerateRowDelete( sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int iCur, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0); sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0); sqliteVdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } /* ** This routine generates VDBE code that causes the deletion of all ** index entries associated with a single row of a single table. ** ** The VDBE must be in a particular state when this routine is called. ** These are the requirements: ** ** 1. A read/write cursor pointing to pTab, the table containing the row ** to be deleted, must be opened as cursor number "iCur". ** ** 2. Read/write cursors for all indices of pTab must be open as ** cursor number iCur+i for the i-th index. ** ** 3. The "iCur" cursor must be pointing to the row that is to be ** deleted. */ void sqliteGenerateRowIndexDelete( sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int iCur, /* Cursor number for the table */ char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ ){ int i; Index *pIdx; for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ int j; if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue; sqliteVdbeAddOp(v, OP_Recno, iCur, 0); for(j=0; jnColumn; j++){ int idx = pIdx->aiColumn[j]; if( idx==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Dup, j, 0); }else{ sqliteVdbeAddOp(v, OP_Column, iCur, idx); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx); sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0); } } DBD-SQLite2-0.36/encode.c0000644000175000017500000002142212126353147014226 0ustar rurbanrurban/* ** 2002 April 25 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains helper routines used to translate binary data into ** a null-terminated string (suitable for use in SQLite) and back again. ** These are convenience routines for use by people who want to store binary ** data in an SQLite database. The code in this file is not used by any other ** part of the SQLite library. ** ** $Id: encode.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $ */ #include #include /* ** How This Encoder Works ** ** The output is allowed to contain any character except 0x27 (') and ** 0x00. This is accomplished by using an escape character to encode ** 0x27 and 0x00 as a two-byte sequence. The escape character is always ** 0x01. An 0x00 is encoded as the two byte sequence 0x01 0x01. The ** 0x27 character is encoded as the two byte sequence 0x01 0x28. Finally, ** the escape character itself is encoded as the two-character sequence ** 0x01 0x02. ** ** To summarize, the encoder works by using an escape sequences as follows: ** ** 0x00 -> 0x01 0x01 ** 0x01 -> 0x01 0x02 ** 0x27 -> 0x01 0x28 ** ** If that were all the encoder did, it would work, but in certain cases ** it could double the size of the encoded string. For example, to ** encode a string of 100 0x27 characters would require 100 instances of ** the 0x01 0x03 escape sequence resulting in a 200-character output. ** We would prefer to keep the size of the encoded string smaller than ** this. ** ** To minimize the encoding size, we first add a fixed offset value to each ** byte in the sequence. The addition is modulo 256. (That is to say, if ** the sum of the original character value and the offset exceeds 256, then ** the higher order bits are truncated.) The offset is chosen to minimize ** the number of characters in the string that need to be escaped. For ** example, in the case above where the string was composed of 100 0x27 ** characters, the offset might be 0x01. Each of the 0x27 characters would ** then be converted into an 0x28 character which would not need to be ** escaped at all and so the 100 character input string would be converted ** into just 100 characters of output. Actually 101 characters of output - ** we have to record the offset used as the first byte in the sequence so ** that the string can be decoded. Since the offset value is stored as ** part of the output string and the output string is not allowed to contain ** characters 0x00 or 0x27, the offset cannot be 0x00 or 0x27. ** ** Here, then, are the encoding steps: ** ** (1) Choose an offset value and make it the first character of ** output. ** ** (2) Copy each input character into the output buffer, one by ** one, adding the offset value as you copy. ** ** (3) If the value of an input character plus offset is 0x00, replace ** that one character by the two-character sequence 0x01 0x01. ** If the sum is 0x01, replace it with 0x01 0x02. If the sum ** is 0x27, replace it with 0x01 0x03. ** ** (4) Put a 0x00 terminator at the end of the output. ** ** Decoding is obvious: ** ** (5) Copy encoded characters except the first into the decode ** buffer. Set the first encoded character aside for use as ** the offset in step 7 below. ** ** (6) Convert each 0x01 0x01 sequence into a single character 0x00. ** Convert 0x01 0x02 into 0x01. Convert 0x01 0x28 into 0x27. ** ** (7) Subtract the offset value that was the first character of ** the encoded buffer from all characters in the output buffer. ** ** The only tricky part is step (1) - how to compute an offset value to ** minimize the size of the output buffer. This is accomplished by testing ** all offset values and picking the one that results in the fewest number ** of escapes. To do that, we first scan the entire input and count the ** number of occurances of each character value in the input. Suppose ** the number of 0x00 characters is N(0), the number of occurances of 0x01 ** is N(1), and so forth up to the number of occurances of 0xff is N(255). ** An offset of 0 is not allowed so we don't have to test it. The number ** of escapes required for an offset of 1 is N(1)+N(2)+N(40). The number ** of escapes required for an offset of 2 is N(2)+N(3)+N(41). And so forth. ** In this way we find the offset that gives the minimum number of escapes, ** and thus minimizes the length of the output string. */ /* ** Encode a binary buffer "in" of size n bytes so that it contains ** no instances of characters '\'' or '\000'. The output is ** null-terminated and can be used as a string value in an INSERT ** or UPDATE statement. Use sqlite_decode_binary() to convert the ** string back into its original binary. ** ** The result is written into a preallocated output buffer "out". ** "out" must be able to hold at least 2 +(257*n)/254 bytes. ** In other words, the output will be expanded by as much as 3 ** bytes for every 254 bytes of input plus 2 bytes of fixed overhead. ** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.) ** ** The return value is the number of characters in the encoded ** string, excluding the "\000" terminator. ** ** If out==NULL then no output is generated but the routine still returns ** the number of characters that would have been generated if out had ** not been NULL. */ int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out){ int i, j, e, m; unsigned char x; int cnt[256]; if( n<=0 ){ if( out ){ out[0] = 'x'; out[1] = 0; } return 1; } memset(cnt, 0, sizeof(cnt)); for(i=n-1; i>=0; i--){ cnt[in[i]]++; } m = n; for(i=1; i<256; i++){ int sum; if( i=='\'' ) continue; sum = cnt[i] + cnt[(i+1)&0xff] + cnt[(i+'\'')&0xff]; if( sum /* ** The subroutines above are not tested by the usual test suite. To test ** these routines, compile just this one file with a -DENCODER_TEST=1 option ** and run the result. */ int main(int argc, char **argv){ int i, j, n, m, nOut, nByteIn, nByteOut; unsigned char in[30000]; unsigned char out[33000]; nByteIn = nByteOut = 0; for(i=0; i%d (max %d)", n, strlen(out)+1, m); if( strlen(out)+1>m ){ printf(" ERROR output too big\n"); exit(1); } for(j=0; out[j]; j++){ if( out[j]=='\'' ){ printf(" ERROR contains (')\n"); exit(1); } } j = sqlite_decode_binary(out, out); if( j!=n ){ printf(" ERROR decode size %d\n", j); exit(1); } if( memcmp(in, out, n)!=0 ){ printf(" ERROR decode mismatch\n"); exit(1); } printf(" OK\n"); } fprintf(stderr,"Finished. Total encoding: %d->%d bytes\n", nByteIn, nByteOut); fprintf(stderr,"Avg size increase: %.3f%%\n", (nByteOut-nByteIn)*100.0/(double)nByteIn); } #endif /* ENCODER_TEST */ DBD-SQLite2-0.36/sqliteInt.h0000644000175000017500000016013012126353147014752 0ustar rurbanrurban/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "parse.h" #include "btree.h" #include #include #include #include /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. */ #define MAX_PAGES 2000 #define TEMP_PAGES 500 /* ** If the following macro is set to 1, then NULL values are considered ** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT ** compound queries. No other SQL database engine (among those tested) ** works this way except for OCELOT. But the SQL92 spec implies that ** this is how things should work. ** ** If the following macro is set to 0, then NULLs are indistinct for ** SELECT DISTINCT and for UNION. */ #define NULL_ALWAYS_DISTINCT 0 /* ** If the following macro is set to 1, then NULL values are considered ** distinct when determining whether or not two entries are the same ** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, ** OCELOT, and Firebird all work. The SQL92 spec explicitly says this ** is the way things are suppose to work. ** ** If the following macro is set to 0, the NULLs are indistinct for ** a UNIQUE index. In this mode, you can only have a single NULL entry ** for a column declared UNIQUE. This is the way Informix and SQL Server ** work. */ #define NULL_DISTINCT_FOR_UNIQUE 1 /* ** The maximum number of attached databases. This must be at least 2 ** in order to support the main database file (0) and the file used to ** hold temporary tables (1). And it must be less than 256 because ** an unsigned character is used to stored the database index. */ #define MAX_ATTACHED 10 /* ** The next macro is used to determine where TEMP tables and indices ** are stored. Possible values: ** ** 0 Always use a temporary files ** 1 Use a file unless overridden by "PRAGMA temp_store" ** 2 Use memory unless overridden by "PRAGMA temp_store" ** 3 Always use memory */ #ifndef TEMP_STORE # define TEMP_STORE 1 #endif /* ** When building SQLite for embedded systems where memory is scarce, ** you can define one or more of the following macros to omit extra ** features of the library and thus keep the size of the library to ** a minimum. */ /* #define SQLITE_OMIT_AUTHORIZATION 1 */ /* #define SQLITE_OMIT_INMEMORYDB 1 */ /* #define SQLITE_OMIT_VACUUM 1 */ /* #define SQLITE_OMIT_DATETIME_FUNCS 1 */ /* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */ /* ** Integers of known sizes. These typedefs might change for architectures ** where the sizes very. Preprocessor macros are available so that the ** types can be conveniently redefined at compile-type. Like this: ** ** cc '-DUINTPTR_TYPE=long long int' ... */ #ifndef UINT32_TYPE # define UINT32_TYPE unsigned int #endif #ifndef UINT16_TYPE # define UINT16_TYPE unsigned short int #endif #ifndef INT16_TYPE # define INT16_TYPE short int #endif #ifndef UINT8_TYPE # define UINT8_TYPE unsigned char #endif #ifndef INT8_TYPE # define INT8_TYPE signed char #endif #ifndef INTPTR_TYPE # if SQLITE_PTR_SZ==4 # define INTPTR_TYPE int # else # define INTPTR_TYPE long long # endif #endif typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ typedef INT16_TYPE i16; /* 2-byte signed integer */ typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ typedef UINT8_TYPE i8; /* 1-byte signed integer */ typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */ typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */ /* ** Defer sourcing vdbe.h until after the "u8" typedef is defined. */ #include "vdbe.h" /* ** Most C compilers these days recognize "long double", don't they? ** Just in case we encounter one that does not, we will create a macro ** for long double so that it can be easily changed to just "double". */ #ifndef LONGDOUBLE_TYPE # define LONGDOUBLE_TYPE long double #endif /* ** This macro casts a pointer to an integer. Useful for doing ** pointer arithmetic. */ #define Addr(X) ((uptr)X) /* ** The maximum number of bytes of data that can be put into a single ** row of a single table. The upper bound on this limit is 16777215 ** bytes (or 16MB-1). We have arbitrarily set the limit to just 1MB ** here because the overflow page chain is inefficient for really big ** records and we want to discourage people from thinking that ** multi-megabyte records are OK. If your needs are different, you can ** change this define and recompile to increase or decrease the record ** size. ** ** The 16777198 is computed as follows: 238 bytes of payload on the ** original pages plus 16448 overflow pages each holding 1020 bytes of ** data. */ #define MAX_BYTES_PER_ROW 1048576 /* #define MAX_BYTES_PER_ROW 16777198 */ /* ** If memory allocation problems are found, recompile with ** ** -DMEMORY_DEBUG=1 ** ** to enable some sanity checking on malloc() and free(). To ** check for memory leaks, recompile with ** ** -DMEMORY_DEBUG=2 ** ** and a line of text will be written to standard error for ** each malloc() and free(). This output can be analyzed ** by an AWK script to determine if there are any leaks. */ #ifdef MEMORY_DEBUG # define sqliteMalloc(X) sqliteMalloc_(X,1,__FILE__,__LINE__) # define sqliteMallocRaw(X) sqliteMalloc_(X,0,__FILE__,__LINE__) # define sqliteFree(X) sqliteFree_(X,__FILE__,__LINE__) # define sqliteRealloc(X,Y) sqliteRealloc_(X,Y,__FILE__,__LINE__) # define sqliteStrDup(X) sqliteStrDup_(X,__FILE__,__LINE__) # define sqliteStrNDup(X,Y) sqliteStrNDup_(X,Y,__FILE__,__LINE__) void sqliteStrRealloc(char**); #else # define sqliteRealloc_(X,Y) sqliteRealloc(X,Y) # define sqliteStrRealloc(X) #endif /* ** This variable gets set if malloc() ever fails. After it gets set, ** the SQLite library shuts down permanently. */ extern int sqlite_malloc_failed; /* ** The following global variables are used for testing and debugging ** only. They only work if MEMORY_DEBUG is defined. */ #ifdef MEMORY_DEBUG extern int sqlite_nMalloc; /* Number of sqliteMalloc() calls */ extern int sqlite_nFree; /* Number of sqliteFree() calls */ extern int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */ #endif /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. */ #define MASTER_NAME "sqlite_master" #define TEMP_MASTER_NAME "sqlite_temp_master" /* ** The name of the schema table. */ #define SCHEMA_TABLE(x) (x?TEMP_MASTER_NAME:MASTER_NAME) /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Forward references to structures */ typedef struct Column Column; typedef struct Table Table; typedef struct Index Index; typedef struct Instruction Instruction; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct Parse Parse; typedef struct Token Token; typedef struct IdList IdList; typedef struct SrcList SrcList; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; typedef struct Select Select; typedef struct AggExpr AggExpr; typedef struct FuncDef FuncDef; typedef struct Trigger Trigger; typedef struct TriggerStep TriggerStep; typedef struct TriggerStack TriggerStack; typedef struct FKey FKey; typedef struct Db Db; typedef struct AuthContext AuthContext; /* ** Each database file to be accessed by the system is an instance ** of the following structure. There are normally two of these structures ** in the sqlite.aDb[] array. aDb[0] is the main database file and ** aDb[1] is the database file used to hold temporary tables. Additional ** databases may be attached. */ struct Db { char *zName; /* Name of this database */ Btree *pBt; /* The B*Tree structure for this database file */ int schema_cookie; /* Database schema version number for this file */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash trigHash; /* All triggers indexed by name */ Hash aFKey; /* Foreign keys indexed by to-table */ u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ u16 flags; /* Flags associated with this database */ void *pAux; /* Auxiliary data. Usually NULL */ void (*xFreeAux)(void*); /* Routine to free pAux */ }; /* ** These macros can be used to test, set, or clear bits in the ** Db.flags field. */ #define DbHasProperty(D,I,P) (((D)->aDb[I].flags&(P))==(P)) #define DbHasAnyProperty(D,I,P) (((D)->aDb[I].flags&(P))!=0) #define DbSetProperty(D,I,P) (D)->aDb[I].flags|=(P) #define DbClearProperty(D,I,P) (D)->aDb[I].flags&=~(P) /* ** Allowed values for the DB.flags field. ** ** The DB_Locked flag is set when the first OP_Transaction or OP_Checkpoint ** opcode is emitted for a database. This prevents multiple occurances ** of those opcodes for the same database in the same program. Similarly, ** the DB_Cookie flag is set when the OP_VerifyCookie opcode is emitted, ** and prevents duplicate OP_VerifyCookies from taking up space and slowing ** down execution. ** ** The DB_SchemaLoaded flag is set after the database schema has been ** read into internal hash tables. ** ** DB_UnresetViews means that one or more views have column names that ** have been filled out. If the schema changes, these column names might ** changes and so the view will need to be reset. */ #define DB_Locked 0x0001 /* OP_Transaction opcode has been emitted */ #define DB_Cookie 0x0002 /* OP_VerifyCookie opcode has been emiited */ #define DB_SchemaLoaded 0x0004 /* The schema has been loaded */ #define DB_UnresetViews 0x0008 /* Some views have defined column names */ /* ** Each database is an instance of the following structure. ** ** The sqlite.file_format is initialized by the database file ** and helps determines how the data in the database file is ** represented. This field allows newer versions of the library ** to read and write older databases. The various file formats ** are as follows: ** ** file_format==1 Version 2.1.0. ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. ** file_format==3 Version 2.6.0. Fix empty-string index bug. ** file_format==4 Version 2.7.0. Add support for separate numeric and ** text datatypes. ** ** The sqlite.temp_store determines where temporary database files ** are stored. If 1, then a file is created to hold those tables. If ** 2, then they are held in memory. 0 means use the default value in ** the TEMP_STORE macro. ** ** The sqlite.lastRowid records the last insert rowid generated by an ** insert statement. Inserts on views do not affect its value. Each ** trigger has its own context, so that lastRowid can be updated inside ** triggers as usual. The previous value will be restored once the trigger ** exits. Upon entering a before or instead of trigger, lastRowid is no ** longer (since after version 2.8.12) reset to -1. ** ** The sqlite.nChange does not count changes within triggers and keeps no ** context. It is reset at start of sqlite_exec. ** The sqlite.lsChange represents the number of changes made by the last ** insert, update, or delete statement. It remains constant throughout the ** length of a statement and is then updated by OP_SetCounts. It keeps a ** context stack just like lastRowid so that the count of changes ** within a trigger is not seen outside the trigger. Changes to views do not ** affect the value of lsChange. ** The sqlite.csChange keeps track of the number of current changes (since ** the last statement) and is used to update sqlite_lsChange. */ struct sqlite { int nDb; /* Number of backends currently in use */ Db *aDb; /* All backends */ Db aDbStatic[2]; /* Static space for the 2 default backends */ int flags; /* Miscellanous flags. See below */ u8 file_format; /* What file format version is this database? */ u8 safety_level; /* How aggressive at synching data to disk */ u8 want_to_close; /* Close after all VDBEs are deallocated */ u8 temp_store; /* 1=file, 2=memory, 0=compile-time default */ u8 onError; /* Default conflict algorithm */ int next_cookie; /* Next value of aDb[0].schema_cookie */ int cache_size; /* Number of pages to use in the cache */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ Hash aFunc; /* All functions that can be in SQL exprs */ int lastRowid; /* ROWID of most recent insert (see above) */ int priorNewRowid; /* Last randomly generated ROWID */ int magic; /* Magic number for detect library misuse */ int nChange; /* Number of rows changed (see above) */ int lsChange; /* Last statement change count (see above) */ int csChange; /* Current statement change count (see above) */ struct sqliteInitInfo { /* Information used during initialization */ int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ u8 busy; /* TRUE if currently initializing */ } init; struct Vdbe *pVdbe; /* List of active virtual machines */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); /* Access authorization function */ void *pAuthArg; /* 1st argument to the access auth function */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int (*xProgress)(void *); /* The progress callback */ void *pProgressArg; /* Argument to the progress callback */ int nProgressOps; /* Number of opcodes for progress callback */ #endif }; /* ** Possible values for the sqlite.flags and or Db.flags fields. ** ** On sqlite.flags, the SQLITE_InTrans value means that we have ** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement ** transaction is active on that particular database file. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ #define SQLITE_Initialized 0x00000002 /* True after initialization */ #define SQLITE_Interrupt 0x00000004 /* Cancel current operation */ #define SQLITE_InTrans 0x00000008 /* True if in a transaction */ #define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ #define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ #define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_ReportTypes 0x00000200 /* Include information on datatypes */ /* in 4th argument of callback */ /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ #define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ #define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ #define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ #define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ struct FuncDef { void (*xFunc)(sqlite_func*,int,const char**); /* Regular function */ void (*xStep)(sqlite_func*,int,const char**); /* Aggregate function step */ void (*xFinalize)(sqlite_func*); /* Aggregate function finializer */ signed char nArg; /* Number of arguments. -1 means unlimited */ signed char dataType; /* Arg that determines datatype. -1=NUMERIC, */ /* -2=TEXT. -3=SQLITE_ARGS */ u8 includeTypes; /* Add datatypes to args of xFunc and xStep */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ }; /* ** information about each column of an SQL table is held in an instance ** of this structure. */ struct Column { char *zName; /* Name of this column */ char *zDflt; /* Default value of this column */ char *zType; /* Data type for this column */ u8 notNull; /* True if there is a NOT NULL constraint */ u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ u8 sortOrder; /* Some combination of SQLITE_SO_... values */ u8 dottedName; /* True if zName contains a "." character */ }; /* ** The allowed sort orders. ** ** The TEXT and NUM values use bits that do not overlap with DESC and ASC. ** That way the two can be combined into a single number. */ #define SQLITE_SO_UNK 0 /* Use the default collating type. (SCT_NUM) */ #define SQLITE_SO_TEXT 2 /* Sort using memcmp() */ #define SQLITE_SO_NUM 4 /* Sort using sqliteCompare() */ #define SQLITE_SO_TYPEMASK 6 /* Mask to extract the collating sequence */ #define SQLITE_SO_ASC 0 /* Sort in ascending order */ #define SQLITE_SO_DESC 1 /* Sort in descending order */ #define SQLITE_SO_DIRMASK 1 /* Mask to extract the sort direction */ /* ** Each SQL table is represented in memory by an instance of the ** following structure. ** ** Table.zName is the name of the table. The case of the original ** CREATE TABLE statement is stored, but case is not significant for ** comparisons. ** ** Table.nCol is the number of columns in this table. Table.aCol is a ** pointer to an array of Column structures, one for each column. ** ** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of ** the column that is that key. Otherwise Table.iPKey is negative. Note ** that the datatype of the PRIMARY KEY must be INTEGER for this field to ** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of ** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid ** is generated for each row of the table. Table.hasPrimKey is true if ** the table has any PRIMARY KEY, INTEGER or otherwise. ** ** Table.tnum is the page number for the root BTree page of the table in the ** database file. If Table.iDb is the index of the database table backend ** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that ** holds temporary tables and indices. If Table.isTransient ** is true, then the table is stored in a file that is automatically deleted ** when the VDBE cursor to the table is closed. In this case Table.tnum ** refers VDBE cursor number that holds the table open, not to the root ** page number. Transient tables are used to hold the results of a ** sub-query that appears instead of a real table name in the FROM clause ** of a SELECT statement. */ struct Table { char *zName; /* Name of the table */ int nCol; /* Number of columns in this table */ Column *aCol; /* Information about each column */ int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ Index *pIndex; /* List of SQL indexes on this table. */ int tnum; /* Root BTree node for this table (see note above) */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ u8 readOnly; /* True if this table should not be written by the user */ u8 iDb; /* Index into sqlite.aDb[] of the backend for this table */ u8 isTransient; /* True if automatically deleted when VDBE finishes */ u8 hasPrimKey; /* True if there exists a primary key */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ Trigger *pTrigger; /* List of SQL triggers on this table */ FKey *pFKey; /* Linked list of all foreign keys in this table */ }; /* ** Each foreign key constraint is an instance of the following structure. ** ** A foreign key is associated with two tables. The "from" table is ** the table that contains the REFERENCES clause that creates the foreign ** key. The "to" table is the table that is named in the REFERENCES clause. ** Consider this example: ** ** CREATE TABLE ex1( ** a INTEGER PRIMARY KEY, ** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) ** ); ** ** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". ** ** Each REFERENCES clause generates an instance of the following structure ** which is attached to the from-table. The to-table need not exist when ** the from-table is created. The existance of the to-table is not checked ** until an attempt is made to insert data into the from-table. ** ** The sqlite.aFKey hash table stores pointers to this structure ** given the name of a to-table. For each to-table, all foreign keys ** associated with that table are on a linked list using the FKey.pNextTo ** field. */ struct FKey { Table *pFrom; /* The table that constains the REFERENCES clause */ FKey *pNextFrom; /* Next foreign key in pFrom */ char *zTo; /* Name of table that the key points to */ FKey *pNextTo; /* Next foreign key that points to zTo */ int nCol; /* Number of columns in this key */ struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ int iFrom; /* Index of column in pFrom */ char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ } *aCol; /* One entry for each of nCol column s */ u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ u8 updateConf; /* How to resolve conflicts that occur on UPDATE */ u8 deleteConf; /* How to resolve conflicts that occur on DELETE */ u8 insertConf; /* How to resolve conflicts that occur on INSERT */ }; /* ** SQLite supports many different ways to resolve a contraint ** error. ROLLBACK processing means that a constraint violation ** causes the operation in process to fail and for the current transaction ** to be rolled back. ABORT processing means the operation in process ** fails and any prior changes from that one operation are backed out, ** but the transaction is not rolled back. FAIL processing means that ** the operation in progress stops and returns an error code. But prior ** changes due to the same operation are not backed out and no rollback ** occurs. IGNORE means that the particular row that caused the constraint ** error is not inserted or updated. Processing continues and no error ** is returned. REPLACE means that preexisting database rows that caused ** a UNIQUE constraint violation are removed so that the new insert or ** update can proceed. Processing continues and no error is reported. ** ** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. ** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the ** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign ** key is set to NULL. CASCADE means that a DELETE or UPDATE of the ** referenced table row is propagated into the row that holds the ** foreign key. ** ** The following symbolic values are used to record which type ** of action to take. */ #define OE_None 0 /* There is no constraint to check */ #define OE_Rollback 1 /* Fail the operation and rollback the transaction */ #define OE_Abort 2 /* Back out changes but do no rollback transaction */ #define OE_Fail 3 /* Stop the operation but leave all prior changes */ #define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ #define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ #define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ #define OE_SetNull 7 /* Set the foreign key value to NULL */ #define OE_SetDflt 8 /* Set the foreign key value to its default */ #define OE_Cascade 9 /* Cascade the changes */ #define OE_Default 99 /* Do whatever the default action is */ /* ** Each SQL index is represented in memory by an ** instance of the following structure. ** ** The columns of the table that are to be indexed are described ** by the aiColumn[] field of this structure. For example, suppose ** we have the following table and index: ** ** CREATE TABLE Ex1(c1 int, c2 int, c3 text); ** CREATE INDEX Ex2 ON Ex1(c3,c1); ** ** In the Table structure describing Ex1, nCol==3 because there are ** three columns in the table. In the Index structure describing ** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. ** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the ** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. ** The second column to be indexed (c1) has an index of 0 in ** Ex1.aCol[], hence Ex2.aiColumn[1]==0. ** ** The Index.onError field determines whether or not the indexed columns ** must be unique and what to do if they are not. When Index.onError=OE_None, ** it means this is not a unique index. Otherwise it is a unique index ** and the value of Index.onError indicate the which conflict resolution ** algorithm to employ whenever an attempt is made to insert a non-unique ** element. */ struct Index { char *zName; /* Name of this index */ int nColumn; /* Number of columns in the table used by this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ Table *pTable; /* The SQL table being indexed */ int tnum; /* Page containing root of this index in database file */ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */ Index *pNext; /* The next index associated with the same table */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** ** Note if Token.z==0 then Token.dyn and Token.n are undefined and ** may contain random values. Do not make any assuptions about Token.dyn ** and Token.n when Token.z==0. */ struct Token { const char *z; /* Text of the token. Not NULL-terminated! */ unsigned dyn : 1; /* True for malloced memory, false for static */ unsigned n : 31; /* Number of characters in this token */ }; /* ** Each node of an expression in the parse tree is an instance ** of this structure. ** ** Expr.op is the opcode. The integer parser token codes are reused ** as opcodes here. For example, the parser defines TK_GE to be an integer ** code representing the ">=" operator. This same integer code is reused ** to represent the greater-than-or-equal-to operator in the expression ** tree. ** ** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list ** of argument if the expression is a function. ** ** Expr.token is the operator token for this node. For some expressions ** that have subexpressions, Expr.token can be the complete text that gave ** rise to the Expr. In the latter case, the token is marked as being ** a compound token. ** ** An expression of the form ID or ID.ID refers to a column in a table. ** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is ** the integer cursor number of a VDBE cursor pointing to that table and ** Expr.iColumn is the column number for the specific column. If the ** expression is used as a result in an aggregate SELECT, then the ** value is also stored in the Expr.iAgg column in the aggregate so that ** it can be accessed after all aggregates are computed. ** ** If the expression is a function, the Expr.iTable is an integer code ** representing which function. If the expression is an unbound variable ** marker (a question mark character '?' in the original SQL) then the ** Expr.iTable holds the index number for that variable. ** ** The Expr.pSelect field points to a SELECT statement. The SELECT might ** be the right operand of an IN operator. Or, if a scalar SELECT appears ** in an expression the opcode is TK_SELECT and Expr.pSelect is the only ** operand. */ struct Expr { u8 op; /* Operation performed by this node */ u8 dataType; /* Either SQLITE_SO_TEXT or SQLITE_SO_NUM */ u8 iDb; /* Database referenced by this expression */ u8 flags; /* Various flags. See below */ Expr *pLeft, *pRight; /* Left and right subnodes */ ExprList *pList; /* A list of expressions used as function arguments ** or in " IN (useAgg==TRUE, pull ** result from the iAgg-th element of the aggregator */ Select *pSelect; /* When the expression is a sub-select. Also the ** right side of " IN (