#!/www/server/bin/php -qC
<?php

#  Tests for it_dbi.class

# Initialize DB
$db = array('db' => "lib_search_ch", 'safety' => 0);
$dbi = new it_dbi($db);
$dbi->query('create temporary table it_dbi_test (
	ID int not null auto_increment,
	x int,
	foo varchar(42),
	dyncols LONGBLOB,
	primary key(ID)
);');

$record = new it_dbi($db + array('table' => "it_dbi_test"));

$record->insert(array('x' => 42, 'foo' => null));
$record->insert(array('foo' => "bar"));
$record->insert(array('x' => 64738, 'foo' => "q'uux"));

is(
	$record->ID,
	3,
	"auto_increment"
);

$record->read(1);
is(
	array($record->_key, $record->x, $record->foo),
	array(1, 42, null),
	"read"
);

is(
	$record->select(),
	3,
	"select without parameters select all"
);

is(
	$record->select(array('foo <>' => ""), "LIMIT 1"),
	1,
	"select with multiple parameters (LIMIT part)"
);
is(
	$record->foo,
	"bar",
	"select with multiple parameters (foo part)"
);
is(
	$record->select(array('ID IN' => array(2,3))),
	2,
	"select with IN"
);
is(
	$record->select(array('ID NI' => array(2,3))),
	2,
	"select with NI"
);
is(
	$record->select(array('ID NOT IN' => array(2,3))),
	1,
	"select with NOT IN"
);
is(
	$record->select(array('ID IN' => array())),
	0,
	"select with empty IN"
);
is(
	$record->select(array('ID NOT IN' => array())),
	3,
	"select with empty NOT IN"
);
is(
	$record->select(array('ID' => array(2,3))),
	2,
	"select with implicit IN"
);

it_dbi::createclass(array('table' => "it_dbi_test", 'forcecreate' => true));

$record = new it_dbi_test;
is(
	$record->x,
	null,
	"constructor of created class without argument"
);

$record = new it_dbi_test(2);
is(
	$record->ID,
	2,
	"constructor of created class with id parameter"
);

$record = new it_dbi_test(array('x >' => 0), "ORDER BY x DESC");
is(
	$record->x,
	64738,
	"constructor of created class with multiple select parameters"
);

$record = new it_dbi_test(array('foo' => 'bar'));
is(
	$record->ID,
	2,
	"constructor of created class with single array parameter"
);

$record = new it_dbi($db + array('table' => "it_dbi_test"));
is(
	$record->x,
	null,
	"constructor without parameters"
);

$record = new it_dbi($db + array('table' => "it_dbi_test"), array('x >' => 0), "ORDER BY x DESC");
is(
	$record->x,
	64738,
	"constructor with multiple select parameters"
);

$record->select(array('x' => 64738));
is(
	array($record->_key, $record->x, $record->foo),
	array(3, 64738, "q'uux"),
	"select"
);

$record->update(array('x' => 17));
is(
	array($record->_key, $record->x, $record->foo),
	array(3, 17, "q'uux"),
	"update"
);

is(
	$record->update(array('x' => 18), array('x' => 17)),
	1,
	"return affected rows"
);

is(
	$record->update(array('x' => 18), array('x' => 17)),
	0,
	"return zero affected rows"
);

$record->update(array('-x' => 'POW(2,2) * 10'));
is(
	array($record->_key, $record->x, $record->foo),
	array(3, 40, "q'uux"),
	"update with function"
);

$record->update(array('foo' => "00"));
$rand = $record->x;
is (
	$record->_set(array('x' => $rand, 'foo' => "0")),
	"SET `foo`='0'",
	'update: _set optimization'
);

$record->update(array('foo' => NULL));
is (
	$record->_set(array('foo' => "")),
	"SET `foo`=''",
	'update: _set optimization with NULL => ""'
);
$record->update(array('foo' => "bar"));
$record->update(array('foo' => ""));
is (
	$record->_set(array('foo' => NULL)),
	"SET `foo`=NULL",
	'update: _set optimization with "" => NULL'
);

$record->update(array('foo' => "bar"));
$record->select(array('foo' => "bar"));
$record->iterate();
is(
	array($record->_key, $record->x, $record->foo),
	array(2, null, "bar"),
	"iterate record 2"
);
$record->update(array('foo' => "qux"));
$record->iterate();
is(
	array($record->_key, $record->x, $record->foo),
	array(3, $rand, "bar"),
	"iterate record 3"
);
$record->update(array('foo' => "quux"));

$record->read(2);
is(
	array($record->_key, isset($record->x), $record->foo),
	array(2, false, "qux"),
	"iterate update record 2"
);

$record->read(3);
is(
	array($record->_key, $record->x, $record->foo),
	array(3, $rand, "quux"),
	"iterate update record 3"
);

is(
	gettype($record->_key) . "/" . gettype($record->x) . "/" . gettype($record->_data['x']) . "/" . gettype($record->foo),
	"integer/integer/integer/string",
	"automatic type detection"
);

$count = 0;
foreach (new it_dbi_test as $id => $record)
{
	$count++;
	is($record->_key, $id, "Iterator id $id");
}
is($count, 3, "Iterator without select");

$count = 0;
foreach (new it_dbi_test(array('foo <>' => "")) as $id => $record)
{
	$count++;
	is($record->_key, $id, "Iterator id $id");
}
is($count, 2, "Iterator with select");

$count = 0;
foreach ($record as $dummy_rec)
	$count++;
is($count, 2, "Iterator reused");

$GLOBALS['debug_sqllog'] = true;
@$record->store(array('ID' => 5, 'x' => 6));
like(
	$record->_sqllog[1]['query'],
	"REPLACE",
	"store => REPLACE for new entries"
);
$record->clear();
@$record->read(5);
is(
	$record->x,
	6,
	"saving with store"
);

$record->_sqllog = array();
@$record->store(array('ID' => 5, 'x' => 7));
like(
	$record->_sqllog[1]['query'],
	"UPDATE",
	"store => UPDATE for existing entries"
);
$record->clear();
@$record->read(5);
is(
	$record->x,
	7,
	"updating with store"
);

$record->_sqllog = array();
@$record->store(array('ID' => 5, 'x' => 7));
is(
	$record->_sqllog[1]['query'],
	null,	# Only SELECT, no UPDATE
	"Optimized away UPDATE with same values"
);
$GLOBALS['debug_sqllog'] = false;

# test latin1 (produces warnings on stderr for failing)

$record = new it_dbi(array('table' => 'it_dbi_test', 'charset' => 'latin1'));
$record->select(array('foo' => "\xc3\x28"));

# Test field localization feature

$dbi->query('create temporary table it_dbi_testlocalized (
	ID int not null auto_increment,
	foobar_de varchar(42),
	foobar_fr varchar(42),
	primary key(ID)
);');

$record = new it_dbi($db + array('table' => "it_dbi_testlocalized"));
$record->insert(array('foobar_de' => "deutsch", 'foobar_fr' => "franz"));
$record->insert(array('foobar_de' => "deutsch2", 'foobar_fr' => "franz2"));

T_set_language('de');
$record->select(array());
$record->iterate();
is(
	array($record->_key, $record->foobar),
	array(1, "deutsch"),
	"localized field foobar_de"
);
$record->iterate();
is(
	array($record->_key, $record->foobar),
	array(2, "deutsch2"),
	"localized field foobar_de iterate"
);

T_set_language('fr');
$record->read(1);
is(
	array($record->_key, $record->foobar),
	array(1, "franz"),
	"localized field foobar_fr"
);

#
# Test saving/retrieving/matching values in dynamically created columns
#
$record = new it_dbi_test;
$record->replace(['ID' => 5, 'key1' => "val1"]); is($record->key1, "val1");
$record->update(['key2' => "val2"]);             is($record->key1, "val1"); is($record->key2, "val2");
$record->update(['-key3' => "2*2"]);             is($record->key1, "val1"); is($record->key2, "val2"); is($record->key3, 4);
$record->update(['key1' => "val0"]);             is($record->key1, "val0"); is($record->key2, "val2"); is($record->key3, 4);
$record->replace(['ID' => 6, 'key4' => "val4"]); is($record->key4, "val4");
$record->select(['key2' => "val2"]);             is($record->key2, "val2"); is($record->key4, null, "clear previous fields");

#
# Test tracked update
#
function allrecs()
{
	foreach (new it_dbi_test([0 => "ORDER BY ID"]) as $r)
		$result[] = ['ID' => $r->ID, 'foo' => $r->foo];
	return json_encode($result);
}

$record = new it_dbi_test;
$record->delete(['WHERE 1' ]);
$record->upsert(['ID' => 1, 'foo' => "a"]);
$record->upsert(['ID' => 2, 'foo' => "b"]);
$record->upsert(['ID' => 2, 'foo' => "B"]);
is($record->delete_untouched(), 0, 'delete_untouched');
is(allrecs(), '[{"ID":1,"foo":"a"},{"ID":2,"foo":"B"}]', 'data after delete_untouched');

$record->upsert(['ID' => 1, 'foo' => "A"]);
$record->upsert(['ID' => 3, 'foo' => "c"]);
is($record->delete_untouched([ 'ID >' => 2 ]), 0, 'delete_untouched with query');
is(allrecs(), '[{"ID":1,"foo":"A"},{"ID":2,"foo":"B"},{"ID":3,"foo":"c"}]', 'data after delete_untouched with query');

$record->upsert(['ID' => 3, 'foo' => "C"]);
is($record->delete_untouched(), 2, 'delete_untouched with query');
is(allrecs(), '[{"ID":3,"foo":"C"}]', 'data after delete_untouched with query');

$record->replace(['ID' => 4, 'foo' => "C"]);
is($record->delete_untouched(), 1, 'delete_untouched after replace');
is(allrecs(), '[{"ID":4,"foo":"C"}]', 'data after delete_untouched after replace');

$record->upsert(['ID' => 4, 'foo' => "C"]);
is($record->delete_untouched(), 0, 'delete_untouched after upsert without changes');
is(allrecs(), '[{"ID":4,"foo":"C"}]', 'data after delete_untouched after upsert without changes');