Skip to content

Commit

Permalink
Merge branch 'w14_MDL-39038_m25_oracleconcat' of git://github.com/sko…
Browse files Browse the repository at this point in the history
…dak/moodle
  • Loading branch information
stronk7 committed Apr 9, 2013
2 parents cf42eec + 031a6de commit 13af1f0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 36 deletions.
64 changes: 39 additions & 25 deletions lib/dml/oci_native_moodle_database.php
Original file line number Diff line number Diff line change
Expand Up @@ -1540,43 +1540,57 @@ public function sql_like($fieldname, $param, $casesensitive = true, $accentsensi
}

public function sql_concat() {
// NOTE: Oracle concat implementation isn't ANSI compliant when using NULLs (the result of
// any concatenation with NULL must return NULL) because of his inability to differentiate
// NULLs and empty strings. So this function will cause some tests to fail. Hopefully
// it's only a side case and it won't affect normal concatenation operations in Moodle.
$arr = func_get_args();
if ($this->oci_package_installed()) {
foreach ($arr as $k => $v) {
if (strpos($v, "'") === 0) {
continue;
}
$arr[$k] = "MOODLELIB.UNDO_DIRTY_HACK($v)";
}
}
$s = implode(' || ', $arr);
if ($s === '') {
if (empty($arr)) {
return " ' ' ";
}
return " MOODLELIB.DIRTY_HACK($s) ";
foreach ($arr as $k => $v) {
if ($v === "' '") {
$arr[$k] = "'*OCISP*'"; // New mega hack.
}
}
$s = $this->recursive_concat($arr);
return " MOODLELIB.UNDO_MEGA_HACK($s) ";
}

public function sql_concat_join($separator="' '", $elements=array()) {
if ($this->oci_package_installed()) {
foreach ($elements as $k => $v) {
if (strpos($v, "'") === 0) {
continue;
}
$elements[$k] = "MOODLELIB.UNDO_DIRTY_HACK($v)";
public function sql_concat_join($separator="' '", $elements = array()) {
if ($separator === "' '") {
$separator = "'*OCISP*'"; // New mega hack.
}
foreach ($elements as $k => $v) {
if ($v === "' '") {
$elements[$k] = "'*OCISP*'"; // New mega hack.
}
}
for ($n = count($elements)-1; $n > 0 ; $n--) {
array_splice($elements, $n, 0, $separator);
}
$s = implode(' || ', $elements);
if ($s === '') {
if (empty($elements)) {
return " ' ' ";
}
return " MOODLELIB.DIRTY_HACK($s) ";
$s = $this->recursive_concat($elements);
return " MOODLELIB.UNDO_MEGA_HACK($s) ";
}

/**
* Mega hacky magic to work around crazy Oracle NULL concats.
* @param array $args
* @return string
*/
protected function recursive_concat(array $args) {
$count = count($args);
if ($count == 1) {
$arg = reset($args);
return $arg;
}
if ($count == 2) {
$args[] = "' '";
// No return here intentionally.
}
$first = array_shift($args);
$second = array_shift($args);
$third = $this->recursive_concat($args);
return "MOODLELIB.TRICONCAT($first, $second, $third)";
}

/**
Expand Down
43 changes: 33 additions & 10 deletions lib/dml/oci_native_moodle_package.sql
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ FUNCTION GET_HANDLE (lock_name IN VARCHAR2) RETURN VARCHAR2;
FUNCTION GET_LOCK (lock_name IN VARCHAR2, lock_timeout IN INTEGER) RETURN INTEGER;
FUNCTION RELEASE_LOCK(lock_name IN VARCHAR2) RETURN INTEGER;

FUNCTION DIRTY_HACK(somestring IN VARCHAR2) RETURN VARCHAR2;
FUNCTION UNDO_DIRTY_HACK(hackedstring IN VARCHAR2) RETURN VARCHAR2;
FUNCTION UNDO_MEGA_HACK(hackedstring IN VARCHAR2) RETURN VARCHAR2;
FUNCTION TRICONCAT(string1 IN VARCHAR2, string2 IN VARCHAR2, string3 IN VARCHAR2) RETURN VARCHAR2;

END MOODLELIB;
/
Expand Down Expand Up @@ -101,15 +102,6 @@ BEGIN
RETURN 1;
END RELEASE_LOCK;

FUNCTION DIRTY_HACK(somestring IN VARCHAR2) RETURN VARCHAR2 IS

BEGIN
IF somestring = '' THEN
RETURN ' ';
END IF;
RETURN somestring;
END DIRTY_HACK;

FUNCTION UNDO_DIRTY_HACK(hackedstring IN VARCHAR2) RETURN VARCHAR2 IS

BEGIN
Expand All @@ -119,5 +111,36 @@ BEGIN
RETURN hackedstring;
END UNDO_DIRTY_HACK;

FUNCTION UNDO_MEGA_HACK(hackedstring IN VARCHAR2) RETURN VARCHAR2 IS

BEGIN
IF hackedstring IS NULL THEN
RETURN hackedstring;
END IF;
RETURN REPLACE(hackedstring, '*OCISP*', ' ');
END UNDO_MEGA_HACK;

FUNCTION TRICONCAT(string1 IN VARCHAR2, string2 IN VARCHAR2, string3 IN VARCHAR2) RETURN VARCHAR2 IS
stringresult VARCHAR2(1333);
BEGIN
IF string1 IS NULL THEN
RETURN NULL;
END IF;
IF string2 IS NULL THEN
RETURN NULL;
END IF;
IF string3 IS NULL THEN
RETURN NULL;
END IF;

stringresult := CONCAT(CONCAT(MOODLELIB.UNDO_DIRTY_HACK(string1), MOODLELIB.UNDO_DIRTY_HACK(string2)), MOODLELIB.UNDO_DIRTY_HACK(string3));

IF stringresult IS NULL THEN
RETURN ' ';
END IF;

RETURN stringresult;
END;

END MOODLELIB;
/
2 changes: 1 addition & 1 deletion lib/dml/tests/dml_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -3796,7 +3796,7 @@ function test_sql_concat() {
$this->assertEquals('123456', $DB->get_field_sql($sql, $params));
// float, null and strings
$params = array(123.45, null, 'test');
$this->assertNull($DB->get_field_sql($sql, $params), 'ANSI behaviour: Concatenating NULL must return NULL - But in Oracle :-(. [%s]'); // Concatenate NULL with anything result = NULL
$this->assertNull($DB->get_field_sql($sql, $params)); // Concatenate NULL with anything result = NULL

// Testing fieldnames + values and also integer fieldnames
$table = $this->get_test_table();
Expand Down

0 comments on commit 13af1f0

Please sign in to comment.