Friday, April 5, 2013
#
Well, ok, I wouldn't use this to generate reports; will still have to use scripts.
But imagine that when you are debugging a problem trying to find anything that references, load data into, load data from, a table or view. Having this tool from Red Gate will save you a lot of time. I wrote a post a while ago about some script that can be used to search for stuff, but that doesn't cover all the databases in the same server. Red Gate SQL Search does.
One thing I do wish for, is the ability to search in "All servers" saved in the settings. Because of this, I will still have to use SSIS to run the script to do a complete search.
Here is the screenshot:

Wednesday, April 3, 2013
#
In my forever personal battle on which MP3/MP4 player to use, iTune is now getting a leg up. I still don't use iTune as the primary player on desktop because it doesn't have a mini player mode for video podcast, but this feature I found is great and puts iTune back on top as the better mobile player, one I would use as portable media player (I still prefer to use Zune player on my desktop)
I have got tired of listening to a 3-4 minute podcast, switch to other screens to do work, then switch back so that I can listen to the next one. I wanted something like a playlist, which can update itself (kick out the played podcast and add in the new ones). I couldn't find any solution for Zune, but found one in iTune.
Here are the steps:
- In iTune, go to Sidebar.
- Click on the big + button at the bottom left (shown in screenshot)
- Select "New Smart Playlist"

- Add in the criteria:
- Plays is 0 (unplayed)
- Media Kind is Podcast

- Click "Live updating"
And you have a smart, self-updating playlist for unplayed podcast.
P.S. Question, are we still calling these things MP3 players?
Wednesday, March 27, 2013
#
I don't remember ever have to set this up before, but I don't see it in my Outlook 2010 at work. Here are the steps:
- In Navigation pane, right-click on "Search Folders", select "New Search Folder"
- In the dialogue box, under "Reading Mail", select "Mail flagged for follow up", then click "OK"
- A new folder shows up in the Search Folders. Right-click on that and select "Show in Favorites"
- Press the Easy button.

Tuesday, March 19, 2013
#
Maybe this is me not really knowing all the in's and out's of IOS. I just couldn't get the iTune to play my video podcast in mini player mode. Either I get a screen that is tiny like a thumbnail, or I get a player that takes up half of the screen. Even though I starting to like my iPhone more and more, this feature is a score 1 for Microsoft. So much so that I've decided to carry 3 mobile devices for the short future (iPhone, Zune, my own dumb phone). And after moving all my podcasts to iPhone, I have now switched all the video feeds back onto Zune.
In the Zune player, I can choose 2 sizes (3 if you count full screen). The smaller size takes up about 3 inch by 1.5 inch area, where I can still comfortably do work.
I just never liked Twitter; RSS is my way. But is that because Google Reader has been such a good tool? Now it's gone, what will I use? I don't know just yet, but I really don't think I'll go back to Twitter. Buy Microsoft outlook and port over my RSS? Yikes! I tried Feedly, don't like it.
Suggestions? Advice? Time to move on into the 21st century?
I'm glad my work laptop and my other machines are maintained centrally and not going out to get the latest updates on everything. We have one laptop running Home Premium that is setup to automatically update anything. It got Internet Explorer 10 last week, and my wife brought it to my attention that the password field has an "Eye" besides it and when you click and hold on it, it shows your password.
After spending all of last night trying to disable that "feature", I gave up. All the posts I saw said I had to use Local Group Policy Editor, which is not available to laptops running the "Home" versions. The more I read it, the angrier I get at these people calling it a feature. How is this supposed to help anything? If you want to see what password you typed, open a notepad or a text editor and type it in there. Some people say it's only dangerous if there is people standing behind you. Really? What about people who walked away from there laptops? What about people who save their form data? Suddenly everyone needs to learn to lock their computer, even if they get up and stretch? Oh yea, make sure all the tablets you have automatically lock itself after a minute, and tape that to your behind if you go to an airport bathroom. I have to rant about this one because some of the reasoning I heard about this "feature" is just so idiotic and I'm really having a hard time understanding how this feature is helping any user.
I'm a long time Microsoft user, but for this one, Apple got it right. I have an iPhone now and the password field let you see the character you just typed in. If you go back, you don't see the character. If you want to help a user using a touchscreen keyboard, that's the way to do it. I don't understand this new idiotic feature.
That said, I found a post on how to disable this without using Local Group Policy Editor; will definitely give this a try tonight. http://social.technet.microsoft.com/Forums/en-US/ieitprocurrentver/thread/fb28ef90-2091-483e-8293-1ec1c6dd0ca6v
Monday, March 18, 2013
#
Been going through different setup for SQL server setup. One problem I ran into was that I ran into this error "{FileName}.mdf is Compressed But Does not Reside in a Read-only Database or Filegroup. The File Must be Decompressed".
First Bing search result put me through to a path trying to alter the backup file, but that didn't work. After reading this one (http://blogs.msdn.com/b/sanchan/archive/2006/06/04/617585.aspxhttp://blogs.msdn.com/b/sanchan/archive/2006/06/04/617585.aspx), I was able to fix it by re-format the partition to turn off "Enable file and folder compression". Unfortunately, I do feel that this feature is built to cater to 99% of customers, but killing the need for the very few. I'll try to see if there is a way around it.
Brought in 2 perfectly working 400GB SATA drives and needed to set up a spare drive at work to keep the SQL files. Was on my merry way to create a striped volume, and bang, bang, bang, bang. Just can't do it.
Found out you CANNOT convert to dynamic disk if you are one of the following:
- portable computers
- removable disks
- detachable disks that use Universal Serial Bus (USB) or IEEE 1394 (also called FireWire) interfaces
- disks connected to shared SCSI buses
Reference: http://technet.microsoft.com/en-us/library/cc731274.aspx
Friday, March 1, 2013
#
I love doing database design with people. I've done my fair share of database modeling on my own; those are the easy projects, sure, but with no feedback. However, working with people on database never fails to help me look at things from different perspective.
A very simple thing like whether a NOT NULL table column should have default values get very different reaction from a BI guy and a System Integration guy. Let me put some of the priorities out from different projects I've been in to help understand why these people make database design decisions the way they did.
System Integration Projects:
- As little data across the network as possible
- If there is bad data, let the good data process as much as possible; flag the bad data to wait for update
- Want the interface to be as automated as possible
BI Projects:
- Data has to be 100% accurate at that point of time
- If there is one bad record, back out the entire load
Once I think through these, it's very easy to understand why a System Integration Developer would want every NOT NULL column to have a default value (when it makes sense) and why a BI developer does not want any.
This is me on the latest gadget, I just don't get them. First, there is certain price factor attached to them that unless they are proportional to the hype and my want, I won't even look at them until years later I see them at 50% of the original cost, then I'll look at them.
Second, I have so many things to do daily that I almost never get to purchase something on the day I see them. The result is after a night's sleep, I decided I don't really need them so I'll wait until they are reasonably priced. And my reasoning almost always results in that I don't really need a lot of things in life.
That said, I got the Zune player second hand to now be able to listen to podcast in my commute, and that has been such a difference maker in my learning that I wish I had purchased it sooner. Today I decided to play around with the desktop Zune media player, and discovered that I can have a video version of the podcast playing in a really tiny screen while I work. Man, I wish I had discovered these sooner.
Next up on my list: iPhone and Windows 8. Windows 8 because I found out Hyper-V is built in so that I can migrate all my virtual environment to 64-bit (didn't really want to run server version software everywhere in the house).
Saturday, December 1, 2012
#
The version number of Hyper-V manager is 6.2.9200.16384 This is what came with my Windows 8 work laptop (by enabling Windows features)
The blogs I read indicated that I need an external switch for my guest OS to access internet, and an internal one for them to share folder with my Host OS. I proceeded to create an external virtual switch, and here is the screenshot.

After setting up the network adapters on the guest OS, I peeked into host OS networking, and saw that Network Bridge was already created. GREAT! So I fired up my guest OS and darn, no internet. Then I noticed that my host internet was gone, too. I looked further and found that even though I have a network bridge, no connection has the status "Bridged"
Once I removed the bridge (by removing individual connection from the bridge, I know, weird, since none of them say "Bridged" in status) I re-selected the connection that I want and add them to the bridge to create a new network bridge. Once my wireless connection status shows "Bridged", I was able to get to internet from my guest OS.
Two things I noticed after I got internet for everyone ( my host and guest OS):
- My network adapters in the host OS no longer shows "Bridged", but everyone can still get to the internet
- The virtual switch that I set up for "External" is now showing to be "Internal", and I was able to create shared folder between host and guest OS. This means I didn't have to create the other "Internal" virtual switch.
Wednesday, November 28, 2012
#
One thing I really miss is the ability to create shared folder between host and guest. Virtual PC does this well, you can create Shared Folder to be used every time, or just this one. I have read some posts on how to do this. Some people suggest using ISO Creator to package up the files and mount the image to DVD drive, but what I need is truly a "shared" environment, so I'm currently looking into creating Virtual switch and creating an internal network between the host and guest. Let's see how that works out.
I would have loved to give Virtual SAN Manager a try, but I don't have a local Fibre Channel to set one up.
I guess this might be an extension to my original post: http://geekswithblogs.net/LifeLongTechie/archive/2011/05/05/windows-virtual-pc-vs.-hyper-v-virtual-machines-vs.-windows-virtual.aspx
I recently made a comment "I hate everything virtual" while responding to a SQL server performance question. I then promptly fired up my Hyper-V development environment to do my proof of concept stuff, and realized that I made the cardinal sin of making a generalized comment about something, instead of saying "It depends".
The bottom line is if the virtual environment gives the throughput that the server needs, then it is not that big of a deal. I just have seen so many environment set up with SQL server sitting in virtual environment sitting in a SAN, so on top of having to plan for loss data, I now have to plan for my virtual environment failing for so many different reasons, thought SQL 2012 High Availability Group should make that easier. To me, a virtual environment makes sense for a stateless application with big scalibility requirement, but doesn't give much benefit to an application where performance and data integrity are both important. If security is not a concern, I would just build servers with multiple instances on them to balance the workload.
Maybe this is also too generalized a comment, and I'll confess that I'm not a DBA by trade. I'd love to hear the pros and cons of virtualizing a SQL server, or other examples where virtualization makes total sense (not just money, but recovery, rollback, etc.)
Thursday, November 22, 2012
#
Here is a good blog on how to create a SSIS Catalog and setting up environments. http://sqlblog.com/blogs/jamie_thomson/archive/2010/11/13/ssis-server-catalogs-environments-environment-variables-in-ssis-in-denali.aspx
Here I will summarize 3 ways I know so far to execute a package while using variables set up in SSIS Catalog environment.
First way, we have SSIS project having reference to environment, and having one of the project parameter using a value set up in the environment called "Development". With this set up, you are limited to calling the packages by right-clicking on the packages in the SSIS catalog list and select Execute, but you are free to choose absolute or relative path of the environment.

The following screenshot shows the 2 available paths to your SSIS environments. Personally, I use absolute path because of Option 3, just to keep everything simple for myself.

The second option is to call through SQL Job. This does require you to configure your project to already reference an environment and use its variable. When a job step is set up, the configuration part will require you to select that reference again. This is more useful when you want to automate the same package that needs to be run in different environments.

The third option is the most important to me as I have a SSIS framework that calls hundreds of packages. The main part of the stored procedure is in this post (http://geekswithblogs.net/LifeLongTechie/archive/2012/11/14/time-to-stop-using-ldquoexecute-package-taskrdquondash-a-way-to.aspx). But the top part had to be modified to include the logic to use environment reference.
CREATE PROCEDURE [AUDIT].[LaunchPackageExecutionInSSISCatalog]
@PackageName NVARCHAR(255)
, @ProjectFolder NVARCHAR(255)
, @ProjectName NVARCHAR(255)
, @AuditKey INT
, @DisableNotification BIT
, @PackageExecutionLogID INT
, @EnvironmentName NVARCHAR(128) = NULL
, @Use32BitRunTime BIT = FALSE
AS
BEGIN TRY
DECLARE @execution_id BIGINT = 0;
-- Create a package execution
IF @EnvironmentName IS NULL BEGIN
EXEC [SSISDB].[catalog].[create_execution]
@package_name=@PackageName,
@execution_id=@execution_id OUTPUT,
@folder_name=@ProjectFolder,
@project_name=@ProjectName,
@use32bitruntime=@Use32BitRunTime;
END
ELSE BEGIN
DECLARE @EnvironmentID AS INT
SELECT @EnvironmentID = [reference_id]
FROM SSISDB.[internal].[environment_references] WITH(NOLOCK)
WHERE [environment_name] = @EnvironmentName
AND [environment_folder_name] = @ProjectFolder
EXEC [SSISDB].[catalog].[create_execution]
@package_name=@PackageName,
@execution_id=@execution_id OUTPUT,
@folder_name=@ProjectFolder,
@project_name=@ProjectName,
@reference_id=@EnvironmentID,
@use32bitruntime=@Use32BitRunTime;
END
Wednesday, November 21, 2012
#
There are so many funny quirks in SSIS 2012 that I have to list them, to save other people from the misery.
- If you want to move items to one direction, make sure you "grab" the opposite side. For example, you want a whole bunch of data flows to move up, select them all and grab the lowest item.
- When you drag the arrow to connect Precendence Constraint, make sure you drop it on the area of target that has no text, otherwise, it thinks you want to edit the text and change the target item layout
Always was able to do it in a .NET application and a reporting project. This took me a while to realize. In SSIS 2012 project, once you create project.params, you can add them to your configuration settings by clicking this button

A dialogue pops up where you can add your project params and specify their values in different configuration set.
Refer to my previous post (http://geekswithblogs.net/LifeLongTechie/archive/2012/11/14/time-to-stop-using-ldquoexecute-package-taskrdquondash-a-way-to.aspx) about dynamic package calling and multiple packages execution in these posts:
I only saw this twice, other times the stored procedure was able to call the packages successfully. After the service pack, I haven't seen it...yet.
http://support.microsoft.com/kb/2699720
Wednesday, November 14, 2012
#
I set out to find a way to dynamically call package in SSIS 2012. The following are 2 excellent blogs I found; I used them heavily. The code below has some addition to parameter types and message types, but was made essentially derived entirely from the blogs.
http://sqlblog.com/blogs/jamie_thomson/archive/2011/07/16/ssis-logging-in-denali.aspx
http://www.ssistalk.com/2012/07/24/quick-tip-run-ssis-2012-packages-synchronously-and-other-execution-options/
The code:
Every package will be called by a PackageController package. The packageController is initialized with some information on which package to run and what information to pass in.

The following is the stored procedure called from the “Execute SQL Task”. Here is the highlight of the stored procedure
- It takes in packageName, project name, and folder name (folder in SSIS project deployment to SSIS catalog)
- The stored procedure sets the package variables of the upcoming package execution
- Execute package in SSIS Catalog
- Get the status of the execution. Also, if exists, get the error message’s message_id and store them in the management database.
- Return value to “Execute SQL Task” to manage failure properly
CREATE PROCEDURE [AUDIT].[LaunchPackageExecutionInSSISCatalog]
@PackageName NVARCHAR(255)
, @ProjectFolder NVARCHAR(255)
, @ProjectName NVARCHAR(255)
, @AuditKey INT
, @DisableNotification BIT
, @PackageExecutionLogID INT
AS
BEGIN TRY
DECLARE @execution_id BIGINT = 0;
-- Create a package execution
EXEC [SSISDB].[catalog].[create_execution]
@package_name=@PackageName,
@execution_id=@execution_id OUTPUT,
@folder_name=@ProjectFolder,
@project_name=@ProjectName,
@use32bitruntime=False;
UPDATE [AUDIT].[PackageInstanceExecutionLog] WITH(ROWLOCK)
SET [SSISCatalogExecutionID] = @execution_id
WHERE [PackageInstanceExecutionLogID] = @PackageExecutionLogID
-- this is to set the execution synchronized so that I can check the result in the end
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=50,
@parameter_name=N'SYNCHRONIZED',
@parameter_value=1; -- true
/********************************************************
********************************************************
Section: setting parameters
Source table: SSISDB.internal.object_parameters
object_type list:
20: project level variables
30: package level variables
50: execution parameter
********************************************************
********************************************************/
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=30,
@parameter_name=N'FromParent_AuditKey',
@parameter_value=@AuditKey; -- true
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=30,
@parameter_name=N'FromParent_DisableNotification',
@parameter_value=@DisableNotification; -- true
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=30,
@parameter_name=N'FromParent_PackageInstanceExecutionID',
@parameter_value=@PackageExecutionLogID; -- true
/********************************************************
********************************************************
Section: setting variables END
********************************************************
********************************************************/
/* This section is carried over from example code
I don't see a reason to change them yet
*/
-- Set our package parameters
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=50,
@parameter_name=N'DUMP_ON_EVENT',
@parameter_value=1; -- true
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=50,
@parameter_name=N'DUMP_EVENT_CODE',
@parameter_value=N'0x80040E4D;0x80004005';
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=50,
@parameter_name=N'LOGGING_LEVEL',
@parameter_value= 1; -- Basic
EXEC [SSISDB].[catalog].[set_execution_parameter_value]
@execution_id,
@object_type=50,
@parameter_name=N'DUMP_ON_ERROR',
@parameter_value=1; -- true
/********************************************************
********************************************************
Section: EXECUTING
********************************************************
********************************************************/
EXEC [SSISDB].[catalog].[start_execution]
@execution_id;
/********************************************************
********************************************************
Section: EXECUTING END
********************************************************
********************************************************/
/********************************************************
********************************************************
Section: checking execution result
Source table: [SSISDB].[catalog].[executions]
status:
1: created
2: running
3: cancelled
4: failed
5: pending
6: ended unexpectedly
7: succeeded
8: stopping
9: completed
********************************************************
********************************************************/
if EXISTS(SELECT TOP 1 1
FROM [SSISDB].[catalog].[executions] WITH(NOLOCK)
WHERE [execution_id] = @execution_id
AND [status] NOT IN (2, 7, 9)) BEGIN
/********************************************************
********************************************************
Section: logging error messages
Source table: [SSISDB].[internal].[operation_messages]
message type:
10: OnPreValidate
20: OnPostValidate
30: OnPreExecute
40: OnPostExecute
60: OnProgress
70: OnInformation
90: Diagnostic
110: OnWarning
120: OnError
130: Failure
140: DiagnosticEx
200: Custom events
400: OnPipeline
message source type:
10: Messages logged by the entry APIs (e.g. T-SQL, CLR Stored procedures)
20: Messages logged by the external process used to run package (ISServerExec)
30: Messages logged by the package-level objects
40: Messages logged by tasks in the control flow
50: Messages logged by containers (For, ForEach, Sequence) in the control flow
60: Messages logged by the Data Flow Task
********************************************************
********************************************************/
INSERT INTO AUDIT.PackageInstanceExecutionOperationErrorLink
SELECT @PackageExecutionLogID
,[operation_message_id]
FROM [SSISDB].[internal].[operation_messages] WITH(NOLOCK)
WHERE operation_id = @execution_id
AND message_type IN (120, 130)
EXEC [AUDIT].[FailPackageInstanceExecution] @PackageExecutionLogID, 'SSISDB Internal operation_messages found'
GOTO ReturnTrueAsErrorFlag
/********************************************************
********************************************************
Section: checking messages END
********************************************************
********************************************************/
/* This part is not really working, so now using rowcount to pass status
--DECLARE @PackageErrorMessage NVARCHAR(4000)
--SET @PackageErrorMessage = @PackageName + 'failed with executionID: ' + CONVERT(VARCHAR(20), @execution_id)
--RAISERROR (@PackageErrorMessage -- Message text.
-- , 18 -- Severity,
-- , 1 -- State,
-- , N'check table AUDIT.PackageInstanceExecutionErrorMessages' -- First argument.
-- );
*/
END
ELSE BEGIN
GOTO ReturnFalseAsErrorFlagToSignalSuccess
END
/********************************************************
********************************************************
Section: checking execution result END
********************************************************
********************************************************/
END TRY
BEGIN CATCH
DECLARE @SSISCatalogCallError NVARCHAR(MAX)
SELECT @SSISCatalogCallError = ERROR_MESSAGE()
EXEC [AUDIT].[FailPackageInstanceExecution] @PackageExecutionLogID, @SSISCatalogCallError
GOTO ReturnTrueAsErrorFlag
END CATCH;
/********************************************************
********************************************************
Section: end result
********************************************************
********************************************************/
ReturnTrueAsErrorFlag:
SELECT CONVERT(BIT, 1) AS PackageExecutionErrorExists
ReturnFalseAsErrorFlagToSignalSuccess:
SELECT CONVERT(BIT, 0) AS PackageExecutionErrorExists
GO
Thursday, November 8, 2012
#
There are quite a few good articles/blogs on this. For a straight forward deployment, read this (http://www.bibits.co/post/2012/08/23/SSIS-SQL-Server-2012-Project-Deployment.aspx). For a more dynamic and comprehensive understanding about all the different settings, read part 1 (http://www.mssqltips.com/sqlservertip/2450/ssis-package-deployment-model-in-sql-server-2012-part-1-of-2/) and part 2 (http://www.mssqltips.com/sqlservertip/2451/ssis-package-deployment-model-in-sql-server-2012-part-2-of-2/)
Microsoft official doc: http://technet.microsoft.com/en-us/library/hh213373
This only thing I would add is the following. After your first deployment, you'll notice that the subsequent deployment skips the second step (go directly "Select Destination" and skipped "Select Source"). That's because after your initial deployment, a ispac file is created to track deployment. If you decide to go back to "Select Source" and select SSIS catalog again, the deployment process will complete, but the packages will not be deployed.
%20via%20SQL%20Server%20Data%20Tools%20screenshot%201_thumb.jpg)
%20via%20SQL%20Server%20Data%20Tools%20screenshot%202_thumb_1.jpg)
%20via%20SQL%20Server%20Data%20Tools%20screenshot%203_thumb.jpg)
Wednesday, November 7, 2012
#
I'm slowing and surely getting used to Windows 8. It is no doubt a slow process since I still run daily on an XP machine, a Vista machine, and 3 windows 7 box.
A new quirk I found regarding Windows 8. I never thought it was important to learn how to close a "formerly known as Metro" app (what do we call those these days?). Then I attached a portable drive to my laptop and opened up a PDF file, and I couldn't safely remove the hard drive afterwards because I did not know how to close the PDF reader app.
I have since learned that if you want to close an app, you can try
- Alt + F4
- mouse over the top left corner and swipe down, right-click to close you app
- Windows Key + TAB, right-click to close the app
All these make me wonder, how do you do this in a phone or tablet?
Saturday, November 3, 2012
#
Suffice to say there is now a document in place and I'm the drill sergeant, harassing people to do proper check in, and throw out those who don't.
Some people suggest that in a SSIS project, it doesn't really matter if developers don't have the latest version of the project since package check in put the package in the repository, which we can pull out later. I beg to differ because:
- When people don't see the package, they might start creating one because their user story require the use of the table. So they will proceed to create a package and override whatever might already be in the repository.
- I didn't really see anywhere in the repository to say that which packages were for "deletion". So I ended up restoring them all, and send the list out to developers. Then we get into the area where we are relying on people's memory.
I'd love to hear other people's experience using Subversion to manage a BI project.
Tuesday, October 16, 2012
#
I got on this site after attending one of Jeff's session at Day of .NET. Have been trying to blog since. My schedule was spotty at best, so I can't imagine what amount of work Jeff has put into the site so that people like us can put our 2 cents out there, track our own development progress, and just simply document our learning.
Thanks, Jeff. And hope you will still blog here!
Today is the second day I'm using a Windows 8 laptop. Load up time is fast, and changing applications is very smooth. However, I keep finding myself hitting the windows key (double-clicking a PDF file, and, what? How do I get back?)
Other than that, the experience has been fine. So far this has not been any worse than other windows upgrade experience I had so far. No bad news is good news here.
Really cannot describe the disappointment felt at this moment. A month ago there was rumor out there saying Surface tablet will be around $200. Even though everybody agreed at the time that's not possible, or fair to Microsoft partners, the expectation was set.
I'll wait.
It was on first floor near the Apple store (Apple store is on 2nd floor). But since I was with wife and kids, I didn't linger...
Now the question is whether to wait for the intel-based one; I guess the question before that one is whom I'm getting this tablet for.
Still sworn off smartphone...
[UPDATE 2012-10-16]
This post was made minutes before another one, which destroyed my enthusiasm for Microsoft popup store.