Pages from custom table

Your code worked absolutely fine for me, so I suspected you forgot to flush the rewrite rules.

Each time after you added code which alters the WordPress rewrite rules, e.g. add_rewrite_rule() or code which registers/un-registers a CPT or custom taxonomy with URL rewriting enabled, you should always flush the rewrite rules which means WordPress will empty/reset the saved rewrite rules (in the database and .htaccess file) and regenerate (and re-save) them which would include your newly added or updated rewrite rules.

How to flush the rewrite rules: Just visit the Settings → Permalink Settings page. And there’s no need to click on the “Save Changes” button.

There’s also a programmatic way (see flush_rewrite_rules()), but in general, the above trick is the preferred way unless you are writing a plugin where you would for example, call the function during the plugin activation and deactivation.