Re: queries against CIDR fail against 8.0.3?
От | Russell Francis |
---|---|
Тема | Re: queries against CIDR fail against 8.0.3? |
Дата | |
Msg-id | 433DF50D.7060206@ev.net обсуждение исходный текст |
Ответ на | Re: queries against CIDR fail against 8.0.3? (Kris Jurka <books@ejurka.com>) |
Ответы |
Re: queries against CIDR fail against 8.0.3?
(Russell Francis <rfrancis@ev.net>)
|
Список | pgsql-jdbc |
> > Seems reasonable for us to offer a PGxxx class for every core backend > type. Send them in and we'll take a look... > > Kris Jurka > Kris, Attached is an implementation for the proposed PGcidr & PGinet classes. I have tried to follow the formatting conventions used in the geometric extensions but is is a first attempt, please let me know if there is anything else I should/could do to improve these. I will take any comments / suggestions and incorporate them into the PGmacaddr class also. Cheers, Russ /*------------------------------------------------------------------------- * * Copyright (C) 2005, PostgreSQL Global Development Group * *-------------------------------------------------------------------------- */ package org.postgresql.net; import java.io.Serializable; import java.sql.SQLException; import org.postgresql.util.GT; import org.postgresql.util.PGobject; import org.postgresql.util.PGtokenizer; import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLState; /** * This represents org.postgresql's cidr datatype, which is * used to hold network addresses. * * <p> * This class wraps the postgresql specific CIDR datatype. It * supports IPV4 network addresses in the following format. * <p> * a[.b[.c[.d]]][/e] * * @author Russell Francis < rfrancis@ev.net > */ public class PGcidr extends PGobject implements Serializable, Cloneable { protected int hashValue; /** * This constructor takes a string in the * cidr format a[.b[.c[.d]]][/e] and creates * a PGcidr to represent it. * * @param s The representation of the cidr as a string. * @exception SQLException if the string is not in the proper format. */ public PGcidr( String s ) throws SQLException { this(); setValue( s ); } /** * A simple constructor. */ public PGcidr() { setType( "cidr" ); } /** * Set the value of this CIDR. * * <p>This accepts strings in the a[.b[.c[.d]]][/netmask] format. * * @param v The string representation of this network address. * @exception SQLException If it is not in a valid cidr format. */ public void setValue( String v ) throws SQLException { int a = 0; int b = 0; int c = 0; int d = 0; int netmask = -1; if( v == null ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } PGtokenizer t = new PGtokenizer( v, '/' ); int size = t.getSize(); if( ( size != 1 ) && ( size != 2 ) ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } try { if( size == 2 ) { // we have a netmask to read netmask = Integer.valueOf( t.getToken( 1 ) ).intValue(); if( ( netmask < 0 ) || ( netmask > 32 ) ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } } // read the body a.b.c.d t = new PGtokenizer( t.getToken( 0 ), '.' ); size = t.getSize(); if( ( size < 1 ) || ( size > 4 ) ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } a = Integer.valueOf( t.getToken( 0 ) ).intValue(); if( size >= 2 ) { b = Integer.valueOf( t.getToken( 1 ) ).intValue(); } if( size >= 3 ) { c = Integer.valueOf( t.getToken( 2 ) ).intValue(); } if( size >= 4 ) { d = Integer.valueOf( t.getToken( 3 ) ).intValue(); } } catch( NumberFormatException e ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v }), PSQLState.DATA_TYPE_MISMATCH, e ) ); } if( ( a < 0 ) || ( a > 255 ) || ( b < 0 ) || ( b > 255 ) || ( c < 0 ) || ( c > 255 ) || ( d < 0 ) || ( d > 255 ) ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } // If the netmask is not set in the parameter, // we will take a guess like PG does. // // 1.0.0.0 - 127.0.0.0 - class A, netmask 8 // 128.0.0.0 - 191.0.0.0 - class B, netmask 16 // 192.0.0.0 - 223.0.0.0 - class C, netmask 24 if( netmask == -1 ) { // start with a safe default, we will try to trim // this down depending on the values of a,b,c & d. netmask = 32; if( a >= 1 || a <= 127 ) { if( b == 0 && c == 0 && d == 0 ) { netmask = 8; } else if( c == 0 && d == 0 ) { netmask = 16; } else if( d == 0 ) { netmask = 24; } } else if( a >= 128 && a <= 191 ) { if( c == 0 && d == 0 ) { netmask = 16; } else if( d == 0 ) { netmask = 24; } } else if( a >= 192 && a <= 223 ) { if( d == 0 ) { netmask = 24; } } } // verify that there are no bits to the right of the netmask if( netmask < 32 ) { int address = ( a << 24 ) | ( b << 16 ) | ( c << 8 ) | d; address <<= netmask; if( address != 0 ) { // There are bits to the right of the netmask throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v }), PSQLState.DATA_TYPE_MISMATCH ) ); } } // Seems like it will generate a decent hash? this.hashValue = ((a ^ b) << 24) | ((b ^ c) << 8) | ((c ^ d) << 16) | (d ^ netmask); // ok, the parameter cleared all of out tests, // a.b.c.d/netmask should contain out new CIDR value. this.value = "" + a + "." + b + "." + c + "." + d + "/" + netmask; } /** * Get the hash code for this network address. * * @return The hash value for this object. */ public int hashCode() { return( this.hashValue ); } /** * Compare two PGcidr objects for equality. * * <p>This will return true if the parameter obj is of type PGcidr * and represents the same network as this. * * @param obj The object which we wish to compare. * @return true if it represents the same network as this, false otherwise. */ public boolean equals( Object obj ) { if( obj instanceof PGcidr ) { PGcidr cidr = (PGcidr)obj; if( this.getValue().equals( cidr.getValue() ) ) { return( true ); } } return( false ); } /** * This will make a duplicate of the current PGcidr object. * * @return null on failure, or a new PGcidr object which * represents the same network address as the invoking * object. */ public Object clone() { try { return( new PGcidr( this.getValue() ) ); } catch( SQLException e ) { return( null ); } } } /*------------------------------------------------------------------------- * * Copyright (C) 2005, PostgreSQL Global Development Group * *-------------------------------------------------------------------------- */ package org.postgresql.net; import java.io.Serializable; import java.sql.SQLException; import org.postgresql.util.GT; import org.postgresql.util.PGobject; import org.postgresql.util.PGtokenizer; import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLState; /** * This represents org.postgresql's inet datatype, which is used * to hold IPV4 network addresses and ip addresses. * * <p> * This class wraps the postgresql specific INET datatype. It supports * values in the following format. * <p> * a.b.c.d[/netmask] * * @author Russell Francis < rfrancis@ev.net > */ public class PGinet extends PGobject implements Serializable, Cloneable { private int hashValue; /** * This constructor takes a string in the inet format * a.b.c.d[/netmask] and creates a new PGinet to * represent it. * * @param s The string representation of the inet value. * @exception SQLException If the string is invalid. */ public PGinet( String s ) throws SQLException { this(); this.setValue( s ); } /** * A simple constructor. */ public PGinet() { setType( "inet" ); } /** * This method sets the value of this PGinet object. * * @param v A string representation of an inet address a.b.c.d[/netmask] * @exception SQLException If the parameter is not a valid inet address. */ public void setValue( String v ) throws SQLException { if( v == null ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } PGtokenizer t = new PGtokenizer( v, '/' ); int size = t.getSize(); if( ( size != 1 ) && ( size != 2 ) ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } int a = 0; int b = 0; int c = 0; int d = 0; int netmask = 32; try { if( size == 2 ) { netmask = Integer.valueOf( t.getToken( 1 ) ).intValue(); if( ( netmask < 0 ) || ( netmask > 32 ) ) { throw( new PSQLException( GT.tr( "Conversion to typ {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } } t = new PGtokenizer( t.getToken( 0 ), '.' ); if( t.getSize() != 4 ) { throw( new PSQLException( GT.tr( "Conversion to typ {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } a = Integer.valueOf( t.getToken( 0 ) ).intValue(); b = Integer.valueOf( t.getToken( 1 ) ).intValue(); c = Integer.valueOf( t.getToken( 2 ) ).intValue(); d = Integer.valueOf( t.getToken( 3 ) ).intValue(); } catch( NumberFormatException e ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH, e ) ); } // ensure that the values are within a valid range. if( ( a < 0 ) || ( a > 255 ) || ( b < 0 ) || ( b > 255 ) || ( c < 0 ) || ( c > 255 ) || ( d < 0 ) || ( d > 255 ) ) { throw( new PSQLException( GT.tr( "Conversion to type {0} failed: {1}.", new Object[]{ type, v } ), PSQLState.DATA_TYPE_MISMATCH ) ); } this.hashValue = ((a ^ c) << 24) | ((b ^ d) << 16) | ((b ^ c) << 8) | (d ^ netmask); this.value = "" + a + "." + b + "." + c + "." + d + ((netmask == 32) ? "" : ("/" + netmask)); } /** * Get the hash code for this network address. * * @return The hash value for this object. */ public int hashCode() { return( this.hashValue ); } /** * Compare two PGinet's for equality. * * @param obj The object which we wish to compare. * @return true if it represents the same network or ip address * as this PGinet, false otherwise. */ public boolean equals( Object obj ) { if( obj instanceof PGinet ) { PGinet inet = (PGinet)obj; if( this.toString().equals( inet.toString() ) ) { return( true ); } } return( false ); } /** * Make a duplicate of this PGinet object. * * @return null on failure, or a new PGinet address * which is equal to this object. */ public Object clone() { try { return( new PGinet( this.getValue() ) ); } catch( SQLException e ) { return( null ); } } }
В списке pgsql-jdbc по дате отправления:
Следующее
От: andres@sayago.infoДата:
Сообщение: Problems with alias in UPDATE over JDeveloper+ADF: I have the answer