Index: wp-includes/version.php
===================================================================
--- wp-includes/version.php	(revision 3707)
+++ wp-includes/version.php	(working copy)
@@ -3,6 +3,6 @@
 // This just holds the version number, in a separate file so we can bump it without cluttering the SVN
 
 $wp_version = '2.1-alpha1';
-$wp_db_version = 3672;
+$wp_db_version = 3673;
 
 ?>
\ No newline at end of file
Index: wp-includes/functions-post.php
===================================================================
--- wp-includes/functions-post.php	(revision 3707)
+++ wp-includes/functions-post.php	(working copy)
@@ -574,6 +574,11 @@
 
 	$wpdb->query("DELETE FROM $wpdb->posts WHERE ID = $postid");
 
+	// A little extra effort here, but it saves us from having to store post_ids with comment meta
+	$comment_ids = $wpdb->get_col("SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = $postid");
+	$comment_ids = implode(',', $comment_ids);
+	$wpdb->query("DELETE FROM $wpdb->commentmeta WHERE comment_ID IN ($comment_ids)");
+
 	$wpdb->query("DELETE FROM $wpdb->comments WHERE comment_post_ID = $postid");
 
 	$wpdb->query("DELETE FROM $wpdb->post2cat WHERE post_id = $postid");
Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php	(revision 3707)
+++ wp-includes/functions.php	(working copy)
@@ -428,12 +428,39 @@
 	return true;
 }
 
+function setup_meta_vars($type = 'post') {
+	global $wpdb;
+	if ( $type != 'post' && $type != 'comment' )
+		return false; // Garbage control
+	$return = array();
+	$return['table'] = $type . 'meta';
+	$return['table'] = $wpdb->$return['table'];
+	$return['id_col'] = $type . '_id';
+	$return['cache'] = $type . '_meta_cache';
+	return $return;
+}
+
+function add_comment_meta($comment_id, $key, $value, $unique = false) {
+	return wp_add_meta($comment_id, $key, $value, $unique, 'comment');
+}
+
 function add_post_meta($post_id, $key, $value, $unique = false) {
-	global $wpdb, $post_meta_cache;
+	return wp_add_meta($post_id, $key, $value, $unique, 'post');
+}
 
+function wp_add_meta($id, $key, $value, $unique = false, $type = 'post') {
+	global $wpdb;
+
+	if ( $vars = setup_meta_vars($type) ) {
+		extract($vars);
+		global $$cache;
+	} else {
+		return false;
+	}
+
 	if ( $unique ) {
-		if ( $wpdb->get_var("SELECT meta_key FROM $wpdb->postmeta WHERE meta_key
-= '$key' AND post_id = '$post_id'") ) {
+		if ( $wpdb->get_var("SELECT meta_key FROM $table WHERE meta_key
+= '$key' AND $id_col = '$id'") ) {
 			return false;
 		}
 	}
@@ -442,57 +469,87 @@
 	if ( is_array($value) || is_object($value) )
 		$value = $wpdb->escape(serialize($value));
 
-	$wpdb->query("INSERT INTO $wpdb->postmeta (post_id,meta_key,meta_value) VALUES ('$post_id','$key','$value')");
+	$wpdb->query("INSERT INTO $table ($id_col,meta_key,meta_value) VALUES ('$id','$key','$value')");
 
-	$post_meta_cache['$post_id'][$key][] = $original;
+	${$cache}['$id'][$key][] = $original;
 
 	return true;
 }
 
+function delete_comment_meta($comment_id, $key, $value = '') {
+	return wp_delete_meta($comment_id, $key, $value, 'comment');
+}
+
 function delete_post_meta($post_id, $key, $value = '') {
-	global $wpdb, $post_meta_cache;
+	return wp_delete_meta($post_id, $key, $value, 'post');
+}
 
+function wp_delete_meta($id, $key, $value = '', $type = 'post') {
+	global $wpdb;
+
+	if ( $vars = setup_meta_vars($type) ) {
+		extract($vars);
+		global $$cache;
+	} else {
+		return false;
+	}
+
 	if ( empty($value) ) {
-		$meta_id = $wpdb->get_var("SELECT meta_id FROM $wpdb->postmeta WHERE
-post_id = '$post_id' AND meta_key = '$key'");
+		$meta_id = $wpdb->get_var("SELECT meta_id FROM $table WHERE
+$id_col = '$id' AND meta_key = '$key'");
 	} else {
-		$meta_id = $wpdb->get_var("SELECT meta_id FROM $wpdb->postmeta WHERE
-post_id = '$post_id' AND meta_key = '$key' AND meta_value = '$value'");
+		$meta_id = $wpdb->get_var("SELECT meta_id FROM $table WHERE
+$id_col = '$id' AND meta_key = '$key' AND meta_value = '$value'");
 	}
 
 	if ( !$meta_id )
 		return false;
 
 	if ( empty($value) ) {
-		$wpdb->query("DELETE FROM $wpdb->postmeta WHERE post_id = '$post_id'
+		$wpdb->query("DELETE FROM $table WHERE $id_col = '$id'
 AND meta_key = '$key'");
-		unset($post_meta_cache['$post_id'][$key]);
+		unset(${$cache}['$id'][$key]);
 	} else {
-		$wpdb->query("DELETE FROM $wpdb->postmeta WHERE post_id = '$post_id'
+		$wpdb->query("DELETE FROM $table WHERE $id_col = '$id'
 AND meta_key = '$key' AND meta_value = '$value'");
-		$cache_key = $post_meta_cache['$post_id'][$key];
+		$cache_key = ${$cache}['$id'][$key];
 		if ($cache_key) foreach ( $cache_key as $index => $data )
 			if ( $data == $value )
-				unset($post_meta_cache['$post_id'][$key][$index]);
+				unset(${$cache}['$id'][$key][$index]);
 	}
 
-	unset($post_meta_cache['$post_id'][$key]);
+	unset(${$cache}['$id'][$key]);
 
 	return true;
 }
 
+function get_comment_meta($comment_id, $key, $single = false) {
+	return wp_get_meta($comment_id, $key, $single, 'comment');
+}
+
 function get_post_meta($post_id, $key, $single = false) {
-	global $wpdb, $post_meta_cache;
+	return wp_get_meta($post_id, $key, $single, 'post');
+}
 
-	if ( isset($post_meta_cache[$post_id][$key]) ) {
+function wp_get_meta($id, $key, $single = false, $type = 'post') {
+	global $wpdb;
+
+	if ( $vars = setup_meta_vars($type) ) {
+		extract($vars);
+		global $$cache;
+	} else {
+		return false;
+	}
+
+	if ( isset(${$cache}[$id][$key]) ) {
 		if ( $single ) {
-			return maybe_unserialize( $post_meta_cache[$post_id][$key][0] );
+			return maybe_unserialize( ${$cache}[$id][$key][0] );
 		} else {
-			return maybe_unserialize( $post_meta_cache[$post_id][$key] );
+			return maybe_unserialize( ${$cache}[$id][$key] );
 		}
 	}
 
-	$metalist = $wpdb->get_results("SELECT meta_value FROM $wpdb->postmeta WHERE post_id = '$post_id' AND meta_key = '$key'", ARRAY_N);
+	$metalist = $wpdb->get_results("SELECT meta_value FROM $table WHERE $id_col = '$id' AND meta_key = '$key'", ARRAY_N);
 
 	$values = array();
 	if ( $metalist ) {
@@ -514,9 +571,24 @@
 	return maybe_unserialize($return);
 }
 
+function update_comment_meta($comment_id, $key, $value, $prev_value = '') {
+	return wp_update_meta($comment_id, $key, $value, $prev_value, 'comment');
+}
+
 function update_post_meta($post_id, $key, $value, $prev_value = '') {
-	global $wpdb, $post_meta_cache;
+	return wp_update_meta($post_id, $key, $value, $prev_value, 'post');
+}
 
+function wp_update_meta($id, $key, $value, $prev_value = '', $type = 'post') {
+	global $wpdb;
+
+	if ( $vars = setup_meta_vars($type) ) {
+		extract($vars);
+		global $$cache;
+	} else {
+		return false;
+	}
+
 	$original_value = $value;
 	if ( is_array($value) || is_object($value) )
 		$value = $wpdb->escape(serialize($value));
@@ -525,26 +597,26 @@
 	if ( is_array($prev_value) || is_object($prev_value) )
 		$prev_value = $wpdb->escape(serialize($prev_value));
 
-	if (! $wpdb->get_var("SELECT meta_key FROM $wpdb->postmeta WHERE meta_key
-= '$key' AND post_id = '$post_id'") ) {
+	if (! $wpdb->get_var("SELECT meta_key FROM $table WHERE meta_key
+= '$key' AND $id_col = '$id'") ) {
 		return false;
 	}
 
 	if ( empty($prev_value) ) {
-		$wpdb->query("UPDATE $wpdb->postmeta SET meta_value = '$value' WHERE
-meta_key = '$key' AND post_id = '$post_id'");
-		$cache_key = $post_meta_cache['$post_id'][$key];
+		$wpdb->query("UPDATE $table SET meta_value = '$value' WHERE
+meta_key = '$key' AND $id_col = '$id'");
+		$cache_key = ${$cache}['$id'][$key];
 		if ( !empty($cache_key) )
 			foreach ($cache_key as $index => $data)
-				$post_meta_cache['$post_id'][$key][$index] = $original_value;
+				${$cache}['$id'][$key][$index] = $original_value;
 	} else {
-		$wpdb->query("UPDATE $wpdb->postmeta SET meta_value = '$value' WHERE
-meta_key = '$key' AND post_id = '$post_id' AND meta_value = '$prev_value'");
-		$cache_key = $post_meta_cache['$post_id'][$key];
+		$wpdb->query("UPDATE $table SET meta_value = '$value' WHERE
+meta_key = '$key' AND $id_col = '$id' AND meta_value = '$prev_value'");
+		$cache_key = ${$cache}['$id'][$key];
 		if ( !empty($cache_key) )
 			foreach ($cache_key as $index => $data)
 				if ( $data == $original_prev )
-					$post_meta_cache['$post_id'][$key][$index] = $original_value;
+					${$cache}['$id'][$key][$index] = $original_value;
 	}
 
 	return true;
Index: wp-includes/comment-functions.php
===================================================================
--- wp-includes/comment-functions.php	(revision 3707)
+++ wp-includes/comment-functions.php	(working copy)
@@ -3,7 +3,7 @@
 // Template functions
 
 function comments_template( $file = '/comments.php' ) {
-	global $wp_query, $withcomments, $post, $wpdb, $id, $comment, $user_login, $user_ID, $user_identity;
+	global $wp_query, $withcomments, $post, $wpdb, $id, $comment, $comment_meta_cache, $user_login, $user_ID, $user_identity;
 
 	if ( is_single() || is_page() || $withcomments ) :
 		$req = get_settings('require_name_email');
@@ -34,6 +34,34 @@
 		$comments = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_post_ID = '$post->ID' AND ( comment_approved = '1' OR ( comment_author = '$author_db' AND comment_author_email = '$email_db' AND comment_approved = '0' ) ) ORDER BY comment_date");
 	}
 
+	// Comment Meta
+	if ( $comments ) {
+		$cid_list = array();
+		foreach ( $comments as $c )
+			$cid_list[] =  $c->comment_ID;
+		$cid_list = implode(',', $cid_list);
+
+		// Get comment-meta info
+		if ( $meta_list = $wpdb->get_results("SELECT comment_id, meta_key, meta_value FROM $wpdb->commentmeta WHERE comment_id IN($cid_list) ORDER BY comment_id, meta_key", ARRAY_A) ) {
+			// Change from flat structure to hierarchical:
+			$comment_meta_cache = array();
+			foreach ($meta_list as $metarow) {
+				$mpid = $metarow['comment_id'];
+				$mkey = $metarow['meta_key'];
+				$mval = $metarow['meta_value'];
+
+				// Force subkeys to be array type:
+				if ( !isset($comment_meta_cache[$mpid]) || !is_array($comment_meta_cache[$mpid]) )
+					$comment_meta_cache[$mpid] = array();
+				if ( !isset($comment_meta_cache[$mpid]["$mkey"]) || !is_array($comment_meta_cache[$mpid]["$mkey"]) )
+					$comment_meta_cache[$mpid]["$mkey"] = array();
+
+				// Add a value to the current pid/key:
+				$comment_meta_cache[$mpid][$mkey][] = $mval;
+			}
+		}
+	}
+
 	define('COMMENTS_TEMPLATE', true);
 	$include = apply_filters('comments_template', TEMPLATEPATH . $file );
 	if ( file_exists( $include ) )
@@ -222,6 +250,8 @@
 	if ( ! $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_ID='$comment_id' LIMIT 1") )
 		return false;
 
+	$wpdb->query("DELETE FROM $wpdb->commentmeta WHERE comment_id = '$comment_id'");
+
 	$post_id = $comment->comment_post_ID;
 	if ( $post_id && $comment->comment_approved == 1 )
 		$wpdb->query( "UPDATE $wpdb->posts SET comment_count = comment_count - 1 WHERE ID = '$post_id'" );
Index: wp-content/plugins/wp-db-backup.php
===================================================================
--- wp-content/plugins/wp-db-backup.php	(revision 3707)
+++ wp-content/plugins/wp-db-backup.php	(working copy)
@@ -31,7 +31,7 @@
 	var $backup_errors = array();
 	var $basename;
 	// Simple table name storage
-	var	$wp_table_names = array('categories','comments','link2cat','links','options','post2cat','postmeta','posts','users','usermeta');
+	var	$wp_table_names = array('categories','comments','commentmeta','link2cat','links','options','post2cat','postmeta','posts','users','usermeta');
 
 	function gzip() {
 		return function_exists('gzopen');
Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 3707)
+++ wp-settings.php	(working copy)
@@ -77,6 +77,7 @@
 $wpdb->categories       = $table_prefix . 'categories';
 $wpdb->post2cat         = $table_prefix . 'post2cat';
 $wpdb->comments         = $table_prefix . 'comments';
+$wpdb->commentmeta      = $table_prefix . 'commentmeta';
 $wpdb->link2cat         = $table_prefix . 'link2cat';
 $wpdb->links            = $table_prefix . 'links';
 $wpdb->linkcategories   = $table_prefix . 'linkcategories';
Index: wp-admin/upgrade-schema.php
===================================================================
--- wp-admin/upgrade-schema.php	(revision 3707)
+++ wp-admin/upgrade-schema.php	(working copy)
@@ -14,6 +14,15 @@
   PRIMARY KEY  (cat_ID),
   KEY category_nicename (category_nicename)
 );
+CREATE TABLE $wpdb->commentmeta (
+  meta_id bigint(20) NOT NULL auto_increment,
+  comment_id bigint(20) NOT NULL default '0',
+  meta_key varchar(255) default NULL,
+  meta_value longtext,
+  PRIMARY KEY  (meta_id),
+  KEY post_id (comment_id),
+  KEY meta_key (meta_key)
+);
 CREATE TABLE $wpdb->comments (
   comment_ID bigint(20) unsigned NOT NULL auto_increment,
   comment_post_ID int(11) NOT NULL default '0',
