Sunday, 12 August 2012

PowerShell and SubVersion with XML

Recently I was asked if it was possible to automate part of our release process whereby our release management department needed to find what SQL scripts in a particular database directory had changed between specific repo revisions on a specific path. It is possible to automate the above and I have chosen PowerShell using the SVN client binaries (which output XML that can be easily processed) to achieve this. I have listed an example of the XML skeleton returned by SVN and the majority of the PowerShell code which will collect the SQL file URLs - once you have the URLs, they can be exported.

So, the SVN client binaries can output, in XML format, which files have been modified on a certain path between certain revisions and PowerShell can process XML using the Select-Xml cmdlet with some XPath. To generate an XML document which can be piped to the PowerShell Select-Xml cmdlet, execute a command similar to the following:

svn.exe log http://path/to/do/an/svn/log/on --verbose --xml --revision 4453:4478

The above will return an XML document ready for piping - the following is an example of the skeleton. It contains two SVN logentries (one logentry = one commit).

<?xml version="1.0"?>
<log>
    <logentry revision="4467">
        <author>jdolan</author>
        <date>2012-02-24T17:06:46.686349Z</date>
        <paths>
            <path
               kind="file"
               action="M">[/project_name/etc]</path>
            <path
               kind="file"
               action="M">[/project_name/etc]</path>
        </paths>
        <msg>[the_commit_message]</msg>
    </logentry>
    <logentry revision="4488">
        <author>ccallaghan</author>
        <date>2012-02-29T12:36:10.386087Z</date>
        <paths>
            <path
               kind="dir"
               copyfrom-path="[/project_name/etc]"
               copyfrom-rev="4566"
               action="A">[/project_name/etc]</path>
        </paths>
        <msg>[the_commit_message]</msg>
    </logentry>
</log>

The pseudo-code for the PowerShell script below is:
  • Get an XML document representing all SVN logentries on a particular path between particular revisions and pipe it to...
  • The Select-Xml cmdlet which uses XPath to get a per logentry and pipe it to...
  • The ForEach-Object cmdlet which iterates over each logentry and allows for the processing to take place. Here we can obtain the revision, if the file has been modified, added or deleted, the commit date, the path to each file and even the log message. After some processing, we can add to a list the fully qualified paths to the SQL files we are interested in.
You will need to fill in the appropriate blanks, such as the root and log URLs, to revision, from revision, the file extension to match, etc - for convenience, I have declared these for you at the top of the script below. As the script is well commented, I'll let it speak for itself rather than dissecting it too much

$fromRev = 4453
$toRev = 4478
$svnUrlRoot = "http://root/path/to/repo"
$svnUrlLog = "$svnUrlRoot/path/to/do/an/svn/log/on"
$fileExt = ".sql"

# Using the svn log command, get an XML document representing the preset criteria 
# and cast it to an XML object, pipe this to the Select-Xml cmdlet to get the 
# logentries and pipe these to the ForEach-Object cmdlet to iterate over them.
([xml] (svn.exe log $svnUrlLog --verbose --xml --revision ""$fromRev"":""$toRev"")) |
        Select-Xml -XPath /log/logentry |
        ForEach-Object {
            $logEntry = $_
            $logEntryPaths = $logEntry.Node.paths.path
           
            # Iterate through each path in the logEntryPaths XmlElement.
            foreach ($logEntryPath in $logEntryPaths)
            {                   
                # Get the contents (relative HTTP path) of the logEntryPath and append it to 
                # the SVN root URL. #text must be in double quotes to ensure the hash / pound symbol is 
                # correctly dealt with by PowerShell.
                $sqlFileUrl = ($svnUrlRoot, $logEntryPath."#text") -join ""
               
                # Ensure that URL's matching the component database 
                # pattern and ending with .SQL are examined.
                if ($sqlFileUrl -imatch $sqlFileUrl.EndsWith($fileExt))
                {
                    $fileAction = $logEntryPath.action
                   
                    # If the SQL file has been deleted, it should be ignored 
                    # as it no longer exists.
                    if (! ($fileAction -ieq "D"))
                    {
                        # Determine if the SQL file already exists
                        # in the array from a previous relevant rev,
                        # if not, add the complete URL to the array
                        # for export later. This prevents
                        # duplicates as a developer may have made
                        # many commits to the same SQL file.
 
                       if ($sqlFileList -inotcontains $sqlFileUrl)
                        {
                            $sqlFileList += $sqlFileTagUrl
                        }
                    }
                }
            }
        }

Now that we have a list called $sqlFileList containing the paths to all the fully qualified SQL files, we can put it into a foreach loop and using the svn export command to export them to our desired location.

If using the standard trunk, tag, and branches repo layout, remember that if executing this script on tag, the paths which the svn log will return, will probably be from trunk so if you wish to export the SQL files from the tag, you will have to replace part of the URL from trunk to tags, before adding the URL to the export list.
       
We also had a requirement whereby we would like to ignore any SQL files which were forward merged. This can be achieved in a variety of ways but we have found the easiest to be the following: ensure there is a standard commit message for forward merging and in the above powershell script, extract the log message per logentry and compare it to the pre-defined message and if it matches, ignore the contents of that revision.

As an aside, much of the above code can be reused to read and process any XML document in PowerShell. Consider replacing the svn log command line above with the Get-Content cmdlet which allows you to read the document from a file instead of the output returned from a command. The XPath and SVN specific logic can also be replaced. Another useful test before processing XML is ensuring the XML element has child nodes. To do this in the above example with logentry, add an if statement that evaluates $logEntry.Node.HasChildNodes which was omitted as the svn log XML will always have child nodes.

Saturday, 3 March 2012

SubVersion BAT / batch pre-commit hook to exclude specific directories

[2012-04-27] Updated based on user feedback: thanks to Alex & Dan.

Recently, I have encountered an issue where I found that Microsoft .NET bin and obj directories were being committed to our codebase. These directories are compilation output directories used by MSBuild / Visual Studio and thus should not be added to the SubVersion codebase. In an effort to stop this, writing a pre-commit hook was the obvious answer. However, I have chosen to write it in batch / BAT.

Yes, BAT files, I know what you are going to say... Why not Perl, Python or even some BAT file that calls out to Powershell (which is my favourite scripting language)? Well, the simple answer is speed. With time constraints in place, getting Perl and Python interpreters set up on the SubVersion server with a language learning curve for our team may not be justifiable for a single pre-commit hook where a quickly written BAT file would suffice. Initial investigation suggests that getting Powershell running with a pre-commit hook BAT wrapper may prove too time costly also, so batch was chosen. This entry assumes a basic familiarity with BAT files.

OK, some interesting points of note about SubVersion pre-commit hooks. 
  • Because this is a pre-commit hook, it does not deal with revisions, it deals with transactions, which, may or may not be persisted becoming revisions, depending on the outcome of the pre-commit hook. The format of transaction IDs differs compared to revisions IDs.
  • If the pre-commit hook exits with a return code of 0, then the transaction is persisted and becomes a revision. If the pre-commit exits with a non-zero return code, the transaction will fail to be committed. There is scope here to provide a specific message which is sent back to the user, detailing why the hook failed which can be seen with each of the four echo commands below and how that command's standard output is redirected to the standard error via the >&2 code.
  • When the BAT pre-commit hook below is executed, there is no environment set - such as the system path, so when using the svnlook executable, the absolute path must be provided. Similar for other commands. Don't forget to wrap paths in double quotes if they contain spaces!
The example below prevents commits which include empty bin and obj directories and bin and obj directories which contain one or more files / folders. The core of the example is using svnlook to examine what paths have changed on the current transaction and piping these to the Windows findstr command which uses a regular expression and checks to see if bin and obj directories exist on those paths.

Finally, to add this to SubVersion for a specific repo, navitate to the repo on the file system, and under the hooks directory, create a new file called pre-commit.bat and add the script below to it.The only update you'll need to make to this script to get it working is to set the correct path to the svnlook executable in each of four locations below. Save the file. The moment this file exists and the contents are valid, the pre-commit hook is live on the repo.

:: Set the first incoming parameter to the absolute path to the repository and the second incoming parameter to the transaction ID. This is standard in all SubVerison pre-commit hooks.
SET REPOS=%1
SET TXN=%2 


:: Check if there is an attempt made to commit changes to a bin directory. This also includes an attempt to commit an empty bin directory.
"E:\csvn\bin\svnlook.exe" changed -t %TXN% %REPOS% | FINDSTR /R /I "./bin/.*"
IF %ERRORLEVEL% EQU 1 GOTO CHECK_OBJ_DIR
ECHO "It is forbidden to commit empty bin directories or to commit to existing bin directories to
SubVersion as these are generated .NET output and not part of the SubVersion version controlled codebase" >&2
EXIT 1
:: Check if there is an attempt made to commit changes to an obj directory. This also includes an attempt to commit an empty obj directory.
:CHECK_OBJ_DIR
"E:\csvn\bin\svnlook.exe" changed -t %TXN% %REPOS% | FINDSTR /R /I "./obj/.*"
IF %ERRORLEVEL% EQU 1 GOTO OK
ECHO "It is forbidden to commit empty obj directories or to commit to existing obj directories to
SubVersion as these are generated .NET output and not part of the SubVersion version controlled codebase" >&2
EXIT 1

:: All checks passed, so allow the commit.
:OK
EXIT 0

Tuesday, 31 January 2012

Considerations when Changing Jobs

[This post has been updated as of 2013-03-26]

While this is a little off topic, I think this could be useful for people considering changing job. It started as a list of considerations which I casually discussed with a friend but eventually grew to what is detailed below. I have also updated it with experiences discussed with other people I know. It assumes that you are happy enough in your current sector. First, a bit about me to give my musings context. I'm in my late twenties, and was lucky enough to work for a good independent software vendor straight after college, spending six years there before changing jobs in August 2011 to another company. The items are not in any particular order as the priority will differ depending on one's lifestyle, family, personality, circumstances, etc.

Salary. Generally, if a move is not based on a lifestyle choice and the responsibilities are similar or greater with the new role, it stands to reason that the new employer will pay more. A great place to start estimating salary is on a a jobs / recruitment site.

Experience. This can be more important than salary when looking for a challenge, starting out a career or looking to move sideways in a career. Sometimes, it may become damaging to a career to continue to stay in a company with few challenges and / or where technology is somewhat stagnant or completely bespoken to said company. A new experience also helps to fight the inevitable institutionalism with which can occur after many years. Another big part of this is if the work in the new company appeals more so than the old.

Corporate culture. Which is always hard to judge because at the interview, a glimpse is all that is really gotten of how things work. Knowing somebody already in the company or having a friend or a friend of a friend who works there can help. Failing that there's plenty of information online about the larger companies and how they function. If possible, ask to be shown around the office to get a better feel of how things hang together.

Work ethic. Tied to corporate culture and differs from person to person and place to place. Also, just because the offices are based in one region, doesn't mean it will inherit that localities work ethic. 


Career progress. Possibly part of the reason for wanting to leave a current employer. Sometimes a move upwards in salary is a move upwards in responsibility, sometimes it's just a move sideways. Career progress in a company is something which should be seriously considered before the interview.

Job security. An increasingly important point. Check if the company is public or private and if it Irish owned or is it a subsidiary or similar of some conglomerate. There are pros and cons to each of the above which are beyond the scope of this post.

Socialising. Not to be underestimated. People make a company and great people make companies great. A company which has an active sports and social committee is generally a good sign. Check the average age group of the company compared to the current company - it can be a somewhat daunting starting out in a company where most are ten years or more senior, many have families and are settled.

Number of working hours. This is a niggley one and usually falls somewhere between 37.5 and 40 hours for much of the IT sector. Also note that it's important to find out if it will be expected to work overtime and if so, what the compensations is - money, days in lieu or nothing at all. I've found that the corporate culture and work ethic have quite a role to play in this too. I
t was only after an offer was posed to me but before I accepted that I realised that I would be working an addition 2.5 hours per week. This must be factored into a pay rise - ie: if the hours are greater, then subtract from the rise and vice versa. Again, for those with a family or thinking of starting one, the extra time could make an impact either getting up earlier or working later.

Holiday allowance. The number of days leave per annum, and number of days per years of service. While losing holidays when changing jobs does not equate to a lot of money financially, still equates to time off. Also, it may be possible to buy days or take unpaid leave or that the company give personal days or that days can be worked up in over-time.


Location. Check in detail where the company is based and if it is convenient to get to and socialise from. Also, check for places of interest around the company such as places to eat or gyms etc. if necessary. While many of these are relatively trivial issues, when they start to negatively come together, it can make for some serious consideration.

Healthcare. This is becoming important given the increasing cost of it this year (2012), especially for families and a subsidised or complete company healthcare scheme is certainly valuable.

Pension. Most of us will get old and probably live longer than the current life expectancy - pensions are important! Remember that if a company does not have a pension fund and do not contribute towards private funds, you must factor this into a pay rise. Also, in a company like this, there may be more cost associated with a contribution as it may come out of your net pay rather than gross and so be worth much less.

Family benefits. Family oriented benefits past the legal minimum such as additional days off for dads, an on-site crèche, inclusive healthcare, opportunity to negotiate taking a day off a week for several months while rearing children - these are all very convenient.

Flexi-time. Useful to have, especially with regard to a family oriented lifestyle - picking kids up from school, for example. 


Working from home. This is another benefit that can be very useful to have, especially when there may be a long commute involved, distracting working conditions and other more family oriented reasons.

Hardware. For a person working in the software industry, a fast computer and dual screens are invaluable and should be the de facto. Another point to note is that the computer should be clean - as in re-ghosted or reinstalled from scratch - not somebody's hand-me-down with all sorts of stuff on it. Even a proper ergonomic chair, keyboard and mouse are great, considering the sheer amount of time spent sitting down, typing and clicking

Perks. Which can include Christmas bonus, company performance bonus, personal performance bonus, quota bonus, company car and many others.

Probation. While this might not be normal for all, it certainly applies in the software sector in Ireland and when on probation, the employee won't have their healthcare paid for or benefit from a company pension contribution which should be taken into consideration. This means that for many months, a little pay cut will have to be taken to pay for healthcare and consideration given as to what to do with an existing pension before moving it to the company's pot.


Title. Preservation of existing title may be important to you. You may be a Senior Build and Release Engineer and a company you wish to move to may be just looking for a Build Engineer and while the role may be similar or have greater responsibility and remuneration, the title may not reflect this.

Freedom of expression. having the freedom to express one’s self and opinions is very important, especially given all the mediums which make information so darn accessible these days. Writing code outside of work hours (perhaps contributing to some open source project, designing websites, etc?) and blogging is great fun and very rewarding but what exactly does the contract say about this? What is the company's position on this? Perhaps nothing at all or perhaps it is quite restrictive, making it more difficult to be yourself.

Notice. In IT, giving the company notice of resignation is usually one month in advance of physically leaving. However, depending on the company and the amount of responsibility the role contains, this may be extended. Do not assume that it is one month! Ensure you know what what your notice period is and that it suits you. It may be easier to move to a new company when the notice period of your current company is one month but if it was two months, it might be too big a gap for the prospective employer to wait, especially if you assumed it was one month and only found out it was two upon handing in your notice!

Requirements / comportment regarding Twitter, Facebook, MySpace and the plethora of other social networking sites. Does the contract mention these sites, one's conduct, a requirement for an official work account, etc? Company's are becoming ever more vigilant about how they are perceived, especially online and may have rules about what sort of comments their employees can make about them via the above media. They may also encourage / require you to open / maintain an work account with one or more such sites - I'm unsure of the legalese here.

Non-Compete / Anti-Compete / Covenant-Not-To-Complete Clause. This is where an employee agrees not to work in a new but similar role which competes (at least in the employers view) against the their past employer for a specified duration such as 6 months. This is one to look out for, especially when it comes to the ICT sector. Be wary of clauses such as this innocuously appearing in the contract without the prospective employer or recruiter drawing attention to it. 

Pre-booked holidays. Don't forget to mention any holidays which you may have already pre-booked as it would be a nasty surprise to change job, only to find out that that summer holiday which you were looking forward to may no longer be possible. 

The contract. Read it carefully and compare it with your current role and what has been promised in the new role, especially with regard to working hours, notice, social networking comportment, non-compete/anti-compete/covenant-not-to-compete clauses. Ensure a printed and signed copy of the contract is mailed out, ideally before starting in the new company. A physical contract can be very important later on, as for example, if the role is being made redundant and there is a redundancy entitlement - if no signed physical or even virtual contract exists, then it becomes hard to prove one's entitlements. 

Finally...  Just some general advice - be mindful (love that word :) of what items above are discussed during the interview and what are discussed after an offer is made but before the offer is accepted. The former is a position with much less bargaining power than the latter - know what to ask in the interview and what to negotiate after the offer but before accepting. I will add to this post when I think of / discover any additional, useful information and perhaps tighten it up a bit over time.  A wise friend once said that a change is as good as a break - he was right. 

Saturday, 5 November 2011

TIP: Running NAnt 0.91 on Windows 7

Since I've joined a company several months back which is primarily .NET based, I've been working with a recent version of NAnt on 32-bit Windows XP Pro SP3, which I didn't get to install and configure as it was a hand-me-down desktop. While deciding to do a little experimentation with NAnt 0.91 at home on 64-bit Windows 7, I discovered that it wasn't just as easy as downloading it, unzipping it to a directory, putting it on the system path and running it. Naturally, without observing the RTFM rule, I tried the above and encountered two errors. After RTFM, I was still none-the-wiser : ) Here I explain what these command line errors are and how to resolve them. Note that the my Windows 7 UAC (User Account Control) sub-system and et cetera have default settings on my system.

First Error: .NET Framework Related
 

C:\Development\nant-tests>nant
 

NAnt 0.91 (Build 0.91.4312.0; release; 22/10/2011)
Copyright (C) 2001-2011 Gerry Shaw
http://nant.sourceforge.net


INTERNAL ERROR
 

Could not load file or assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
 

    Could not load file or assembly 'System.Web, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
 

For more information regarding the cause of the build failure, run the build again in verbose mode.
Please send a bug report (including the version of NAnt you're using) to nant-developers@lists.sourceforge.net

 
C:\Development\nant-tests>


After having a look at the requirements section of the NAnt 0.91 manual, I still found things a little confusing - for example, I thought I had .NET installed as the following directory existed C:\Windows\Microsoft.NET\Framework64\v4.0.30319 and similar for Framework directory for the 32-bit version but this was not the case. Unbeknownst to me, I only had the client profile installed which can be seen by opening up the Programs and Features window in the Control Panel and searching for Microsoft .NET Framework 4 Client Profile. After a bit of online perusing and a pinch of intuition, I found that I needed to download and install the dotNetFx40_Full_x86_x64.exe executable from the Microsoft website and once done, Microsoft .NET Framework 4 Extended appeared under the Programs and Features window in the Control Panel and the above .NET Framework error was resolved.

Second Error: Windows 7 Security Related 


C:\Development\nant-tests>nant
 

log4net:ERROR XmlConfiguratorAttribute: Exception getting ConfigurationFileLocation. Must be able to resolve ConfigurationFileLocation when ConfigFile and ConfigFileExtension properties are not set.
System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
   at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
   at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark)
   at System.Security.CodeAccessPermission.Demand()
   at System.AppDomainSetup.VerifyDir(String dir, Boolean normalize)
   at log4net.Util.SystemInfo.get_ConfigurationFileLocation()
   at log4net.Config.XmlConfiguratorAttribute.ConfigureFromFile(Assembly sourceAssembly, ILoggerRepository targetRepository)
 

The action that failed was:
Demand
The type of the first permission that failed was:
System.Security.Permissions.FileIOPermission
The Zone of the assembly that failed was:
Internet

 
Unhandled Exception: System.Security.SecurityException: Request for ConfigurationPermission failed while attempting to access configuration section 'nant'. To allow all callers to access the data for this section, set section attribute 'requirePermission' equal 'false' in the configuration file where this section is declared. ---> System.Security.SecurityException: Request for the permission of type 'System.Configuration.ConfigurationPermission, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' failed.
   at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
   at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark)
   at System.Security.CodeAccessPermission.Demand()
   at System.Configuration.BaseConfigurationRecord.CheckPermissionAllowed(String configKey, Boolean requirePermission, Boolean isTrustedWithoutAptca)
   --- End of inner exception stack trace ---
   at System.Configuration.BaseConfigurationRecord.CheckPermissionAllowed(String configKey, Boolean requirePermission, Boolean isTrustedWithoutAptca)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
   at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
   at System.Configuration.ConfigurationManager.GetSection(String sectionName)
   at NAnt.Console.ConsoleStub.Framework.GetRuntimeFramework()
   at NAnt.Console.ConsoleStub.Main(String[] args
 

C:\Development\nant-tests> 

In addition to the above being spat out into the command line, Windows 7 will pop up a window to let you know that NAnt has stopped workingIf you click on the View problem details link, you can see that one of the Problem Signatures reads System.Security.Security - this is a clue as to what the issue is. After searching online again, I found that the problem was Windows 7 security related in that the downloaded NAnt 0.91 zip file needed additional security related configuration to be performed: before extracting, one must right click on the zip file, select Properties and under the General tab, click the button labelled Unblock, then click OK on the Properties window. Now, extract the file to your desired location, ensure it is on the system path, open a new command line and NAnt should run successfully.

Note that when using NAnt Contrib tasks with the loadtasks task, ensure that the zip which the Contrib tasks was extracted from was unblocked as above. If not, either delete the current Contrib directory, unblocking the Contrib zip and extracting again or configure the the DLL used in loadtasks by unblocking it separately, just like the zip.

Sunday, 23 October 2011

TIP: Configuring Notepad++ to use the XML lexer on any file type with XML content

Say you've inherited a build infrastructure which you must maintain which has many files with different file extensions but the file format for all files is XML. Some of these extensions could be legitimate .xml, .config and .xslt for example with other files having proprietary extensions such as .nant, .deploy, .dist and many more. The goal is not just to be able to double click on them to automatically open them in Notepad++ (simple), but to have Notepad++ open the file with the XML lexer so all those XML tokens come up nice and colourful for ease of reading / editing. This saves time and makes editing files much less error prone. So, how is this done? In two parts... This example has been done on 32-bit Windows XP and 64-bit Windows 7 with 32-bit Notepad++ 5.8.7 and higher.

Associating the file extensions with the Notepad++ application


First the easy part... For each distinct file extension, right click, select Open with, select Choose default program. If Notepad++ is not listed, click Browse and find the executable and select it and click Open. Ensure the Always use the selected program to open this kind of file check box is ticked. Click OK and voila! FYI: the association of an application with a file extension is stored in the Windows registry.

Associating any file extension with the Notepad++ XML lexer

Now, for the less obvious part... It took me a while to realise that you can tell Notepad++ what file extensions (both standard and proprietary) should use the XML lexer rather than than having to manually set it every time (annoying!) via the Notepad++ Languages menu. To achieve this, open Notepad++, select Settings from the menu bar and click on Style configurator... Under Language, select XML. Under this list is a text box called Default ext which lists what extensions currently use the XML lexer. Opposite that text box is another called Custom ext. Add your new extensions, such as .config, .nant, .deploy or .dist etc here - ensure they are space delimited excluding the dot / period so the list looks like config nant deploy dist and click OK. FYI: these changes are saved in Notepad++'s styles.xml file usually found under said programs application data location (default location is under Documents & Settings for XP and Users for Win7).

Now, whenever you double click on any .config, .xslt, .nant, .deploy or .dist file, it will be automatically opened in Notepad++ with the XML lexer. Happy days!

ARTICLE: Linking SQL Server databases together via linked servers

This entry describes the process of linking two remote SQL Server databases via a remote SQL Server client. The process is known in SQL Server as Linked Servers. Once databases are linked, tables in the source database server can be accessed on the destination database server.

Assumptions
  • The first remote server shall be referred to as source and second remote server shall be referred to as destination. Once the database linking has been completed, the source database tables can be accessed when connected to the destination database.
  • That the source, destination and client database software are installed correctly and in working order.
  • Readers have a basic understanding of SQL and the dialects used by the above vendor.
  • SQL Server command usages coloured blue, examples coloured green.

Environment
  • Source and destination server version / platform: 64-bit SQL Server 2008 Developer Edition on 64-bit Windows Server 2008 R2. 
  • Client version / platform: SQL Server 2008 Client on 64-bit Windows 7 Professional.
  • Settings for SQL Server are added / modified via the console in SQL Server 2008 Management Studio.
  • The following is to be used in a development environment with no thought give to database security between servers - this is a factor which bears consideration in all production environments and even some development environments.

SQL Server - Linked Servers
  1. Log into the destination server via the SQL Server 2008 Management Studio with user of sufficient privileges.
  2. In the console, execute the following to create the linked server.
    Usage:

        EXEC sp_addlinkedserver
            @server='
    [unique_name_of_linked_server]',
            @datasrc='[
    linked_server_hostname]',
            @srvproduct='',
            @provider='SQLNCLI'

    Example:
        EXEC sp_addlinkedserver
            @server='SRCDBLINK',
            @datasrc='SRCDBSRV',
            @srvproduct='',
            @provider='SQLNCLI'
  3. In the console, execute the following to create the login for the above linked server.
    Usage:
        EXEC sp_addlinkedsrvlogin
            @rmtsrvname='[unique_name_of_linked_server]',
            @useself='false',
            @locallogin='[domain]\[username]',
            @rmtuser='[username]',
            @rmtpassword='[password]'
    Example:
        EXEC sp_addlinkedsrvlogin
            @rmtsrvname='
    SRCDBLINK',
            @useself='false',
            @locallogin='CORP\sqlsuser',
            @rmtuser='
    sqlsuser',
            @rmtpassword='
    sqlsuser1'
  4. In the console, execute the following to update for RPCs (remote procedure calls) rpc and rpc out for the link.
    Usage:
         EXEC sp_serveroption '[unique_name_of_linked_server]', 'rpc', 'true';
    Example:
        EXEC sp_serveroption '
    SRCDBLINK', 'rpc', 'true';
    Usage:
         EXEC sp_serveroption '[unique_name_of_linked_server]', 'rpc out', 'true';
    Example:
       
    EXEC sp_serveroption 'SRCDBLINK', 'rpc out', 'true';
  5. Finally, to access the source database table via a connection to destination database, use the client to connect to the destination database execute the following.
    Usage:
       
    SELECT * FROM [[database_link]].[[database_name]].[dbo].[[table]].
    Example:

        SELECT * FROM [
    SRCDBLINK].[MyDatabase].[dbo].[MyTable]

ARTICLE: Linking Oracle databases together via database links

This entry describes the process of linking two remote Oracle databases via a remote Oracle client. The process is known in Oracle as Database Links. Once databases are linked, tables in the source database server can be accessed on the destination database server.

Assumptions
  • The first remote server shall be referred to as source and second remote server shall be referred to as destination. Once the database linking has been completed, the source database tables can be accessed when connected to the destination database.
  • That the source, destination and client database software are installed correctly and in working order.
  • Readers have a basic understanding of SQL and the dialects used by the above vendor.
  • Oracle command usages coloured blue, examples coloured green.

Environment
  • Source and destination server version / platform: 64-bit Oracle Enterprise Server 11g r2 on 64-bit Red Hat Enterprise Linux v5 r2. 
  • Client version / platform: 64-bit Oracle Client 11g r2 on 64-bit Windows 7 Professional.
  • Settings for Oracle are added / modified via the use of a command line client (SQLPLUS) connected only to the destination server. The tnsnames.ora should be modified using your favourite text editor.
  • The following is to be used in a development environment with no thought give to database security between servers - this is a factor which bears consideration in all production environments and even some development environments.

Oracle - Database Links
  1. The clients tnsnames.ora file must be updated with entries for both the source and destination databases.
  2. In order to create the (uni-directional) database link from the Oracle destination database to the Oracle source database, the destination database must have an entry in it's tnsnames.ora file for the source database. If the destination database does not said entry, it will need to have its said details supplied during the creation of the database link - ensure this entry exists.
  3. On the source database, create the source user used in the database link. Usage: CREATE USER [username] IDENTIFIED BY [password];. Example: CREATE USER srcUser IDENTIFIED BY srcUser;
  4. On the source database, grant permissions to the source user. Usage: GRANT CONNECT, RESOURCE, DBA TO [username];. Example: GRANT CONNECT, RESOURCE, DBA TO srcUser;.
  5. On the destination database, create the destination user who will be logged into SQLPLUS to create the database link and who will also have read/write access to the destination database. Usage: CREATE USER [username] IDENTIFIED BY [password];. Example: CREATE USER destUser IDENTIFIED BY destUser; 
  6. On the destination database, grant permissions to the destination user. Usage: GRANT CONNECT, RESOURCE, DBA TO [username];. Example: GRANT CONNECT, RESOURCE, DBA TO destUser;.
  7. On the destination database, logged in to the destination database as the above destUser, create the uni-directional database link. Usage: CREATE DATABASE LINK [source_database_link_name] CONNECT TO srcUser IDENTIFIED BY srcUser USING '[oracle_sid|tnsname_connection_details]';. Example: CREATE DATABASE LINK sourceDBLink CONNECT TO srcUser IDENTIFIED BY srcUser USING 'ORA11GU'; 
  8. Finally, to access the source database table via a connection to destination database, use the client to connect to the destination database execute the following. Usage: SELECT * FROM [user].[table_name]@[src_database_link];. Example: SELECT * FROM MyUser.MyTable@sourceDBLink;