Commit b8eaff85 by Scott

Coding style (db admin)

parent 4b284792
......@@ -20,87 +20,92 @@
More about this license: http://www.question2answer.org/license.php
*/
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
}
function qa_db_mysql_version()
/*
Return the current version of MySQL
*/
{
/**
* Return the current version of MySQL
*/
function qa_db_mysql_version()
{
return qa_db_read_one_value(qa_db_query_raw('SELECT VERSION()'));
}
}
function qa_db_table_size()
/*
Return the total size in bytes of all relevant tables in the Q2A database
*/
{
/**
* Return the total size in bytes of all relevant tables in the Q2A database
*/
function qa_db_table_size()
{
if (defined('QA_MYSQL_USERS_PREFIX')) { // check if one of the prefixes is a prefix itself of the other
if (stripos(QA_MYSQL_USERS_PREFIX, QA_MYSQL_TABLE_PREFIX)===0)
$prefixes=array(QA_MYSQL_TABLE_PREFIX);
elseif (stripos(QA_MYSQL_TABLE_PREFIX, QA_MYSQL_USERS_PREFIX)===0)
$prefixes=array(QA_MYSQL_USERS_PREFIX);
if (stripos(QA_MYSQL_USERS_PREFIX, QA_MYSQL_TABLE_PREFIX) === 0)
$prefixes = array(QA_MYSQL_TABLE_PREFIX);
elseif (stripos(QA_MYSQL_TABLE_PREFIX, QA_MYSQL_USERS_PREFIX) === 0)
$prefixes = array(QA_MYSQL_USERS_PREFIX);
else
$prefixes=array(QA_MYSQL_TABLE_PREFIX, QA_MYSQL_USERS_PREFIX);
$prefixes = array(QA_MYSQL_TABLE_PREFIX, QA_MYSQL_USERS_PREFIX);
} else
$prefixes=array(QA_MYSQL_TABLE_PREFIX);
$prefixes = array(QA_MYSQL_TABLE_PREFIX);
$size=0;
$size = 0;
foreach ($prefixes as $prefix) {
$statuses=qa_db_read_all_assoc(qa_db_query_raw(
"SHOW TABLE STATUS LIKE '".$prefix."%'"
$statuses = qa_db_read_all_assoc(qa_db_query_raw(
"SHOW TABLE STATUS LIKE '" . $prefix . "%'"
));
foreach ($statuses as $status)
$size+=$status['Data_length']+$status['Index_length'];
$size += $status['Data_length'] + $status['Index_length'];
}
return $size;
}
}
function qa_db_count_posts($type=null, $fromuser=null)
/*
Return a count of the number of posts of $type in database.
Set $fromuser to true to only count non-anonymous posts, false to only count anonymous posts
*/
{
$wheresql='';
/**
* Return a count of the number of posts of $type in database.
* Set $fromuser to true to only count non-anonymous posts, false to only count anonymous posts
* @param $type
* @param $fromuser
* @return mixed|null
*/
function qa_db_count_posts($type = null, $fromuser = null)
{
$wheresql = '';
if (isset($type))
$wheresql.=' WHERE type='.qa_db_argument_to_mysql($type, true);
$wheresql .= ' WHERE type=' . qa_db_argument_to_mysql($type, true);
if (isset($fromuser))
$wheresql.=(strlen($wheresql) ? ' AND' : ' WHERE').' userid '.($fromuser ? 'IS NOT' : 'IS').' NULL';
$wheresql .= (strlen($wheresql) ? ' AND' : ' WHERE') . ' userid ' . ($fromuser ? 'IS NOT' : 'IS') . ' NULL';
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^posts'.$wheresql
'SELECT COUNT(*) FROM ^posts' . $wheresql
));
}
}
function qa_db_count_users()
/*
Return number of registered users in database.
*/
{
/**
* Return number of registered users in database.
*/
function qa_db_count_users()
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^users'
));
}
}
function qa_db_count_active_users($table)
/*
Return number of active users in database $table
*/
{
/**
* Return number of active users in database $table
* @param $table
* @return mixed|null
*/
function qa_db_count_active_users($table)
{
switch ($table) {
case 'posts':
case 'uservotes':
......@@ -113,63 +118,71 @@
}
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(DISTINCT(userid)) FROM ^'.$table
'SELECT COUNT(DISTINCT(userid)) FROM ^' . $table
));
}
}
function qa_db_count_categories()
/*
Return number of categories in the database
*/
{
/**
* Return number of categories in the database
*/
function qa_db_count_categories()
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^categories'
));
}
}
function qa_db_count_categoryid_qs($categoryid)
/*
Return number of questions in the database in $categoryid exactly, and not one of its subcategories
*/
{
/**
* Return number of questions in the database in $categoryid exactly, and not one of its subcategories
* @param $categoryid
* @return mixed|null
*/
function qa_db_count_categoryid_qs($categoryid)
{
return qa_db_read_one_value(qa_db_query_sub(
"SELECT COUNT(*) FROM ^posts WHERE categoryid<=># AND type='Q'",
$categoryid
));
}
}
function qa_db_get_user_visible_postids($userid)
/*
Return list of postids of visible or queued posts by $userid
*/
{
/**
* Return list of postids of visible or queued posts by $userid
* @param $userid
* @return array
*/
function qa_db_get_user_visible_postids($userid)
{
return qa_db_read_all_values(qa_db_query_sub(
"SELECT postid FROM ^posts WHERE userid=# AND type IN ('Q', 'A', 'C', 'Q_QUEUED', 'A_QUEUED', 'C_QUEUED')",
$userid
));
}
}
function qa_db_get_ip_visible_postids($ip)
/*
Return list of postids of visible or queued posts from $ip address
*/
{
/**
* Return list of postids of visible or queued posts from $ip address
* @param $ip
* @return array
*/
function qa_db_get_ip_visible_postids($ip)
{
return qa_db_read_all_values(qa_db_query_sub(
"SELECT postid FROM ^posts WHERE createip=$ AND type IN ('Q', 'A', 'C', 'Q_QUEUED', 'A_QUEUED', 'C_QUEUED')",
@inet_pton($ip)
));
}
}
function qa_db_postids_count_dependents($postids)
/*
Return an array whose keys contain the $postids which exist, and whose elements contain the number of other posts depending on each one
*/
{
/**
* Return an array whose keys contain the $postids which exist, and whose elements contain the number of other posts depending on each one
* @param $postids
* @return array
*/
function qa_db_postids_count_dependents($postids)
{
if (count($postids))
return qa_db_read_all_assoc(qa_db_query_sub(
"SELECT postid, COALESCE(childcount, 0) AS count FROM ^posts LEFT JOIN (SELECT parentid, COUNT(*) AS childcount FROM ^posts WHERE parentid IN (#) AND LEFT(type, 1) IN ('A', 'C') GROUP BY parentid) x ON postid=x.parentid WHERE postid IN (#)",
......@@ -177,234 +190,270 @@
), 'postid', 'count');
else
return array();
}
function qa_db_get_unapproved_users($count)
/*
Return an array of the (up to) $count most recently created users who are awaiting approval and have not been blocked.
The array element for each user includes a 'profile' key whose value is an array of non-empty profile fields of the user.
*/
{
$results=qa_db_read_all_assoc(qa_db_query_sub(
}
/**
* Return an array of the (up to) $count most recently created users who are awaiting approval and have not been blocked.
* The array element for each user includes a 'profile' key whose value is an array of non-empty profile fields of the user.
* @param $count
* @return array
*/
function qa_db_get_unapproved_users($count)
{
$results = qa_db_read_all_assoc(qa_db_query_sub(
"SELECT ^users.userid, UNIX_TIMESTAMP(created) AS created, createip, email, handle, flags, title, content FROM ^users LEFT JOIN ^userprofile ON ^users.userid=^userprofile.userid AND LENGTH(content)>0 WHERE level<# AND NOT (flags&#) ORDER BY created DESC LIMIT #",
QA_USER_LEVEL_APPROVED, QA_USER_FLAGS_USER_BLOCKED, $count
));
$users=array();
$users = array();
foreach ($results as $result) {
$userid=$result['userid'];
$userid = $result['userid'];
if (!isset($users[$userid])) {
$users[$result['userid']]=$result;
$users[$result['userid']]['profile']=array();
$users[$result['userid']] = $result;
$users[$result['userid']]['profile'] = array();
unset($users[$userid]['title']);
unset($users[$userid]['content']);
}
if (isset($result['title']) && isset($result['content']))
$users[$userid]['profile'][$result['title']]=$result['content'];
$users[$userid]['profile'][$result['title']] = $result['content'];
}
return $users;
}
}
function qa_db_has_blobs_on_disk()
/*
Return whether there are any blobs whose content has been stored as a file on disk
*/
{
/**
* Return whether there are any blobs whose content has been stored as a file on disk
*/
function qa_db_has_blobs_on_disk()
{
return qa_db_read_one_value(qa_db_query_sub('SELECT blobid FROM ^blobs WHERE content IS NULL LIMIT 1'), true) != null;
}
}
function qa_db_has_blobs_in_db()
/*
Return whether there are any blobs whose content has been stored in the database
*/
{
/**
* Return whether there are any blobs whose content has been stored in the database
*/
function qa_db_has_blobs_in_db()
{
return qa_db_read_one_value(qa_db_query_sub('SELECT blobid FROM ^blobs WHERE content IS NOT NULL LIMIT 1'), true) != null;
}
}
function qa_db_category_last_pos($parentid)
/*
Return the maximum position of the categories with $parentid
*/
{
/**
* Return the maximum position of the categories with $parentid
* @param $parentid
* @return mixed|null
*/
function qa_db_category_last_pos($parentid)
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COALESCE(MAX(position), 0) FROM ^categories WHERE parentid<=>#',
$parentid
));
}
}
function qa_db_category_child_depth($categoryid)
/*
Return how many levels of subcategory there are below $categoryid
*/
{
/**
* Return how many levels of subcategory there are below $categoryid
* @param $categoryid
* @return int
*/
function qa_db_category_child_depth($categoryid)
{
// This is potentially a very slow query since it counts all the multi-generational offspring of a particular category
// But it's only used for admin purposes when moving a category around so I don't think it's worth making more efficient
// (Incidentally, this could be done by keeping a count for every category of how many generations of offspring it has.)
$result=qa_db_read_one_assoc(qa_db_query_sub(
$result = qa_db_read_one_assoc(qa_db_query_sub(
'SELECT COUNT(child1.categoryid) AS count1, COUNT(child2.categoryid) AS count2, COUNT(child3.categoryid) AS count3 FROM ^categories AS child1 LEFT JOIN ^categories AS child2 ON child2.parentid=child1.categoryid LEFT JOIN ^categories AS child3 ON child3.parentid=child2.categoryid WHERE child1.parentid=#;', // requires QA_CATEGORY_DEPTH=4
$categoryid
));
for ($depth=QA_CATEGORY_DEPTH-1; $depth>=1; $depth--)
if ($result['count'.$depth])
for ($depth = QA_CATEGORY_DEPTH - 1; $depth >= 1; $depth--)
if ($result['count' . $depth])
return $depth;
return 0;
}
}
function qa_db_category_create($parentid, $title, $tags)
/*
Create a new category with $parentid, $title (=name) and $tags (=slug) in the database
*/
{
$lastpos=qa_db_category_last_pos($parentid);
/**
* Create a new category with $parentid, $title (=name) and $tags (=slug) in the database
* @param $parentid
* @param $title
* @param $tags
* @return mixed
*/
function qa_db_category_create($parentid, $title, $tags)
{
$lastpos = qa_db_category_last_pos($parentid);
qa_db_query_sub(
'INSERT INTO ^categories (parentid, title, tags, position) VALUES (#, $, $, #)',
$parentid, $title, $tags, 1+$lastpos
$parentid, $title, $tags, 1 + $lastpos
);
$categoryid=qa_db_last_insert_id();
$categoryid = qa_db_last_insert_id();
qa_db_categories_recalc_backpaths($categoryid);
return $categoryid;
}
}
function qa_db_categories_recalc_backpaths($firstcategoryid, $lastcategoryid=null)
/*
Recalculate the backpath columns for all categories from $firstcategoryid to $lastcategoryid (if specified)
*/
{
/**
* Recalculate the backpath columns for all categories from $firstcategoryid to $lastcategoryid (if specified)
* @param $firstcategoryid
* @param $lastcategoryid
*/
function qa_db_categories_recalc_backpaths($firstcategoryid, $lastcategoryid = null)
{
if (!isset($lastcategoryid))
$lastcategoryid=$firstcategoryid;
$lastcategoryid = $firstcategoryid;
qa_db_query_sub(
"UPDATE ^categories AS x, (SELECT cat1.categoryid, CONCAT_WS('/', cat1.tags, cat2.tags, cat3.tags, cat4.tags) AS backpath FROM ^categories AS cat1 LEFT JOIN ^categories AS cat2 ON cat1.parentid=cat2.categoryid LEFT JOIN ^categories AS cat3 ON cat2.parentid=cat3.categoryid LEFT JOIN ^categories AS cat4 ON cat3.parentid=cat4.categoryid WHERE cat1.categoryid BETWEEN # AND #) AS a SET x.backpath=a.backpath WHERE x.categoryid=a.categoryid",
$firstcategoryid, $lastcategoryid // requires QA_CATEGORY_DEPTH=4
);
}
}
function qa_db_category_rename($categoryid, $title, $tags)
/*
Set the name of $categoryid to $title and its slug to $tags in the database
*/
{
/**
* Set the name of $categoryid to $title and its slug to $tags in the database
* @param $categoryid
* @param $title
* @param $tags
*/
function qa_db_category_rename($categoryid, $title, $tags)
{
qa_db_query_sub(
'UPDATE ^categories SET title=$, tags=$ WHERE categoryid=#',
$title, $tags, $categoryid
);
qa_db_categories_recalc_backpaths($categoryid); // may also require recalculation of its offspring's backpaths
}
}
function qa_db_category_set_content($categoryid, $content)
/*
Set the content (=description) of $categoryid to $content
*/
{
/**
* Set the content (=description) of $categoryid to $content
* @param $categoryid
* @param $content
*/
function qa_db_category_set_content($categoryid, $content)
{
qa_db_query_sub(
'UPDATE ^categories SET content=$ WHERE categoryid=#',
$content, $categoryid
);
}
}
function qa_db_category_get_parent($categoryid)
/*
Return the parentid of $categoryid
*/
{
/**
* Return the parentid of $categoryid
* @param $categoryid
* @return mixed|null
*/
function qa_db_category_get_parent($categoryid)
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT parentid FROM ^categories WHERE categoryid=#',
$categoryid
));
}
}
function qa_db_category_set_position($categoryid, $newposition)
/*
Move the category $categoryid into position $newposition under its parent
*/
{
/**
* Move the category $categoryid into position $newposition under its parent
* @param $categoryid
* @param $newposition
*/
function qa_db_category_set_position($categoryid, $newposition)
{
qa_db_ordered_move('categories', 'categoryid', $categoryid, $newposition,
qa_db_apply_sub('parentid<=>#', array(qa_db_category_get_parent($categoryid))));
}
}
function qa_db_category_set_parent($categoryid, $newparentid)
/*
Set the parent of $categoryid to $newparentid, placing it in last position (doesn't do necessary recalculations)
*/
{
$oldparentid=qa_db_category_get_parent($categoryid);
/**
* Set the parent of $categoryid to $newparentid, placing it in last position (doesn't do necessary recalculations)
* @param $categoryid
* @param $newparentid
*/
function qa_db_category_set_parent($categoryid, $newparentid)
{
$oldparentid = qa_db_category_get_parent($categoryid);
if (strcmp($oldparentid, $newparentid)) { // if we're changing parent, move to end of old parent, then end of new parent
$lastpos=qa_db_category_last_pos($oldparentid);
$lastpos = qa_db_category_last_pos($oldparentid);
qa_db_ordered_move('categories', 'categoryid', $categoryid, $lastpos, qa_db_apply_sub('parentid<=>#', array($oldparentid)));
$lastpos=qa_db_category_last_pos($newparentid);
$lastpos = qa_db_category_last_pos($newparentid);
qa_db_query_sub(
'UPDATE ^categories SET parentid=#, position=# WHERE categoryid=#',
$newparentid, 1+$lastpos, $categoryid
$newparentid, 1 + $lastpos, $categoryid
);
}
}
}
function qa_db_category_reassign($categoryid, $reassignid)
/*
Change the categoryid of any posts with (exact) $categoryid to $reassignid
*/
{
/**
* Change the categoryid of any posts with (exact) $categoryid to $reassignid
* @param $categoryid
* @param $reassignid
*/
function qa_db_category_reassign($categoryid, $reassignid)
{
qa_db_query_sub('UPDATE ^posts SET categoryid=# WHERE categoryid<=>#', $reassignid, $categoryid);
}
}
function qa_db_category_delete($categoryid)
/*
Delete the category $categoryid in the database
*/
{
/**
* Delete the category $categoryid in the database
* @param $categoryid
*/
function qa_db_category_delete($categoryid)
{
qa_db_ordered_delete('categories', 'categoryid', $categoryid,
qa_db_apply_sub('parentid<=>#', array(qa_db_category_get_parent($categoryid))));
}
}
function qa_db_category_slug_to_id($parentid, $slug)
/*
Return the categoryid for the category with parent $parentid and $slug
*/
{
/**
* Return the categoryid for the category with parent $parentid and $slug
* @param $parentid
* @param $slug
* @return mixed|null
*/
function qa_db_category_slug_to_id($parentid, $slug)
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT categoryid FROM ^categories WHERE parentid<=># AND tags=$',
$parentid, $slug
), true);
}
function qa_db_page_create($title, $flags, $tags, $heading, $content, $permit=null)
/*
Create a new custom page (or link) in the database
*/
{
$position=qa_db_read_one_value(qa_db_query_sub('SELECT 1+COALESCE(MAX(position), 0) FROM ^pages'));
}
/**
* Create a new custom page (or link) in the database
* @param $title
* @param $flags
* @param $tags
* @param $heading
* @param $content
* @param $permit
* @return mixed
*/
function qa_db_page_create($title, $flags, $tags, $heading, $content, $permit = null)
{
$position = qa_db_read_one_value(qa_db_query_sub('SELECT 1+COALESCE(MAX(position), 0) FROM ^pages'));
qa_db_query_sub(
'INSERT INTO ^pages (title, nav, flags, permit, tags, heading, content, position) VALUES ($, \'\', #, #, $, $, $, #)',
......@@ -412,100 +461,125 @@
);
return qa_db_last_insert_id();
}
function qa_db_page_set_fields($pageid, $title, $flags, $tags, $heading, $content, $permit=null)
/*
Set the fields of $pageid to the values provided in the database
*/
{
}
/**
* Set the fields of $pageid to the values provided in the database
* @param $pageid
* @param $title
* @param $flags
* @param $tags
* @param $heading
* @param $content
* @param $permit
*/
function qa_db_page_set_fields($pageid, $title, $flags, $tags, $heading, $content, $permit = null)
{
qa_db_query_sub(
'UPDATE ^pages SET title=$, flags=#, permit=#, tags=$, heading=$, content=$ WHERE pageid=#',
$title, $flags, $permit, $tags, $heading, $content, $pageid
);
}
}
function qa_db_page_move($pageid, $nav, $newposition)
/*
Move the page $pageid into navigation menu $nav and position $newposition in the database
*/
{
/**
* Move the page $pageid into navigation menu $nav and position $newposition in the database
* @param $pageid
* @param $nav
* @param $newposition
*/
function qa_db_page_move($pageid, $nav, $newposition)
{
qa_db_query_sub(
'UPDATE ^pages SET nav=$ WHERE pageid=#',
$nav, $pageid
);
qa_db_ordered_move('pages', 'pageid', $pageid, $newposition);
}
}
function qa_db_page_delete($pageid)
/*
Delete the page $pageid in the database
*/
{
/**
* Delete the page $pageid in the database
* @param $pageid
*/
function qa_db_page_delete($pageid)
{
qa_db_ordered_delete('pages', 'pageid', $pageid);
}
}
function qa_db_ordered_move($table, $idcolumn, $id, $newposition, $conditionsql=null)
/*
Move the entity identified by $idcolumn=$id into position $newposition (within optional $conditionsql) in $table in the database
*/
{
$andsql=isset($conditionsql) ? (' AND '.$conditionsql) : '';
/**
* Move the entity identified by $idcolumn=$id into position $newposition (within optional $conditionsql) in $table in the database
* @param $table
* @param $idcolumn
* @param $id
* @param $newposition
* @param $conditionsql
*/
function qa_db_ordered_move($table, $idcolumn, $id, $newposition, $conditionsql = null)
{
$andsql = isset($conditionsql) ? (' AND ' . $conditionsql) : '';
qa_db_query_sub('LOCK TABLES ^'.$table.' WRITE');
qa_db_query_sub('LOCK TABLES ^' . $table . ' WRITE');
$oldposition=qa_db_read_one_value(qa_db_query_sub('SELECT position FROM ^'.$table.' WHERE '.$idcolumn.'=#'.$andsql, $id));
$oldposition = qa_db_read_one_value(qa_db_query_sub('SELECT position FROM ^' . $table . ' WHERE ' . $idcolumn . '=#' . $andsql, $id));
if ($newposition!=$oldposition) {
$lastposition=qa_db_read_one_value(qa_db_query_sub('SELECT MAX(position) FROM ^'.$table.' WHERE TRUE'.$andsql));
if ($newposition != $oldposition) {
$lastposition = qa_db_read_one_value(qa_db_query_sub('SELECT MAX(position) FROM ^' . $table . ' WHERE TRUE' . $andsql));
$newposition=max(1, min($newposition, $lastposition)); // constrain it to within range
$newposition = max(1, min($newposition, $lastposition)); // constrain it to within range
qa_db_query_sub('UPDATE ^'.$table.' SET position=# WHERE '.$idcolumn.'=#'.$andsql, 1+$lastposition, $id);
// move it temporarily off the top because we have a unique key on the position column
qa_db_query_sub('UPDATE ^' . $table . ' SET position=# WHERE ' . $idcolumn . '=#' . $andsql, 1 + $lastposition, $id);
if ($newposition<$oldposition)
qa_db_query_sub('UPDATE ^'.$table.' SET position=position+1 WHERE position BETWEEN # AND #'.$andsql.' ORDER BY position DESC', $newposition, $oldposition);
if ($newposition < $oldposition)
qa_db_query_sub('UPDATE ^' . $table . ' SET position=position+1 WHERE position BETWEEN # AND #' . $andsql . ' ORDER BY position DESC', $newposition, $oldposition);
else
qa_db_query_sub('UPDATE ^'.$table.' SET position=position-1 WHERE position BETWEEN # AND #'.$andsql.' ORDER BY position', $oldposition, $newposition);
qa_db_query_sub('UPDATE ^' . $table . ' SET position=position-1 WHERE position BETWEEN # AND #' . $andsql . ' ORDER BY position', $oldposition, $newposition);
qa_db_query_sub('UPDATE ^'.$table.' SET position=# WHERE '.$idcolumn.'=#'.$andsql, $newposition, $id);
qa_db_query_sub('UPDATE ^' . $table . ' SET position=# WHERE ' . $idcolumn . '=#' . $andsql, $newposition, $id);
}
qa_db_query_sub('UNLOCK TABLES');
}
}
function qa_db_ordered_delete($table, $idcolumn, $id, $conditionsql=null)
/*
Delete the entity identified by $idcolumn=$id (and optional $conditionsql) in $table in the database
*/
{
$andsql=isset($conditionsql) ? (' AND '.$conditionsql) : '';
/**
* Delete the entity identified by $idcolumn=$id (and optional $conditionsql) in $table in the database
* @param $table
* @param $idcolumn
* @param $id
* @param $conditionsql
*/
function qa_db_ordered_delete($table, $idcolumn, $id, $conditionsql = null)
{
$andsql = isset($conditionsql) ? (' AND ' . $conditionsql) : '';
qa_db_query_sub('LOCK TABLES ^'.$table.' WRITE');
qa_db_query_sub('LOCK TABLES ^' . $table . ' WRITE');
$oldposition=qa_db_read_one_value(qa_db_query_sub('SELECT position FROM ^'.$table.' WHERE '.$idcolumn.'=#'.$andsql, $id));
$oldposition = qa_db_read_one_value(qa_db_query_sub('SELECT position FROM ^' . $table . ' WHERE ' . $idcolumn . '=#' . $andsql, $id));
qa_db_query_sub('DELETE FROM ^'.$table.' WHERE '.$idcolumn.'=#'.$andsql, $id);
qa_db_query_sub('DELETE FROM ^' . $table . ' WHERE ' . $idcolumn . '=#' . $andsql, $id);
qa_db_query_sub('UPDATE ^'.$table.' SET position=position-1 WHERE position>#'.$andsql.' ORDER BY position', $oldposition);
qa_db_query_sub('UPDATE ^' . $table . ' SET position=position-1 WHERE position>#' . $andsql . ' ORDER BY position', $oldposition);
qa_db_query_sub('UNLOCK TABLES');
}
}
function qa_db_userfield_create($title, $content, $flags, $permit=null)
/*
Create a new user field with (internal) tag $title, label $content, $flags and $permit in the database.
*/
{
$position=qa_db_read_one_value(qa_db_query_sub('SELECT 1+COALESCE(MAX(position), 0) FROM ^userfields'));
/**
* Create a new user field with (internal) tag $title, label $content, $flags and $permit in the database.
* @param $title
* @param $content
* @param $flags
* @param $permit
* @return mixed
*/
function qa_db_userfield_create($title, $content, $flags, $permit = null)
{
$position = qa_db_read_one_value(qa_db_query_sub('SELECT 1+COALESCE(MAX(position), 0) FROM ^userfields'));
qa_db_query_sub(
'INSERT INTO ^userfields (title, content, position, flags, permit) VALUES ($, $, #, #, #)',
......@@ -513,45 +587,55 @@
);
return qa_db_last_insert_id();
}
function qa_db_userfield_set_fields($fieldid, $content, $flags, $permit=null)
/*
Change the user field $fieldid to have label $content, $flags and $permit in the database (the title column cannot be changed once set)
*/
{
}
/**
* Change the user field $fieldid to have label $content, $flags and $permit in the database (the title column cannot be changed once set)
* @param $fieldid
* @param $content
* @param $flags
* @param $permit
*/
function qa_db_userfield_set_fields($fieldid, $content, $flags, $permit = null)
{
qa_db_query_sub(
'UPDATE ^userfields SET content=$, flags=#, permit=# WHERE fieldid=#',
$content, $flags, $permit, $fieldid
);
}
}
function qa_db_userfield_move($fieldid, $newposition)
/*
Move the user field $fieldid into position $newposition in the database
*/
{
/**
* Move the user field $fieldid into position $newposition in the database
* @param $fieldid
* @param $newposition
*/
function qa_db_userfield_move($fieldid, $newposition)
{
qa_db_ordered_move('userfields', 'fieldid', $fieldid, $newposition);
}
}
function qa_db_userfield_delete($fieldid)
/*
Delete the user field $fieldid in the database
*/
{
/**
* Delete the user field $fieldid in the database
* @param $fieldid
*/
function qa_db_userfield_delete($fieldid)
{
qa_db_ordered_delete('userfields', 'fieldid', $fieldid);
}
}
function qa_db_widget_create($title, $tags)
/*
Return the ID of a new widget, to be displayed by the widget module named $title on templates within $tags (comma-separated list)
*/
{
$position=qa_db_read_one_value(qa_db_query_sub('SELECT 1+COALESCE(MAX(position), 0) FROM ^widgets'));
/**
* Return the ID of a new widget, to be displayed by the widget module named $title on templates within $tags (comma-separated list)
* @param $title
* @param $tags
* @return mixed
*/
function qa_db_widget_create($title, $tags)
{
$position = qa_db_read_one_value(qa_db_query_sub('SELECT 1+COALESCE(MAX(position), 0) FROM ^widgets'));
qa_db_query_sub(
'INSERT INTO ^widgets (place, position, tags, title) VALUES (\'\', #, $, $)',
......@@ -559,44 +643,45 @@
);
return qa_db_last_insert_id();
}
}
function qa_db_widget_set_fields($widgetid, $tags)
/*
Set the comma-separated list of templates for $widgetid to $tags
*/
{
/**
* Set the comma-separated list of templates for $widgetid to $tags
* @param $widgetid
* @param $tags
*/
function qa_db_widget_set_fields($widgetid, $tags)
{
qa_db_query_sub(
'UPDATE ^widgets SET tags=$ WHERE widgetid=#',
$tags, $widgetid
);
}
}
function qa_db_widget_move($widgetid, $place, $newposition)
/*
Move the widget $widgetit into position $position in the database's order, and show it in $place on the page
*/
{
/**
* Move the widget $widgetit into position $position in the database's order, and show it in $place on the page
* @param $widgetid
* @param $place
* @param $newposition
*/
function qa_db_widget_move($widgetid, $place, $newposition)
{
qa_db_query_sub(
'UPDATE ^widgets SET place=$ WHERE widgetid=#',
$place, $widgetid
);
qa_db_ordered_move('widgets', 'widgetid', $widgetid, $newposition);
}
}
function qa_db_widget_delete($widgetid)
/*
Delete the widget $widgetid in the database
*/
{
/**
* Delete the widget $widgetid in the database
* @param $widgetid
*/
function qa_db_widget_delete($widgetid)
{
qa_db_ordered_delete('widgets', 'widgetid', $widgetid);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
}
......@@ -20,20 +20,20 @@
More about this license: http://www.question2answer.org/license.php
*/
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
}
define('QA_DB_VERSION_CURRENT', 64);
define('QA_DB_VERSION_CURRENT', 64);
function qa_db_user_column_type_verify()
/*
Return the column type for user ids after verifying it is one of the legal options
*/
{
$coltype=strtoupper(qa_get_mysql_user_column_type());
/**
* Return the column type for user ids after verifying it is one of the legal options
*/
function qa_db_user_column_type_verify()
{
$coltype = strtoupper(qa_get_mysql_user_column_type());
switch ($coltype) {
case 'SMALLINT':
......@@ -54,19 +54,19 @@
}
return $coltype;
}
}
function qa_db_table_definitions()
/*
Return an array of table definitions. For each element of the array, the key is the table name (without prefix)
and the value is an array of column definitions, [column name] => [definition]. The column name is omitted for indexes.
*/
{
/**
* Return an array of table definitions. For each element of the array, the key is the table name (without prefix)
* and the value is an array of column definitions, [column name] => [definition]. The column name is omitted for indexes.
*/
function qa_db_table_definitions()
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'db/maxima.php';
require_once QA_INCLUDE_DIR.'app/users.php';
require_once QA_INCLUDE_DIR . 'db/maxima.php';
require_once QA_INCLUDE_DIR . 'app/users.php';
/*
Important note on character encoding in database and PHP connection to MySQL
......@@ -94,15 +94,15 @@
queries together via a UNION in qa_db_multi_select() - see comments in qa-db.php for more information.
*/
$useridcoltype=qa_db_user_column_type_verify();
$useridcoltype = qa_db_user_column_type_verify();
$tables=array(
$tables = array(
'users' => array(
'userid' => $useridcoltype.' NOT NULL AUTO_INCREMENT',
'userid' => $useridcoltype . ' NOT NULL AUTO_INCREMENT',
'created' => 'DATETIME NOT NULL',
'createip' => 'VARBINARY(16) NOT NULL', // INET_ATON of IP address when created
'email' => 'VARCHAR('.QA_DB_MAX_EMAIL_LENGTH.') NOT NULL',
'handle' => 'VARCHAR('.QA_DB_MAX_HANDLE_LENGTH.') NOT NULL', // username
'email' => 'VARCHAR(' . QA_DB_MAX_EMAIL_LENGTH . ') NOT NULL',
'handle' => 'VARCHAR(' . QA_DB_MAX_HANDLE_LENGTH . ') NOT NULL', // username
'avatarblobid' => 'BIGINT UNSIGNED', // blobid of stored avatar
'avatarwidth' => 'SMALLINT UNSIGNED', // pixel width of stored avatar
'avatarheight' => 'SMALLINT UNSIGNED', // pixel height of stored avatar
......@@ -127,7 +127,7 @@
),
'userlogins' => array(
'userid' => $useridcoltype.' NOT NULL',
'userid' => $useridcoltype . ' NOT NULL',
'source' => 'VARCHAR (16) CHARACTER SET ascii NOT NULL', // e.g. facebook, openid, etc...
'identifier' => 'VARBINARY (1024) NOT NULL', // depends on source, e.g. Facebook uid or OpenID url
'identifiermd5' => 'BINARY (16) NOT NULL', // used to reduce size of index on identifier
......@@ -136,7 +136,7 @@
),
'userlevels' => array(
'userid' => $useridcoltype.' NOT NULL', // the user who has this level
'userid' => $useridcoltype . ' NOT NULL', // the user who has this level
'entitytype' => 'CHAR(1) CHARACTER SET ascii NOT NULL', // see qa-app-updates.php
'entityid' => 'INT UNSIGNED NOT NULL', // relevant postid / userid / tag wordid / categoryid
'level' => 'TINYINT UNSIGNED', // if not NULL, special permission level for that user and that entity
......@@ -145,16 +145,16 @@
),
'userprofile' => array(
'userid' => $useridcoltype.' NOT NULL',
'title' => 'VARCHAR('.QA_DB_MAX_PROFILE_TITLE_LENGTH.') NOT NULL', // profile field name
'content' => 'VARCHAR('.QA_DB_MAX_PROFILE_CONTENT_LENGTH.') NOT NULL', // profile field value
'userid' => $useridcoltype . ' NOT NULL',
'title' => 'VARCHAR(' . QA_DB_MAX_PROFILE_TITLE_LENGTH . ') NOT NULL', // profile field name
'content' => 'VARCHAR(' . QA_DB_MAX_PROFILE_CONTENT_LENGTH . ') NOT NULL', // profile field value
'UNIQUE userid (userid,title)',
),
'userfields' => array(
'fieldid' => 'SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT',
'title' => 'VARCHAR('.QA_DB_MAX_PROFILE_TITLE_LENGTH.') NOT NULL', // to match title column in userprofile table
'content' => 'VARCHAR('.QA_DB_MAX_PROFILE_TITLE_LENGTH.')', // label for display on user profile pages - NULL means use default
'title' => 'VARCHAR(' . QA_DB_MAX_PROFILE_TITLE_LENGTH . ') NOT NULL', // to match title column in userprofile table
'content' => 'VARCHAR(' . QA_DB_MAX_PROFILE_TITLE_LENGTH . ')', // label for display on user profile pages - NULL means use default
'position' => 'SMALLINT UNSIGNED NOT NULL',
'flags' => 'TINYINT UNSIGNED NOT NULL', // QA_FIELD_FLAGS_* at top of qa-app-users.php
'permit' => 'TINYINT UNSIGNED', // minimum user level required to view (uses QA_PERMIT_* constants), null means no restriction
......@@ -164,12 +164,12 @@
'messages' => array(
'messageid' => 'INT UNSIGNED NOT NULL AUTO_INCREMENT',
'type' => "ENUM('PUBLIC', 'PRIVATE') NOT NULL DEFAULT 'PRIVATE'",
'fromuserid' => $useridcoltype.' NOT NULL',
'touserid' => $useridcoltype.' NOT NULL',
'fromuserid' => $useridcoltype . ' NOT NULL',
'touserid' => $useridcoltype . ' NOT NULL',
'fromhidden' => 'TINYINT(1) UNSIGNED NOT NULL DEFAULT 0',
'tohidden' => 'TINYINT(1) UNSIGNED NOT NULL DEFAULT 0',
'content' => 'VARCHAR('.QA_DB_MAX_CONTENT_LENGTH.') NOT NULL',
'format' => 'VARCHAR('.QA_DB_MAX_FORMAT_LENGTH.') CHARACTER SET ascii NOT NULL',
'content' => 'VARCHAR(' . QA_DB_MAX_CONTENT_LENGTH . ') NOT NULL',
'format' => 'VARCHAR(' . QA_DB_MAX_FORMAT_LENGTH . ') CHARACTER SET ascii NOT NULL',
'created' => 'DATETIME NOT NULL',
'PRIMARY KEY (messageid)',
'KEY type (type, fromuserid, touserid, created)',
......@@ -179,7 +179,7 @@
),
'userfavorites' => array(
'userid' => $useridcoltype.' NOT NULL', // the user who favorited the entity
'userid' => $useridcoltype . ' NOT NULL', // the user who favorited the entity
'entitytype' => 'CHAR(1) CHARACTER SET ascii NOT NULL', // see qa-app-updates.php
'entityid' => 'INT UNSIGNED NOT NULL', // favorited postid / userid / tag wordid / categoryid
'nouserevents' => 'TINYINT UNSIGNED NOT NULL', // do we skip writing events to the user stream?
......@@ -190,17 +190,17 @@
'usernotices' => array(
'noticeid' => 'INT UNSIGNED NOT NULL AUTO_INCREMENT',
'userid' => $useridcoltype.' NOT NULL', // the user to whom the notice is directed
'content' => 'VARCHAR('.QA_DB_MAX_CONTENT_LENGTH.') NOT NULL',
'format' => 'VARCHAR('.QA_DB_MAX_FORMAT_LENGTH.') CHARACTER SET ascii NOT NULL',
'tags' => 'VARCHAR('.QA_DB_MAX_CAT_PAGE_TAGS_LENGTH.')', // any additional information for a plugin to access
'userid' => $useridcoltype . ' NOT NULL', // the user to whom the notice is directed
'content' => 'VARCHAR(' . QA_DB_MAX_CONTENT_LENGTH . ') NOT NULL',
'format' => 'VARCHAR(' . QA_DB_MAX_FORMAT_LENGTH . ') CHARACTER SET ascii NOT NULL',
'tags' => 'VARCHAR(' . QA_DB_MAX_CAT_PAGE_TAGS_LENGTH . ')', // any additional information for a plugin to access
'created' => 'DATETIME NOT NULL',
'PRIMARY KEY (noticeid)',
'KEY userid (userid, created)',
),
'userevents' => array(
'userid' => $useridcoltype.' NOT NULL', // the user to be informed about this event in their updates
'userid' => $useridcoltype . ' NOT NULL', // the user to be informed about this event in their updates
'entitytype' => 'CHAR(1) CHARACTER SET ascii NOT NULL', // see qa-app-updates.php
'entityid' => 'INT UNSIGNED NOT NULL', // favorited source of event - see userfavorites table - 0 means not from a favorite
'questionid' => 'INT UNSIGNED NOT NULL', // the affected question
......@@ -236,28 +236,28 @@
'categories' => array(
'categoryid' => 'INT UNSIGNED NOT NULL AUTO_INCREMENT',
'parentid' => 'INT UNSIGNED',
'title' => 'VARCHAR('.QA_DB_MAX_CAT_PAGE_TITLE_LENGTH.') NOT NULL', // category name
'tags' => 'VARCHAR('.QA_DB_MAX_CAT_PAGE_TAGS_LENGTH.') NOT NULL', // slug (url fragment) used to identify category
'content' => 'VARCHAR('.QA_DB_MAX_CAT_CONTENT_LENGTH.') NOT NULL DEFAULT \'\'', // description of category
'title' => 'VARCHAR(' . QA_DB_MAX_CAT_PAGE_TITLE_LENGTH . ') NOT NULL', // category name
'tags' => 'VARCHAR(' . QA_DB_MAX_CAT_PAGE_TAGS_LENGTH . ') NOT NULL', // slug (url fragment) used to identify category
'content' => 'VARCHAR(' . QA_DB_MAX_CAT_CONTENT_LENGTH . ') NOT NULL DEFAULT \'\'', // description of category
'qcount' => 'INT UNSIGNED NOT NULL DEFAULT 0',
'position' => 'SMALLINT UNSIGNED NOT NULL',
'backpath' => 'VARCHAR('.(QA_CATEGORY_DEPTH*(QA_DB_MAX_CAT_PAGE_TAGS_LENGTH+1)).') NOT NULL DEFAULT \'\'',
// full slug path for category, with forward slash separators, in reverse order to make index from effective
'backpath' => 'VARCHAR(' . (QA_CATEGORY_DEPTH * (QA_DB_MAX_CAT_PAGE_TAGS_LENGTH + 1)) . ') NOT NULL DEFAULT \'\'',
'PRIMARY KEY (categoryid)',
'UNIQUE parentid (parentid, tags)',
'UNIQUE parentid_2 (parentid, position)',
'KEY backpath (backpath('.QA_DB_MAX_CAT_PAGE_TAGS_LENGTH.'))',
'KEY backpath (backpath(' . QA_DB_MAX_CAT_PAGE_TAGS_LENGTH . '))',
),
'pages' => array(
'pageid' => 'SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT',
'title' => 'VARCHAR('.QA_DB_MAX_CAT_PAGE_TITLE_LENGTH.') NOT NULL', // title for navigation
'title' => 'VARCHAR(' . QA_DB_MAX_CAT_PAGE_TITLE_LENGTH . ') NOT NULL', // title for navigation
'nav' => 'CHAR(1) CHARACTER SET ascii NOT NULL', // which navigation does it go in (M=main, F=footer, B=before main, O=opposite main, other=none)
'position' => 'SMALLINT UNSIGNED NOT NULL', // global ordering, which allows links to be ordered within each nav area
'flags' => 'TINYINT UNSIGNED NOT NULL', // local or external, open in new window?
'permit' => 'TINYINT UNSIGNED', // is there a minimum user level required for it (uses QA_PERMIT_* constants), null means no restriction
'tags' => 'VARCHAR('.QA_DB_MAX_CAT_PAGE_TAGS_LENGTH.') NOT NULL', // slug (url fragment) for page, or url for external pages
'heading' => 'VARCHAR('.QA_DB_MAX_TITLE_LENGTH.')', // for display within <h1> tags
'tags' => 'VARCHAR(' . QA_DB_MAX_CAT_PAGE_TAGS_LENGTH . ') NOT NULL', // slug (url fragment) for page, or url for external pages
'heading' => 'VARCHAR(' . QA_DB_MAX_TITLE_LENGTH . ')', // for display within <h1> tags
'content' => 'MEDIUMTEXT', // remainder of page HTML
'PRIMARY KEY (pageid)',
'KEY tags (tags)',
......@@ -266,13 +266,13 @@
'widgets' => array(
'widgetid' => 'SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT',
'place' => 'CHAR(2) CHARACTER SET ascii NOT NULL',
// full region: FT=very top of page, FH=below nav area, FL=above footer, FB = very bottom of page
// side region: ST=top of side, SH=below sidebar, SL=below categories, SB=very bottom of side
// main region: MT=top of main, MH=below page title, ML=above links, MB=very bottom of main region
'place' => 'CHAR(2) CHARACTER SET ascii NOT NULL',
'position' => 'SMALLINT UNSIGNED NOT NULL', // global ordering, which allows widgets to be ordered within each place
'tags' => 'VARCHAR('.QA_DB_MAX_WIDGET_TAGS_LENGTH.') CHARACTER SET ascii NOT NULL', // comma-separated list of templates to display on
'title' => 'VARCHAR('.QA_DB_MAX_WIDGET_TITLE_LENGTH.') NOT NULL', // name of widget module that should be displayed
'tags' => 'VARCHAR(' . QA_DB_MAX_WIDGET_TAGS_LENGTH . ') CHARACTER SET ascii NOT NULL', // comma-separated list of templates to display on
'title' => 'VARCHAR(' . QA_DB_MAX_WIDGET_TITLE_LENGTH . ') NOT NULL', // name of widget module that should be displayed
'PRIMARY KEY (widgetid)',
'UNIQUE position (position)',
),
......@@ -288,9 +288,9 @@
'acount' => 'SMALLINT UNSIGNED NOT NULL DEFAULT 0', // number of answers (for questions)
'amaxvote' => 'SMALLINT UNSIGNED NOT NULL DEFAULT 0', // highest netvotes of child answers (for questions)
'selchildid' => 'INT UNSIGNED', // selected answer (for questions)
'closedbyid' => 'INT UNSIGNED', // not null means question is closed
// if closed due to being a duplicate, this is the postid of that other question
// if closed for another reason, that reason should be added as a comment on the question, and this field is the comment's id
'closedbyid' => 'INT UNSIGNED', // not null means question is closed
'userid' => $useridcoltype, // which user wrote it
'cookieid' => 'BIGINT UNSIGNED', // which cookie wrote it, if an anonymous post
'createip' => 'VARBINARY(16)', // INET_ATON of IP address used to create the post
......@@ -303,15 +303,15 @@
'views' => 'INT UNSIGNED NOT NULL DEFAULT 0',
'hotness' => 'FLOAT',
'flagcount' => 'TINYINT UNSIGNED NOT NULL DEFAULT 0',
'format' => 'VARCHAR('.QA_DB_MAX_FORMAT_LENGTH.') CHARACTER SET ascii NOT NULL DEFAULT \'\'', // format of content, e.g. 'html'
'format' => 'VARCHAR(' . QA_DB_MAX_FORMAT_LENGTH . ') CHARACTER SET ascii NOT NULL DEFAULT \'\'', // format of content, e.g. 'html'
'created' => 'DATETIME NOT NULL',
'updated' => 'DATETIME', // time of last update
'updatetype' => 'CHAR(1) CHARACTER SET ascii', // see qa-app-updates.php
'title' => 'VARCHAR('.QA_DB_MAX_TITLE_LENGTH.')',
'content' => 'VARCHAR('.QA_DB_MAX_CONTENT_LENGTH.')',
'tags' => 'VARCHAR('.QA_DB_MAX_TAGS_LENGTH.')', // string of tags separated by commas
'name' => 'VARCHAR('.QA_DB_MAX_NAME_LENGTH.')', // name of author if post anonymonus
'notify' => 'VARCHAR('.QA_DB_MAX_EMAIL_LENGTH.')', // email address, or @ to get from user, or NULL for none
'title' => 'VARCHAR(' . QA_DB_MAX_TITLE_LENGTH . ')',
'content' => 'VARCHAR(' . QA_DB_MAX_CONTENT_LENGTH . ')',
'tags' => 'VARCHAR(' . QA_DB_MAX_TAGS_LENGTH . ')', // string of tags separated by commas
'name' => 'VARCHAR(' . QA_DB_MAX_NAME_LENGTH . ')', // name of author if post anonymonus
'notify' => 'VARCHAR(' . QA_DB_MAX_EMAIL_LENGTH . ')', // email address, or @ to get from user, or NULL for none
'PRIMARY KEY (postid)',
'KEY type (type, created)', // for getting recent questions, answers, comments
'KEY type_2 (type, acount, created)', // for getting unanswered questions
......@@ -343,9 +343,9 @@
'blobs' => array(
'blobid' => 'BIGINT UNSIGNED NOT NULL',
'format' => 'VARCHAR('.QA_DB_MAX_FORMAT_LENGTH.') CHARACTER SET ascii NOT NULL', // format e.g. 'jpeg', 'gif', 'png'
'format' => 'VARCHAR(' . QA_DB_MAX_FORMAT_LENGTH . ') CHARACTER SET ascii NOT NULL', // format e.g. 'jpeg', 'gif', 'png'
'content' => 'MEDIUMBLOB', // null means it's stored on disk in QA_BLOBS_DIRECTORY
'filename' => 'VARCHAR('.QA_DB_MAX_BLOB_FILE_NAME_LENGTH.')', // name of source file (if appropriate)
'filename' => 'VARCHAR(' . QA_DB_MAX_BLOB_FILE_NAME_LENGTH . ')', // name of source file (if appropriate)
'userid' => $useridcoltype, // which user created it
'cookieid' => 'BIGINT UNSIGNED', // which cookie created it
'createip' => 'VARBINARY(16)', // INET_ATON of IP address that created it
......@@ -355,7 +355,7 @@
'words' => array(
'wordid' => 'INT UNSIGNED NOT NULL AUTO_INCREMENT',
'word' => 'VARCHAR('.QA_DB_MAX_WORD_LENGTH.') NOT NULL',
'word' => 'VARCHAR(' . QA_DB_MAX_WORD_LENGTH . ') NOT NULL',
'titlecount' => 'INT UNSIGNED NOT NULL DEFAULT 0', // only counts one per post
'contentcount' => 'INT UNSIGNED NOT NULL DEFAULT 0', // only counts one per post
'tagwordcount' => 'INT UNSIGNED NOT NULL DEFAULT 0', // for words in tags - only counts one per post
......@@ -407,7 +407,7 @@
'uservotes' => array(
'postid' => 'INT UNSIGNED NOT NULL',
'userid' => $useridcoltype.' NOT NULL',
'userid' => $useridcoltype . ' NOT NULL',
'vote' => 'TINYINT NOT NULL', // -1, 0 or 1
'flag' => 'TINYINT NOT NULL', // 0 or 1
'UNIQUE userid (userid, postid)',
......@@ -418,7 +418,7 @@
// many userpoints columns could be unsigned but MySQL appears to mess up points calculations that go negative as a result
'userpoints' => array(
'userid' => $useridcoltype.' NOT NULL',
'userid' => $useridcoltype . ' NOT NULL',
'points' => 'INT NOT NULL DEFAULT 0', // user's points as displayed, after final multiple
'qposts' => 'MEDIUMINT NOT NULL DEFAULT 0', // number of questions by user (excluding hidden/queued)
'aposts' => 'MEDIUMINT NOT NULL DEFAULT 0', // number of answers by user (excluding hidden/queued)
......@@ -439,7 +439,7 @@
),
'userlimits' => array(
'userid' => $useridcoltype.' NOT NULL',
'userid' => $useridcoltype . ' NOT NULL',
'action' => 'CHAR(1) CHARACTER SET ascii NOT NULL', // see constants at top of qa-app-limits.php
'period' => 'INT UNSIGNED NOT NULL', // integer representing hour of last action
'count' => 'SMALLINT UNSIGNED NOT NULL', // how many of this action has been performed within that hour
......@@ -457,8 +457,8 @@
),
'options' => array(
'title' => 'VARCHAR('.QA_DB_MAX_OPTION_TITLE_LENGTH.') NOT NULL', // name of option
'content' => 'VARCHAR('.QA_DB_MAX_CONTENT_LENGTH.') NOT NULL', // value of option
'title' => 'VARCHAR(' . QA_DB_MAX_OPTION_TITLE_LENGTH . ') NOT NULL', // name of option
'content' => 'VARCHAR(' . QA_DB_MAX_CONTENT_LENGTH . ') NOT NULL', // value of option
'PRIMARY KEY (title)',
),
......@@ -473,32 +473,32 @@
),
'usermetas' => array(
'userid' => $useridcoltype.' NOT NULL',
'title' => 'VARCHAR('.QA_DB_MAX_META_TITLE_LENGTH.') NOT NULL',
'content' => 'VARCHAR('.QA_DB_MAX_META_CONTENT_LENGTH.') NOT NULL',
'userid' => $useridcoltype . ' NOT NULL',
'title' => 'VARCHAR(' . QA_DB_MAX_META_TITLE_LENGTH . ') NOT NULL',
'content' => 'VARCHAR(' . QA_DB_MAX_META_CONTENT_LENGTH . ') NOT NULL',
'PRIMARY KEY (userid, title)',
),
'postmetas' => array(
'postid' => 'INT UNSIGNED NOT NULL',
'title' => 'VARCHAR('.QA_DB_MAX_META_TITLE_LENGTH.') NOT NULL',
'content' => 'VARCHAR('.QA_DB_MAX_META_CONTENT_LENGTH.') NOT NULL',
'title' => 'VARCHAR(' . QA_DB_MAX_META_TITLE_LENGTH . ') NOT NULL',
'content' => 'VARCHAR(' . QA_DB_MAX_META_CONTENT_LENGTH . ') NOT NULL',
'PRIMARY KEY (postid, title)',
'CONSTRAINT ^postmetas_ibfk_1 FOREIGN KEY (postid) REFERENCES ^posts(postid) ON DELETE CASCADE',
),
'categorymetas' => array(
'categoryid' => 'INT UNSIGNED NOT NULL',
'title' => 'VARCHAR('.QA_DB_MAX_META_TITLE_LENGTH.') NOT NULL',
'content' => 'VARCHAR('.QA_DB_MAX_META_CONTENT_LENGTH.') NOT NULL',
'title' => 'VARCHAR(' . QA_DB_MAX_META_TITLE_LENGTH . ') NOT NULL',
'content' => 'VARCHAR(' . QA_DB_MAX_META_CONTENT_LENGTH . ') NOT NULL',
'PRIMARY KEY (categoryid, title)',
'CONSTRAINT ^categorymetas_ibfk_1 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE CASCADE',
),
'tagmetas' => array(
'tag' => 'VARCHAR('.QA_DB_MAX_WORD_LENGTH.') NOT NULL',
'title' => 'VARCHAR('.QA_DB_MAX_META_TITLE_LENGTH.') NOT NULL',
'content' => 'VARCHAR('.QA_DB_MAX_META_CONTENT_LENGTH.') NOT NULL',
'tag' => 'VARCHAR(' . QA_DB_MAX_WORD_LENGTH . ') NOT NULL',
'title' => 'VARCHAR(' . QA_DB_MAX_META_TITLE_LENGTH . ') NOT NULL',
'content' => 'VARCHAR(' . QA_DB_MAX_META_CONTENT_LENGTH . ') NOT NULL',
'PRIMARY KEY (tag, title)',
),
......@@ -512,136 +512,144 @@
unset($tables['messages']);
} else {
$userforeignkey='FOREIGN KEY (userid) REFERENCES ^users(userid)';
$tables['userlogins'][]='CONSTRAINT ^userlogins_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$tables['userprofile'][]='CONSTRAINT ^userprofile_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$tables['posts'][]='CONSTRAINT ^posts_ibfk_1 '.$userforeignkey.' ON DELETE SET NULL';
$tables['uservotes'][]='CONSTRAINT ^uservotes_ibfk_2 '.$userforeignkey.' ON DELETE CASCADE';
$tables['userlimits'][]='CONSTRAINT ^userlimits_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$tables['userfavorites'][]='CONSTRAINT ^userfavorites_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$tables['usernotices'][]='CONSTRAINT ^usernotices_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$tables['userevents'][]='CONSTRAINT ^userevents_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$tables['userlevels'][]='CONSTRAINT ^userlevels_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$tables['usermetas'][]='CONSTRAINT ^usermetas_ibfk_1 '.$userforeignkey.' ON DELETE CASCADE';
$userforeignkey = 'FOREIGN KEY (userid) REFERENCES ^users(userid)';
$tables['userlogins'][] = 'CONSTRAINT ^userlogins_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['userprofile'][] = 'CONSTRAINT ^userprofile_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['posts'][] = 'CONSTRAINT ^posts_ibfk_1 ' . $userforeignkey . ' ON DELETE SET NULL';
$tables['uservotes'][] = 'CONSTRAINT ^uservotes_ibfk_2 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['userlimits'][] = 'CONSTRAINT ^userlimits_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['userfavorites'][] = 'CONSTRAINT ^userfavorites_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['usernotices'][] = 'CONSTRAINT ^usernotices_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['userevents'][] = 'CONSTRAINT ^userevents_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['userlevels'][] = 'CONSTRAINT ^userlevels_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
$tables['usermetas'][] = 'CONSTRAINT ^usermetas_ibfk_1 ' . $userforeignkey . ' ON DELETE CASCADE';
}
return $tables;
}
}
function qa_array_to_keys($array)
/*
Return array with all values from $array as keys
*/
{
/**
* Return array with all values from $array as keys
* @param $array
* @return array
*/
function qa_array_to_keys($array)
{
return empty($array) ? array() : array_combine($array, array_fill(0, count($array), true));
}
}
function qa_db_missing_tables($definitions)
/*
Return a list of tables missing from the database, [table name] => [column/index definitions]
*/
{
$keydbtables=qa_array_to_keys(qa_db_list_tables());
/**
* Return a list of tables missing from the database, [table name] => [column/index definitions]
* @param $definitions
* @return array
*/
function qa_db_missing_tables($definitions)
{
$keydbtables = qa_array_to_keys(qa_db_list_tables());
$missing=array();
$missing = array();
foreach ($definitions as $rawname => $definition)
if (!isset($keydbtables[qa_db_add_table_prefix($rawname)]))
$missing[$rawname]=$definition;
$missing[$rawname] = $definition;
return $missing;
}
}
function qa_db_missing_columns($table, $definition)
/*
Return a list of columns missing from $table in the database, given the full definition set in $definition
*/
{
$keycolumns=qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^'.$table)));
/**
* Return a list of columns missing from $table in the database, given the full definition set in $definition
* @param $table
* @param $definition
* @return array
*/
function qa_db_missing_columns($table, $definition)
{
$keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^' . $table)));
$missing=array();
$missing = array();
foreach ($definition as $colname => $coldefn)
if ( (!is_int($colname)) && !isset($keycolumns[$colname]) )
$missing[$colname]=$coldefn;
if ((!is_int($colname)) && !isset($keycolumns[$colname]))
$missing[$colname] = $coldefn;
return $missing;
}
}
function qa_db_get_db_version()
/*
Return the current version of the Q2A database, to determine need for DB upgrades
*/
{
$definitions=qa_db_table_definitions();
/**
* Return the current version of the Q2A database, to determine need for DB upgrades
*/
function qa_db_get_db_version()
{
$definitions = qa_db_table_definitions();
if (count(qa_db_missing_columns('options', $definitions['options']))==0) {
$version=(int)qa_db_read_one_value(qa_db_query_sub("SELECT content FROM ^options WHERE title='db_version'"), true);
if (count(qa_db_missing_columns('options', $definitions['options'])) == 0) {
$version = (int)qa_db_read_one_value(qa_db_query_sub("SELECT content FROM ^options WHERE title='db_version'"), true);
if ($version>0)
if ($version > 0)
return $version;
}
return null;
}
}
function qa_db_set_db_version($version)
/*
Set the current version in the database
*/
{
/**
* Set the current version in the database
* @param $version
*/
function qa_db_set_db_version($version)
{
require_once QA_INCLUDE_DIR . 'db/options.php';
qa_db_set_option('db_version', $version);
}
}
function qa_db_check_tables()
/*
Return a string describing what is wrong with the database, or false if everything is just fine
*/
{
/**
* Return a string describing what is wrong with the database, or false if everything is just fine
*/
function qa_db_check_tables()
{
qa_db_query_raw('UNLOCK TABLES'); // we could be inside a lock tables block
$version=qa_db_read_one_value(qa_db_query_raw('SELECT VERSION()'));
$version = qa_db_read_one_value(qa_db_query_raw('SELECT VERSION()'));
if (((float)$version)<4.1)
qa_fatal_error('MySQL version 4.1 or later is required - you appear to be running MySQL '.$version);
if (((float)$version) < 4.1)
qa_fatal_error('MySQL version 4.1 or later is required - you appear to be running MySQL ' . $version);
$definitions=qa_db_table_definitions();
$missing=qa_db_missing_tables($definitions);
$definitions = qa_db_table_definitions();
$missing = qa_db_missing_tables($definitions);
if (count($missing) == count($definitions))
return 'none';
else {
if (!isset($missing['options'])) {
$version=qa_db_get_db_version();
$version = qa_db_get_db_version();
if (isset($version) && ($version<QA_DB_VERSION_CURRENT))
if (isset($version) && ($version < QA_DB_VERSION_CURRENT))
return 'old-version';
}
if (count($missing)) {
if (defined('QA_MYSQL_USERS_PREFIX')) { // special case if two installations sharing users
$datacount=0;
$datamissing=0;
$datacount = 0;
$datamissing = 0;
foreach ($definitions as $rawname => $definition)
if (qa_db_add_table_prefix($rawname)==(QA_MYSQL_TABLE_PREFIX.$rawname)) {
if (qa_db_add_table_prefix($rawname) == (QA_MYSQL_TABLE_PREFIX . $rawname)) {
$datacount++;
if (isset($missing[$rawname]))
$datamissing++;
}
if ( ($datacount==$datamissing) && ($datamissing==count($missing)) )
if (($datacount == $datamissing) && ($datamissing == count($missing)))
return 'non-users-missing';
}
......@@ -654,92 +662,95 @@
}
return false;
}
}
function qa_db_install_tables()
/*
Install any missing database tables and/or columns and automatically set version as latest.
This is not suitable for use if the database needs upgrading.
*/
{
$definitions=qa_db_table_definitions();
/**
* Install any missing database tables and/or columns and automatically set version as latest.
* This is not suitable for use if the database needs upgrading.
*/
function qa_db_install_tables()
{
$definitions = qa_db_table_definitions();
$missingtables=qa_db_missing_tables($definitions);
$missingtables = qa_db_missing_tables($definitions);
foreach ($missingtables as $rawname => $definition) {
qa_db_query_sub(qa_db_create_table_sql($rawname, $definition));
if ($rawname=='userfields')
if ($rawname == 'userfields')
qa_db_query_sub(qa_db_default_userfields_sql());
}
foreach ($definitions as $table => $definition) {
$missingcolumns=qa_db_missing_columns($table, $definition);
$missingcolumns = qa_db_missing_columns($table, $definition);
foreach ($missingcolumns as $colname => $coldefn)
qa_db_query_sub('ALTER TABLE ^'.$table.' ADD COLUMN '.$colname.' '.$coldefn);
qa_db_query_sub('ALTER TABLE ^' . $table . ' ADD COLUMN ' . $colname . ' ' . $coldefn);
}
qa_db_set_db_version(QA_DB_VERSION_CURRENT);
}
}
function qa_db_create_table_sql($rawname, $definition)
/*
Return the SQL command to create a table with $rawname and $definition obtained from qa_db_table_definitions()
*/
{
$querycols='';
/**
* Return the SQL command to create a table with $rawname and $definition obtained from qa_db_table_definitions()
* @param $rawname
* @param $definition
* @return string
*/
function qa_db_create_table_sql($rawname, $definition)
{
$querycols = '';
foreach ($definition as $colname => $coldef)
if (isset($coldef))
$querycols.=(strlen($querycols) ? ', ' : '').(is_int($colname) ? $coldef : ($colname.' '.$coldef));
$querycols .= (strlen($querycols) ? ', ' : '') . (is_int($colname) ? $coldef : ($colname . ' ' . $coldef));
return 'CREATE TABLE ^'.$rawname.' ('.$querycols.') ENGINE=InnoDB CHARSET=utf8';
}
return 'CREATE TABLE ^' . $rawname . ' (' . $querycols . ') ENGINE=InnoDB CHARSET=utf8';
}
function qa_db_default_userfields_sql()
/*
Return the SQL to create the default entries in the userfields table (before 1.3 these were hard-coded in PHP)
*/
{
$oldprofileflags=array(
/**
* Return the SQL to create the default entries in the userfields table (before 1.3 these were hard-coded in PHP)
*/
function qa_db_default_userfields_sql()
{
$oldprofileflags = array(
'name' => 0,
'location' => 0,
'website' => QA_FIELD_FLAGS_LINK_URL,
'about' => QA_FIELD_FLAGS_MULTI_LINE,
);
$sql='INSERT INTO ^userfields (title, position, flags) VALUES '; // content column will be NULL, meaning use default from lang files
$sql = 'INSERT INTO ^userfields (title, position, flags) VALUES '; // content column will be NULL, meaning use default from lang files
$index=0;
$index = 0;
foreach ($oldprofileflags as $title => $flags)
$sql.=($index ? ', ' : '')."('".qa_db_escape_string($title)."', ".(++$index).", ".(int)@$oldprofileflags[$title].")";
$sql .= ($index ? ', ' : '') . "('" . qa_db_escape_string($title) . "', " . (++$index) . ", " . (int)@$oldprofileflags[$title] . ")";
return $sql;
}
}
function qa_db_upgrade_tables()
/*
Upgrade the database schema to the latest version, outputting progress to the browser
*/
{
require_once QA_INCLUDE_DIR.'app/recalc.php';
/**
* Upgrade the database schema to the latest version, outputting progress to the browser
*/
function qa_db_upgrade_tables()
{
require_once QA_INCLUDE_DIR . 'app/recalc.php';
$definitions=qa_db_table_definitions();
$keyrecalc=array();
$definitions = qa_db_table_definitions();
$keyrecalc = array();
// Write-lock all Q2A tables before we start so no one can read or write anything
$keydbtables=qa_array_to_keys(qa_db_list_tables());
$keydbtables = qa_array_to_keys(qa_db_list_tables());
foreach ($definitions as $rawname => $definition)
if (isset($keydbtables[qa_db_add_table_prefix($rawname)]))
$locks[]='^'.$rawname.' WRITE';
$locks[] = '^' . $rawname . ' WRITE';
$locktablesquery='LOCK TABLES '.implode(', ', $locks);
$locktablesquery = 'LOCK TABLES ' . implode(', ', $locks);
qa_db_upgrade_query($locktablesquery);
......@@ -749,56 +760,56 @@
$skipMessage = 'Skipping upgrading %s table since it was already upgraded by another Q2A site sharing it.';
while (1) {
$version=qa_db_get_db_version();
$version = qa_db_get_db_version();
if ($version>=QA_DB_VERSION_CURRENT)
if ($version >= QA_DB_VERSION_CURRENT)
break;
$newversion=$version+1;
$newversion = $version + 1;
qa_db_upgrade_progress(QA_DB_VERSION_CURRENT-$version.' upgrade step/s remaining...');
qa_db_upgrade_progress(QA_DB_VERSION_CURRENT - $version . ' upgrade step/s remaining...');
switch ($newversion) {
// Up to here: Version 1.0 beta 1
case 2:
qa_db_upgrade_query('ALTER TABLE ^posts DROP COLUMN votes, ADD COLUMN upvotes '.$definitions['posts']['upvotes'].
' AFTER cookieid, ADD COLUMN downvotes '.$definitions['posts']['downvotes'].' AFTER upvotes');
qa_db_upgrade_query('ALTER TABLE ^posts DROP COLUMN votes, ADD COLUMN upvotes ' . $definitions['posts']['upvotes'] .
' AFTER cookieid, ADD COLUMN downvotes ' . $definitions['posts']['downvotes'] . ' AFTER upvotes');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecountposts']=true;
$keyrecalc['dorecountposts'] = true;
break;
case 3:
qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN upvoteds '.$definitions['userpoints']['upvoteds'].
' AFTER avoteds, ADD COLUMN downvoteds '.$definitions['userpoints']['downvoteds'].' AFTER upvoteds');
qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN upvoteds ' . $definitions['userpoints']['upvoteds'] .
' AFTER avoteds, ADD COLUMN downvoteds ' . $definitions['userpoints']['downvoteds'] . ' AFTER upvoteds');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecalcpoints']=true;
$keyrecalc['dorecalcpoints'] = true;
break;
case 4:
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastuserid '.$definitions['posts']['lastuserid'].' AFTER cookieid, CHANGE COLUMN updated updated '.$definitions['posts']['updated']);
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastuserid ' . $definitions['posts']['lastuserid'] . ' AFTER cookieid, CHANGE COLUMN updated updated ' . $definitions['posts']['updated']);
qa_db_upgrade_query($locktablesquery);
qa_db_upgrade_query('UPDATE ^posts SET updated=NULL WHERE updated=0 OR updated=created');
break;
case 5:
qa_db_upgrade_query('ALTER TABLE ^contentwords ADD COLUMN type '.$definitions['contentwords']['type'].' AFTER count, ADD COLUMN questionid '.$definitions['contentwords']['questionid'].' AFTER type');
qa_db_upgrade_query('ALTER TABLE ^contentwords ADD COLUMN type ' . $definitions['contentwords']['type'] . ' AFTER count, ADD COLUMN questionid ' . $definitions['contentwords']['questionid'] . ' AFTER type');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['doreindexcontent']=true;
$keyrecalc['doreindexcontent'] = true;
break;
// Up to here: Version 1.0 beta 2
case 6:
qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN cposts '.$definitions['userpoints']['cposts'].' AFTER aposts');
qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN cposts ' . $definitions['userpoints']['cposts'] . ' AFTER aposts');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecalcpoints']=true;
$keyrecalc['dorecalcpoints'] = true;
break;
case 7:
if (!QA_FINAL_EXTERNAL_USERS) {
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessioncode '.$definitions['users']['sessioncode'].' AFTER writeip');
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessioncode ' . $definitions['users']['sessioncode'] . ' AFTER writeip');
qa_db_upgrade_query($locktablesquery);
}
break;
......@@ -806,14 +817,14 @@
case 8:
qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY (type, acount, created)');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecountposts']=true; // for unanswered question count
$keyrecalc['dorecountposts'] = true; // for unanswered question count
break;
// Up to here: Version 1.0 beta 3, 1.0, 1.0.1 beta, 1.0.1
case 9:
if (!QA_FINAL_EXTERNAL_USERS) {
qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN resetcode emailcode '.$definitions['users']['emailcode'].', ADD COLUMN flags '.$definitions['users']['flags'].' AFTER sessioncode');
qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN resetcode emailcode ' . $definitions['users']['emailcode'] . ', ADD COLUMN flags ' . $definitions['users']['flags'] . ' AFTER sessioncode');
qa_db_upgrade_query($locktablesquery);
qa_db_upgrade_query('UPDATE ^users SET flags=1');
}
......@@ -832,12 +843,12 @@
'UNIQUE position (position)',
))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage
$locktablesquery.=', ^categories WRITE';
$locktablesquery .= ', ^categories WRITE';
qa_db_upgrade_query($locktablesquery);
break;
case 11:
qa_db_upgrade_query('ALTER TABLE ^posts ADD CONSTRAINT ^posts_ibfk_2 FOREIGN KEY (parentid) REFERENCES ^posts(postid), ADD COLUMN categoryid '.$definitions['posts']['categoryid'].' AFTER parentid, ADD KEY categoryid (categoryid, type, created), ADD CONSTRAINT ^posts_ibfk_3 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE SET NULL');
qa_db_upgrade_query('ALTER TABLE ^posts ADD CONSTRAINT ^posts_ibfk_2 FOREIGN KEY (parentid) REFERENCES ^posts(postid), ADD COLUMN categoryid ' . $definitions['posts']['categoryid'] . ' AFTER parentid, ADD KEY categoryid (categoryid, type, created), ADD CONSTRAINT ^posts_ibfk_3 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE SET NULL');
// foreign key on parentid important now that deletion is possible
qa_db_upgrade_query($locktablesquery);
break;
......@@ -857,19 +868,19 @@
'UNIQUE tags (tags)',
'UNIQUE position (position)',
))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage
$locktablesquery.=', ^pages WRITE';
$locktablesquery .= ', ^pages WRITE';
qa_db_upgrade_query($locktablesquery);
break;
case 13:
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN createip '.$definitions['posts']['createip'].' AFTER cookieid, ADD KEY createip (createip, created)');
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN createip ' . $definitions['posts']['createip'] . ' AFTER cookieid, ADD KEY createip (createip, created)');
qa_db_upgrade_query($locktablesquery);
break;
case 14:
qa_db_upgrade_query('ALTER TABLE ^userpoints DROP COLUMN qvotes, DROP COLUMN avotes, ADD COLUMN qupvotes '.$definitions['userpoints']['qupvotes'].' AFTER aselecteds, ADD COLUMN qdownvotes '.$definitions['userpoints']['qdownvotes'].' AFTER qupvotes, ADD COLUMN aupvotes '.$definitions['userpoints']['aupvotes'].' AFTER qdownvotes, ADD COLUMN adownvotes '.$definitions['userpoints']['adownvotes'].' AFTER aupvotes');
qa_db_upgrade_query('ALTER TABLE ^userpoints DROP COLUMN qvotes, DROP COLUMN avotes, ADD COLUMN qupvotes ' . $definitions['userpoints']['qupvotes'] . ' AFTER aselecteds, ADD COLUMN qdownvotes ' . $definitions['userpoints']['qdownvotes'] . ' AFTER qupvotes, ADD COLUMN aupvotes ' . $definitions['userpoints']['aupvotes'] . ' AFTER qdownvotes, ADD COLUMN adownvotes ' . $definitions['userpoints']['adownvotes'] . ' AFTER aupvotes');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecalcpoints']=true;
$keyrecalc['dorecalcpoints'] = true;
break;
// Up to here: Version 1.2 beta 1
......@@ -891,7 +902,7 @@
case 16:
qa_db_upgrade_table_columns($definitions, 'posts', array('format'));
qa_db_upgrade_query($locktablesquery);
$keyrecalc['doreindexcontent']=true; // because of new treatment of apostrophes in words
$keyrecalc['doreindexcontent'] = true; // because of new treatment of apostrophes in words
break;
case 17:
......@@ -900,13 +911,13 @@
break;
case 18:
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastip '.$definitions['posts']['lastip'].' AFTER lastuserid, ADD KEY lastip (lastip, updated, type)');
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastip ' . $definitions['posts']['lastip'] . ' AFTER lastuserid, ADD KEY lastip (lastip, updated, type)');
qa_db_upgrade_query($locktablesquery);
break;
case 19:
if (!QA_FINAL_EXTERNAL_USERS)
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN avatarblobid '.$definitions['users']['avatarblobid'].' AFTER handle, ADD COLUMN avatarwidth '.$definitions['users']['avatarwidth'].' AFTER avatarblobid, ADD COLUMN avatarheight '.$definitions['users']['avatarheight'].' AFTER avatarwidth');
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN avatarblobid ' . $definitions['users']['avatarblobid'] . ' AFTER handle, ADD COLUMN avatarwidth ' . $definitions['users']['avatarwidth'] . ' AFTER avatarblobid, ADD COLUMN avatarheight ' . $definitions['users']['avatarheight'] . ' AFTER avatarwidth');
// hard-code list of columns and indexes to ensure we ignore any added at a later stage
......@@ -916,7 +927,7 @@
'blobid' => $definitions['blobs']['blobid'],
'format' => $definitions['blobs']['format'],
'content' => $definitions['blobs']['content'],
'PRIMARY KEY (blobid)'
'PRIMARY KEY (blobid)',
)));
qa_db_upgrade_query(qa_db_create_table_sql('cache', array(
......@@ -929,7 +940,7 @@
'KEY (lastread)',
))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage
$locktablesquery.=', ^blobs WRITE, ^cache WRITE';
$locktablesquery .= ', ^blobs WRITE, ^cache WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -947,9 +958,9 @@
'CONSTRAINT ^userlogins_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE',
)));
qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN passsalt passsalt '.$definitions['users']['passsalt'].', CHANGE COLUMN passcheck passcheck '.$definitions['users']['passcheck']);
qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN passsalt passsalt ' . $definitions['users']['passsalt'] . ', CHANGE COLUMN passcheck passcheck ' . $definitions['users']['passcheck']);
$locktablesquery.=', ^userlogins WRITE';
$locktablesquery .= ', ^userlogins WRITE';
qa_db_upgrade_query($locktablesquery);
}
break;
......@@ -967,7 +978,7 @@
'PRIMARY KEY (fieldid)',
)));
$locktablesquery.=', ^userfields WRITE';
$locktablesquery .= ', ^userfields WRITE';
qa_db_upgrade_query($locktablesquery);
qa_db_upgrade_query(qa_db_default_userfields_sql());
......@@ -978,7 +989,7 @@
case 22:
if (!QA_FINAL_EXTERNAL_USERS) {
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessionsource '.$definitions['users']['sessionsource'].' AFTER sessioncode');
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessionsource ' . $definitions['users']['sessionsource'] . ' AFTER sessioncode');
qa_db_upgrade_query($locktablesquery);
}
break;
......@@ -998,7 +1009,7 @@
'UNIQUE position (position)',
)));
$locktablesquery.=', ^widgets WRITE';
$locktablesquery .= ', ^widgets WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1014,55 +1025,55 @@
'CONSTRAINT ^tagwords_ibfk_2 FOREIGN KEY (wordid) REFERENCES ^words(wordid)',
)));
$locktablesquery.=', ^tagwords WRITE';
$locktablesquery .= ', ^tagwords WRITE';
qa_db_upgrade_query('ALTER TABLE ^words ADD COLUMN tagwordcount '.$definitions['words']['tagwordcount'].' AFTER contentcount');
qa_db_upgrade_query('ALTER TABLE ^words ADD COLUMN tagwordcount ' . $definitions['words']['tagwordcount'] . ' AFTER contentcount');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['doreindexcontent']=true;
$keyrecalc['doreindexcontent'] = true;
break;
// Up to here: Version 1.4 developer preview
case 25:
$keycolumns=qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^blobs')));
$keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^blobs')));
// might be using blobs table shared with another installation, so check if we need to upgrade
if (isset($keycolumns['filename']))
qa_db_upgrade_progress('Skipping upgrading blobs table since it was already upgraded by another Q2A site sharing it.');
else {
qa_db_upgrade_query('ALTER TABLE ^blobs ADD COLUMN filename '.$definitions['blobs']['filename'].' AFTER content, ADD COLUMN userid '.$definitions['blobs']['userid'].' AFTER filename, ADD COLUMN cookieid '.$definitions['blobs']['cookieid'].' AFTER userid, ADD COLUMN createip '.$definitions['blobs']['createip'].' AFTER cookieid, ADD COLUMN created '.$definitions['blobs']['created'].' AFTER createip');
qa_db_upgrade_query('ALTER TABLE ^blobs ADD COLUMN filename ' . $definitions['blobs']['filename'] . ' AFTER content, ADD COLUMN userid ' . $definitions['blobs']['userid'] . ' AFTER filename, ADD COLUMN cookieid ' . $definitions['blobs']['cookieid'] . ' AFTER userid, ADD COLUMN createip ' . $definitions['blobs']['createip'] . ' AFTER cookieid, ADD COLUMN created ' . $definitions['blobs']['created'] . ' AFTER createip');
qa_db_upgrade_query($locktablesquery);
}
break;
case 26:
qa_db_upgrade_query('ALTER TABLE ^uservotes ADD COLUMN flag '.$definitions['uservotes']['flag'].' AFTER vote');
qa_db_upgrade_query('ALTER TABLE ^uservotes ADD COLUMN flag ' . $definitions['uservotes']['flag'] . ' AFTER vote');
qa_db_upgrade_query($locktablesquery);
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN flagcount '.$definitions['posts']['flagcount'].' AFTER downvotes, ADD KEY type_3 (type, flagcount, created)');
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN flagcount ' . $definitions['posts']['flagcount'] . ' AFTER downvotes, ADD KEY type_3 (type, flagcount, created)');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecountposts']=true;
$keyrecalc['dorecountposts'] = true;
break;
case 27:
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN netvotes '.$definitions['posts']['netvotes'].' AFTER downvotes, ADD KEY type_4 (type, netvotes, created)');
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN netvotes ' . $definitions['posts']['netvotes'] . ' AFTER downvotes, ADD KEY type_4 (type, netvotes, created)');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecountposts']=true;
$keyrecalc['dorecountposts'] = true;
break;
case 28:
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN views '.$definitions['posts']['views'].' AFTER netvotes, ADD COLUMN hotness '.$definitions['posts']['hotness'].' AFTER views, ADD KEY type_5 (type, views, created), ADD KEY type_6 (type, hotness)');
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN views ' . $definitions['posts']['views'] . ' AFTER netvotes, ADD COLUMN hotness ' . $definitions['posts']['hotness'] . ' AFTER views, ADD KEY type_5 (type, views, created), ADD KEY type_6 (type, hotness)');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecountposts']=true;
$keyrecalc['dorecountposts'] = true;
break;
case 29:
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastviewip '.$definitions['posts']['lastviewip'].' AFTER netvotes');
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastviewip ' . $definitions['posts']['lastviewip'] . ' AFTER netvotes');
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1073,10 +1084,10 @@
qa_db_upgrade_query('ALTER TABLE ^posts DROP KEY categoryid, DROP KEY categoryid_2');
qa_db_upgrade_query($locktablesquery);
qa_db_upgrade_query('ALTER TABLE ^categories CHANGE COLUMN categoryid categoryid '.$definitions['categories']['categoryid'].', ADD COLUMN parentid '.$definitions['categories']['parentid'].' AFTER categoryid, ADD COLUMN backpath '.$definitions['categories']['backpath'].' AFTER position, ADD COLUMN content '.$definitions['categories']['content'].' AFTER tags, DROP INDEX tags, DROP INDEX position, ADD UNIQUE parentid (parentid, tags), ADD UNIQUE parentid_2 (parentid, position), ADD KEY backpath (backpath('.QA_DB_MAX_CAT_PAGE_TAGS_LENGTH.'))');
qa_db_upgrade_query('ALTER TABLE ^categories CHANGE COLUMN categoryid categoryid ' . $definitions['categories']['categoryid'] . ', ADD COLUMN parentid ' . $definitions['categories']['parentid'] . ' AFTER categoryid, ADD COLUMN backpath ' . $definitions['categories']['backpath'] . ' AFTER position, ADD COLUMN content ' . $definitions['categories']['content'] . ' AFTER tags, DROP INDEX tags, DROP INDEX position, ADD UNIQUE parentid (parentid, tags), ADD UNIQUE parentid_2 (parentid, position), ADD KEY backpath (backpath(' . QA_DB_MAX_CAT_PAGE_TAGS_LENGTH . '))');
qa_db_upgrade_query($locktablesquery);
qa_db_upgrade_query('ALTER TABLE ^posts CHANGE COLUMN categoryid categoryid '.$definitions['posts']['categoryid'].', ADD COLUMN catidpath1 '.$definitions['posts']['catidpath1'].' AFTER categoryid, ADD COLUMN catidpath2 '.$definitions['posts']['catidpath2'].' AFTER catidpath1, ADD COLUMN catidpath3 '.$definitions['posts']['catidpath3'].' AFTER catidpath2'); // QA_CATEGORY_DEPTH=4
qa_db_upgrade_query('ALTER TABLE ^posts CHANGE COLUMN categoryid categoryid ' . $definitions['posts']['categoryid'] . ', ADD COLUMN catidpath1 ' . $definitions['posts']['catidpath1'] . ' AFTER categoryid, ADD COLUMN catidpath2 ' . $definitions['posts']['catidpath2'] . ' AFTER catidpath1, ADD COLUMN catidpath3 ' . $definitions['posts']['catidpath3'] . ' AFTER catidpath2'); // QA_CATEGORY_DEPTH=4
qa_db_upgrade_query($locktablesquery);
qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY catidpath1 (catidpath1, type, created), ADD KEY catidpath2 (catidpath2, type, created), ADD KEY catidpath3 (catidpath3, type, created), ADD KEY categoryid (categoryid, type, created), ADD KEY catidpath1_2 (catidpath1, updated, type), ADD KEY catidpath2_2 (catidpath2, updated, type), ADD KEY catidpath3_2 (catidpath3, updated, type), ADD KEY categoryid_2 (categoryid, updated, type)');
......@@ -1085,13 +1096,13 @@
qa_db_upgrade_query('ALTER TABLE ^posts ADD CONSTRAINT ^posts_ibfk_3 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE SET NULL');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecalccategories']=true;
$keyrecalc['dorecalccategories'] = true;
break;
// Up to here: Version 1.4 betas and release
case 31:
qa_db_upgrade_query('ALTER TABLE ^posts CHANGE COLUMN type type '.$definitions['posts']['type'].', ADD COLUMN updatetype '.$definitions['posts']['updatetype'].' AFTER updated, ADD COLUMN closedbyid '.$definitions['posts']['closedbyid'].' AFTER selchildid, ADD KEY closedbyid (closedbyid), ADD CONSTRAINT ^posts_ibfk_4 FOREIGN KEY (closedbyid) REFERENCES ^posts(postid)');
qa_db_upgrade_query('ALTER TABLE ^posts CHANGE COLUMN type type ' . $definitions['posts']['type'] . ', ADD COLUMN updatetype ' . $definitions['posts']['updatetype'] . ' AFTER updated, ADD COLUMN closedbyid ' . $definitions['posts']['closedbyid'] . ' AFTER selchildid, ADD KEY closedbyid (closedbyid), ADD CONSTRAINT ^posts_ibfk_4 FOREIGN KEY (closedbyid) REFERENCES ^posts(postid)');
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1100,13 +1111,13 @@
break;
case 33:
qa_db_upgrade_query('ALTER TABLE ^contentwords CHANGE COLUMN type type '.$definitions['contentwords']['type']);
qa_db_upgrade_query('ALTER TABLE ^contentwords CHANGE COLUMN type type ' . $definitions['contentwords']['type']);
qa_db_upgrade_query($locktablesquery);
break;
case 34:
if (!QA_FINAL_EXTERNAL_USERS) {
$keytables=qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW TABLES')));
$keytables = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW TABLES')));
// might be using messages table shared with another installation, so check if we need to upgrade
if (isset($keytables[qa_db_add_table_prefix('messages')]))
......@@ -1126,7 +1137,7 @@
'KEY fromuserid (fromuserid, touserid, created)',
)));
$locktablesquery.=', ^messages WRITE';
$locktablesquery .= ', ^messages WRITE';
qa_db_upgrade_query($locktablesquery);
}
}
......@@ -1146,7 +1157,7 @@
QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^userfavorites_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE',
)));
$locktablesquery.=', ^userfavorites WRITE';
$locktablesquery .= ', ^userfavorites WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1167,10 +1178,10 @@
QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^userevents_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE',
)));
$locktablesquery.=', ^userevents WRITE';
$locktablesquery .= ', ^userevents WRITE';
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorefillevents']=true;
$keyrecalc['dorefillevents'] = true;
break;
case 37:
......@@ -1188,10 +1199,10 @@
'KEY questionid (questionid, entitytype, entityid)',
)));
$locktablesquery.=', ^sharedevents WRITE';
$locktablesquery .= ', ^sharedevents WRITE';
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorefillevents']=true;
$keyrecalc['dorefillevents'] = true;
break;
case 38:
......@@ -1205,12 +1216,12 @@
break;
case 40:
qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN bonus '.$definitions['userpoints']['bonus'].' AFTER downvoteds');
qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN bonus ' . $definitions['userpoints']['bonus'] . ' AFTER downvoteds');
qa_db_upgrade_query($locktablesquery);
break;
case 41:
qa_db_upgrade_query('ALTER TABLE ^pages ADD COLUMN permit '.$definitions['pages']['permit'].' AFTER flags');
qa_db_upgrade_query('ALTER TABLE ^pages ADD COLUMN permit ' . $definitions['pages']['permit'] . ' AFTER flags');
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1225,7 +1236,7 @@
QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^usermetas_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE',
)));
$locktablesquery.=', ^usermetas WRITE';
$locktablesquery .= ', ^usermetas WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1240,7 +1251,7 @@
'CONSTRAINT ^postmetas_ibfk_1 FOREIGN KEY (postid) REFERENCES ^posts(postid) ON DELETE CASCADE',
)));
$locktablesquery.=', ^postmetas WRITE';
$locktablesquery .= ', ^postmetas WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1255,7 +1266,7 @@
'CONSTRAINT ^categorymetas_ibfk_1 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE CASCADE',
)));
$locktablesquery.=', ^categorymetas WRITE';
$locktablesquery .= ', ^categorymetas WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1269,7 +1280,7 @@
'PRIMARY KEY (tag, title)',
)));
$locktablesquery.=', ^tagmetas WRITE';
$locktablesquery .= ', ^tagmetas WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1277,7 +1288,7 @@
qa_db_upgrade_query('ALTER TABLE ^posts DROP KEY selchildid, ADD KEY selchildid (selchildid, type, created), ADD COLUMN amaxvote SMALLINT UNSIGNED NOT NULL DEFAULT 0 AFTER acount, ADD KEY type_7 (type, amaxvote, created)');
qa_db_upgrade_query($locktablesquery);
$keyrecalc['dorecountposts']=true;
$keyrecalc['dorecountposts'] = true;
break;
case 47:
......@@ -1295,7 +1306,7 @@
QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^usernotices_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE',
)));
$locktablesquery.=', ^usernotices WRITE';
$locktablesquery .= ', ^usernotices WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1303,14 +1314,14 @@
case 48:
if (!QA_FINAL_EXTERNAL_USERS) {
$keycolumns=qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^messages')));
$keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^messages')));
// might be using messages table shared with another installation, so check if we need to upgrade
if (isset($keycolumns['type']))
qa_db_upgrade_progress('Skipping upgrading messages table since it was already upgraded by another Q2A site sharing it.');
else {
qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN type '.$definitions['messages']['type'].' AFTER messageid, DROP KEY fromuserid, ADD key type (type, fromuserid, touserid, created), ADD KEY touserid (touserid, type, created)');
qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN type ' . $definitions['messages']['type'] . ' AFTER messageid, DROP KEY fromuserid, ADD key type (type, fromuserid, touserid, created), ADD KEY touserid (touserid, type, created)');
qa_db_upgrade_query($locktablesquery);
}
}
......@@ -1318,26 +1329,26 @@
case 49:
if (!QA_FINAL_EXTERNAL_USERS) {
qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN flags flags '.$definitions['users']['flags']);
qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN flags flags ' . $definitions['users']['flags']);
qa_db_upgrade_query($locktablesquery);
}
break;
case 50:
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN name '.$definitions['posts']['name'].' AFTER tags');
qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN name ' . $definitions['posts']['name'] . ' AFTER tags');
qa_db_upgrade_query($locktablesquery);
break;
case 51:
if (!QA_FINAL_EXTERNAL_USERS) {
$keycolumns=qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^userfields')));
// might be using userfields table shared with another installation, so check if we need to upgrade
$keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^userfields')));
if (isset($keycolumns['permit']))
qa_db_upgrade_progress('Skipping upgrading userfields table since it was already upgraded by another Q2A site sharing it.');
else {
qa_db_upgrade_query('ALTER TABLE ^userfields ADD COLUMN permit '.$definitions['userfields']['permit'].' AFTER flags');
qa_db_upgrade_query('ALTER TABLE ^userfields ADD COLUMN permit ' . $definitions['userfields']['permit'] . ' AFTER flags');
qa_db_upgrade_query($locktablesquery);
}
}
......@@ -1345,7 +1356,7 @@
case 52:
if (!QA_FINAL_EXTERNAL_USERS) {
$keyindexes=qa_array_to_keys(qa_db_read_all_assoc(qa_db_query_sub('SHOW INDEX FROM ^users'), null, 'Key_name'));
$keyindexes = qa_array_to_keys(qa_db_read_all_assoc(qa_db_query_sub('SHOW INDEX FROM ^users'), null, 'Key_name'));
if (isset($keyindexes['created']))
qa_db_upgrade_progress('Skipping upgrading users table since it was already upgraded by another Q2A site sharing it.');
......@@ -1358,7 +1369,7 @@
break;
case 53:
qa_db_upgrade_query('ALTER TABLE ^blobs CHANGE COLUMN content content '.$definitions['blobs']['content']);
qa_db_upgrade_query('ALTER TABLE ^blobs CHANGE COLUMN content content ' . $definitions['blobs']['content']);
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1377,7 +1388,7 @@
QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^userlevels_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE',
)));
$locktablesquery.=', ^userlevels WRITE';
$locktablesquery .= ', ^userlevels WRITE';
qa_db_upgrade_query($locktablesquery);
break;
......@@ -1385,14 +1396,14 @@
case 55:
if (!QA_FINAL_EXTERNAL_USERS) {
$keycolumns=qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^users')));
// might be using users table shared with another installation, so check if we need to upgrade
$keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^users')));
if (isset($keycolumns['wallposts']))
qa_db_upgrade_progress('Skipping upgrading users table since it was already upgraded by another Q2A site sharing it.');
else {
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN wallposts '.$definitions['users']['wallposts'].' AFTER flags');
qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN wallposts ' . $definitions['users']['wallposts'] . ' AFTER flags');
qa_db_upgrade_query($locktablesquery);
}
}
......@@ -1415,8 +1426,8 @@
if (isset($keycolumns['fromhidden']))
qa_db_upgrade_progress('Skipping upgrading messages table since it was already upgraded by another Q2A site sharing it.');
else {
qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN fromhidden '.$definitions['messages']['fromhidden'].' AFTER touserid');
qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN tohidden '.$definitions['messages']['tohidden'].' AFTER fromhidden');
qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN fromhidden ' . $definitions['messages']['fromhidden'] . ' AFTER touserid');
qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN tohidden ' . $definitions['messages']['tohidden'] . ' AFTER fromhidden');
qa_db_upgrade_query('ALTER TABLE ^messages ADD KEY fromhidden (fromhidden), ADD KEY tohidden (tohidden)');
qa_db_upgrade_query($locktablesquery);
......@@ -1458,15 +1469,15 @@
$oldlength = qa_db_read_one_value(qa_db_query_sub($query, QA_FINAL_MYSQL_DATABASE, $tablename));
if ($oldlength < $newlength) {
qa_db_upgrade_query('ALTER TABLE ^posts MODIFY content '.$definitions['posts']['content']);
qa_db_upgrade_query('ALTER TABLE ^posts MODIFY content ' . $definitions['posts']['content']);
}
break;
case 62:
if (!QA_FINAL_EXTERNAL_USERS) {
$keycolumns=qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^users')));
// might be using users table shared with another installation, so check if we need to upgrade
$keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^users')));
if (isset($keycolumns['passhash']))
qa_db_upgrade_progress(sprintf($skipMessage, 'users'));
......@@ -1484,11 +1495,11 @@
if (strtolower($fieldDef['Type']) === 'varbinary(16)')
qa_db_upgrade_progress(sprintf($skipMessage, 'cookies'));
else {
qa_db_upgrade_query('ALTER TABLE ^cookies MODIFY writeip '.$definitions['cookies']['writeip'].', MODIFY createip '.$definitions['cookies']['createip']);
qa_db_upgrade_query('ALTER TABLE ^cookies MODIFY writeip ' . $definitions['cookies']['writeip'] . ', MODIFY createip ' . $definitions['cookies']['createip']);
qa_db_upgrade_query('UPDATE ^cookies SET writeip = UNHEX(HEX(CAST(writeip AS UNSIGNED))), createip = UNHEX(HEX(CAST(createip AS UNSIGNED)))');
}
qa_db_upgrade_query('ALTER TABLE ^iplimits MODIFY ip '.$definitions['iplimits']['ip']);
qa_db_upgrade_query('ALTER TABLE ^iplimits MODIFY ip ' . $definitions['iplimits']['ip']);
qa_db_upgrade_query('UPDATE ^iplimits SET ip = UNHEX(HEX(CAST(ip AS UNSIGNED)))');
// check for shared blobs table
......@@ -1496,11 +1507,11 @@
if (strtolower($fieldDef['Type']) === 'varbinary(16)')
qa_db_upgrade_progress(sprintf($skipMessage, 'blobs'));
else {
qa_db_upgrade_query('ALTER TABLE ^blobs MODIFY createip '.$definitions['blobs']['createip']);
qa_db_upgrade_query('ALTER TABLE ^blobs MODIFY createip ' . $definitions['blobs']['createip']);
qa_db_upgrade_query('UPDATE ^blobs SET createip = UNHEX(HEX(CAST(createip AS UNSIGNED)))');
}
qa_db_upgrade_query('ALTER TABLE ^posts MODIFY lastviewip '.$definitions['posts']['lastviewip'].', MODIFY lastip '.$definitions['posts']['lastip'].', MODIFY createip '.$definitions['posts']['createip']);
qa_db_upgrade_query('ALTER TABLE ^posts MODIFY lastviewip ' . $definitions['posts']['lastviewip'] . ', MODIFY lastip ' . $definitions['posts']['lastip'] . ', MODIFY createip ' . $definitions['posts']['createip']);
qa_db_upgrade_query('UPDATE ^posts SET lastviewip = UNHEX(HEX(CAST(lastviewip AS UNSIGNED))), lastip = UNHEX(HEX(CAST(lastip AS UNSIGNED))), createip = UNHEX(HEX(CAST(createip AS UNSIGNED)))');
if (!QA_FINAL_EXTERNAL_USERS) {
......@@ -1509,7 +1520,7 @@
if (strtolower($fieldDef['Type']) === 'varbinary(16)')
qa_db_upgrade_progress(sprintf($skipMessage, 'users'));
else {
qa_db_upgrade_query('ALTER TABLE ^users MODIFY createip '.$definitions['users']['createip'].', MODIFY loginip '.$definitions['users']['loginip'].', MODIFY writeip '.$definitions['users']['writeip']);
qa_db_upgrade_query('ALTER TABLE ^users MODIFY createip ' . $definitions['users']['createip'] . ', MODIFY loginip ' . $definitions['users']['loginip'] . ', MODIFY writeip ' . $definitions['users']['writeip']);
qa_db_upgrade_query('UPDATE ^users SET createip = UNHEX(HEX(CAST(createip AS UNSIGNED))), loginip = UNHEX(HEX(CAST(loginip AS UNSIGNED))), writeip = UNHEX(HEX(CAST(writeip AS UNSIGNED)))');
}
}
......@@ -1529,7 +1540,7 @@
qa_db_set_db_version($newversion);
if (qa_db_get_db_version()!=$newversion)
if (qa_db_get_db_version() != $newversion)
qa_fatal_error('Could not increment database version');
}
......@@ -1541,50 +1552,50 @@
while ($state) {
set_time_limit(60);
$stoptime=time()+2;
$stoptime = time() + 2;
while ( qa_recalc_perform_step($state) && (time()<$stoptime) )
while (qa_recalc_perform_step($state) && (time() < $stoptime))
;
qa_db_upgrade_progress(qa_recalc_get_message($state));
}
}
}
function qa_db_upgrade_table_columns($definitions, $table, $columns)
/*
Reset the definitions of $columns in $table according to the $definitions array
*/
{
$sqlchanges=array();
/**
* Reset the definitions of $columns in $table according to the $definitions array
* @param $definitions
* @param $table
* @param $columns
*/
function qa_db_upgrade_table_columns($definitions, $table, $columns)
{
$sqlchanges = array();
foreach ($columns as $column)
$sqlchanges[]='CHANGE COLUMN '.$column.' '.$column.' '.$definitions[$table][$column];
$sqlchanges[] = 'CHANGE COLUMN ' . $column . ' ' . $column . ' ' . $definitions[$table][$column];
qa_db_upgrade_query('ALTER TABLE ^'.$table.' '.implode(', ', $sqlchanges));
}
qa_db_upgrade_query('ALTER TABLE ^' . $table . ' ' . implode(', ', $sqlchanges));
}
function qa_db_upgrade_query($query)
/*
Perform upgrade $query and output progress to the browser
*/
{
qa_db_upgrade_progress('Running query: '.qa_db_apply_sub($query, array()).' ...');
/**
* Perform upgrade $query and output progress to the browser
* @param $query
*/
function qa_db_upgrade_query($query)
{
qa_db_upgrade_progress('Running query: ' . qa_db_apply_sub($query, array()) . ' ...');
qa_db_query_sub($query);
}
}
function qa_db_upgrade_progress($text)
/*
Output $text to the browser (after converting to HTML) and do all we can to get it displayed
*/
{
echo qa_html($text).str_repeat(' ', 1024)."<br><br>\n";
/**
* Output $text to the browser (after converting to HTML) and do all we can to get it displayed
* @param $text
*/
function qa_db_upgrade_progress($text)
{
echo qa_html($text) . str_repeat(' ', 1024) . "<br><br>\n";
flush();
}
/*
Omit PHP closing tag to help avoid accidental output
*/
}
......@@ -20,58 +20,66 @@
More about this license: http://www.question2answer.org/license.php
*/
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser
header('Location: ../');
exit;
}
}
require_once QA_INCLUDE_DIR.'db/post-create.php';
require_once QA_INCLUDE_DIR . 'db/post-create.php';
// For reindexing pages...
function qa_db_count_pages()
/*
Return the number of custom pages currently in the database
*/
{
/**
* Return the number of custom pages currently in the database
*/
function qa_db_count_pages()
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^pages'
));
}
}
function qa_db_pages_get_for_reindexing($startpageid, $count)
/*
Return the information to reindex up to $count pages starting from $startpageid in the database
*/
{
/**
* Return the information to reindex up to $count pages starting from $startpageid in the database
* @param $startpageid
* @param $count
* @return array
*/
function qa_db_pages_get_for_reindexing($startpageid, $count)
{
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT pageid, flags, tags, heading, content FROM ^pages WHERE pageid>=# ORDER BY pageid LIMIT #',
$startpageid, $count
), 'pageid');
}
}
// For reindexing posts...
function qa_db_posts_get_for_reindexing($startpostid, $count)
/*
Return the information required to reindex up to $count posts starting from $startpostid in the database
*/
{
/**
* Return the information required to reindex up to $count posts starting from $startpostid in the database
* @param $startpostid
* @param $count
* @return array
*/
function qa_db_posts_get_for_reindexing($startpostid, $count)
{
return qa_db_read_all_assoc(qa_db_query_sub(
"SELECT ^posts.postid, ^posts.title, ^posts.content, ^posts.format, ^posts.tags, ^posts.categoryid, ^posts.type, IF (^posts.type='Q', ^posts.postid, IF(parent.type='Q', parent.postid, grandparent.postid)) AS questionid, ^posts.parentid FROM ^posts LEFT JOIN ^posts AS parent ON ^posts.parentid=parent.postid LEFT JOIN ^posts as grandparent ON parent.parentid=grandparent.postid WHERE ^posts.postid>=# AND ( (^posts.type='Q') OR (^posts.type='A' AND parent.type<=>'Q') OR (^posts.type='C' AND parent.type<=>'Q') OR (^posts.type='C' AND parent.type<=>'A' AND grandparent.type<=>'Q') ) ORDER BY postid LIMIT #",
$startpostid, $count
), 'postid');
}
}
function qa_db_prepare_for_reindexing($firstpostid, $lastpostid)
/*
Prepare posts $firstpostid to $lastpostid for reindexing in the database by removing their prior index entries
*/
{
/**
* Prepare posts $firstpostid to $lastpostid for reindexing in the database by removing their prior index entries
* @param $firstpostid
* @param $lastpostid
*/
function qa_db_prepare_for_reindexing($firstpostid, $lastpostid)
{
qa_db_query_sub(
'DELETE FROM ^titlewords WHERE postid>=# AND postid<=#',
$firstpostid, $lastpostid
......@@ -91,14 +99,15 @@
'DELETE FROM ^posttags WHERE postid>=# AND postid<=#',
$firstpostid, $lastpostid
);
}
}
function qa_db_truncate_indexes($firstpostid)
/*
Remove any rows in the database word indexes with postid from $firstpostid upwards
*/
{
/**
* Remove any rows in the database word indexes with postid from $firstpostid upwards
* @param $firstpostid
*/
function qa_db_truncate_indexes($firstpostid)
{
qa_db_query_sub(
'DELETE FROM ^titlewords WHERE postid>=#',
$firstpostid
......@@ -118,37 +127,42 @@
'DELETE FROM ^posttags WHERE postid>=#',
$firstpostid
);
}
}
function qa_db_count_words()
/*
Return the number of words currently referenced in the database
*/
{
/**
* Return the number of words currently referenced in the database
*/
function qa_db_count_words()
{
return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^words'
));
}
}
function qa_db_words_prepare_for_recounting($startwordid, $count)
/*
Return the ids of up to $count words in the database starting from $startwordid
*/
{
/**
* Return the ids of up to $count words in the database starting from $startwordid
* @param $startwordid
* @param $count
* @return array
*/
function qa_db_words_prepare_for_recounting($startwordid, $count)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT wordid FROM ^words WHERE wordid>=# ORDER BY wordid LIMIT #',
$startwordid, $count
));
}
}
function qa_db_words_recount($firstwordid, $lastwordid)
/*
Recalculate the cached counts for words $firstwordid to $lastwordid in the database
*/
{
/**
* Recalculate the cached counts for words $firstwordid to $lastwordid in the database
* @param $firstwordid
* @param $lastwordid
*/
function qa_db_words_recount($firstwordid, $lastwordid)
{
qa_db_query_sub(
'UPDATE ^words AS x, (SELECT ^words.wordid, COUNT(^titlewords.wordid) AS titlecount FROM ^words LEFT JOIN ^titlewords ON ^titlewords.wordid=^words.wordid WHERE ^words.wordid>=# AND ^words.wordid<=# GROUP BY wordid) AS a SET x.titlecount=a.titlecount WHERE x.wordid=a.wordid',
$firstwordid, $lastwordid
......@@ -173,43 +187,50 @@
'DELETE FROM ^words WHERE wordid>=# AND wordid<=# AND titlecount=0 AND contentcount=0 AND tagwordcount=0 AND tagcount=0',
$firstwordid, $lastwordid
);
}
}
// For recalculating numbers of votes and answers for questions...
function qa_db_posts_get_for_recounting($startpostid, $count)
/*
Return the ids of up to $count posts in the database starting from $startpostid
*/
{
/**
* Return the ids of up to $count posts in the database starting from $startpostid
* @param $startpostid
* @param $count
* @return array
*/
function qa_db_posts_get_for_recounting($startpostid, $count)
{
return qa_db_read_all_values(qa_db_query_sub(
'SELECT postid FROM ^posts WHERE postid>=# ORDER BY postid LIMIT #',
$startpostid, $count
));
}
}
function qa_db_posts_votes_recount($firstpostid, $lastpostid)
/*
Recalculate the cached vote counts for posts $firstpostid to $lastpostid in the database
*/
{
/**
* Recalculate the cached vote counts for posts $firstpostid to $lastpostid in the database
* @param $firstpostid
* @param $lastpostid
*/
function qa_db_posts_votes_recount($firstpostid, $lastpostid)
{
qa_db_query_sub(
'UPDATE ^posts AS x, (SELECT ^posts.postid, COALESCE(SUM(GREATEST(0,^uservotes.vote)),0) AS upvotes, -COALESCE(SUM(LEAST(0,^uservotes.vote)),0) AS downvotes, COALESCE(SUM(IF(^uservotes.flag, 1, 0)),0) AS flagcount FROM ^posts LEFT JOIN ^uservotes ON ^uservotes.postid=^posts.postid WHERE ^posts.postid>=# AND ^posts.postid<=# GROUP BY postid) AS a SET x.upvotes=a.upvotes, x.downvotes=a.downvotes, x.netvotes=a.upvotes-a.downvotes, x.flagcount=a.flagcount WHERE x.postid=a.postid',
$firstpostid, $lastpostid
);
qa_db_hotness_update($firstpostid, $lastpostid);
}
}
function qa_db_posts_answers_recount($firstpostid, $lastpostid)
/*
Recalculate the cached answer counts for posts $firstpostid to $lastpostid in the database, along with the highest netvotes of any of their answers
*/
{
require_once QA_INCLUDE_DIR.'db/hotness.php';
/**
* Recalculate the cached answer counts for posts $firstpostid to $lastpostid in the database, along with the highest netvotes of any of their answers
* @param $firstpostid
* @param $lastpostid
*/
function qa_db_posts_answers_recount($firstpostid, $lastpostid)
{
require_once QA_INCLUDE_DIR . 'db/hotness.php';
qa_db_query_sub(
'UPDATE ^posts AS x, (SELECT parents.postid, COUNT(children.postid) AS acount, COALESCE(GREATEST(MAX(children.netvotes), 0), 0) AS amaxvote FROM ^posts AS parents LEFT JOIN ^posts AS children ON parents.postid=children.parentid AND children.type=\'A\' WHERE parents.postid>=# AND parents.postid<=# GROUP BY postid) AS a SET x.acount=a.acount, x.amaxvote=a.amaxvote WHERE x.postid=a.postid',
......@@ -217,17 +238,20 @@
);
qa_db_hotness_update($firstpostid, $lastpostid);
}
}
// For recalculating user points...
function qa_db_users_get_for_recalc_points($startuserid, $count)
/*
Return the ids of up to $count users in the database starting from $startuserid
If using single sign-on integration, base this on user activity rather than the users table which we don't have
*/
{
/**
* Return the ids of up to $count users in the database starting from $startuserid
* If using single sign-on integration, base this on user activity rather than the users table which we don't have
* @param $startuserid
* @param $count
* @return array
*/
function qa_db_users_get_for_recalc_points($startuserid, $count)
{
if (QA_FINAL_EXTERNAL_USERS)
return qa_db_read_all_values(qa_db_query_sub(
'SELECT userid FROM ((SELECT DISTINCT userid FROM ^posts WHERE userid>=# ORDER BY userid LIMIT #) UNION (SELECT DISTINCT userid FROM ^uservotes WHERE userid>=# ORDER BY userid LIMIT #)) x ORDER BY userid LIMIT #',
......@@ -238,29 +262,31 @@
'SELECT DISTINCT userid FROM ^users WHERE userid>=# ORDER BY userid LIMIT #',
$startuserid, $count
));
}
}
function qa_db_users_recalc_points($firstuserid, $lastuserid)
/*
Recalculate all userpoints columns for users $firstuserid to $lastuserid in the database
*/
{
require_once QA_INCLUDE_DIR.'db/points.php';
/**
* Recalculate all userpoints columns for users $firstuserid to $lastuserid in the database
* @param $firstuserid
* @param $lastuserid
*/
function qa_db_users_recalc_points($firstuserid, $lastuserid)
{
require_once QA_INCLUDE_DIR . 'db/points.php';
$qa_userpoints_calculations=qa_db_points_calculations();
$qa_userpoints_calculations = qa_db_points_calculations();
qa_db_query_sub(
'DELETE FROM ^userpoints WHERE userid>=# AND userid<=# AND bonus=0', // delete those with no bonus
$firstuserid, $lastuserid
);
$zeropoints='points=0';
$zeropoints = 'points=0';
foreach ($qa_userpoints_calculations as $field => $calculation)
$zeropoints.=', '.$field.'=0';
$zeropoints .= ', ' . $field . '=0';
qa_db_query_sub(
'UPDATE ^userpoints SET '.$zeropoints.' WHERE userid>=# AND userid<=#', // zero out the rest
'UPDATE ^userpoints SET ' . $zeropoints . ' WHERE userid>=# AND userid<=#', // zero out the rest
$firstuserid, $lastuserid
);
......@@ -275,150 +301,165 @@
$firstuserid, $lastuserid
);
$updatepoints=(int)qa_opt('points_base');
$updatepoints = (int)qa_opt('points_base');
foreach ($qa_userpoints_calculations as $field => $calculation) {
qa_db_query_sub(
'UPDATE ^userpoints, (SELECT userid_src.userid, '.str_replace('~', ' BETWEEN # AND #', $calculation['formula']).' GROUP BY userid) AS results '.
'SET ^userpoints.'.$field.'=results.'.$field.' WHERE ^userpoints.userid=results.userid',
'UPDATE ^userpoints, (SELECT userid_src.userid, ' . str_replace('~', ' BETWEEN # AND #', $calculation['formula']) . ' GROUP BY userid) AS results ' .
'SET ^userpoints.' . $field . '=results.' . $field . ' WHERE ^userpoints.userid=results.userid',
$firstuserid, $lastuserid
);
$updatepoints.='+('.((int)$calculation['multiple']).'*'.$field.')';
$updatepoints .= '+(' . ((int)$calculation['multiple']) . '*' . $field . ')';
}
qa_db_query_sub(
'UPDATE ^userpoints SET points='.$updatepoints.'+bonus WHERE userid>=# AND userid<=#',
'UPDATE ^userpoints SET points=' . $updatepoints . '+bonus WHERE userid>=# AND userid<=#',
$firstuserid, $lastuserid
);
}
}
function qa_db_truncate_userpoints($lastuserid)
/*
Remove any rows in the userpoints table where userid is greater than $lastuserid
*/
{
/**
* Remove any rows in the userpoints table where userid is greater than $lastuserid
* @param $lastuserid
*/
function qa_db_truncate_userpoints($lastuserid)
{
qa_db_query_sub(
'DELETE FROM ^userpoints WHERE userid>#',
$lastuserid
);
}
}
// For refilling event streams...
function qa_db_qs_get_for_event_refilling($startpostid, $count)
/*
Return the ids of up to $count questions in the database starting from $startpostid
*/
{
/**
* Return the ids of up to $count questions in the database starting from $startpostid
* @param $startpostid
* @param $count
* @return array
*/
function qa_db_qs_get_for_event_refilling($startpostid, $count)
{
return qa_db_read_all_values(qa_db_query_sub(
"SELECT postid FROM ^posts WHERE postid>=# AND LEFT(type, 1)='Q' ORDER BY postid LIMIT #",
$startpostid, $count
));
}
}
// For recalculating categories...
function qa_db_posts_get_for_recategorizing($startpostid, $count)
/*
Return the ids of up to $count posts (including queued/hidden) in the database starting from $startpostid
*/
{
/**
* Return the ids of up to $count posts (including queued/hidden) in the database starting from $startpostid
* @param $startpostid
* @param $count
* @return array
*/
function qa_db_posts_get_for_recategorizing($startpostid, $count)
{
return qa_db_read_all_values(qa_db_query_sub(
"SELECT postid FROM ^posts WHERE postid>=# ORDER BY postid LIMIT #",
$startpostid, $count
));
}
}
function qa_db_posts_recalc_categoryid($firstpostid, $lastpostid)
/*
Recalculate the (exact) categoryid for the posts (including queued/hidden) between $firstpostid and $lastpostid
in the database, where the category of comments and answers is set by the category of the antecedent question
*/
{
/**
* Recalculate the (exact) categoryid for the posts (including queued/hidden) between $firstpostid and $lastpostid
* in the database, where the category of comments and answers is set by the category of the antecedent question
* @param $firstpostid
* @param $lastpostid
*/
function qa_db_posts_recalc_categoryid($firstpostid, $lastpostid)
{
qa_db_query_sub(
"UPDATE ^posts AS x, (SELECT ^posts.postid, IF(LEFT(parent.type, 1)='Q', parent.categoryid, grandparent.categoryid) AS categoryid FROM ^posts LEFT JOIN ^posts AS parent ON ^posts.parentid=parent.postid LEFT JOIN ^posts AS grandparent ON parent.parentid=grandparent.postid WHERE ^posts.postid BETWEEN # AND # AND LEFT(^posts.type, 1)!='Q') AS a SET x.categoryid=a.categoryid WHERE x.postid=a.postid",
$firstpostid, $lastpostid
);
}
}
function qa_db_categories_get_for_recalcs($startcategoryid, $count)
/*
Return the ids of up to $count categories in the database starting from $startcategoryid
*/
{
/**
* Return the ids of up to $count categories in the database starting from $startcategoryid
* @param $startcategoryid
* @param $count
* @return array
*/
function qa_db_categories_get_for_recalcs($startcategoryid, $count)
{
return qa_db_read_all_values(qa_db_query_sub(
"SELECT categoryid FROM ^categories WHERE categoryid>=# ORDER BY categoryid LIMIT #",
$startcategoryid, $count
));
}
}
// For deleting hidden posts...
function qa_db_posts_get_for_deleting($type, $startpostid=0, $limit=null)
/*
Return the ids of up to $limit posts of $type that can be deleted from the database (i.e. have no dependents)
*/
{
$limitsql=isset($limit) ? (' ORDER BY ^posts.postid LIMIT '.(int)$limit) : '';
/**
* Return the ids of up to $limit posts of $type that can be deleted from the database (i.e. have no dependents)
* @param $type
* @param int $startpostid
* @param $limit
* @return array
*/
function qa_db_posts_get_for_deleting($type, $startpostid = 0, $limit = null)
{
$limitsql = isset($limit) ? (' ORDER BY ^posts.postid LIMIT ' . (int)$limit) : '';
return qa_db_read_all_values(qa_db_query_sub(
"SELECT ^posts.postid FROM ^posts LEFT JOIN ^posts AS child ON child.parentid=^posts.postid LEFT JOIN ^posts AS dupe ON dupe.closedbyid=^posts.postid WHERE ^posts.type=$ AND ^posts.postid>=# AND child.postid IS NULL AND dupe.postid IS NULL".$limitsql,
$type.'_HIDDEN', $startpostid
"SELECT ^posts.postid FROM ^posts LEFT JOIN ^posts AS child ON child.parentid=^posts.postid LEFT JOIN ^posts AS dupe ON dupe.closedbyid=^posts.postid WHERE ^posts.type=$ AND ^posts.postid>=# AND child.postid IS NULL AND dupe.postid IS NULL" . $limitsql,
$type . '_HIDDEN', $startpostid
));
}
}
// For moving blobs between database and disk...
function qa_db_count_blobs_in_db()
/*
Return the number of blobs whose content is stored in the database, rather than on disk
*/
{
/**
* Return the number of blobs whose content is stored in the database, rather than on disk
*/
function qa_db_count_blobs_in_db()
{
return qa_db_read_one_value(qa_db_query_sub('SELECT COUNT(*) FROM ^blobs WHERE content IS NOT NULL'));
}
}
function qa_db_get_next_blob_in_db($startblobid)
/*
Return the id, content and format of the first blob whose content is stored in the database starting from $startblobid
*/
{
/**
* Return the id, content and format of the first blob whose content is stored in the database starting from $startblobid
* @param $startblobid
* @return array|null
*/
function qa_db_get_next_blob_in_db($startblobid)
{
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT blobid, content, format FROM ^blobs WHERE blobid>=# AND content IS NOT NULL LIMIT 1',
$startblobid
), true);
}
}
function qa_db_count_blobs_on_disk()
/*
Return the number of blobs whose content is stored on disk, rather than in the database
*/
{
/**
* Return the number of blobs whose content is stored on disk, rather than in the database
*/
function qa_db_count_blobs_on_disk()
{
return qa_db_read_one_value(qa_db_query_sub('SELECT COUNT(*) FROM ^blobs WHERE content IS NULL'));
}
}
function qa_db_get_next_blob_on_disk($startblobid)
/*
Return the id and format of the first blob whose content is stored on disk starting from $startblobid
*/
{
/**
* Return the id and format of the first blob whose content is stored on disk starting from $startblobid
* @param $startblobid
* @return array|null
*/
function qa_db_get_next_blob_on_disk($startblobid)
{
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT blobid, format FROM ^blobs WHERE blobid>=# AND content IS NULL LIMIT 1',
$startblobid
), true);
}
/*
Omit PHP closing tag to help avoid accidental output
*/
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment