{"id":3853,"date":"2010-06-09T13:30:00","date_gmt":"2010-06-09T13:30:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2010\/06\/09\/exploring-the-visual-c-browse-database\/"},"modified":"2019-02-18T18:45:30","modified_gmt":"2019-02-18T18:45:30","slug":"exploring-the-visual-c-browse-database","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/exploring-the-visual-c-browse-database\/","title":{"rendered":"Exploring the Visual C++ Browse Database"},"content":{"rendered":"<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">Hello, this is Jim Springfield.<span>&nbsp; <\/span>This post will cover some low-level details about how we represent information in the browse database in VS 2010.<span>&nbsp; <\/span>As I&rsquo;ve mentioned in a previous <\/span><a href=\"http:\/\/blogs.msdn.com\/b\/vcblog\/archive\/2008\/02\/29\/intellisense-part-2-the-future.aspx\"><span style=\"font-size: small;font-family: Calibri\">post<\/span><\/a><span style=\"font-size: small;font-family: Calibri\">, we are using SQL Server Compact Edition (SSCE) for storing information about all of the C, C++, and IDL files in your solution.<span>&nbsp; <\/span>I will show some SQL examples that illustrate how to mine this database for information about your code.<\/span><\/p>\n<p class=\"MsoNormal\"><b><i><span style=\"font-size: small\"><span style=\"font-family: Calibri\">NOTE: The particular database schema we use in VS2010 may very well change in future versions, so the examples I show may not work in future versions of VS.<\/p>\n<p><\/span><\/span><\/i><\/b><\/p>\n<h2 style=\"margin: 10pt 0in 0pt\"><span style=\"font-size: medium;color: #4f81bd;font-family: Cambria\">Opening the SDF file<\/span><\/h2>\n<p class=\"MsoNormal\"><span style=\"font-size: small\"><span style=\"font-family: Calibri\">The database file (SDF) can normally be found in the same directory as your solution file (SLN), although it may get relocated if your SLN is on a network share or a flash drive.<span>&nbsp; <\/span>You can open the SDF using several different tools.<span>&nbsp; <\/span>SSMS (SQL Server Management Studio) is a good one if you have access to it.<span>&nbsp; <\/span>However, you can also open it in Visual Studio itself.<span>&nbsp; <\/span>Before opening the SDF to play with, it is best to close the associated solution.<span>&nbsp; <\/span><\/span><\/span><\/p>\n<p class=\"MsoListParagraphCxSpFirst\"><span><span><span style=\"font-size: small;font-family: Calibri\">1.<\/span><span style=\"font: 7pt 'Times New Roman'\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><span style=\"font-size: small;font-family: Calibri\">Within VS, go to the &ldquo;Server Explorer&rdquo; window, right click on &ldquo;Data Connections&rdquo;, and select &ldquo;Add Connection&hellip;&rdquo;.<\/span><\/p>\n<p class=\"MsoListParagraphCxSpMiddle\"><span><span><span style=\"font-size: small;font-family: Calibri\">2.<\/span><span style=\"font: 7pt 'Times New Roman'\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><span style=\"font-size: small;font-family: Calibri\">Select &ldquo;Microsoft SQL Server Compact 3.5&rdquo; for the Data Source and click &ldquo;Continue&rdquo;.<\/span><\/p>\n<p class=\"MsoListParagraphCxSpMiddle\"><span><span><span style=\"font-size: small;font-family: Calibri\">3.<\/span><span style=\"font: 7pt 'Times New Roman'\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><span style=\"font-size: small;font-family: Calibri\">Click the &ldquo;Browse&hellip;&rdquo; button and then navigate to the SDF file to open.<\/span><\/p>\n<p class=\"MsoListParagraphCxSpMiddle\"><span><span><span style=\"font-size: small;font-family: Calibri\">4.<\/span><span style=\"font: 7pt 'Times New Roman'\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><span style=\"font-size: small;font-family: Calibri\">If the SDF file is large (i.e. &gt; 250MB), you will need to set an option before opening.<span>&nbsp; <\/span>To do this, click the &ldquo;Advanced&hellip;&rdquo; button and set &ldquo;Max Database Size&rdquo; to something larger than the SDF you are opening.<span>&nbsp; <\/span>4091MB is the largest value allowed and you can just use that if you wish.<\/span><\/p>\n<p class=\"MsoListParagraphCxSpLast\"><span><span><span style=\"font-size: small;font-family: Calibri\">5.<\/span><span style=\"font: 7pt 'Times New Roman'\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><span style=\"font-size: small;font-family: Calibri\">Finally, click the &ldquo;OK&rdquo; button and VS should open your SDF file.<\/span><\/p>\n<h2 style=\"margin: 10pt 0in 0pt\"><span style=\"font-size: medium;color: #4f81bd;font-family: Cambria\">Learning your way around<\/span><\/h2>\n<p class=\"MsoNormal\"><span style=\"font-size: small\"><span style=\"font-family: Calibri\">If you expand the new node for your SDF in Server Explorer, you will see a &ldquo;Tables&rdquo; node.<span>&nbsp; <\/span>Expand that and you can see all of the tables that are currently defined.<span>&nbsp; <\/span>The &ldquo;code_items&rdquo; table contains information on every definition and declaration that occur in your source.<span>&nbsp; <\/span>I don&rsquo;t have space to cover what all of the tables do, but take a look around.<span>&nbsp; <\/span>Don&rsquo;t expect to see data in the refs or symbols tables as those are there for some possible future use.<span>&nbsp; <\/span><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><b><i><span style=\"font-size: small\"><span style=\"font-family: Calibri\">Note:<span>&nbsp; <\/span>Don&rsquo;t try to make changes to the schema or indexes and expect that to persist.<span>&nbsp; <\/span>When we open the SDF for actual browsing use, we do a consistency check and if anything is not &ldquo;correct&rdquo;, we delete the SDF and rebuild it.<\/p>\n<p><\/span><\/span><\/i><\/b><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">Take a look at the &ldquo;code_item_kinds&rdquo; table.<span>&nbsp; <\/span>You can see the contents by right-clicking and selecting &ldquo;Show Table Data&rdquo;.<span>&nbsp; <\/span>There should be 59 entries here.<span>&nbsp; <\/span>These values are used in the &ldquo;code_items&rdquo; table and you can use them in queries to find certain types of code items.<\/span><\/p>\n<h2 style=\"margin: 10pt 0in 0pt\"><span style=\"font-size: medium;color: #4f81bd;font-family: Cambria\">Creating a query<\/span><\/h2>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">Right click on the &ldquo;code_items&rdquo; table and select &ldquo;New Query&rdquo;.<span>&nbsp; <\/span>You will get a query window with some tools that help you build and run queries.<span>&nbsp; <\/span>A window will popup asking you to add a table.<span>&nbsp; <\/span>Just click close as you will just be copying queries into the query window for now.<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">Try this query first to get your feet wet.<span>&nbsp; <\/span>To run a query, click the red exclamation icon in the toolbar or press &ldquo;Ctrl+R&rdquo;.<\/span><\/p>\n<p class=\"Code\"><span style=\"font-size: small;font-family: Courier New\">select * from code_items where kind=1<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">This query returns all code items that are C++ classes.<span>&nbsp; <\/span>If you look at all of the columns, most should ma\nke sense.<span>&nbsp; <\/span>Note that the database gives start and end position information for the entire class and just the name portion of the code item.<span>&nbsp; <\/span>It is hard to see what file a code item comes from, however, as the code_items table uses a file_id and not a filename.<span>&nbsp; <\/span>To see the filename as well, try the following query which does a join with the files table to get the filename.<\/span><\/p>\n<p class=\"CodeCxSpFirst\"><span style=\"font-size: small;font-family: Courier New\">SELECT<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>f.name, ci.*<\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small;font-family: Courier New\">FROM<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>code_items AS ci<\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small\"><span style=\"font-family: Courier New\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>INNER JOIN files AS f ON ci.file_id = f.id<\/span><\/span><\/p>\n<p class=\"CodeCxSpLast\"><span style=\"font-size: small;font-family: Courier New\">WHERE<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>(ci.kind = 1)<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">One thing to notice is that this query returns information on code items that occur in your own code as well as in the SDK and other headers.<span>&nbsp; <\/span>You can return information for files that are explicitly in your solution by using the &ldquo;config_files&rdquo; table.<span>&nbsp; <\/span>This table has a column that indicates whether a file is implicit or explicit.<span>&nbsp; <\/span>A file may have multiple entries in the config_files table as a file can be used in multiple configs\/projects.<span>&nbsp; <\/span>The &ldquo;DISTINCT&rdquo; keyword prevents returning duplicate copies of code items.<\/span><\/p>\n<p class=\"CodeCxSpFirst\"><span style=\"font-size: small;font-family: Courier New\">SELECT<span>&nbsp;&nbsp; <\/span>DISTINCT f.name, ci.*<\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small;font-family: Courier New\">FROM<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>code_items AS ci <\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small\"><span style=\"font-family: Courier New\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>INNER JOIN files AS f ON ci.file_id = f.id<\/span><\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small\"><span style=\"font-family: Courier New\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>INNER JOIN config_files AS cf ON ci.file_id = cf.file_id<\/span><\/span><\/p>\n<p class=\"CodeCxSpLast\"><span style=\"font-size: small;font-family: Courier New\">WHERE<span>&nbsp;&nbsp;&nbsp; <\/span>(cf.implicit = 0) AND (ci.kind = 1)<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">The parent_id in the code_items table refers to another item in the code_items table.<span>&nbsp; <\/span>Using this information, you can get some parent\/child information.<span>&nbsp; <\/span>The id of 0 is the global namespace.<span>&nbsp; <\/span>So, to get all functions in the global namespace you could do this.<\/span><\/p>\n<p class=\"CodeCxSpFirst\"><span style=\"font-size: small;font-family: Courier New\">SELECT<span>&nbsp;&nbsp;&nbsp; <\/span>*<\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small;font-family: Courier New\">FROM<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>code_items<\/span><\/p>\n<p class=\"CodeCxSpLast\"><span style=\"font-size: small;font-family: Courier New\">WHERE<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>(kind = 22) AND (parent_id = 0)<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">You can also join the code_items table to itself to find a set of code_items whose parent matches some set of criteria.<span>&nbsp; <\/span>The following example finds all functions whose parent code_item is named &ldquo;ATL&rdquo;.<\/span><\/p>\n<p class=\"CodeCxSpFirst\"><span style=\"font-size: small;font-family: Courier New\">SELECT<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ci1.*<\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small;font-family: Courier New\">FROM<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>code_items AS ci1 INNER JOIN<\/span><\/p>\n<p class=\"CodeCxSpMiddle\"><span style=\"font-size: small\"><span style=\"font-family: Courier New\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>code_items AS ci2 ON ci2.id = ci1.parent_id<\/span><\/span><\/p>\n<p class=\"CodeCxSpLast\"><span style=\"font-size: small;font-family: Courier New\">WHERE<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>(ci1.kind = 22) AND (ci2.name = &#8216;ATL&#8217;)<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">I have only scratched the surface of what you can do to mine the SDF for interesting information about your source code.<span>&nbsp; <\/span>There are many other ways to leverage the data contained in the SDF to gather information about your source code.<span>&nbsp; <\/span>All of our browsing features for C\/C++ are implemented on top of the SDF.<span>&nbsp; <\/span>We do take advantage of some caching, prepared commands, and the special &ldquo;table direct&rdquo; mode that SSCE provides in order to increase performance, but everything comes from the SDF at some point.<\/span><\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">The query processor in SSCE is limited in some ways, but you could even replicate the data from the SDF into a full SQL database and perform even more complex queries than are allowed by SSCE.<\/span><\/p>\n<p class=\"MsoNormal\">\n<p><span style=\"font-size: small;font-family: Calibri\">&nbsp;<\/span><\/p>\n<\/p>\n<p class=\"MsoNormal\"><span style=\"font-size: small;font-family: Calibri\">Jim Springfield<br \/>Visual C++ Architect<\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello, this is Jim Springfield.&nbsp; This post will cover some low-level details about how we represent information in the browse database in VS 2010.&nbsp; As I&rsquo;ve mentioned in a previous post, we are using SQL Server Compact Edition (SSCE) for storing information about all of the C, C++, and IDL files in your solution.&nbsp; I [&hellip;]<\/p>\n","protected":false},"author":289,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[45,47],"class_list":["post-3853","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","tag-browsing","tag-sdf"],"acf":[],"blog_post_summary":"<p>Hello, this is Jim Springfield.&nbsp; This post will cover some low-level details about how we represent information in the browse database in VS 2010.&nbsp; As I&rsquo;ve mentioned in a previous post, we are using SQL Server Compact Edition (SSCE) for storing information about all of the C, C++, and IDL files in your solution.&nbsp; I [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/3853","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/289"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=3853"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/3853\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=3853"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=3853"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=3853"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}