PHP's define() will accept string concatenation, as well as nested methods if you need; the problem is that it works just fine everywhere else in the code.
The only place where $wpdb->prefix isn't appended properly is inside the activation callback. Everywhere else I get wp_#_tablename. It's like it somehow strips it, or calls the function as though it existed outside of the file somewhere in limbo.
...
It gets odder than that. Apparently if you don't add a deactivation hook, Wordpress calls the activation hook on deactivation? It also runs twice on activation....
I wrote the following quick'n'dirty to demonstrate;
<?php /*
Plugin Name: WPDB Object Test
Description: If you only knew.
Version: 0.1
*/
define( 'WPDB_TEST_TABLE', $wpdb->prefix . 'table_name' );
$outside_data = WPDB_TEST_TABLE;
function wpdb_test_activate( $outside_data ) {
global $wpdb;
$file = dirname( __FILE__ ) . '/test.log';
$data = 'Outside: ' . $outside_data . "\n";
$data .= 'Constant: ' .WPDB_TEST_TABLE . "\n";
$data .= 'Inside: ' . $wpdb->prefix . "table_name\n\n";
$fp = @fopen( $file, 'a' );
if ( $fp )
fwrite( $fp, $data );
fclose( $fp );
}
register_activation_hook( __FILE__, call_user_func( 'wpdb_test_activate', $outside_data ) );
It writes to the file twice on activation, the first time around stripping the prefix from the constant, the second time around it works (wtf?). If you then deactivate the plugin, it writes to the file again, which means the activation hook is running on deactivation.
I say again... w-t-f? :)