Saturday, February 19, 2011

Checking if a variable is defined in Ruby

How do you check whether a variable is defined in Ruby? Is there an "isset"-type method available?

From stackoverflow
  • defined?(your_var) will work. Depending on what you're doing you can also do something like your_var.nil?

  • use defined? It will return a string with the kind of the item or nil if it don't exist

    irb(main):007:0> a = 1
    => 1
    irb(main):008:0> defined? a
    => "local-variable"
    irb(main):009:0> defined? b
    => nil
    irb(main):010:0> defined? String
    => "constant"
    irb(main):011:0> defined? 1
    => "expression"
    
  • this is useful if you want to do nothing if it does exist but create it if it doesn't exist

    def get_var
      @var ||= SomeClass.new()
    end
    

    this only creates the new class once after that just keeps returning the var

  • Here is some code, nothing rocket science but it works well enough

    require 'rubygems'
    require 'rainbow'
    if defined?(var).nil?
     print "var is not defined\n".color(:red)
    else
     print "car is defined\n".color(:green)
    end
    

Linked Images

I have made it so that when I double click on certain images in Visio, it will take you to another page. Is there a way that the image can be identified as being linked so that if i sent it to someone, they would know to click on it?

From stackoverflow
  • Firstly the appearance of the shape can to a lot to suggest the shape is a link. See the "Off-page connector" shape

    Also take a look at how the "Off-page reference" shape is implemented. It uses a Hyperlink in addition to the double click event. This causes the pointer change when you mouse over the shape.

    Unfortunately both approaches suggest that the shape links somewhere but don't tell you have to double click to follow the link.

How do you add a NOT NULL Column to a large table in SQL Server?

To add a NOT NULL Column to a table with many records, a DEFAULT constraint needs to be applied. This constraint causes the entire ALTER TABLE command to take a long time to run if the table is very large. This is because:

Assumptions:

  1. The DEFAULT constraint modifies existing records. This means that the db needs to increase the size of each record, which causes it to shift records on full data-pages to other data-pages and that takes time.
  2. The DEFAULT update executes as an atomic transaction. This means that the transaction log will need to be grown so that a roll-back can be executed if necessary.
  3. The transaction log keeps track of the entire record. Therefore, even though only a single field is modified, the space needed by the log will be based on the size of the entire record multiplied by the # of existing records. This means that adding a column to a table with small records will be faster than adding a column to a table with large records even if the total # of records are the same for both tables.

Possible solutions:

  1. Suck it up and wait for the process to complete. Just make sure to set the timeout period to be very long. The problem with this is that it may take hours or days to do depending on the # of records.
  2. Add the column but allow NULL. Afterward, run an UPDATE query to set the DEFAULT value for existing rows. Do not do UPDATE *. Update batches of records at a time or you'll end up with the same problem as solution #1. The problem with this approach is that you end up with a column that allows NULL when you know that this is an unnecessary option. I believe that there are some best practice documents out there that says that you should not have columns that allow NULL unless it's necessary.
  3. Create a new table with the same schema. Add the column to that schema. Transfer the data over from the original table. Drop the original table and rename the new table. I'm not certain how this is any better than #1.

Question:

1) Are my assumptions correct? 2) Are these my only solutions? If so, which one is the best? If not, what else could I do?

From stackoverflow
  • I think this depends on the SQL flavor you are using, but what if you took option 2, but at the very end alter table table to not null with the default value?

    Would it be fast, since it sees all the values are not null?

  • Vertically segment the table. This means you will have two tables, with the same primary key, and exactly the same number of records... One will be the one you already have, the other will have just the key, and the new Non-Null column (with default value) . Modify all Insert, Update, and delete code so they keep the two tables in synch... If you want you can create a view that "joins" the two tables together to create a single logical combination of the two that appears like a single table for client Select statements...

    Vinko Vrsalovic : Did you mean vertically?
    Charles Bretana : ahh yes, missed a t... I'm unfortunately a 2-finger typer...
    rmeador : This seems like a very dangerous solution. Do it the right way. If you do attempt this solution, make the new view that joins the two tables be the name of the original table (so no client code needs to be changed).
  • Here's what I would try:

    • Do a full backup of the database.
    • Add the new column, allowing nulls - don't set a default.
    • Set SIMPLE recovery, which truncates the tran log as soon as each batch is committed.
    • The SQL is: ALTER DATABASE XXX SET RECOVERY SIMPLE
    • Run the update in batches as you discussed above, committing after each one.
    • Reset the new column to no longer allow nulls.
    • Go back to the normal FULL recovery.
    • The SQL is: ALTER DATABASE XXX SET RECOVERY FULL
    • Backup the database again.

    The use of the SIMPLE recovery model doesn't stop logging, but it significantly reduces its impact. This is because the server discards the recovery information after every commit.

    Lamar : Depending on size of the table, make sure you have enough log space. Resetting the column to no longer allow nulls is log intensive.
  • I would use CURSOR instead of UPDATE. Cursor will update all matching records in batch, record by record -- it takes time but not locks table.

    If you want to avoid locks use WAIT.

    Also I am not sure, that DEFAULT constrain changes existing rows. Probably NOT NULL constrain use together with DEFAULT causes case described by author.

    If it changes add it in the end So pseudocode will look like:

    -- without NOT NULL constrain -- we will add it in the end
    ALTER TABLE table ADD new_column INT DEFAULT 0
    
    DECLARE fillNullColumn CURSOR LOCAL FAST_FORWARD
        SELECT 
            key
        FROM
            table WITH (NOLOCK)
        WHERE
            new_column IS NULL
    
    OPEN fillNullColumn
    
    DECLARE 
        @key INT
    
    FETCH NEXT FROM fillNullColumn INTO @key
    
    WHILE @@FETCH_STATUS = 0 BEGIN
         UPDATE
             table WITH (ROWLOCK)
         SET
             new_column = 0 -- default value
         WHERE
             key = @key
    
         WAIT 00:00:05 --wait 5 seconds, keep in mind it causes updating only 12 rows per minute
    
         FETCH NEXT FROM fillNullColumn INTO @key
    END
    
    CLOSE fillNullColumn
    DEALLOCATE fillNullColumn
    
    ALTER TABLE table ALTER COLUMN new_column ADD CONSTRAIN xxx
    

    I am sure that there are some syntax errors, but I hope that this help to solve your problem.

    Good luck!

  • If you want the column in the same table, you'll just have to do it. Now, option 3 is potentially the best for this because you can still have the database "live" while this operation is going on. If you use option 1, the table is locked while the operation happens and then you're really stuck.

    If you don't really care if the column is in the table, then I suppose a segmented approach is the next best. Though, I really try to avoid that (to the point that I don't do it) because then like Charles Bretana says, you'll have to make sure and find all the places that update/insert that table and modify those. Ugh!

  • You could:

    1. Start a transaction.
    2. Grab a write lock on your original table so no one writes to it.
    3. Create a shadow table with the new schema.
    4. Transfer all the data from the original table.
    5. execute sp_rename to rename the old table out.
    6. execute sp_rename to rename the new table in.
    7. Finally, you commit the transaction.

    The advantage of this approach is that your readers will be able to access the table during the long process and that you can perform any kind of schema change in the background.

  • I had a similar problem, and went for your option #2. It takes 20 minutes this way, as opposed to 32 hours the other way!!! Huge difference, thanks for the tip. I wrote a full blog entry about it, but here's the important sql:

    Alter table MyTable
    Add MyNewColumn char(10) null default '?';
    go
    
    update MyTable set MyNewColumn='?' where MyPrimaryKey between 0 and 1000000
    go
    update MyTable set MyNewColumn='?' where MyPrimaryKey between 1000000 and 2000000
    go
    update MyTable set MyNewColumn='?' where MyPrimaryKey between 2000000 and 3000000
    go
    ..etc..
    
    Alter table MyTable
    Alter column MyNewColumn char(10) not null;
    

    And the blog entry if you're interested: http://splinter.com.au/blog/?p=116

  • ran into this problem for my work also. And my solution is along #2.

    Here are my steps (I am using SQL Server 2005)

    1) ALTER TABLE MyTable ADD MyColumn varchar(40) DEFAULT('')

    2) Add Not null constraint with nocheck option. NOCHECK option does not enforce on existing values.

    ALTER TABLE MyTable WITH NOCHECK ADD CONSTRAINT MyColumn_NOTNULL CHECK (MyColumn IS NOT NULL)

    3) UPDATE TOP(3000) MyTable SET MyColumn = '' WHERE MyColumn IS NULL GO 1000

    • The update statement will only update maximum 3000 records. This allow to save a chunk of data at the time. I have to use "MyColumn IS NULL" because my table does not have a sequence primary key.

    • GO 1000 will execute the previous statement 1000 times. This will update 3 millions records, if you need more just increase this number. I will continue to execute untill sql server return 0 records for UPDATE statement.

Get the position of a div/span tag

Can someone show me how to get the .top & .left position of a div or span tag when one is not specified?

ie:

<span id='11a' style='top:55px;' onmouseover="GetPos(this);">stuff</span>
<span id='12a' onmouseover="GetPos(this);">stuff</span>

In the above, if i do:

document.getElementById('11a').style.top

The the value of 55px is returned. However if i try that for span '12a', then nothing gets returned. I have a bunch of div/spans on a page that i cannot specify the top/left properties for, but i need to display a div directly under that element.

Thanks for lookin :-)

From stackoverflow
  • This function will tell you the x,y position of the element relative to the page. Basically you have to loop up through all the element's parents and add their offsets together.

    function getPos(el) {
        // yay readability
        for (var lx=0, ly=0;
             el != null;
             lx += el.offsetLeft, ly += el.offsetTop, el = el.offsetParent);
        return {x: lx,y: ly};
    }
    

    However, if you just wanted the x,y position of the element relative to its container, then all you need is:

    var x = el.offsetLeft, y = el.offsetTop;
    

    To put an element directly below this one, you'll also need to know its height. This is stored in the offsetHeight/offsetWidth property.

    var yPositionOfNewElement = el.offsetTop + el.offsetHeight + someMargin;
    
  • If using jQuery (don't implement it only for this solution but) you can use the more succinct code.

    left = $('.span').offset().left;
    top = $('.span').offset().top;
    

Article on using Firebird.NET in a WinForms application

Hi all, Can anyone provide me with a link to good article about using Firebird.NET with a WinForms application? A simple google search did not yield good results - I am looking for a step-by-step guide which will help me to quickly a few things and am not sure the documentation is a good place to start.

Thanks in advance. Anindya

From stackoverflow

$1 and \1 in Ruby

When using regular expressions in Ruby, what is the difference between $1 and \1?

From stackoverflow
  • \1 is a backreference which will only work in the same sub or gsub method call, e.g.:

    "foobar".sub(/foo(.*)/, "\1\1") # => "barbar"

    $1 is a global variable which can be used in later code:

    if "foobar" =~ /foo(.*)/ then 
      puts "The matching word was #{$1}"
    end
    

    (prints "The matching word was bar")

  • Keep in mind there's a third option, the block form of sub. Sometimes you need it. Say you want to replace some text with the reverse of that text. You can't use $1 because it's not bound quickly enough:

    "foobar".sub(/(.*)/, $1.reverse)  # WRONG: either uses a PREVIOUS value of $1, 
                                      # or gives an error if $1 is unbound
    

    You also can't use \1, because the sub method just does a simple text-substitution of \1 with the appropriate captured text, there's no magic taking place here:

    "foobar".sub(/(.*)/, '\1'.reverse) # WRONG: returns '1\'
    

    So if you want to do anything fancy, you should use the block form of sub ($1, $2, $`, $' etc. will be available):

    "foobar".sub(/.*/){|m| m.reverse} # => returns 'raboof'
    "foobar".sub(/(...)(...)/){$1.reverse + $2.reverse} # => returns 'oofrab'
    
    rampion : Your example could be misleading - the match is what's passed to the block, not the matchgroups. So, if you wanted to change "foobar" to "foorab", you'd have to do `str.sub(/(foo)(\w+)/) { $1 + $2.reverse }`
    rampion : See ri String#sub: In the block form, the current match string is passed in as a parameter, and variables such as $1, $2, $`, $&, and $' will be set appropriately. The value returned by the block will be substituted for the match on each call.
    Brian Carper : Right, I'll edit to clear it up.
    Adrian : You saved my day!
  • That "\1\1" in the main answer should be '\1\1'

How do I read an MSMQ message from a VB6 app using .NET code?

I am writing a simple xml string to an MSMQ from a VB6 app, but when I attempt to read the message off the queue in C# using the XmlMessageFormatter I get the following error:

"Name cannot begin with the '.' character"

How do I successfully read these messages using .Net code?

From stackoverflow
  • first inspect your data to make sure it really is as the error message implies. If it is, first read the data as text or binary, remove the offending '.', then use the xmlmessageformatter

  • I believe that you have to use the ActiveXMessageFormatter, and not the XmlMessageFormatter. The XmlMessageFormatter is for sending objects between .net applications. What you are sending is not xml but string. And not a .net string. According to the documentation of the ActiveXMessageFormatter it is for:

    Serializes or deserializes primitive data types and other objects to or from the body of a Message Queuing message, using a format that is compatible with the MSMQ ActiveX Component

    When you send from vb6 you are using the msmq com interface. Which is another name for ActiveX interface. After you receive the string with the ActiveXMessageFormatter. Convert it to xml object explicitly.